SITL: break up GPS backends into separate files

This commit is contained in:
Peter Barker
2023-11-29 18:04:56 +11:00
committed by Andrew Tridgell
parent 0a4eb251c6
commit 568d633dcc
21 changed files with 2057 additions and 1778 deletions
+25 -1537
View File
File diff suppressed because it is too large Load Diff
+22 -241
View File
File diff suppressed because it is too large Load Diff
+67
View File
@@ -0,0 +1,67 @@
#include "SIM_config.h"
#if AP_SIM_GPS_FILE_ENABLED
#include "SIM_GPS_FILE.h"
#include <AP_HAL/AP_HAL.h>
#include <SITL/SITL.h>
extern const AP_HAL::HAL& hal;
using namespace SITL;
/*
read file data logged from AP_GPS_DEBUG_LOGGING_ENABLED
*/
void GPS_FILE::publish(const GPS_Data *d)
{
static int fd[2] = {-1,-1};
static uint32_t base_time[2];
const uint16_t lognum = uint16_t(_sitl->gps_log_num.get());
if (instance > 1) {
return;
}
if (fd[instance] == -1) {
char fname[] = "gpsN_NNN.log";
hal.util->snprintf(fname, 13, "gps%u_%03u.log", instance+1, lognum);
fd[instance] = open(fname, O_RDONLY|O_CLOEXEC);
if (fd[instance] == -1) {
return;
}
}
const uint32_t magic = 0x7fe53b04;
struct {
uint32_t magic;
uint32_t time_ms;
uint32_t n;
} header;
uint8_t *buf = nullptr;
while (true) {
if (::read(fd[instance], (void *)&header, sizeof(header)) != sizeof(header) ||
header.magic != magic) {
goto rewind_file;
}
if (header.time_ms+base_time[instance] > AP_HAL::millis()) {
// not ready for this data yet
::lseek(fd[instance], -sizeof(header), SEEK_CUR);
return;
}
buf = new uint8_t[header.n];
if (buf != nullptr && ::read(fd[instance], buf, header.n) == ssize_t(header.n)) {
write_to_autopilot((const char *)buf, header.n);
delete[] buf;
buf = nullptr;
continue;
}
goto rewind_file;
}
rewind_file:
::printf("GPS[%u] rewind\n", unsigned(instance));
base_time[instance] = AP_HAL::millis();
::lseek(fd[instance], 0, SEEK_SET);
delete[] buf;
}
#endif // AP_SIM_GPS_FILE_ENABLED
+20
View File
@@ -0,0 +1,20 @@
#include "SIM_config.h"
#if AP_SIM_GPS_FILE_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class GPS_FILE : public GPS_Backend {
public:
CLASS_NO_COPY(GPS_FILE);
using GPS_Backend::GPS_Backend;
void publish(const GPS_Data *d) override;
};
};
#endif // AP_SIM_GPS_FILE_ENABLED
File diff suppressed because it is too large Load Diff
+149
View File
@@ -0,0 +1,149 @@
#pragma once
#include "SIM_config.h"
#if AP_SIM_GPS_GSOF_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class DCOL_Parser {
// The DCOL parser is used by Trimble GSOF devices.
// It's used for doing configuration.
// https://receiverhelp.trimble.com/oem-gnss/API_DataCollectorFormatPackets.html
public:
// Feed data in to the DCOL parser.
// If the data reaches a parse state that needs to write ACK/NACK back out,
// the function returns true with a populated data_out value.
// Otherwise, it returns false waiting for more data.
bool dcol_parse(const char data_in);
static constexpr uint8_t STX = 0x02;
static constexpr uint8_t ETX = 0x03;
// Receiver status code
enum class Status : uint8_t {
OK = 0x00,
};
// https://receiverhelp.trimble.com/oem-gnss/API_DataCollectorFormatPackets.html
enum class Command_Response : uint8_t {
ACK = 0x06,
NACK = 0x15,
};
// https://receiverhelp.trimble.com/oem-gnss/ICD_Command64h_AppFile_Output.html#Frequenc
enum class Output_Rate : uint8_t {
OFF = 0,
FREQ_10_HZ = 1,
FREQ_50_HZ = 15,
FREQ_100_HZ = 16,
};
// https://receiverhelp.trimble.com/oem-gnss/ICD_ApplicationFilePackets.html?tocpath=API%20Documentation%7CCommand%20and%20report%20packets%7CApplication%20file%20packets%7C_____0
enum class Packet_Type : uint8_t {
COMMAND_APPFILE = 0x64,
};
// https://receiverhelp.trimble.com/oem-gnss/ICD_Pkt_Command64h_APPFILE.html
enum class Appfile_Record_Type : uint8_t {
SERIAL_PORT_BAUD_RATE_FORMAT = 0x02,
OUTPUT_MESSAGE = 0x07,
};
// https://receiverhelp.trimble.com/oem-gnss/ICD_Command64h_AppFile_Output.html#Output
enum class Output_Msg_Msg_Type : uint8_t {
GSOF = 10,
};
// https://receiverhelp.trimble.com/oem-gnss/ICD_Command64h_AppFile_Output.html#Output2
enum class Gsof_Msg_Record_Type : uint8_t {
POSITION_TIME = 1,
LLH = 2,
VELOCITY_DATA = 8,
PDOP_INFO = 9,
POSITION_SIGMA_INFO = 12,
};
protected:
// https://receiverhelp.trimble.com/oem-gnss/API_DataCollectorFormatPacketStructure.html
static constexpr uint8_t MAX_PAYLOAD_SIZE = 255;
// GSOF supports this many different packet types.
// Only a fraction are supported by the simulator.
// Waste some RAM and allocate arrays for the whole set.
// https://receiverhelp.trimble.com/oem-gnss/ICD_Command64h_AppFile_Output.html#Output2
static constexpr uint8_t MAX_CHANNEL_NUM = 70;
// Rates of dynamically enabled channels.
// Assume factory behavior of no enabled channels.
// Each channel can send data out at its own rate.
Output_Rate channel_rates[MAX_CHANNEL_NUM] = {Output_Rate::OFF};
// Last publish time of dynamically enabled channels.
uint32_t last_publish_ms[MAX_CHANNEL_NUM];
static uint32_t RateToPeriodMs(const Output_Rate rate);
private:
// Internal parser implementation state
enum class Parse_State {
WAITING_ON_STX,
WAITING_ON_STATUS,
WAITING_ON_PACKET_TYPE,
WAITING_ON_LENGTH,
WAITING_ON_PACKET_DATA,
WAITING_ON_CSUM,
WAITING_ON_ETX,
};
bool valid_csum();
bool parse_payload();
// https://receiverhelp.trimble.com/oem-gnss/ICD_Pkt_Command64h_APPFILE.html
bool parse_cmd_appfile();
// states for currently parsing packet
Status status;
Parse_State parse_state = {Parse_State::WAITING_ON_STX};
Packet_Type packet_type;
// This is the length in the header.
uint8_t expected_payload_length;
// This is the increasing tally of bytes per packet.
uint8_t cur_payload_idx;
// This is the expected packet checksum in the trailer.
uint8_t expected_csum;
// The application file record transmission number
uint8_t appfile_trans_num;
uint8_t payload[MAX_PAYLOAD_SIZE];
// Clear all parser state/flags for handling a fresh packet.
void reset();
};
class GPS_GSOF : public GPS_Backend, public DCOL_Parser {
public:
CLASS_NO_COPY(GPS_GSOF);
using GPS_Backend::GPS_Backend;
// GPS_Backend overrides
void publish(const GPS_Data *d) override;
void update_read() override;
private:
void send_gsof(const uint8_t *buf, const uint16_t size);
// These packing utilities for GSOF perform a type-safe floating point byteswap.
// They return integer types because returning floating points would involve an extra copy.
uint64_t gsof_pack_double(const double& src) WARN_IF_UNUSED;
uint32_t gsof_pack_float(const float& src) WARN_IF_UNUSED;
};
};
#endif // AP_SIM_GPS_GSOF_ENABLED
+88
View File
@@ -0,0 +1,88 @@
#include "SIM_config.h"
#if AP_SIM_GPS_MSP_ENABLED
#include "SIM_GPS_MSP.h"
#include <SITL/SITL.h>
using namespace SITL;
/*
send MSP GPS data
*/
void GPS_MSP::publish(const GPS_Data *d)
{
struct PACKED {
// header
struct PACKED {
uint8_t dollar = '$';
uint8_t magic = 'X';
uint8_t code = '<';
uint8_t flags;
uint16_t cmd = 0x1F03; // GPS
uint16_t size = 52;
} hdr;
uint8_t instance;
uint16_t gps_week;
uint32_t ms_tow;
uint8_t fix_type;
uint8_t satellites_in_view;
uint16_t horizontal_pos_accuracy; // [cm]
uint16_t vertical_pos_accuracy; // [cm]
uint16_t horizontal_vel_accuracy; // [cm/s]
uint16_t hdop;
int32_t longitude;
int32_t latitude;
int32_t msl_altitude; // cm
int32_t ned_vel_north; // cm/s
int32_t ned_vel_east;
int32_t ned_vel_down;
uint16_t ground_course; // deg * 100, 0..36000
uint16_t true_yaw; // deg * 100, values of 0..36000 are valid. 65535 = no data available
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint8_t sec;
// footer CRC
uint8_t crc;
} msp_gps {};
auto t = gps_time();
struct timeval tv;
simulation_timeval(&tv);
auto *tm = gmtime(&tv.tv_sec);
msp_gps.gps_week = t.week;
msp_gps.ms_tow = t.ms;
msp_gps.fix_type = d->have_lock?3:0;
msp_gps.satellites_in_view = d->have_lock ? _sitl->gps_numsats[instance] : 3;
msp_gps.horizontal_pos_accuracy = _sitl->gps_accuracy[instance]*100;
msp_gps.vertical_pos_accuracy = _sitl->gps_accuracy[instance]*100;
msp_gps.horizontal_vel_accuracy = 30;
msp_gps.hdop = 100;
msp_gps.longitude = d->longitude * 1.0e7;
msp_gps.latitude = d->latitude * 1.0e7;
msp_gps.msl_altitude = d->altitude * 100;
msp_gps.ned_vel_north = 100 * d->speedN;
msp_gps.ned_vel_east = 100 * d->speedE;
msp_gps.ned_vel_down = 100 * d->speedD;
msp_gps.ground_course = ToDeg(atan2f(d->speedE, d->speedN)) * 100;
msp_gps.true_yaw = wrap_360(d->yaw_deg)*100U; // can send 65535 for no yaw
msp_gps.year = tm->tm_year;
msp_gps.month = tm->tm_mon;
msp_gps.day = tm->tm_mday;
msp_gps.hour = tm->tm_hour;
msp_gps.min = tm->tm_min;
msp_gps.sec = tm->tm_sec;
// CRC is over packet without first 3 bytes and trailing CRC byte
msp_gps.crc = crc8_dvb_s2_update(0, (uint8_t *)&msp_gps.hdr.flags, sizeof(msp_gps)-4);
write_to_autopilot((const char *)&msp_gps, sizeof(msp_gps));
}
#endif // AP_SIM_GPS_MSP_ENABLED
+20
View File
@@ -0,0 +1,20 @@
#include "SIM_config.h"
#if AP_SIM_GPS_MSP_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class GPS_MSP : public GPS_Backend {
public:
CLASS_NO_COPY(GPS_MSP);
using GPS_Backend::GPS_Backend;
void publish(const GPS_Data *d) override;
};
}
#endif // AP_SIM_GPS_MSP_ENABLED
+125
View File
@@ -0,0 +1,125 @@
#include "SIM_config.h"
#if AP_SIM_GPS_NMEA_ENABLED
#include "SIM_GPS_NMEA.h"
#include <SITL/SITL.h>
#include <AP_Common/NMEA.h>
#include <AP_HAL/AP_HAL.h>
extern const AP_HAL::HAL& hal;
using namespace SITL;
/*
formatted print of NMEA message, with checksum appended
*/
void GPS_NMEA::nmea_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
char *s = nmea_vaprintf(fmt, ap);
va_end(ap);
if (s != nullptr) {
write_to_autopilot((const char*)s, strlen(s));
free(s);
}
}
/*
send a new GPS NMEA packet
*/
void GPS_NMEA::publish(const GPS_Data *d)
{
struct timeval tv;
struct tm *tm;
char tstring[20];
char dstring[20];
char lat_string[20];
char lng_string[20];
simulation_timeval(&tv);
tm = gmtime(&tv.tv_sec);
// format time string
hal.util->snprintf(tstring, sizeof(tstring), "%02u%02u%06.3f", tm->tm_hour, tm->tm_min, tm->tm_sec + tv.tv_usec*1.0e-6);
// format date string
hal.util->snprintf(dstring, sizeof(dstring), "%02u%02u%02u", tm->tm_mday, tm->tm_mon+1, tm->tm_year % 100);
// format latitude
double deg = fabs(d->latitude);
hal.util->snprintf(lat_string, sizeof(lat_string), "%02u%08.5f,%c",
(unsigned)deg,
(deg - int(deg))*60,
d->latitude<0?'S':'N');
// format longitude
deg = fabs(d->longitude);
hal.util->snprintf(lng_string, sizeof(lng_string), "%03u%08.5f,%c",
(unsigned)deg,
(deg - int(deg))*60,
d->longitude<0?'W':'E');
nmea_printf("$GPGGA,%s,%s,%s,%01d,%02d,%04.1f,%07.2f,M,0.0,M,,",
tstring,
lat_string,
lng_string,
d->have_lock?1:0,
d->have_lock?_sitl->gps_numsats[instance]:3,
1.2,
d->altitude);
const float speed_mps = d->speed_2d();
const float speed_knots = speed_mps * M_PER_SEC_TO_KNOTS;
const auto heading_rad = d->heading();
//$GPVTG,133.18,T,120.79,M,0.11,N,0.20,K,A*24
nmea_printf("$GPVTG,%.2f,T,%.2f,M,%.2f,N,%.2f,K,A",
tstring,
heading_rad,
heading_rad,
speed_knots,
speed_knots * KNOTS_TO_METERS_PER_SECOND * 3.6);
nmea_printf("$GPRMC,%s,%c,%s,%s,%.2f,%.2f,%s,,",
tstring,
d->have_lock?'A':'V',
lat_string,
lng_string,
speed_knots,
heading_rad,
dstring);
if (_sitl->gps_hdg_enabled[instance] == SITL::SIM::GPS_HEADING_HDT) {
nmea_printf("$GPHDT,%.2f,T", d->yaw_deg);
}
else if (_sitl->gps_hdg_enabled[instance] == SITL::SIM::GPS_HEADING_THS) {
nmea_printf("$GPTHS,%.2f,%c,T", d->yaw_deg, d->have_lock ? 'A' : 'V');
} else if (_sitl->gps_hdg_enabled[instance] == SITL::SIM::GPS_HEADING_KSXT) {
// Unicore support
// $KSXT,20211016083433.00,116.31296102,39.95817066,49.4911,223.57,-11.32,330.19,0.024,,1,3,28,27,,,,-0.012,0.021,0.020,,*2D
nmea_printf("$KSXT,%04u%02u%02u%02u%02u%02u.%02u,%.8f,%.8f,%.4f,%.2f,%.2f,%.2f,%.2f,%.3f,%u,%u,%u,%u,,,,%.3f,%.3f,%.3f,,",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, unsigned(tv.tv_usec*1.e-4),
d->longitude, d->latitude,
d->altitude,
wrap_360(d->yaw_deg),
d->pitch_deg,
heading_rad,
speed_mps,
d->roll_deg,
d->have_lock?1:0, // 2=rtkfloat 3=rtkfixed,
3, // fixed rtk yaw solution,
d->have_lock?_sitl->gps_numsats[instance]:3,
d->have_lock?_sitl->gps_numsats[instance]:3,
d->speedE * 3.6,
d->speedN * 3.6,
-d->speedD * 3.6);
}
}
#endif // AP_SIM_GPS_NMEA_ENABLED
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include "SIM_config.h"
#if AP_SIM_GPS_NMEA_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class GPS_NMEA : public GPS_Backend {
public:
CLASS_NO_COPY(GPS_NMEA);
using GPS_Backend::GPS_Backend;
void publish(const GPS_Data *d) override;
private:
uint8_t nmea_checksum(const char *s);
void nmea_printf(const char *fmt, ...);
void update_nmea(const GPS_Data *d);
};
};
#endif // AP_SIM_GPS_NMEA_ENABLED
+177
View File
@@ -0,0 +1,177 @@
#include "SIM_config.h"
#if AP_SIM_GPS_NOVA_ENABLED
#include "SIM_GPS_NOVA.h"
#include <SITL/SITL.h>
using namespace SITL;
void GPS_NOVA::publish(const GPS_Data *d)
{
static struct PACKED nova_header
{
// 0
uint8_t preamble[3];
// 3
uint8_t headerlength;
// 4
uint16_t messageid;
// 6
uint8_t messagetype;
//7
uint8_t portaddr;
//8
uint16_t messagelength;
//10
uint16_t sequence;
//12
uint8_t idletime;
//13
uint8_t timestatus;
//14
uint16_t week;
//16
uint32_t tow;
//20
uint32_t recvstatus;
// 24
uint16_t resv;
//26
uint16_t recvswver;
} header;
struct PACKED psrdop
{
float gdop;
float pdop;
float hdop;
float htdop;
float tdop;
float cutoff;
uint32_t svcount;
// extra data for individual prns
} psrdop {};
struct PACKED bestpos
{
uint32_t solstat;
uint32_t postype;
double lat;
double lng;
double hgt;
float undulation;
uint32_t datumid;
float latsdev;
float lngsdev;
float hgtsdev;
// 4 bytes
uint8_t stnid[4];
float diffage;
float sol_age;
uint8_t svstracked;
uint8_t svsused;
uint8_t svsl1;
uint8_t svsmultfreq;
uint8_t resv;
uint8_t extsolstat;
uint8_t galbeisigmask;
uint8_t gpsglosigmask;
} bestpos {};
struct PACKED bestvel
{
uint32_t solstat;
uint32_t veltype;
float latency;
float age;
double horspd;
double trkgnd;
// + up
double vertspd;
float resv;
} bestvel {};
const auto gps_tow = gps_time();
header.preamble[0] = 0xaa;
header.preamble[1] = 0x44;
header.preamble[2] = 0x12;
header.headerlength = sizeof(header);
header.week = gps_tow.week;
header.tow = gps_tow.ms;
header.messageid = 174;
header.messagelength = sizeof(psrdop);
header.sequence += 1;
psrdop.hdop = 1.20;
psrdop.htdop = 1.20;
nova_send_message((uint8_t*)&header,sizeof(header),(uint8_t*)&psrdop, sizeof(psrdop));
header.messageid = 99;
header.messagelength = sizeof(bestvel);
header.sequence += 1;
bestvel.horspd = norm(d->speedN, d->speedE);
bestvel.trkgnd = ToDeg(atan2f(d->speedE, d->speedN));
bestvel.vertspd = -d->speedD;
nova_send_message((uint8_t*)&header,sizeof(header),(uint8_t*)&bestvel, sizeof(bestvel));
header.messageid = 42;
header.messagelength = sizeof(bestpos);
header.sequence += 1;
bestpos.lat = d->latitude;
bestpos.lng = d->longitude;
bestpos.hgt = d->altitude;
bestpos.svsused = d->have_lock ? _sitl->gps_numsats[instance] : 3;
bestpos.latsdev=0.2;
bestpos.lngsdev=0.2;
bestpos.hgtsdev=0.2;
bestpos.solstat=0;
bestpos.postype=32;
nova_send_message((uint8_t*)&header,sizeof(header),(uint8_t*)&bestpos, sizeof(bestpos));
}
void GPS_NOVA::nova_send_message(uint8_t *header, uint8_t headerlength, uint8_t *payload, uint8_t payloadlen)
{
write_to_autopilot((char*)header, headerlength);
write_to_autopilot((char*)payload, payloadlen);
uint32_t crc = CalculateBlockCRC32(headerlength, header, (uint32_t)0);
crc = CalculateBlockCRC32(payloadlen, payload, crc);
write_to_autopilot((char*)&crc, 4);
}
#define CRC32_POLYNOMIAL 0xEDB88320L
uint32_t GPS_NOVA::CRC32Value(uint32_t icrc)
{
int i;
uint32_t crc = icrc;
for ( i = 8 ; i > 0; i-- )
{
if ( crc & 1 )
crc = ( crc >> 1 ) ^ CRC32_POLYNOMIAL;
else
crc >>= 1;
}
return crc;
}
uint32_t GPS_NOVA::CalculateBlockCRC32(uint32_t length, uint8_t *buffer, uint32_t crc)
{
while ( length-- != 0 )
{
crc = ((crc >> 8) & 0x00FFFFFFL) ^ (CRC32Value(((uint32_t) crc ^ *buffer++) & 0xff));
}
return( crc );
}
#endif // AP_SIM_GPS_NOVA_ENABLED
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "SIM_config.h"
#if AP_SIM_GPS_NOVA_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class GPS_NOVA : public GPS_Backend {
public:
CLASS_NO_COPY(GPS_NOVA);
using GPS_Backend::GPS_Backend;
void publish(const GPS_Data *d) override;
uint32_t device_baud() const override { return 19200; }
private:
void nova_send_message(uint8_t *header, uint8_t headerlength, uint8_t *payload, uint8_t payloadlen);
uint32_t CRC32Value(uint32_t icrc);
uint32_t CalculateBlockCRC32(uint32_t length, uint8_t *buffer, uint32_t crc);
};
};
#endif // AP_SIM_GPS_NOVA_ENABLED
+122
View File
@@ -0,0 +1,122 @@
#include "SIM_GPS_SBP.h"
#if AP_SIM_GPS_SBP_ENABLED
#include <SITL/SITL.h>
using namespace SITL;
void GPS_SBP::publish(const GPS_Data *d)
{
struct sbp_heartbeat_t {
bool sys_error : 1;
bool io_error : 1;
bool nap_error : 1;
uint8_t res : 5;
uint8_t protocol_minor : 8;
uint8_t protocol_major : 8;
uint8_t res2 : 7;
bool ext_antenna : 1;
} hb; // 4 bytes
struct PACKED sbp_gps_time_t {
uint16_t wn; //< GPS week number
uint32_t tow; //< GPS Time of Week rounded to the nearest ms
int32_t ns; //< Nanosecond remainder of rounded tow
uint8_t flags; //< Status flags (reserved)
} t;
struct PACKED sbp_pos_llh_t {
uint32_t tow; //< GPS Time of Week
double lat; //< Latitude
double lon; //< Longitude
double height; //< Height
uint16_t h_accuracy; //< Horizontal position accuracy estimate
uint16_t v_accuracy; //< Vertical position accuracy estimate
uint8_t n_sats; //< Number of satellites used in solution
uint8_t flags; //< Status flags
} pos;
struct PACKED sbp_vel_ned_t {
uint32_t tow; //< GPS Time of Week
int32_t n; //< Velocity North coordinate
int32_t e; //< Velocity East coordinate
int32_t d; //< Velocity Down coordinate
uint16_t h_accuracy; //< Horizontal velocity accuracy estimate
uint16_t v_accuracy; //< Vertical velocity accuracy estimate
uint8_t n_sats; //< Number of satellites used in solution
uint8_t flags; //< Status flags (reserved)
} velned;
struct PACKED sbp_dops_t {
uint32_t tow; //< GPS Time of Week
uint16_t gdop; //< Geometric Dilution of Precision
uint16_t pdop; //< Position Dilution of Precision
uint16_t tdop; //< Time Dilution of Precision
uint16_t hdop; //< Horizontal Dilution of Precision
uint16_t vdop; //< Vertical Dilution of Precision
uint8_t flags; //< Status flags (reserved)
} dops;
static const uint16_t SBP_HEARTBEAT_MSGTYPE = 0xFFFF;
static const uint16_t SBP_GPS_TIME_MSGTYPE = 0x0100;
static const uint16_t SBP_DOPS_MSGTYPE = 0x0206;
static const uint16_t SBP_POS_LLH_MSGTYPE = 0x0201;
static const uint16_t SBP_VEL_NED_MSGTYPE = 0x0205;
const auto gps_tow = gps_time();
t.wn = gps_tow.week;
t.tow = gps_tow.ms;
t.ns = 0;
t.flags = 0;
sbp_send_message(SBP_GPS_TIME_MSGTYPE, 0x2222, sizeof(t), (uint8_t*)&t);
if (!d->have_lock) {
return;
}
pos.tow = gps_tow.ms;
pos.lon = d->longitude;
pos.lat= d->latitude;
pos.height = d->altitude;
pos.h_accuracy = _sitl->gps_accuracy[instance]*1000;
pos.v_accuracy = _sitl->gps_accuracy[instance]*1000;
pos.n_sats = d->have_lock ? _sitl->gps_numsats[instance] : 3;
// Send single point position solution
pos.flags = 0;
sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222, sizeof(pos), (uint8_t*)&pos);
// Send "pseudo-absolute" RTK position solution
pos.flags = 1;
sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222, sizeof(pos), (uint8_t*)&pos);
velned.tow = gps_tow.ms;
velned.n = 1e3 * d->speedN;
velned.e = 1e3 * d->speedE;
velned.d = 1e3 * d->speedD;
velned.h_accuracy = 5e3;
velned.v_accuracy = 5e3;
velned.n_sats = d->have_lock ? _sitl->gps_numsats[instance] : 3;
velned.flags = 0;
sbp_send_message(SBP_VEL_NED_MSGTYPE, 0x2222, sizeof(velned), (uint8_t*)&velned);
static uint32_t do_every_count = 0;
if (do_every_count % 5 == 0) {
dops.tow = gps_tow.ms;
dops.gdop = 1;
dops.pdop = 1;
dops.tdop = 1;
dops.hdop = 100;
dops.vdop = 1;
dops.flags = 1;
sbp_send_message(SBP_DOPS_MSGTYPE, 0x2222, sizeof(dops),
(uint8_t*)&dops);
hb.protocol_major = 0; //Sends protocol version 0
sbp_send_message(SBP_HEARTBEAT_MSGTYPE, 0x2222, sizeof(hb),
(uint8_t*)&hb);
}
do_every_count++;
}
#endif // AP_SIM_GPS_SBP_ENABLED
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "SIM_config.h"
#if AP_SIM_GPS_SBP_ENABLED
#include "SIM_GPS_SBP_Common.h"
namespace SITL {
class GPS_SBP : public GPS_SBP_Common {
public:
CLASS_NO_COPY(GPS_SBP);
using GPS_SBP_Common::GPS_SBP_Common;
void publish(const GPS_Data *d) override;
};
};
#endif // AP_SIM_GPS_SBP_ENABLED
+121
View File
@@ -0,0 +1,121 @@
#include "SIM_GPS_SBP2.h"
#if AP_SIM_GPS_SBP2_ENABLED
#include <SITL/SITL.h>
using namespace SITL;
void GPS_SBP2::publish(const GPS_Data *d)
{
struct sbp_heartbeat_t {
bool sys_error : 1;
bool io_error : 1;
bool nap_error : 1;
uint8_t res : 5;
uint8_t protocol_minor : 8;
uint8_t protocol_major : 8;
uint8_t res2 : 7;
bool ext_antenna : 1;
} hb; // 4 bytes
struct PACKED sbp_gps_time_t {
uint16_t wn; //< GPS week number
uint32_t tow; //< GPS Time of Week rounded to the nearest ms
int32_t ns; //< Nanosecond remainder of rounded tow
uint8_t flags; //< Status flags (reserved)
} t;
struct PACKED sbp_pos_llh_t {
uint32_t tow; //< GPS Time of Week
double lat; //< Latitude
double lon; //< Longitude
double height; //< Height
uint16_t h_accuracy; //< Horizontal position accuracy estimate
uint16_t v_accuracy; //< Vertical position accuracy estimate
uint8_t n_sats; //< Number of satellites used in solution
uint8_t flags; //< Status flags
} pos;
struct PACKED sbp_vel_ned_t {
uint32_t tow; //< GPS Time of Week
int32_t n; //< Velocity North coordinate
int32_t e; //< Velocity East coordinate
int32_t d; //< Velocity Down coordinate
uint16_t h_accuracy; //< Horizontal velocity accuracy estimate
uint16_t v_accuracy; //< Vertical velocity accuracy estimate
uint8_t n_sats; //< Number of satellites used in solution
uint8_t flags; //< Status flags (reserved)
} velned;
struct PACKED sbp_dops_t {
uint32_t tow; //< GPS Time of Week
uint16_t gdop; //< Geometric Dilution of Precision
uint16_t pdop; //< Position Dilution of Precision
uint16_t tdop; //< Time Dilution of Precision
uint16_t hdop; //< Horizontal Dilution of Precision
uint16_t vdop; //< Vertical Dilution of Precision
uint8_t flags; //< Status flags (reserved)
} dops;
static const uint16_t SBP_HEARTBEAT_MSGTYPE = 0xFFFF;
static const uint16_t SBP_GPS_TIME_MSGTYPE = 0x0102;
static const uint16_t SBP_DOPS_MSGTYPE = 0x0208;
static const uint16_t SBP_POS_LLH_MSGTYPE = 0x020A;
static const uint16_t SBP_VEL_NED_MSGTYPE = 0x020E;
const auto gps_tow = gps_time();
t.wn = gps_tow.week;
t.tow = gps_tow.ms;
t.ns = 0;
t.flags = 1;
sbp_send_message(SBP_GPS_TIME_MSGTYPE, 0x2222, sizeof(t), (uint8_t*)&t);
if (!d->have_lock) {
return;
}
pos.tow = gps_tow.ms;
pos.lon = d->longitude;
pos.lat= d->latitude;
pos.height = d->altitude;
pos.h_accuracy = _sitl->gps_accuracy[instance]*1000;
pos.v_accuracy = _sitl->gps_accuracy[instance]*1000;
pos.n_sats = d->have_lock ? _sitl->gps_numsats[instance] : 3;
// Send single point position solution
pos.flags = 1;
sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222, sizeof(pos), (uint8_t*)&pos);
// Send "pseudo-absolute" RTK position solution
pos.flags = 4;
sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222, sizeof(pos), (uint8_t*)&pos);
velned.tow = gps_tow.ms;
velned.n = 1e3 * d->speedN;
velned.e = 1e3 * d->speedE;
velned.d = 1e3 * d->speedD;
velned.h_accuracy = 5e3;
velned.v_accuracy = 5e3;
velned.n_sats = d->have_lock ? _sitl->gps_numsats[instance] : 3;
velned.flags = 1;
sbp_send_message(SBP_VEL_NED_MSGTYPE, 0x2222, sizeof(velned), (uint8_t*)&velned);
static uint32_t do_every_count = 0;
if (do_every_count % 5 == 0) {
dops.tow = gps_tow.ms;
dops.gdop = 1;
dops.pdop = 1;
dops.tdop = 1;
dops.hdop = 100;
dops.vdop = 1;
dops.flags = 1;
sbp_send_message(SBP_DOPS_MSGTYPE, 0x2222, sizeof(dops),
(uint8_t*)&dops);
hb.protocol_major = 2; //Sends protocol version 2.0
sbp_send_message(SBP_HEARTBEAT_MSGTYPE, 0x2222, sizeof(hb),
(uint8_t*)&hb);
}
do_every_count++;
}
#endif // AP_SIM_GPS_SBP2_ENABLED
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "SIM_config.h"
#if AP_SIM_GPS_SBP2_ENABLED
#include "SIM_GPS_SBP_Common.h"
namespace SITL {
class GPS_SBP2 : public GPS_SBP_Common {
public:
CLASS_NO_COPY(GPS_SBP2);
using GPS_SBP_Common::GPS_SBP_Common;
void publish(const GPS_Data *d) override;
};
};
#endif // AP_SIM_GPS_SBP2_ENABLED
+34
View File
@@ -0,0 +1,34 @@
#include "SIM_config.h"
#if HAL_SIM_GPS_ENABLED
#include "SIM_GPS_SBP_Common.h"
#include <AP_Math/crc.h>
using namespace SITL;
void GPS_SBP_Common::sbp_send_message(uint16_t msg_type, uint16_t sender_id, uint8_t len, uint8_t *payload)
{
if (len != 0 && payload == 0) {
return; //SBP_NULL_ERROR;
}
uint8_t preamble = 0x55;
write_to_autopilot((char*)&preamble, 1);
write_to_autopilot((char*)&msg_type, 2);
write_to_autopilot((char*)&sender_id, 2);
write_to_autopilot((char*)&len, 1);
if (len > 0) {
write_to_autopilot((char*)payload, len);
}
uint16_t crc;
crc = crc16_ccitt((uint8_t*)&(msg_type), 2, 0);
crc = crc16_ccitt((uint8_t*)&(sender_id), 2, crc);
crc = crc16_ccitt(&(len), 1, crc);
crc = crc16_ccitt(payload, len, crc);
write_to_autopilot((char*)&crc, 2);
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "SIM_config.h"
#if HAL_SIM_GPS_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class GPS_SBP_Common : public GPS_Backend {
public:
CLASS_NO_COPY(GPS_SBP_Common);
using GPS_Backend::GPS_Backend;
protected:
void sbp_send_message(uint16_t msg_type, uint16_t sender_id, uint8_t len, uint8_t *payload);
};
};
#endif
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
#include "SIM_config.h"
#if AP_SIM_GPS_UBLOX_ENABLED
#include "SIM_GPS.h"
namespace SITL {
class GPS_UBlox : public GPS_Backend {
public:
CLASS_NO_COPY(GPS_UBlox);
using GPS_Backend::GPS_Backend;
void publish(const GPS_Data *d) override;
private:
void send_ubx(uint8_t msgid, uint8_t *buf, uint16_t size);
};
};
#endif // AP_SIM_GPS_UBLOX_ENABLED
+41
View File
@@ -37,3 +37,44 @@
#ifndef AP_SIM_SERIALDEVICE_CORRUPTION_ENABLED
#define AP_SIM_SERIALDEVICE_CORRUPTION_ENABLED 0
#endif
#ifndef HAL_SIM_GPS_ENABLED
#define HAL_SIM_GPS_ENABLED AP_SIM_ENABLED
#endif
#ifndef AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#define AP_SIM_GPS_BACKEND_DEFAULT_ENABLED AP_SIM_ENABLED
#endif
#ifndef AP_SIM_GPS_FILE_ENABLED
// really need to use AP_FileSystem for this.
#define AP_SIM_GPS_FILE_ENABLED (CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX)
#endif
#ifndef AP_SIM_GPS_GSOF_ENABLED
#define AP_SIM_GPS_GSOF_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif
#ifndef AP_SIM_GPS_MSP_ENABLED
#define AP_SIM_GPS_MSP_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif
#ifndef AP_SIM_GPS_NMEA_ENABLED
#define AP_SIM_GPS_NMEA_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif
#ifndef AP_SIM_GPS_NOVA_ENABLED
#define AP_SIM_GPS_NOVA_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif
#ifndef AP_SIM_GPS_SBP2_ENABLED
#define AP_SIM_GPS_SBP2_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif
#ifndef AP_SIM_GPS_SBP_ENABLED
#define AP_SIM_GPS_SBP_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif
#ifndef AP_SIM_GPS_UBLOX_ENABLED
#define AP_SIM_GPS_UBLOX_ENABLED AP_SIM_GPS_BACKEND_DEFAULT_ENABLED
#endif