AP_GPS: make GPS packet timestamps more accurate
this reduces the effect of processing time and uart transmit time
This commit is contained in:
parent
62c26ec5ff
commit
3fe4b9c0f8
@ -603,7 +603,7 @@ void AP_GPS::update_instance(uint8_t instance)
|
|||||||
|
|
||||||
// we have an active driver for this instance
|
// we have an active driver for this instance
|
||||||
bool result = drivers[instance]->read();
|
bool result = drivers[instance]->read();
|
||||||
const uint32_t tnow = AP_HAL::millis();
|
uint32_t tnow = AP_HAL::millis();
|
||||||
|
|
||||||
// if we did not get a message, and the idle timer of 2 seconds
|
// if we did not get a message, and the idle timer of 2 seconds
|
||||||
// has expired, re-initialise the GPS. This will cause GPS
|
// has expired, re-initialise the GPS. This will cause GPS
|
||||||
@ -632,6 +632,12 @@ void AP_GPS::update_instance(uint8_t instance)
|
|||||||
data_should_be_logged = true;
|
data_should_be_logged = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (state[instance].uart_timestamp_ms != 0) {
|
||||||
|
// set the timestamp for this messages based on
|
||||||
|
// set_uart_timestamp() in backend, if available
|
||||||
|
tnow = state[instance].uart_timestamp_ms;
|
||||||
|
state[instance].uart_timestamp_ms = 0;
|
||||||
|
}
|
||||||
// delta will only be correct after parsing two messages
|
// delta will only be correct after parsing two messages
|
||||||
timing[instance].delta_time_ms = tnow - timing[instance].last_message_time_ms;
|
timing[instance].delta_time_ms = tnow - timing[instance].last_message_time_ms;
|
||||||
timing[instance].last_message_time_ms = tnow;
|
timing[instance].last_message_time_ms = tnow;
|
||||||
|
@ -148,6 +148,7 @@ public:
|
|||||||
bool have_horizontal_accuracy; ///< does GPS give horizontal position accuracy? Set to true only once available.
|
bool have_horizontal_accuracy; ///< does GPS give horizontal position accuracy? Set to true only once available.
|
||||||
bool have_vertical_accuracy; ///< does GPS give vertical position accuracy? Set to true only once available.
|
bool have_vertical_accuracy; ///< does GPS give vertical position accuracy? Set to true only once available.
|
||||||
uint32_t last_gps_time_ms; ///< the system time we got the last GPS timestamp, milliseconds
|
uint32_t last_gps_time_ms; ///< the system time we got the last GPS timestamp, milliseconds
|
||||||
|
uint32_t uart_timestamp_ms; ///< optional timestamp from set_uart_timestamp()
|
||||||
|
|
||||||
// all the following fields must only all be filled by RTK capable backend drivers
|
// all the following fields must only all be filled by RTK capable backend drivers
|
||||||
uint32_t rtk_time_week_ms; ///< GPS Time of Week of last baseline in milliseconds
|
uint32_t rtk_time_week_ms; ///< GPS Time of Week of last baseline in milliseconds
|
||||||
|
@ -178,6 +178,8 @@ AP_GPS_ERB::_parse_gps(void)
|
|||||||
}
|
}
|
||||||
state.num_sats = _buffer.stat.satellites;
|
state.num_sats = _buffer.stat.satellites;
|
||||||
if (next_fix >= AP_GPS::GPS_OK_FIX_3D) {
|
if (next_fix >= AP_GPS::GPS_OK_FIX_3D) {
|
||||||
|
// use the uart receive time to make packet timestamps more accurate
|
||||||
|
set_uart_timestamp(_payload_length + sizeof(erb_header) + 2);
|
||||||
state.last_gps_time_ms = AP_HAL::millis();
|
state.last_gps_time_ms = AP_HAL::millis();
|
||||||
state.time_week_ms = _buffer.stat.time;
|
state.time_week_ms = _buffer.stat.time;
|
||||||
state.time_week = _buffer.stat.week;
|
state.time_week = _buffer.stat.week;
|
||||||
|
@ -99,6 +99,7 @@ bool AP_GPS_NMEA::_decode(char c)
|
|||||||
++_term_number;
|
++_term_number;
|
||||||
_term_offset = 0;
|
_term_offset = 0;
|
||||||
_is_checksum_term = c == '*';
|
_is_checksum_term = c == '*';
|
||||||
|
_sentence_length++;
|
||||||
return valid_sentence;
|
return valid_sentence;
|
||||||
|
|
||||||
case '$': // sentence begin
|
case '$': // sentence begin
|
||||||
@ -107,6 +108,7 @@ bool AP_GPS_NMEA::_decode(char c)
|
|||||||
_sentence_type = _GPS_SENTENCE_OTHER;
|
_sentence_type = _GPS_SENTENCE_OTHER;
|
||||||
_is_checksum_term = false;
|
_is_checksum_term = false;
|
||||||
_gps_data_good = false;
|
_gps_data_good = false;
|
||||||
|
_sentence_length = 0;
|
||||||
return valid_sentence;
|
return valid_sentence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +118,8 @@ bool AP_GPS_NMEA::_decode(char c)
|
|||||||
if (!_is_checksum_term)
|
if (!_is_checksum_term)
|
||||||
_parity ^= c;
|
_parity ^= c;
|
||||||
|
|
||||||
|
_sentence_length++;
|
||||||
|
|
||||||
return valid_sentence;
|
return valid_sentence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +256,7 @@ bool AP_GPS_NMEA::_term_complete()
|
|||||||
state.ground_speed = _new_speed*0.01f;
|
state.ground_speed = _new_speed*0.01f;
|
||||||
state.ground_course = wrap_360(_new_course*0.01f);
|
state.ground_course = wrap_360(_new_course*0.01f);
|
||||||
make_gps_time(_new_date, _new_time * 10);
|
make_gps_time(_new_date, _new_time * 10);
|
||||||
|
set_uart_timestamp(_sentence_length);
|
||||||
state.last_gps_time_ms = now;
|
state.last_gps_time_ms = now;
|
||||||
fill_3d_velocity();
|
fill_3d_velocity();
|
||||||
break;
|
break;
|
||||||
|
@ -125,6 +125,7 @@ private:
|
|||||||
uint8_t _sentence_type; ///< the sentence type currently being processed
|
uint8_t _sentence_type; ///< the sentence type currently being processed
|
||||||
uint8_t _term_number; ///< term index within the current sentence
|
uint8_t _term_number; ///< term index within the current sentence
|
||||||
uint8_t _term_offset; ///< character offset with the term being received
|
uint8_t _term_offset; ///< character offset with the term being received
|
||||||
|
uint16_t _sentence_length;
|
||||||
bool _gps_data_good; ///< set when the sentence indicates data is good
|
bool _gps_data_good; ///< set when the sentence indicates data is good
|
||||||
|
|
||||||
// The result of parsing terms within a message is stored temporarily until
|
// The result of parsing terms within a message is stored temporarily until
|
||||||
|
@ -284,6 +284,7 @@ AP_GPS_SBF::process_message(void)
|
|||||||
state.time_week_ms = (uint32_t)(temp.TOW);
|
state.time_week_ms = (uint32_t)(temp.TOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_uart_timestamp(sbf_msg.length);
|
||||||
state.last_gps_time_ms = AP_HAL::millis();
|
state.last_gps_time_ms = AP_HAL::millis();
|
||||||
|
|
||||||
// Update velocity state (don't use −2·10^10)
|
// Update velocity state (don't use −2·10^10)
|
||||||
|
@ -288,6 +288,7 @@ AP_GPS_SBP2::_attempt_state_update()
|
|||||||
state.time_week_ms = last_vel_ned.tow;
|
state.time_week_ms = last_vel_ned.tow;
|
||||||
state.hdop = last_dops.hdop;
|
state.hdop = last_dops.hdop;
|
||||||
state.vdop = last_dops.vdop;
|
state.vdop = last_dops.vdop;
|
||||||
|
set_uart_timestamp(parser_state.msg_len);
|
||||||
state.last_gps_time_ms = now;
|
state.last_gps_time_ms = now;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -833,7 +833,8 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
_unconfigured_messages |= CONFIG_RATE_POSLLH;
|
_unconfigured_messages |= CONFIG_RATE_POSLLH;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_last_pos_time = _buffer.posllh.time;
|
_check_new_itow(_buffer.posllh.itow);
|
||||||
|
_last_pos_time = _buffer.posllh.itow;
|
||||||
state.location.lng = _buffer.posllh.longitude;
|
state.location.lng = _buffer.posllh.longitude;
|
||||||
state.location.lat = _buffer.posllh.latitude;
|
state.location.lat = _buffer.posllh.latitude;
|
||||||
state.location.alt = _buffer.posllh.altitude_msl / 10;
|
state.location.alt = _buffer.posllh.altitude_msl / 10;
|
||||||
@ -883,6 +884,7 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
case MSG_DOP:
|
case MSG_DOP:
|
||||||
Debug("MSG_DOP");
|
Debug("MSG_DOP");
|
||||||
noReceivedHdop = false;
|
noReceivedHdop = false;
|
||||||
|
_check_new_itow(_buffer.dop.itow);
|
||||||
state.hdop = _buffer.dop.hDOP;
|
state.hdop = _buffer.dop.hDOP;
|
||||||
state.vdop = _buffer.dop.vDOP;
|
state.vdop = _buffer.dop.vDOP;
|
||||||
#if UBLOX_FAKE_3DLOCK
|
#if UBLOX_FAKE_3DLOCK
|
||||||
@ -894,6 +896,7 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
Debug("MSG_SOL fix_status=%u fix_type=%u",
|
Debug("MSG_SOL fix_status=%u fix_type=%u",
|
||||||
_buffer.solution.fix_status,
|
_buffer.solution.fix_status,
|
||||||
_buffer.solution.fix_type);
|
_buffer.solution.fix_type);
|
||||||
|
_check_new_itow(_buffer.solution.itow);
|
||||||
if (havePvtMsg) {
|
if (havePvtMsg) {
|
||||||
state.time_week = _buffer.solution.week;
|
state.time_week = _buffer.solution.week;
|
||||||
break;
|
break;
|
||||||
@ -920,7 +923,7 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
state.num_sats = _buffer.solution.satellites;
|
state.num_sats = _buffer.solution.satellites;
|
||||||
if (next_fix >= AP_GPS::GPS_OK_FIX_2D) {
|
if (next_fix >= AP_GPS::GPS_OK_FIX_2D) {
|
||||||
state.last_gps_time_ms = AP_HAL::millis();
|
state.last_gps_time_ms = AP_HAL::millis();
|
||||||
state.time_week_ms = _buffer.solution.time;
|
state.time_week_ms = _buffer.solution.itow;
|
||||||
state.time_week = _buffer.solution.week;
|
state.time_week = _buffer.solution.week;
|
||||||
}
|
}
|
||||||
#if UBLOX_FAKE_3DLOCK
|
#if UBLOX_FAKE_3DLOCK
|
||||||
@ -936,6 +939,7 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
Debug("MSG_PVT");
|
Debug("MSG_PVT");
|
||||||
havePvtMsg = true;
|
havePvtMsg = true;
|
||||||
// position
|
// position
|
||||||
|
_check_new_itow(_buffer.pvt.itow);
|
||||||
_last_pos_time = _buffer.pvt.itow;
|
_last_pos_time = _buffer.pvt.itow;
|
||||||
state.location.lng = _buffer.pvt.lon;
|
state.location.lng = _buffer.pvt.lon;
|
||||||
state.location.lat = _buffer.pvt.lat;
|
state.location.lat = _buffer.pvt.lat;
|
||||||
@ -1023,7 +1027,8 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
_unconfigured_messages |= CONFIG_RATE_VELNED;
|
_unconfigured_messages |= CONFIG_RATE_VELNED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_last_vel_time = _buffer.velned.time;
|
_check_new_itow(_buffer.velned.itow);
|
||||||
|
_last_vel_time = _buffer.velned.itow;
|
||||||
state.ground_speed = _buffer.velned.speed_2d*0.01f; // m/s
|
state.ground_speed = _buffer.velned.speed_2d*0.01f; // m/s
|
||||||
state.ground_course = wrap_360(_buffer.velned.heading_2d * 1.0e-5f); // Heading 2D deg * 100000
|
state.ground_course = wrap_360(_buffer.velned.heading_2d * 1.0e-5f); // Heading 2D deg * 100000
|
||||||
state.have_vertical_velocity = true;
|
state.have_vertical_velocity = true;
|
||||||
@ -1043,6 +1048,7 @@ AP_GPS_UBLOX::_parse_gps(void)
|
|||||||
{
|
{
|
||||||
Debug("MSG_NAV_SVINFO\n");
|
Debug("MSG_NAV_SVINFO\n");
|
||||||
static const uint8_t HardwareGenerationMask = 0x07;
|
static const uint8_t HardwareGenerationMask = 0x07;
|
||||||
|
_check_new_itow(_buffer.svinfo_header.itow);
|
||||||
_hardware_generation = _buffer.svinfo_header.globalFlags & HardwareGenerationMask;
|
_hardware_generation = _buffer.svinfo_header.globalFlags & HardwareGenerationMask;
|
||||||
switch (_hardware_generation) {
|
switch (_hardware_generation) {
|
||||||
case UBLOX_5:
|
case UBLOX_5:
|
||||||
@ -1329,3 +1335,11 @@ void AP_GPS_UBLOX::Write_DataFlash_Log_Startup_messages() const
|
|||||||
_version.swVersion);
|
_version.swVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AP_GPS_UBLOX::_check_new_itow(uint32_t itow)
|
||||||
|
{
|
||||||
|
if (itow != _last_itow) {
|
||||||
|
_last_itow = itow;
|
||||||
|
set_uart_timestamp(_payload_length + sizeof(ubx_header) + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -193,7 +193,7 @@ private:
|
|||||||
uint32_t scanmode1;
|
uint32_t scanmode1;
|
||||||
};
|
};
|
||||||
struct PACKED ubx_nav_posllh {
|
struct PACKED ubx_nav_posllh {
|
||||||
uint32_t time; // GPS msToW
|
uint32_t itow; // GPS msToW
|
||||||
int32_t longitude;
|
int32_t longitude;
|
||||||
int32_t latitude;
|
int32_t latitude;
|
||||||
int32_t altitude_ellipsoid;
|
int32_t altitude_ellipsoid;
|
||||||
@ -202,7 +202,7 @@ private:
|
|||||||
uint32_t vertical_accuracy;
|
uint32_t vertical_accuracy;
|
||||||
};
|
};
|
||||||
struct PACKED ubx_nav_status {
|
struct PACKED ubx_nav_status {
|
||||||
uint32_t time; // GPS msToW
|
uint32_t itow; // GPS msToW
|
||||||
uint8_t fix_type;
|
uint8_t fix_type;
|
||||||
uint8_t fix_status;
|
uint8_t fix_status;
|
||||||
uint8_t differential_status;
|
uint8_t differential_status;
|
||||||
@ -211,7 +211,7 @@ private:
|
|||||||
uint32_t uptime; // milliseconds
|
uint32_t uptime; // milliseconds
|
||||||
};
|
};
|
||||||
struct PACKED ubx_nav_dop {
|
struct PACKED ubx_nav_dop {
|
||||||
uint32_t time; // GPS msToW
|
uint32_t itow; // GPS msToW
|
||||||
uint16_t gDOP;
|
uint16_t gDOP;
|
||||||
uint16_t pDOP;
|
uint16_t pDOP;
|
||||||
uint16_t tDOP;
|
uint16_t tDOP;
|
||||||
@ -221,7 +221,7 @@ private:
|
|||||||
uint16_t eDOP;
|
uint16_t eDOP;
|
||||||
};
|
};
|
||||||
struct PACKED ubx_nav_solution {
|
struct PACKED ubx_nav_solution {
|
||||||
uint32_t time;
|
uint32_t itow;
|
||||||
int32_t time_nsec;
|
int32_t time_nsec;
|
||||||
uint16_t week;
|
uint16_t week;
|
||||||
uint8_t fix_type;
|
uint8_t fix_type;
|
||||||
@ -263,7 +263,7 @@ private:
|
|||||||
uint8_t reserved2[4];
|
uint8_t reserved2[4];
|
||||||
};
|
};
|
||||||
struct PACKED ubx_nav_velned {
|
struct PACKED ubx_nav_velned {
|
||||||
uint32_t time; // GPS msToW
|
uint32_t itow; // GPS msToW
|
||||||
int32_t ned_north;
|
int32_t ned_north;
|
||||||
int32_t ned_east;
|
int32_t ned_east;
|
||||||
int32_t ned_down;
|
int32_t ned_down;
|
||||||
@ -549,6 +549,9 @@ private:
|
|||||||
|
|
||||||
bool havePvtMsg;
|
bool havePvtMsg;
|
||||||
|
|
||||||
|
// itow from previous message
|
||||||
|
uint32_t _last_itow;
|
||||||
|
|
||||||
bool _configure_message_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate);
|
bool _configure_message_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate);
|
||||||
void _configure_rate(void);
|
void _configure_rate(void);
|
||||||
void _configure_sbas(bool enable);
|
void _configure_sbas(bool enable);
|
||||||
@ -561,6 +564,7 @@ private:
|
|||||||
void _request_version(void);
|
void _request_version(void);
|
||||||
void _save_cfg(void);
|
void _save_cfg(void);
|
||||||
void _verify_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate);
|
void _verify_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate);
|
||||||
|
void _check_new_itow(uint32_t itow);
|
||||||
|
|
||||||
void unexpected_message(void);
|
void unexpected_message(void);
|
||||||
void log_mon_hw(void);
|
void log_mon_hw(void);
|
||||||
|
@ -216,3 +216,14 @@ void AP_GPS_Backend::send_mavlink_gps_rtk(mavlink_channel_t chan)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
set a timestamp based on arrival time on uart at current byte,
|
||||||
|
assuming the message started nbytes ago
|
||||||
|
*/
|
||||||
|
void AP_GPS_Backend::set_uart_timestamp(uint16_t nbytes)
|
||||||
|
{
|
||||||
|
if (port) {
|
||||||
|
state.uart_timestamp_ms = port->receive_time_constraint_us(nbytes) / 1000U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -87,4 +87,10 @@ protected:
|
|||||||
void _detection_message(char *buffer, uint8_t buflen) const;
|
void _detection_message(char *buffer, uint8_t buflen) const;
|
||||||
|
|
||||||
bool should_df_log() const;
|
bool should_df_log() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
set a timestamp based on arrival time on uart at current byte,
|
||||||
|
assuming the message started nbytes ago
|
||||||
|
*/
|
||||||
|
void set_uart_timestamp(uint16_t nbytes);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user