mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-22 07:44:03 -04:00
SITL: factor simulated GPS
This commit is contained in:
parent
e2599252a1
commit
cbd2b199eb
@ -44,6 +44,36 @@ struct GPS_TOW {
|
|||||||
uint32_t ms;
|
uint32_t ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ensure the backend we have allocated matches the one that's configured:
|
||||||
|
GPS_Backend::GPS_Backend(GPS &_front, uint8_t _instance)
|
||||||
|
: front{_front},
|
||||||
|
instance{_instance}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t GPS_Backend::write_to_autopilot(const char *p, size_t size) const
|
||||||
|
{
|
||||||
|
return front.write_to_autopilot(p, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t GPS_Backend::read_from_autopilot(char *buffer, size_t size) const
|
||||||
|
{
|
||||||
|
return front.read_from_autopilot(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPS_Backend::update(const GPS_Data &d)
|
||||||
|
{
|
||||||
|
if (_sitl == nullptr) {
|
||||||
|
_sitl = AP::sitl();
|
||||||
|
if (_sitl == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_read(&d);
|
||||||
|
update_write(&d);
|
||||||
|
}
|
||||||
|
|
||||||
GPS::GPS(uint8_t _instance) :
|
GPS::GPS(uint8_t _instance) :
|
||||||
SerialDevice(8192, 2048),
|
SerialDevice(8192, 2048),
|
||||||
instance{_instance}
|
instance{_instance}
|
||||||
@ -68,25 +98,10 @@ GPS::GPS(uint8_t _instance) :
|
|||||||
|
|
||||||
uint32_t GPS::device_baud() const
|
uint32_t GPS::device_baud() const
|
||||||
{
|
{
|
||||||
if (_sitl == nullptr) {
|
if (backend == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
switch ((Type)_sitl->gps_type[instance].get()) {
|
return backend->device_baud();
|
||||||
case Type::NOVA:
|
|
||||||
return 19200;
|
|
||||||
case Type::NONE:
|
|
||||||
case Type::UBLOX:
|
|
||||||
case Type::NMEA:
|
|
||||||
case Type::SBP:
|
|
||||||
case Type::SBP2:
|
|
||||||
case Type::MSP:
|
|
||||||
#if AP_SIM_GPS_FILE_ENABLED
|
|
||||||
case Type::FILE:
|
|
||||||
#endif
|
|
||||||
case Type::GSOF:
|
|
||||||
return 0; // 0 meaning unset
|
|
||||||
}
|
|
||||||
return 0; // 0 meaning unset
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -165,7 +180,7 @@ static void simulation_timeval(struct timeval *tv)
|
|||||||
/*
|
/*
|
||||||
send a UBLOX GPS message
|
send a UBLOX GPS message
|
||||||
*/
|
*/
|
||||||
void GPS::send_ubx(uint8_t msgid, uint8_t *buf, uint16_t size)
|
void GPS_UBlox::send_ubx(uint8_t msgid, uint8_t *buf, uint16_t size)
|
||||||
{
|
{
|
||||||
const uint8_t PREAMBLE1 = 0xb5;
|
const uint8_t PREAMBLE1 = 0xb5;
|
||||||
const uint8_t PREAMBLE2 = 0x62;
|
const uint8_t PREAMBLE2 = 0x62;
|
||||||
@ -209,7 +224,7 @@ static GPS_TOW gps_time()
|
|||||||
/*
|
/*
|
||||||
send a new set of GPS UBLOX packets
|
send a new set of GPS UBLOX packets
|
||||||
*/
|
*/
|
||||||
void GPS::update_ubx(const struct gps_data *d)
|
void GPS_UBlox::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
struct PACKED ubx_nav_posllh {
|
struct PACKED ubx_nav_posllh {
|
||||||
uint32_t time; // GPS msToW
|
uint32_t time; // GPS msToW
|
||||||
@ -495,7 +510,7 @@ void GPS::update_ubx(const struct gps_data *d)
|
|||||||
/*
|
/*
|
||||||
formatted print of NMEA message, with checksum appended
|
formatted print of NMEA message, with checksum appended
|
||||||
*/
|
*/
|
||||||
void GPS::nmea_printf(const char *fmt, ...)
|
void GPS_NMEA::nmea_printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@ -512,7 +527,7 @@ void GPS::nmea_printf(const char *fmt, ...)
|
|||||||
/*
|
/*
|
||||||
send a new GPS NMEA packet
|
send a new GPS NMEA packet
|
||||||
*/
|
*/
|
||||||
void GPS::update_nmea(const struct gps_data *d)
|
void GPS_NMEA::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
@ -602,7 +617,7 @@ void GPS::update_nmea(const struct gps_data *d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPS::sbp_send_message(uint16_t msg_type, uint16_t sender_id, uint8_t len, uint8_t *payload)
|
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) {
|
if (len != 0 && payload == 0) {
|
||||||
return; //SBP_NULL_ERROR;
|
return; //SBP_NULL_ERROR;
|
||||||
@ -625,7 +640,7 @@ void GPS::sbp_send_message(uint16_t msg_type, uint16_t sender_id, uint8_t len, u
|
|||||||
write_to_autopilot((char*)&crc, 2);
|
write_to_autopilot((char*)&crc, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPS::update_sbp(const struct gps_data *d)
|
void GPS_SBP::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
struct sbp_heartbeat_t {
|
struct sbp_heartbeat_t {
|
||||||
bool sys_error : 1;
|
bool sys_error : 1;
|
||||||
@ -739,7 +754,7 @@ void GPS::update_sbp(const struct gps_data *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GPS::update_sbp2(const struct gps_data *d)
|
void GPS_SBP2::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
struct sbp_heartbeat_t {
|
struct sbp_heartbeat_t {
|
||||||
bool sys_error : 1;
|
bool sys_error : 1;
|
||||||
@ -851,7 +866,7 @@ void GPS::update_sbp2(const struct gps_data *d)
|
|||||||
do_every_count++;
|
do_every_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPS::update_nova(const struct gps_data *d)
|
void GPS_NOVA::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
static struct PACKED nova_header
|
static struct PACKED nova_header
|
||||||
{
|
{
|
||||||
@ -982,7 +997,7 @@ void GPS::update_nova(const struct gps_data *d)
|
|||||||
nova_send_message((uint8_t*)&header,sizeof(header),(uint8_t*)&bestpos, sizeof(bestpos));
|
nova_send_message((uint8_t*)&header,sizeof(header),(uint8_t*)&bestpos, sizeof(bestpos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPS::nova_send_message(uint8_t *header, uint8_t headerlength, uint8_t *payload, uint8_t payloadlen)
|
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*)header, headerlength);
|
||||||
write_to_autopilot((char*)payload, payloadlen);
|
write_to_autopilot((char*)payload, payloadlen);
|
||||||
@ -994,7 +1009,7 @@ write_to_autopilot((char*)payload, payloadlen);
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CRC32_POLYNOMIAL 0xEDB88320L
|
#define CRC32_POLYNOMIAL 0xEDB88320L
|
||||||
uint32_t GPS::CRC32Value(uint32_t icrc)
|
uint32_t GPS_NOVA::CRC32Value(uint32_t icrc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32_t crc = icrc;
|
uint32_t crc = icrc;
|
||||||
@ -1008,7 +1023,7 @@ uint32_t GPS::CRC32Value(uint32_t icrc)
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GPS::CalculateBlockCRC32(uint32_t length, uint8_t *buffer, uint32_t crc)
|
uint32_t GPS_NOVA::CalculateBlockCRC32(uint32_t length, uint8_t *buffer, uint32_t crc)
|
||||||
{
|
{
|
||||||
while ( length-- != 0 )
|
while ( length-- != 0 )
|
||||||
{
|
{
|
||||||
@ -1017,7 +1032,7 @@ uint32_t GPS::CalculateBlockCRC32(uint32_t length, uint8_t *buffer, uint32_t crc
|
|||||||
return( crc );
|
return( crc );
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPS::update_gsof(const struct gps_data *d)
|
void GPS_GSOF::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
// https://receiverhelp.trimble.com/oem-gnss/index.html#GSOFmessages_TIME.html?TocPath=Output%2520Messages%257CGSOF%2520Messages%257C_____25
|
// https://receiverhelp.trimble.com/oem-gnss/index.html#GSOFmessages_TIME.html?TocPath=Output%2520Messages%257CGSOF%2520Messages%257C_____25
|
||||||
constexpr uint8_t GSOF_POS_TIME_TYPE { 0x01 };
|
constexpr uint8_t GSOF_POS_TIME_TYPE { 0x01 };
|
||||||
@ -1213,7 +1228,7 @@ void GPS::update_gsof(const struct gps_data *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GPS::send_gsof(const uint8_t *buf, const uint16_t size)
|
void GPS_GSOF::send_gsof(const uint8_t *buf, const uint16_t size)
|
||||||
{
|
{
|
||||||
// All Trimble "Data Collector" packets, including GSOF, are comprised of three fields:
|
// All Trimble "Data Collector" packets, including GSOF, are comprised of three fields:
|
||||||
// * A fixed-length packet header (dcol_header)
|
// * A fixed-length packet header (dcol_header)
|
||||||
@ -1293,7 +1308,7 @@ void GPS::send_gsof(const uint8_t *buf, const uint16_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GPS::pack_double_into_gsof_packet(const double& src)
|
uint64_t GPS_GSOF::pack_double_into_gsof_packet(const double& src)
|
||||||
{
|
{
|
||||||
uint64_t dst;
|
uint64_t dst;
|
||||||
static_assert(sizeof(src) == sizeof(dst));
|
static_assert(sizeof(src) == sizeof(dst));
|
||||||
@ -1302,7 +1317,7 @@ uint64_t GPS::pack_double_into_gsof_packet(const double& src)
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GPS::pack_float_into_gsof_packet(const float& src)
|
uint32_t GPS_GSOF::pack_float_into_gsof_packet(const float& src)
|
||||||
{
|
{
|
||||||
uint32_t dst;
|
uint32_t dst;
|
||||||
static_assert(sizeof(src) == sizeof(dst));
|
static_assert(sizeof(src) == sizeof(dst));
|
||||||
@ -1314,7 +1329,7 @@ uint32_t GPS::pack_float_into_gsof_packet(const float& src)
|
|||||||
/*
|
/*
|
||||||
send MSP GPS data
|
send MSP GPS data
|
||||||
*/
|
*/
|
||||||
void GPS::update_msp(const struct gps_data *d)
|
void GPS_MSP::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
struct PACKED {
|
struct PACKED {
|
||||||
// header
|
// header
|
||||||
@ -1392,7 +1407,7 @@ void GPS::update_msp(const struct gps_data *d)
|
|||||||
read file data logged from AP_GPS_DEBUG_LOGGING_ENABLED
|
read file data logged from AP_GPS_DEBUG_LOGGING_ENABLED
|
||||||
*/
|
*/
|
||||||
#if AP_SIM_GPS_FILE_ENABLED
|
#if AP_SIM_GPS_FILE_ENABLED
|
||||||
void GPS::update_file()
|
void GPS_FILE::update_write(const GPS_Data *d)
|
||||||
{
|
{
|
||||||
static int fd[2] = {-1,-1};
|
static int fd[2] = {-1,-1};
|
||||||
static uint32_t base_time[2];
|
static uint32_t base_time[2];
|
||||||
@ -1443,6 +1458,63 @@ rewind_file:
|
|||||||
}
|
}
|
||||||
#endif // AP_SIM_GPS_FILE_ENABLED
|
#endif // AP_SIM_GPS_FILE_ENABLED
|
||||||
|
|
||||||
|
void GPS::check_backend_allocation()
|
||||||
|
{
|
||||||
|
const Type configured_type = Type(_sitl->gps_type[instance].get());
|
||||||
|
if (allocated_type == configured_type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mismatch; delete any already-allocated backend:
|
||||||
|
if (backend != nullptr) {
|
||||||
|
delete backend;
|
||||||
|
backend = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to allocate backend
|
||||||
|
switch (configured_type) {
|
||||||
|
case Type::NONE:
|
||||||
|
// no GPS attached
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::UBLOX:
|
||||||
|
backend = new GPS_UBlox(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::NMEA:
|
||||||
|
backend = new GPS_NMEA(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::SBP:
|
||||||
|
backend = new GPS_SBP(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::SBP2:
|
||||||
|
backend = new GPS_SBP2(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::NOVA:
|
||||||
|
backend = new GPS_NOVA(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::MSP:
|
||||||
|
backend = new GPS_MSP(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::GSOF:
|
||||||
|
backend = new GPS_GSOF(*this, instance);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if AP_SIM_GPS_FILE_ENABLED
|
||||||
|
case Type::FILE:
|
||||||
|
backend = new GPS_FILE(*this, instance);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
allocated_type = configured_type;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
possibly send a new GPS packet
|
possibly send a new GPS packet
|
||||||
*/
|
*/
|
||||||
@ -1452,6 +1524,11 @@ void GPS::update()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_backend_allocation();
|
||||||
|
if (backend == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double latitude =_sitl->state.latitude;
|
double latitude =_sitl->state.latitude;
|
||||||
double longitude = _sitl->state.longitude;
|
double longitude = _sitl->state.longitude;
|
||||||
float altitude = _sitl->state.altitude;
|
float altitude = _sitl->state.altitude;
|
||||||
@ -1483,7 +1560,7 @@ void GPS::update()
|
|||||||
|
|
||||||
const uint8_t idx = instance; // alias to avoid code churn
|
const uint8_t idx = instance; // alias to avoid code churn
|
||||||
|
|
||||||
struct gps_data d {};
|
struct GPS_Data d {};
|
||||||
|
|
||||||
// simulate delayed lock times
|
// simulate delayed lock times
|
||||||
bool have_lock = (!_sitl->gps_disable[idx] && now_ms >= _sitl->gps_lock_time[idx]*1000UL);
|
bool have_lock = (!_sitl->gps_disable[idx] && now_ms >= _sitl->gps_lock_time[idx]*1000UL);
|
||||||
@ -1493,11 +1570,7 @@ void GPS::update()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// swallow any config bytes
|
last_update = now_ms;
|
||||||
char c;
|
|
||||||
read_from_autopilot(&c, 1);
|
|
||||||
|
|
||||||
last_update = now_ms;
|
|
||||||
|
|
||||||
d.latitude = latitude;
|
d.latitude = latitude;
|
||||||
d.longitude = longitude;
|
d.longitude = longitude;
|
||||||
@ -1563,53 +1636,20 @@ void GPS::update()
|
|||||||
d.longitude += glitch_offsets.y;
|
d.longitude += glitch_offsets.y;
|
||||||
d.altitude += glitch_offsets.z;
|
d.altitude += glitch_offsets.z;
|
||||||
|
|
||||||
|
backend->update(d); // i.e. reading configuration etc from autopilot
|
||||||
|
}
|
||||||
|
|
||||||
// do GPS-type-dependent updates:
|
void GPS_Backend::update_read(const GPS_Data *d)
|
||||||
switch ((Type)_sitl->gps_type[instance].get()) {
|
{
|
||||||
case Type::NONE:
|
// swallow any config bytes
|
||||||
// no GPS attached
|
char c;
|
||||||
break;
|
read_from_autopilot(&c, 1);
|
||||||
|
|
||||||
case Type::UBLOX:
|
|
||||||
update_ubx(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type::NMEA:
|
|
||||||
update_nmea(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type::SBP:
|
|
||||||
update_sbp(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type::SBP2:
|
|
||||||
update_sbp2(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type::NOVA:
|
|
||||||
update_nova(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type::MSP:
|
|
||||||
update_msp(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type::GSOF:
|
|
||||||
update_gsof(&d);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if AP_SIM_GPS_FILE_ENABLED
|
|
||||||
case Type::FILE:
|
|
||||||
update_file();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
get delayed data by interpolation
|
get delayed data by interpolation
|
||||||
*/
|
*/
|
||||||
GPS::gps_data GPS::interpolate_data(const gps_data &d, uint32_t delay_ms)
|
GPS_Data GPS::interpolate_data(const GPS_Data &d, uint32_t delay_ms)
|
||||||
{
|
{
|
||||||
const uint8_t N = ARRAY_SIZE(_gps_history);
|
const uint8_t N = ARRAY_SIZE(_gps_history);
|
||||||
const uint32_t now_ms = d.timestamp_ms;
|
const uint32_t now_ms = d.timestamp_ms;
|
||||||
@ -1624,9 +1664,9 @@ GPS::gps_data GPS::interpolate_data(const gps_data &d, uint32_t delay_ms)
|
|||||||
if (delay_ms >= dt1 && delay_ms <= dt2) {
|
if (delay_ms >= dt1 && delay_ms <= dt2) {
|
||||||
// we will interpolate this pair of samples. Start with
|
// we will interpolate this pair of samples. Start with
|
||||||
// the older sample
|
// the older sample
|
||||||
const gps_data &s1 = _gps_history[i+1];
|
const GPS_Data &s1 = _gps_history[i+1];
|
||||||
const gps_data &s2 = _gps_history[i];
|
const GPS_Data &s2 = _gps_history[i];
|
||||||
gps_data d2 = s1;
|
GPS_Data d2 = s1;
|
||||||
const float p = (dt2 - delay_ms) / MAX(1,float(dt2 - dt1));
|
const float p = (dt2 - delay_ms) / MAX(1,float(dt2 - dt1));
|
||||||
d2.latitude += p * (s2.latitude - s1.latitude);
|
d2.latitude += p * (s2.latitude - s1.latitude);
|
||||||
d2.longitude += p * (s2.longitude - s1.longitude);
|
d2.longitude += p * (s2.longitude - s1.longitude);
|
||||||
@ -1642,13 +1682,13 @@ GPS::gps_data GPS::interpolate_data(const gps_data &d, uint32_t delay_ms)
|
|||||||
return _gps_history[N-1];
|
return _gps_history[N-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
float GPS::gps_data::heading() const
|
float GPS_Data::heading() const
|
||||||
{
|
{
|
||||||
const auto velocity = Vector2d{speedE, speedN};
|
const auto velocity = Vector2d{speedE, speedN};
|
||||||
return velocity.angle();
|
return velocity.angle();
|
||||||
}
|
}
|
||||||
|
|
||||||
float GPS::gps_data::speed_2d() const
|
float GPS_Data::speed_2d() const
|
||||||
{
|
{
|
||||||
const auto velocity = Vector2d{speedN, speedE};
|
const auto velocity = Vector2d{speedN, speedE};
|
||||||
return velocity.length();
|
return velocity.length();
|
||||||
|
@ -44,6 +44,169 @@ param set SERIAL5_PROTOCOL 5
|
|||||||
|
|
||||||
namespace SITL {
|
namespace SITL {
|
||||||
|
|
||||||
|
// for delay simulation:
|
||||||
|
struct GPS_Data {
|
||||||
|
uint32_t timestamp_ms;
|
||||||
|
double latitude;
|
||||||
|
double longitude;
|
||||||
|
float altitude;
|
||||||
|
double speedN;
|
||||||
|
double speedE;
|
||||||
|
double speedD;
|
||||||
|
double yaw_deg;
|
||||||
|
double roll_deg;
|
||||||
|
double pitch_deg;
|
||||||
|
bool have_lock;
|
||||||
|
|
||||||
|
// Get heading [rad], where 0 = North in WGS-84 coordinate system
|
||||||
|
float heading() const WARN_IF_UNUSED;
|
||||||
|
|
||||||
|
// Get 2D speed [m/s] in WGS-84 coordinate system
|
||||||
|
float speed_2d() const WARN_IF_UNUSED;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_Backend);
|
||||||
|
|
||||||
|
GPS_Backend(class GPS &front, uint8_t _instance);
|
||||||
|
virtual ~GPS_Backend() {}
|
||||||
|
|
||||||
|
void update(const GPS_Data &d);
|
||||||
|
|
||||||
|
// 0 baud means "unset" i.e. baud-rate checks should not apply
|
||||||
|
virtual uint32_t device_baud() const { return 0; }
|
||||||
|
|
||||||
|
ssize_t write_to_autopilot(const char *p, size_t size) const;
|
||||||
|
ssize_t read_from_autopilot(char *buffer, size_t size) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint8_t instance;
|
||||||
|
GPS &front;
|
||||||
|
|
||||||
|
class SIM *_sitl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// read and process config from autopilot (e.g.)
|
||||||
|
virtual void update_read(const GPS_Data *d);
|
||||||
|
// writing fix information to autopilot (e.g.)
|
||||||
|
virtual void update_write(const GPS_Data *d) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_FILE : public GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_FILE);
|
||||||
|
|
||||||
|
using GPS_Backend::GPS_Backend;
|
||||||
|
|
||||||
|
void update_write(const GPS_Data *d) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_GSOF : public GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_GSOF);
|
||||||
|
|
||||||
|
using GPS_Backend::GPS_Backend;
|
||||||
|
|
||||||
|
void update_write(const GPS_Data *d) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void send_gsof(const uint8_t *buf, const uint16_t size);
|
||||||
|
|
||||||
|
uint64_t pack_double_into_gsof_packet(const double& src) WARN_IF_UNUSED;
|
||||||
|
uint32_t pack_float_into_gsof_packet(const float& src) WARN_IF_UNUSED;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_NMEA : public GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_NMEA);
|
||||||
|
|
||||||
|
using GPS_Backend::GPS_Backend;
|
||||||
|
|
||||||
|
void update_write(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);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_NOVA : public GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_NOVA);
|
||||||
|
|
||||||
|
using GPS_Backend::GPS_Backend;
|
||||||
|
|
||||||
|
void update_write(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);
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_MSP : public GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_MSP);
|
||||||
|
|
||||||
|
using GPS_Backend::GPS_Backend;
|
||||||
|
|
||||||
|
void update_write(const GPS_Data *d) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_SBP : public GPS_SBP_Common {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_SBP);
|
||||||
|
|
||||||
|
using GPS_SBP_Common::GPS_SBP_Common;
|
||||||
|
|
||||||
|
void update_write(const GPS_Data *d) override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_SBP2 : public GPS_SBP_Common {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_SBP2);
|
||||||
|
|
||||||
|
using GPS_SBP_Common::GPS_SBP_Common;
|
||||||
|
|
||||||
|
void update_write(const GPS_Data *d) override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GPS_UBlox : public GPS_Backend {
|
||||||
|
public:
|
||||||
|
CLASS_NO_COPY(GPS_UBlox);
|
||||||
|
|
||||||
|
using GPS_Backend::GPS_Backend;
|
||||||
|
|
||||||
|
void update_write(const GPS_Data *d) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void send_ubx(uint8_t msgid, uint8_t *buf, uint16_t size);
|
||||||
|
};
|
||||||
|
|
||||||
class GPS : public SerialDevice {
|
class GPS : public SerialDevice {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -80,32 +243,8 @@ private:
|
|||||||
|
|
||||||
uint32_t last_update; // milliseconds
|
uint32_t last_update; // milliseconds
|
||||||
|
|
||||||
// for delay simulation:
|
|
||||||
struct gps_data {
|
|
||||||
uint32_t timestamp_ms;
|
|
||||||
double latitude;
|
|
||||||
double longitude;
|
|
||||||
float altitude;
|
|
||||||
double speedN;
|
|
||||||
double speedE;
|
|
||||||
double speedD;
|
|
||||||
double yaw_deg;
|
|
||||||
double roll_deg;
|
|
||||||
double pitch_deg;
|
|
||||||
bool have_lock;
|
|
||||||
|
|
||||||
// Get heading [rad], where 0 = North in WGS-84 coordinate system
|
|
||||||
float heading() const WARN_IF_UNUSED;
|
|
||||||
|
|
||||||
// Get 2D speed [m/s] in WGS-84 coordinate system
|
|
||||||
float speed_2d() const WARN_IF_UNUSED;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// last 20 samples, allowing for up to 20 samples of delay
|
// last 20 samples, allowing for up to 20 samples of delay
|
||||||
gps_data _gps_history[20];
|
GPS_Data _gps_history[20];
|
||||||
|
|
||||||
|
|
||||||
#if HAL_SIM_GPS_EXTERNAL_FIFO_ENABLED
|
#if HAL_SIM_GPS_EXTERNAL_FIFO_ENABLED
|
||||||
// this will be allocated if needed:
|
// this will be allocated if needed:
|
||||||
@ -113,40 +252,14 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool _gps_has_basestation_position;
|
bool _gps_has_basestation_position;
|
||||||
gps_data _gps_basestation_data;
|
GPS_Data _gps_basestation_data;
|
||||||
|
|
||||||
void send_ubx(uint8_t msgid, uint8_t *buf, uint16_t size);
|
|
||||||
void update_ubx(const struct gps_data *d);
|
|
||||||
|
|
||||||
uint8_t nmea_checksum(const char *s);
|
|
||||||
void nmea_printf(const char *fmt, ...);
|
|
||||||
void update_nmea(const struct gps_data *d);
|
|
||||||
|
|
||||||
void sbp_send_message(uint16_t msg_type, uint16_t sender_id, uint8_t len, uint8_t *payload);
|
|
||||||
|
|
||||||
void update_sbp(const struct gps_data *d);
|
|
||||||
void update_sbp2(const struct gps_data *d);
|
|
||||||
void update_msp(const struct gps_data *d);
|
|
||||||
|
|
||||||
#if AP_SIM_GPS_FILE_ENABLED
|
|
||||||
void update_file();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void update_nova(const struct gps_data *d);
|
|
||||||
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);
|
|
||||||
|
|
||||||
// If gsof gets data in, handle it.
|
|
||||||
// Simply, it should respond to this: https://receiverhelp.trimble.com/oem-gnss/index.html#API_TestingComms.html
|
|
||||||
void on_data_gsof();
|
|
||||||
void update_gsof(const struct gps_data *d);
|
|
||||||
void send_gsof(const uint8_t *buf, const uint16_t size);
|
|
||||||
uint64_t pack_double_into_gsof_packet(const double& src) WARN_IF_UNUSED;
|
|
||||||
uint32_t pack_float_into_gsof_packet(const float& src) WARN_IF_UNUSED;
|
|
||||||
|
|
||||||
// get delayed data
|
// get delayed data
|
||||||
gps_data interpolate_data(const gps_data &d, uint32_t delay_ms);
|
GPS_Data interpolate_data(const GPS_Data &d, uint32_t delay_ms);
|
||||||
|
|
||||||
|
uint8_t allocated_type;
|
||||||
|
GPS_Backend *backend;
|
||||||
|
void check_backend_allocation();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user