mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-03 06:28:27 -04:00
AP_GPS: add support for dual GPS heading using Periph GPSes
This commit is contained in:
parent
e29ddebe3c
commit
9fc57e40b4
@ -81,7 +81,7 @@ const AP_Param::GroupInfo AP_GPS::var_info[] = {
|
|||||||
// @Param: _TYPE
|
// @Param: _TYPE
|
||||||
// @DisplayName: 1st GPS type
|
// @DisplayName: 1st GPS type
|
||||||
// @Description: GPS type of 1st GPS
|
// @Description: GPS type of 1st GPS
|
||||||
// @Values: 0:None,1:AUTO,2:uBlox,3:MTK,4:MTK19,5:NMEA,6:SiRF,7:HIL,8:SwiftNav,9:UAVCAN,10:SBF,11:GSOF,13:ERB,14:MAV,15:NOVA,16:HemisphereNMEA,17:uBlox-MovingBaseline-Base,18:uBlox-MovingBaseline-Rover,19:MSP,20:AllyStar,21:ExternalAHRS
|
// @Values: 0:None,1:AUTO,2:uBlox,3:MTK,4:MTK19,5:NMEA,6:SiRF,7:HIL,8:SwiftNav,9:UAVCAN,10:SBF,11:GSOF,13:ERB,14:MAV,15:NOVA,16:HemisphereNMEA,17:uBlox-MovingBaseline-Base,18:uBlox-MovingBaseline-Rover,19:MSP,20:AllyStar,21:ExternalAHRS,22:UAVCAN-MovingBaseline-Base,23:UAVCAN-MovingBaseline-Rover
|
||||||
// @RebootRequired: True
|
// @RebootRequired: True
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("_TYPE", 0, AP_GPS, _type[0], HAL_GPS_TYPE_DEFAULT),
|
AP_GROUPINFO("_TYPE", 0, AP_GPS, _type[0], HAL_GPS_TYPE_DEFAULT),
|
||||||
@ -90,7 +90,7 @@ const AP_Param::GroupInfo AP_GPS::var_info[] = {
|
|||||||
// @Param: _TYPE2
|
// @Param: _TYPE2
|
||||||
// @DisplayName: 2nd GPS type
|
// @DisplayName: 2nd GPS type
|
||||||
// @Description: GPS type of 2nd GPS
|
// @Description: GPS type of 2nd GPS
|
||||||
// @Values: 0:None,1:AUTO,2:uBlox,3:MTK,4:MTK19,5:NMEA,6:SiRF,7:HIL,8:SwiftNav,9:UAVCAN,10:SBF,11:GSOF,13:ERB,14:MAV,15:NOVA,16:HemisphereNMEA,17:uBlox-MovingBaseline-Base,18:uBlox-MovingBaseline-Rover,19:MSP,20:AllyStar,21:ExternalAHRS
|
// @Values: 0:None,1:AUTO,2:uBlox,3:MTK,4:MTK19,5:NMEA,6:SiRF,7:HIL,8:SwiftNav,9:UAVCAN,10:SBF,11:GSOF,13:ERB,14:MAV,15:NOVA,16:HemisphereNMEA,17:uBlox-MovingBaseline-Base,18:uBlox-MovingBaseline-Rover,19:MSP,20:AllyStar,21:ExternalAHRS,22:UAVCAN-MovingBaseline-Base,23:UAVCAN-MovingBaseline-Rover
|
||||||
// @RebootRequired: True
|
// @RebootRequired: True
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("_TYPE2", 1, AP_GPS, _type[1], 0),
|
AP_GROUPINFO("_TYPE2", 1, AP_GPS, _type[1], 0),
|
||||||
@ -401,6 +401,8 @@ bool AP_GPS::needs_uart(GPS_Type type) const
|
|||||||
case GPS_TYPE_NONE:
|
case GPS_TYPE_NONE:
|
||||||
case GPS_TYPE_HIL:
|
case GPS_TYPE_HIL:
|
||||||
case GPS_TYPE_UAVCAN:
|
case GPS_TYPE_UAVCAN:
|
||||||
|
case GPS_TYPE_UAVCAN_RTK_BASE:
|
||||||
|
case GPS_TYPE_UAVCAN_RTK_ROVER:
|
||||||
case GPS_TYPE_MAV:
|
case GPS_TYPE_MAV:
|
||||||
case GPS_TYPE_MSP:
|
case GPS_TYPE_MSP:
|
||||||
case GPS_TYPE_EXTERNAL_AHRS:
|
case GPS_TYPE_EXTERNAL_AHRS:
|
||||||
@ -573,6 +575,8 @@ void AP_GPS::detect_instance(uint8_t instance)
|
|||||||
|
|
||||||
// user has to explicitly set the UAVCAN type, do not use AUTO
|
// user has to explicitly set the UAVCAN type, do not use AUTO
|
||||||
case GPS_TYPE_UAVCAN:
|
case GPS_TYPE_UAVCAN:
|
||||||
|
case GPS_TYPE_UAVCAN_RTK_BASE:
|
||||||
|
case GPS_TYPE_UAVCAN_RTK_ROVER:
|
||||||
#if HAL_ENABLE_LIBUAVCAN_DRIVERS
|
#if HAL_ENABLE_LIBUAVCAN_DRIVERS
|
||||||
dstate->auto_detected_baud = false; // specified, not detected
|
dstate->auto_detected_baud = false; // specified, not detected
|
||||||
new_gps = AP_GPS_UAVCAN::probe(*this, state[instance]);
|
new_gps = AP_GPS_UAVCAN::probe(*this, state[instance]);
|
||||||
@ -824,7 +828,10 @@ void AP_GPS::update_instance(uint8_t instance)
|
|||||||
timing[instance].last_message_time_ms = tnow;
|
timing[instance].last_message_time_ms = tnow;
|
||||||
timing[instance].delta_time_ms = GPS_TIMEOUT_MS;
|
timing[instance].delta_time_ms = GPS_TIMEOUT_MS;
|
||||||
// do not try to detect again if type is MAV or UAVCAN
|
// do not try to detect again if type is MAV or UAVCAN
|
||||||
if (_type[instance] == GPS_TYPE_MAV || _type[instance] == GPS_TYPE_UAVCAN) {
|
if (_type[instance] == GPS_TYPE_MAV ||
|
||||||
|
_type[instance] == GPS_TYPE_UAVCAN ||
|
||||||
|
_type[instance] == GPS_TYPE_UAVCAN_RTK_BASE ||
|
||||||
|
_type[instance] == GPS_TYPE_UAVCAN_RTK_ROVER) {
|
||||||
state[instance].status = NO_FIX;
|
state[instance].status = NO_FIX;
|
||||||
} else {
|
} else {
|
||||||
// free the driver before we run the next detection, so we
|
// free the driver before we run the next detection, so we
|
||||||
@ -911,6 +918,55 @@ void AP_GPS::update_instance(uint8_t instance)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
void AP_GPS::get_RelPosHeading(uint32_t ×tamp, float &relPosHeading, float &relPosLength, float &relPosD, float &accHeading)
|
||||||
|
{
|
||||||
|
for (uint8_t i=0; i< GPS_MAX_RECEIVERS; i++) {
|
||||||
|
if (drivers[i] && _type[i] == GPS_TYPE_UBLOX_RTK_ROVER) {
|
||||||
|
relPosHeading = state[i].relPosHeading;
|
||||||
|
relPosLength = state[i].relPosLength;
|
||||||
|
relPosD = state[i].relPosD;
|
||||||
|
accHeading = state[i].accHeading;
|
||||||
|
timestamp = state[i].relposheading_ts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_GPS::get_RTCMV3(const uint8_t *&bytes, uint16_t &len)
|
||||||
|
{
|
||||||
|
for (uint8_t i=0; i< GPS_MAX_RECEIVERS; i++) {
|
||||||
|
if (drivers[i] && _type[i] == GPS_TYPE_UBLOX_RTK_BASE) {
|
||||||
|
return drivers[i]->get_RTCMV3(bytes, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AP_GPS::clear_RTCMV3()
|
||||||
|
{
|
||||||
|
for (uint8_t i=0; i< GPS_MAX_RECEIVERS; i++) {
|
||||||
|
if (drivers[i] && _type[i] == GPS_TYPE_UBLOX_RTK_BASE) {
|
||||||
|
drivers[i]->clear_RTCMV3();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inject Moving Baseline Data messages.
|
||||||
|
*/
|
||||||
|
void AP_GPS::inject_MBL_data(uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
for (uint8_t i=0; i< GPS_MAX_RECEIVERS; i++) {
|
||||||
|
if (_type[i] == GPS_TYPE_UBLOX_RTK_ROVER) {
|
||||||
|
// pass the data to the rover
|
||||||
|
inject_data(i, data, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //#if GPS_MOVING_BASELINE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
update all GPS instances
|
update all GPS instances
|
||||||
*/
|
*/
|
||||||
@ -1003,8 +1059,8 @@ void AP_GPS::update_primary(void)
|
|||||||
// rover as it typically is in fix type 6 (RTK) whereas base is
|
// rover as it typically is in fix type 6 (RTK) whereas base is
|
||||||
// usually fix type 3
|
// usually fix type 3
|
||||||
for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
|
for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
|
||||||
if (_type[i] == GPS_TYPE_UBLOX_RTK_BASE &&
|
if (((_type[i] == GPS_TYPE_UBLOX_RTK_BASE) || (_type[i] == GPS_TYPE_UAVCAN_RTK_BASE)) &&
|
||||||
_type[i^1] == GPS_TYPE_UBLOX_RTK_ROVER &&
|
((_type[i^1] == GPS_TYPE_UBLOX_RTK_ROVER) || (_type[i^1] == GPS_TYPE_UAVCAN_RTK_ROVER)) &&
|
||||||
((state[i].status >= GPS_OK_FIX_3D) || (state[i].status >= state[i^1].status))) {
|
((state[i].status >= GPS_OK_FIX_3D) || (state[i].status >= state[i^1].status))) {
|
||||||
if (primary_instance != i) {
|
if (primary_instance != i) {
|
||||||
_last_instance_swap_ms = now;
|
_last_instance_swap_ms = now;
|
||||||
@ -1158,7 +1214,7 @@ void AP_GPS::inject_data(const uint8_t *data, uint16_t len)
|
|||||||
//Support broadcasting to all GPSes.
|
//Support broadcasting to all GPSes.
|
||||||
if (_inject_to == GPS_RTK_INJECT_TO_ALL) {
|
if (_inject_to == GPS_RTK_INJECT_TO_ALL) {
|
||||||
for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
|
for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
|
||||||
if (_type[i] == GPS_TYPE_UBLOX_RTK_ROVER) {
|
if ((_type[i] == GPS_TYPE_UBLOX_RTK_ROVER) || (_type[i] == GPS_TYPE_UAVCAN_RTK_ROVER)) {
|
||||||
// we don't externally inject to moving baseline rover
|
// we don't externally inject to moving baseline rover
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1859,7 +1915,7 @@ bool AP_GPS::is_healthy(uint8_t instance) const
|
|||||||
happens with the RTCMv3 data
|
happens with the RTCMv3 data
|
||||||
*/
|
*/
|
||||||
const uint8_t delay_threshold = 2;
|
const uint8_t delay_threshold = 2;
|
||||||
const float delay_avg_max = _type[instance] == GPS_TYPE_UBLOX_RTK_ROVER?245:215;
|
const float delay_avg_max = _type[instance] == (GPS_TYPE_UBLOX_RTK_ROVER || GPS_TYPE_UAVCAN_RTK_ROVER)?245:215;
|
||||||
const GPS_timing &t = timing[instance];
|
const GPS_timing &t = timing[instance];
|
||||||
bool delay_ok = (t.delayed_count < delay_threshold) &&
|
bool delay_ok = (t.delayed_count < delay_threshold) &&
|
||||||
t.average_delta_ms < delay_avg_max &&
|
t.average_delta_ms < delay_avg_max &&
|
||||||
@ -1888,13 +1944,16 @@ bool AP_GPS::prepare_for_arming(void) {
|
|||||||
bool AP_GPS::backends_healthy(char failure_msg[], uint16_t failure_msg_len) {
|
bool AP_GPS::backends_healthy(char failure_msg[], uint16_t failure_msg_len) {
|
||||||
for (uint8_t i = 0; i < GPS_MAX_RECEIVERS; i++) {
|
for (uint8_t i = 0; i < GPS_MAX_RECEIVERS; i++) {
|
||||||
#if HAL_ENABLE_LIBUAVCAN_DRIVERS
|
#if HAL_ENABLE_LIBUAVCAN_DRIVERS
|
||||||
if (_type[i] == GPS_TYPE_UAVCAN) {
|
if (_type[i] == GPS_TYPE_UAVCAN ||
|
||||||
|
_type[i] == GPS_TYPE_UAVCAN_RTK_BASE ||
|
||||||
|
_type[i] == GPS_TYPE_UAVCAN_RTK_ROVER) {
|
||||||
if (!AP_GPS_UAVCAN::backends_healthy(failure_msg, failure_msg_len)) {
|
if (!AP_GPS_UAVCAN::backends_healthy(failure_msg, failure_msg_len)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (_type[i] == GPS_TYPE_UBLOX_RTK_ROVER) {
|
if (_type[i] == GPS_TYPE_UBLOX_RTK_ROVER ||
|
||||||
|
_type[i] == GPS_TYPE_UAVCAN_RTK_ROVER) {
|
||||||
if (AP_HAL::millis() - state[i].gps_yaw_time_ms > 15000) {
|
if (AP_HAL::millis() - state[i].gps_yaw_time_ms > 15000) {
|
||||||
hal.util->snprintf(failure_msg, failure_msg_len, "GPS[%u] yaw not available", unsigned(i+1));
|
hal.util->snprintf(failure_msg, failure_msg_len, "GPS[%u] yaw not available", unsigned(i+1));
|
||||||
return false;
|
return false;
|
||||||
@ -1995,8 +2054,8 @@ bool AP_GPS::gps_yaw_deg(uint8_t instance, float &yaw_deg, float &accuracy_deg,
|
|||||||
{
|
{
|
||||||
#if GPS_MAX_RECEIVERS > 1
|
#if GPS_MAX_RECEIVERS > 1
|
||||||
if (instance < GPS_MAX_RECEIVERS &&
|
if (instance < GPS_MAX_RECEIVERS &&
|
||||||
_type[instance] == GPS_TYPE_UBLOX_RTK_BASE &&
|
((_type[instance] == GPS_TYPE_UBLOX_RTK_BASE) || (_type[instance] == GPS_TYPE_UAVCAN_RTK_BASE)) &&
|
||||||
_type[instance^1] == GPS_TYPE_UBLOX_RTK_ROVER) {
|
((_type[instance^1] == GPS_TYPE_UBLOX_RTK_ROVER) || (_type[instance^1] == GPS_TYPE_UAVCAN_RTK_ROVER))) {
|
||||||
// return the yaw from the rover
|
// return the yaw from the rover
|
||||||
instance ^= 1;
|
instance ^= 1;
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,8 @@ public:
|
|||||||
GPS_TYPE_MSP = 19,
|
GPS_TYPE_MSP = 19,
|
||||||
GPS_TYPE_ALLYSTAR = 20, // AllyStar NMEA
|
GPS_TYPE_ALLYSTAR = 20, // AllyStar NMEA
|
||||||
GPS_TYPE_EXTERNAL_AHRS = 21,
|
GPS_TYPE_EXTERNAL_AHRS = 21,
|
||||||
|
GPS_TYPE_UAVCAN_RTK_BASE = 22,
|
||||||
|
GPS_TYPE_UAVCAN_RTK_ROVER = 23,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// GPS status codes
|
/// GPS status codes
|
||||||
@ -199,6 +201,13 @@ public:
|
|||||||
int32_t rtk_baseline_z_mm; ///< Current baseline in ECEF z or NED down component in mm
|
int32_t rtk_baseline_z_mm; ///< Current baseline in ECEF z or NED down component in mm
|
||||||
uint32_t rtk_accuracy; ///< Current estimate of 3D baseline accuracy (receiver dependent, typical 0 to 9999)
|
uint32_t rtk_accuracy; ///< Current estimate of 3D baseline accuracy (receiver dependent, typical 0 to 9999)
|
||||||
int32_t rtk_iar_num_hypotheses; ///< Current number of integer ambiguity hypotheses
|
int32_t rtk_iar_num_hypotheses; ///< Current number of integer ambiguity hypotheses
|
||||||
|
|
||||||
|
// UBX Relative Position and Heading message information
|
||||||
|
float relPosHeading; ///< Reported Heading in degrees
|
||||||
|
float relPosLength; ///< Reported Position horizontal distance in meters
|
||||||
|
float relPosD; ///< Reported Vertical distance in meters
|
||||||
|
float accHeading; ///< Reported Heading Accuracy in degrees
|
||||||
|
uint32_t relposheading_ts; ///< True if new data has been received since last time it was false
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Startup initialisation.
|
/// Startup initialisation.
|
||||||
@ -520,6 +529,14 @@ public:
|
|||||||
DoNotChange = 2,
|
DoNotChange = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
// methods used by UAVCAN GPS driver and AP_Periph for moving baseline
|
||||||
|
void inject_MBL_data(uint8_t* data, uint16_t length);
|
||||||
|
void get_RelPosHeading(uint32_t ×tamp, float &relPosHeading, float &relPosLength, float &relPosD, float &accHeading);
|
||||||
|
bool get_RTCMV3(const uint8_t *&bytes, uint16_t &len);
|
||||||
|
void clear_RTCMV3();
|
||||||
|
#endif // GPS_MOVING_BASELINE
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// configuration parameters
|
// configuration parameters
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
#include <uavcan/equipment/gnss/Auxiliary.hpp>
|
#include <uavcan/equipment/gnss/Auxiliary.hpp>
|
||||||
#include <ardupilot/gnss/Heading.hpp>
|
#include <ardupilot/gnss/Heading.hpp>
|
||||||
#include <ardupilot/gnss/Status.hpp>
|
#include <ardupilot/gnss/Status.hpp>
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
#include <ardupilot/gnss/MovingBaselineData.hpp>
|
||||||
|
#include <ardupilot/gnss/RelPosHeading.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const AP_HAL::HAL& hal;
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
@ -42,13 +46,18 @@ UC_REGISTRY_BINDER(Fix2Cb, uavcan::equipment::gnss::Fix2);
|
|||||||
UC_REGISTRY_BINDER(AuxCb, uavcan::equipment::gnss::Auxiliary);
|
UC_REGISTRY_BINDER(AuxCb, uavcan::equipment::gnss::Auxiliary);
|
||||||
UC_REGISTRY_BINDER(HeadingCb, ardupilot::gnss::Heading);
|
UC_REGISTRY_BINDER(HeadingCb, ardupilot::gnss::Heading);
|
||||||
UC_REGISTRY_BINDER(StatusCb, ardupilot::gnss::Status);
|
UC_REGISTRY_BINDER(StatusCb, ardupilot::gnss::Status);
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
UC_REGISTRY_BINDER(MovingBaselineDataCb, ardupilot::gnss::MovingBaselineData);
|
||||||
|
UC_REGISTRY_BINDER(RelPosHeadingCb, ardupilot::gnss::RelPosHeading);
|
||||||
|
#endif
|
||||||
|
|
||||||
AP_GPS_UAVCAN::DetectedModules AP_GPS_UAVCAN::_detected_modules[] = {0};
|
AP_GPS_UAVCAN::DetectedModules AP_GPS_UAVCAN::_detected_modules[] = {0};
|
||||||
HAL_Semaphore AP_GPS_UAVCAN::_sem_registry;
|
HAL_Semaphore AP_GPS_UAVCAN::_sem_registry;
|
||||||
|
|
||||||
// Member Methods
|
// Member Methods
|
||||||
AP_GPS_UAVCAN::AP_GPS_UAVCAN(AP_GPS &_gps, AP_GPS::GPS_State &_state) :
|
AP_GPS_UAVCAN::AP_GPS_UAVCAN(AP_GPS &_gps, AP_GPS::GPS_State &_state, AP_GPS::GPS_Role _role) :
|
||||||
AP_GPS_Backend(_gps, _state, nullptr)
|
AP_GPS_Backend(_gps, _state, nullptr),
|
||||||
|
role(_role)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
AP_GPS_UAVCAN::~AP_GPS_UAVCAN()
|
AP_GPS_UAVCAN::~AP_GPS_UAVCAN()
|
||||||
@ -56,6 +65,10 @@ AP_GPS_UAVCAN::~AP_GPS_UAVCAN()
|
|||||||
WITH_SEMAPHORE(_sem_registry);
|
WITH_SEMAPHORE(_sem_registry);
|
||||||
|
|
||||||
_detected_modules[_detected_module].driver = nullptr;
|
_detected_modules[_detected_module].driver = nullptr;
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
delete rtcm3_parser;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AP_GPS_UAVCAN::subscribe_msgs(AP_UAVCAN* ap_uavcan)
|
void AP_GPS_UAVCAN::subscribe_msgs(AP_UAVCAN* ap_uavcan)
|
||||||
@ -105,6 +118,24 @@ void AP_GPS_UAVCAN::subscribe_msgs(AP_UAVCAN* ap_uavcan)
|
|||||||
AP_HAL::panic("UAVCAN GNSS subscriber start problem\n\r");
|
AP_HAL::panic("UAVCAN GNSS subscriber start problem\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
uavcan::Subscriber<ardupilot::gnss::MovingBaselineData, MovingBaselineDataCb> *gnss_moving_baseline;
|
||||||
|
gnss_moving_baseline = new uavcan::Subscriber<ardupilot::gnss::MovingBaselineData, MovingBaselineDataCb>(*node);
|
||||||
|
const int gnss_moving_baseline_start_res = gnss_moving_baseline->start(MovingBaselineDataCb(ap_uavcan, &handle_moving_baseline_msg_trampoline));
|
||||||
|
if (gnss_moving_baseline_start_res < 0) {
|
||||||
|
AP_HAL::panic("UAVCAN GNSS subscriber start problem\n\r");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uavcan::Subscriber<ardupilot::gnss::RelPosHeading, RelPosHeadingCb> *gnss_relposheading;
|
||||||
|
gnss_relposheading = new uavcan::Subscriber<ardupilot::gnss::RelPosHeading, RelPosHeadingCb>(*node);
|
||||||
|
const int gnss_relposheading_start_res = gnss_relposheading->start(RelPosHeadingCb(ap_uavcan, &handle_relposheading_msg_trampoline));
|
||||||
|
if (gnss_relposheading_start_res < 0) {
|
||||||
|
AP_HAL::panic("UAVCAN GNSS subscriber start problem\n\r");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AP_GPS_Backend* AP_GPS_UAVCAN::probe(AP_GPS &_gps, AP_GPS::GPS_State &_state)
|
AP_GPS_Backend* AP_GPS_UAVCAN::probe(AP_GPS &_gps, AP_GPS::GPS_State &_state)
|
||||||
@ -153,7 +184,22 @@ AP_GPS_Backend* AP_GPS_UAVCAN::probe(AP_GPS &_gps, AP_GPS::GPS_State &_state)
|
|||||||
if (found_match == -1) {
|
if (found_match == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
backend = new AP_GPS_UAVCAN(_gps, _state);
|
// initialise the backend based on the UAVCAN Moving baseline selection
|
||||||
|
switch (_gps.get_type(found_match)) {
|
||||||
|
case AP_GPS::GPS_TYPE_UAVCAN:
|
||||||
|
backend = new AP_GPS_UAVCAN(_gps, _state, AP_GPS::GPS_ROLE_NORMAL);
|
||||||
|
break;
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
case AP_GPS::GPS_TYPE_UAVCAN_RTK_BASE:
|
||||||
|
backend = new AP_GPS_UAVCAN(_gps, _state, AP_GPS::GPS_ROLE_MB_BASE);
|
||||||
|
break;
|
||||||
|
case AP_GPS::GPS_TYPE_UAVCAN_RTK_ROVER:
|
||||||
|
backend = new AP_GPS_UAVCAN(_gps, _state, AP_GPS::GPS_ROLE_MB_ROVER);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (backend == nullptr) {
|
if (backend == nullptr) {
|
||||||
AP::can().log_text(AP_CANManager::LOG_ERROR,
|
AP::can().log_text(AP_CANManager::LOG_ERROR,
|
||||||
LOG_TAG,
|
LOG_TAG,
|
||||||
@ -183,7 +229,16 @@ AP_GPS_Backend* AP_GPS_UAVCAN::probe(AP_GPS &_gps, AP_GPS::GPS_State &_state)
|
|||||||
AP::gps()._node_id[i].set_and_notify(tmp);
|
AP::gps()._node_id[i].set_and_notify(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
if (_detected_modules[found_match].driver->role == AP_GPS::GPS_ROLE_MB_BASE) {
|
||||||
|
_detected_modules[found_match].driver->rtcm3_parser = new RTCM3_Parser;
|
||||||
|
if (_detected_modules[found_match].driver->rtcm3_parser == nullptr) {
|
||||||
|
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "UAVCAN%u-%u: failed RTCMv3 parser allocation", _detected_modules[found_match].ap_uavcan->get_driver_index()+1, _detected_modules[found_match].node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // GPS_MOVING_BASELINE
|
||||||
}
|
}
|
||||||
|
|
||||||
return backend;
|
return backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,6 +605,67 @@ void AP_GPS_UAVCAN::handle_status_msg(const StatusCb &cb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
/*
|
||||||
|
handle moving baseline data.
|
||||||
|
*/
|
||||||
|
void AP_GPS_UAVCAN::handle_moving_baseline_msg(const MovingBaselineDataCb &cb)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(sem);
|
||||||
|
if ((rtcm3_parser == nullptr) || (role != AP_GPS::GPS_ROLE_MB_BASE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto &c : cb.msg->data) {
|
||||||
|
rtcm3_parser->read(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
handle relposheading message
|
||||||
|
*/
|
||||||
|
void AP_GPS_UAVCAN::handle_relposheading_msg(const RelPosHeadingCb &cb)
|
||||||
|
{
|
||||||
|
if (role != AP_GPS::GPS_ROLE_MB_ROVER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WITH_SEMAPHORE(sem);
|
||||||
|
|
||||||
|
interim_state.gps_yaw_configured = true;
|
||||||
|
// push raw heading data to calculate moving baseline heading states
|
||||||
|
if (calculate_moving_base_yaw(interim_state,
|
||||||
|
cb.msg->reported_heading_deg,
|
||||||
|
cb.msg->relative_distance_m,
|
||||||
|
cb.msg->relative_down_pos_m)) {
|
||||||
|
if (cb.msg->reported_heading_acc_available) {
|
||||||
|
interim_state.gps_yaw_accuracy = cb.msg->reported_heading_acc_deg;
|
||||||
|
}
|
||||||
|
interim_state.have_gps_yaw_accuracy = cb.msg->reported_heading_acc_available;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// support for retrieving RTCMv3 data from a moving baseline base
|
||||||
|
bool AP_GPS_UAVCAN::get_RTCMV3(const uint8_t *&bytes, uint16_t &len)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(sem);
|
||||||
|
if (rtcm3_parser != nullptr) {
|
||||||
|
len = rtcm3_parser->get_len(bytes);
|
||||||
|
return len > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear previous RTCM3 packet
|
||||||
|
void AP_GPS_UAVCAN::clear_RTCMV3(void)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(sem);
|
||||||
|
if (rtcm3_parser != nullptr) {
|
||||||
|
rtcm3_parser->clear_packet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GPS_MOVING_BASELINE
|
||||||
|
|
||||||
void AP_GPS_UAVCAN::handle_fix_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const FixCb &cb)
|
void AP_GPS_UAVCAN::handle_fix_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const FixCb &cb)
|
||||||
{
|
{
|
||||||
WITH_SEMAPHORE(_sem_registry);
|
WITH_SEMAPHORE(_sem_registry);
|
||||||
@ -600,6 +716,28 @@ void AP_GPS_UAVCAN::handle_status_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
// Moving Baseline msg trampoline
|
||||||
|
void AP_GPS_UAVCAN::handle_moving_baseline_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const MovingBaselineDataCb &cb)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(_sem_registry);
|
||||||
|
AP_GPS_UAVCAN* driver = get_uavcan_backend(ap_uavcan, node_id);
|
||||||
|
if (driver != nullptr) {
|
||||||
|
driver->handle_moving_baseline_msg(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RelPosHeading msg trampoline
|
||||||
|
void AP_GPS_UAVCAN::handle_relposheading_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const RelPosHeadingCb &cb)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(_sem_registry);
|
||||||
|
AP_GPS_UAVCAN* driver = get_uavcan_backend(ap_uavcan, node_id);
|
||||||
|
if (driver != nullptr) {
|
||||||
|
driver->handle_relposheading_msg(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Consume new data and mark it received
|
// Consume new data and mark it received
|
||||||
bool AP_GPS_UAVCAN::read(void)
|
bool AP_GPS_UAVCAN::read(void)
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <AP_HAL/AP_HAL.h>
|
#include <AP_HAL/AP_HAL.h>
|
||||||
#include "AP_GPS.h"
|
#include "AP_GPS.h"
|
||||||
#include "GPS_Backend.h"
|
#include "GPS_Backend.h"
|
||||||
|
#include "RTCM3_Parser.h"
|
||||||
#include <AP_UAVCAN/AP_UAVCAN.h>
|
#include <AP_UAVCAN/AP_UAVCAN.h>
|
||||||
|
|
||||||
class FixCb;
|
class FixCb;
|
||||||
@ -30,10 +30,14 @@ class Fix2Cb;
|
|||||||
class AuxCb;
|
class AuxCb;
|
||||||
class HeadingCb;
|
class HeadingCb;
|
||||||
class StatusCb;
|
class StatusCb;
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
class MovingBaselineDataCb;
|
||||||
|
class RelPosHeadingCb;
|
||||||
|
#endif
|
||||||
|
|
||||||
class AP_GPS_UAVCAN : public AP_GPS_Backend {
|
class AP_GPS_UAVCAN : public AP_GPS_Backend {
|
||||||
public:
|
public:
|
||||||
AP_GPS_UAVCAN(AP_GPS &_gps, AP_GPS::GPS_State &_state);
|
AP_GPS_UAVCAN(AP_GPS &_gps, AP_GPS::GPS_State &_state, AP_GPS::GPS_Role role);
|
||||||
~AP_GPS_UAVCAN();
|
~AP_GPS_UAVCAN();
|
||||||
|
|
||||||
bool read() override;
|
bool read() override;
|
||||||
@ -54,12 +58,19 @@ public:
|
|||||||
static void handle_aux_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const AuxCb &cb);
|
static void handle_aux_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const AuxCb &cb);
|
||||||
static void handle_heading_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const HeadingCb &cb);
|
static void handle_heading_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const HeadingCb &cb);
|
||||||
static void handle_status_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const StatusCb &cb);
|
static void handle_status_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const StatusCb &cb);
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
static void handle_moving_baseline_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const MovingBaselineDataCb &cb);
|
||||||
|
static void handle_relposheading_msg_trampoline(AP_UAVCAN* ap_uavcan, uint8_t node_id, const RelPosHeadingCb &cb);
|
||||||
|
#endif
|
||||||
static bool backends_healthy(char failure_msg[], uint16_t failure_msg_len);
|
static bool backends_healthy(char failure_msg[], uint16_t failure_msg_len);
|
||||||
void inject_data(const uint8_t *data, uint16_t len) override;
|
void inject_data(const uint8_t *data, uint16_t len) override;
|
||||||
|
|
||||||
bool get_error_codes(uint32_t &error_codes) const override { error_codes = error_code; return seen_status; };
|
bool get_error_codes(uint32_t &error_codes) const override { error_codes = error_code; return seen_status; };
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
bool get_RTCMV3(const uint8_t *&data, uint16_t &len) override;
|
||||||
|
void clear_RTCMV3() override;
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
void handle_fix_msg(const FixCb &cb);
|
void handle_fix_msg(const FixCb &cb);
|
||||||
void handle_fix2_msg(const Fix2Cb &cb);
|
void handle_fix2_msg(const Fix2Cb &cb);
|
||||||
@ -67,6 +78,11 @@ private:
|
|||||||
void handle_heading_msg(const HeadingCb &cb);
|
void handle_heading_msg(const HeadingCb &cb);
|
||||||
void handle_status_msg(const StatusCb &cb);
|
void handle_status_msg(const StatusCb &cb);
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
void handle_moving_baseline_msg(const MovingBaselineDataCb &cb);
|
||||||
|
void handle_relposheading_msg(const RelPosHeadingCb &cb);
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool take_registry();
|
static bool take_registry();
|
||||||
static void give_registry();
|
static void give_registry();
|
||||||
static AP_GPS_UAVCAN* get_uavcan_backend(AP_UAVCAN* ap_uavcan, uint8_t node_id);
|
static AP_GPS_UAVCAN* get_uavcan_backend(AP_UAVCAN* ap_uavcan, uint8_t node_id);
|
||||||
@ -96,4 +112,12 @@ private:
|
|||||||
} _detected_modules[GPS_MAX_RECEIVERS];
|
} _detected_modules[GPS_MAX_RECEIVERS];
|
||||||
|
|
||||||
static HAL_Semaphore _sem_registry;
|
static HAL_Semaphore _sem_registry;
|
||||||
|
|
||||||
|
#if GPS_MOVING_BASELINE
|
||||||
|
// RTCM3 parser for when in moving baseline base mode
|
||||||
|
RTCM3_Parser *rtcm3_parser;
|
||||||
|
#endif
|
||||||
|
// the role set from GPS_TYPE
|
||||||
|
AP_GPS::GPS_Role role;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -50,13 +50,27 @@
|
|||||||
extern const AP_HAL::HAL& hal;
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
#if UBLOX_DEBUGGING
|
#if UBLOX_DEBUGGING
|
||||||
|
#if defined(HAL_BUILD_AP_PERIPH)
|
||||||
|
extern "C" {
|
||||||
|
void can_printf(const char *fmt, ...);
|
||||||
|
}
|
||||||
|
# define Debug(fmt, args ...) do {can_printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args);} while(0)
|
||||||
|
#else
|
||||||
# define Debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); hal.scheduler->delay(1); } while(0)
|
# define Debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); hal.scheduler->delay(1); } while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
# define Debug(fmt, args ...)
|
# define Debug(fmt, args ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UBLOX_MB_DEBUGGING
|
#if UBLOX_MB_DEBUGGING
|
||||||
|
#if defined(HAL_BUILD_AP_PERIPH)
|
||||||
|
extern "C" {
|
||||||
|
void can_printf(const char *fmt, ...);
|
||||||
|
}
|
||||||
|
# define MB_Debug(fmt, args ...) do {can_printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args);} while(0)
|
||||||
|
#else
|
||||||
# define MB_Debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); hal.scheduler->delay(1); } while(0)
|
# define MB_Debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); hal.scheduler->delay(1); } while(0)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
# define MB_Debug(fmt, args ...)
|
# define MB_Debug(fmt, args ...)
|
||||||
#endif
|
#endif
|
||||||
@ -1353,15 +1367,21 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
MB_Debug("RELPOSNED ITOW %u %u\n", unsigned(_buffer.relposned.iTOW), unsigned(_last_relposned_itow));
|
MB_Debug("RELPOSNED ITOW %u %u\n", unsigned(_buffer.relposned.iTOW), unsigned(_last_relposned_itow));
|
||||||
}
|
}
|
||||||
_last_relposned_itow = _buffer.relposned.iTOW;
|
_last_relposned_itow = _buffer.relposned.iTOW;
|
||||||
|
MB_Debug("RELPOSNED flags: %lx valid: %lx invalid: %lx\n", _buffer.relposned.flags, valid_mask, invalid_mask);
|
||||||
if (((_buffer.relposned.flags & valid_mask) == valid_mask) &&
|
if (((_buffer.relposned.flags & valid_mask) == valid_mask) &&
|
||||||
((_buffer.relposned.flags & invalid_mask) == 0) &&
|
((_buffer.relposned.flags & invalid_mask) == 0)) {
|
||||||
calculate_moving_base_yaw(_buffer.relposned.relPosHeading * 1e-5,
|
if (calculate_moving_base_yaw(_buffer.relposned.relPosHeading * 1e-5,
|
||||||
_buffer.relposned.relPosLength * 0.01,
|
_buffer.relposned.relPosLength * 0.01,
|
||||||
_buffer.relposned.relPosD*0.01)) {
|
_buffer.relposned.relPosD*0.01)) {
|
||||||
state.gps_yaw_accuracy = _buffer.relposned.accHeading * 1e-5;
|
state.have_gps_yaw_accuracy = true;
|
||||||
state.have_gps_yaw_accuracy = true;
|
state.gps_yaw_accuracy = _buffer.relposned.accHeading * 1e-5;
|
||||||
_last_relposned_ms = AP_HAL::millis();
|
_last_relposned_ms = AP_HAL::millis();
|
||||||
|
}
|
||||||
|
state.relPosHeading = _buffer.relposned.relPosHeading * 1e-5;
|
||||||
|
state.relPosLength = _buffer.relposned.relPosLength * 0.01;
|
||||||
|
state.relPosD = _buffer.relposned.relPosD * 0.01;
|
||||||
|
state.accHeading = _buffer.relposned.accHeading * 1e-5;
|
||||||
|
state.relposheading_ts = AP_HAL::millis();
|
||||||
} else {
|
} else {
|
||||||
state.have_gps_yaw_accuracy = false;
|
state.have_gps_yaw_accuracy = false;
|
||||||
}
|
}
|
||||||
|
@ -302,20 +302,23 @@ void AP_GPS_Backend::check_new_itow(uint32_t itow, uint32_t msg_length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if GPS_MOVING_BASELINE
|
#if GPS_MOVING_BASELINE
|
||||||
bool AP_GPS_Backend::calculate_moving_base_yaw(const float reported_heading_deg, const float reported_distance, const float reported_D)
|
bool AP_GPS_Backend::calculate_moving_base_yaw(float reported_heading_deg, const float reported_distance, const float reported_D) {
|
||||||
{
|
return calculate_moving_base_yaw(state, reported_heading_deg, reported_distance, reported_D);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_GPS_Backend::calculate_moving_base_yaw(AP_GPS::GPS_State &interim_state, const float reported_heading_deg, const float reported_distance, const float reported_D) {
|
||||||
constexpr float minimum_antenna_seperation = 0.05; // meters
|
constexpr float minimum_antenna_seperation = 0.05; // meters
|
||||||
constexpr float permitted_error_length_pct = 0.2; // percentage
|
constexpr float permitted_error_length_pct = 0.2; // percentage
|
||||||
|
|
||||||
bool selectedOffset = false;
|
bool selectedOffset = false;
|
||||||
Vector3f offset;
|
Vector3f offset;
|
||||||
switch (MovingBase::Type(gps.mb_params[state.instance].type.get())) {
|
switch (MovingBase::Type(gps.mb_params[interim_state.instance].type.get())) {
|
||||||
case MovingBase::Type::RelativeToAlternateInstance:
|
case MovingBase::Type::RelativeToAlternateInstance:
|
||||||
offset = gps._antenna_offset[state.instance^1].get() - gps._antenna_offset[state.instance].get();
|
offset = gps._antenna_offset[interim_state.instance^1].get() - gps._antenna_offset[interim_state.instance].get();
|
||||||
selectedOffset = true;
|
selectedOffset = true;
|
||||||
break;
|
break;
|
||||||
case MovingBase::Type::RelativeToCustomBase:
|
case MovingBase::Type::RelativeToCustomBase:
|
||||||
offset = gps.mb_params[state.instance].base_offset.get();
|
offset = gps.mb_params[interim_state.instance].base_offset.get();
|
||||||
selectedOffset = true;
|
selectedOffset = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -385,13 +388,16 @@ bool AP_GPS_Backend::calculate_moving_base_yaw(const float reported_heading_deg,
|
|||||||
state.gps_yaw = wrap_360(reported_heading_deg - degrees(rotation_offset_rad));
|
state.gps_yaw = wrap_360(reported_heading_deg - degrees(rotation_offset_rad));
|
||||||
state.have_gps_yaw = true;
|
state.have_gps_yaw = true;
|
||||||
state.gps_yaw_time_ms = AP_HAL::millis();
|
state.gps_yaw_time_ms = AP_HAL::millis();
|
||||||
|
interim_state.gps_yaw = state.gps_yaw;
|
||||||
|
interim_state.have_gps_yaw = state.have_gps_yaw;
|
||||||
|
interim_state.gps_yaw_time_ms = AP_HAL::millis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bad_yaw:
|
bad_yaw:
|
||||||
state.have_gps_yaw = false;
|
interim_state.have_gps_yaw = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // GPS_MOVING_BASELINE
|
#endif // GPS_MOVING_BASELINE
|
||||||
|
@ -131,6 +131,7 @@ protected:
|
|||||||
|
|
||||||
#if GPS_MOVING_BASELINE
|
#if GPS_MOVING_BASELINE
|
||||||
bool calculate_moving_base_yaw(const float reported_heading_deg, const float reported_distance, const float reported_D);
|
bool calculate_moving_base_yaw(const float reported_heading_deg, const float reported_distance, const float reported_D);
|
||||||
|
bool calculate_moving_base_yaw(AP_GPS::GPS_State &interim_state, const float reported_heading_deg, const float reported_distance, const float reported_D);
|
||||||
#endif //GPS_MOVING_BASELINE
|
#endif //GPS_MOVING_BASELINE
|
||||||
|
|
||||||
// get GPS type, for subtype config
|
// get GPS type, for subtype config
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
RTCMv3 parser, used to support moving baseline RTK mode between two
|
RTCMv3 parser, used to support moving baseline RTK mode between two
|
||||||
GPS modules
|
GPS modules
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define RTCM3_MAX_PACKET_LEN 300
|
||||||
class RTCM3_Parser {
|
class RTCM3_Parser {
|
||||||
public:
|
public:
|
||||||
// process one byte, return true if packet found
|
// process one byte, return true if packet found
|
||||||
@ -40,7 +41,7 @@ private:
|
|||||||
const uint8_t RTCMv3_PREAMBLE = 0xD3;
|
const uint8_t RTCMv3_PREAMBLE = 0xD3;
|
||||||
|
|
||||||
// raw packet, we shouldn't need over 300 bytes for the MB configs we use
|
// raw packet, we shouldn't need over 300 bytes for the MB configs we use
|
||||||
uint8_t pkt[300];
|
uint8_t pkt[RTCM3_MAX_PACKET_LEN];
|
||||||
|
|
||||||
// number of bytes in pkt[]
|
// number of bytes in pkt[]
|
||||||
uint16_t pkt_bytes;
|
uint16_t pkt_bytes;
|
||||||
|
Loading…
Reference in New Issue
Block a user