48 #include <mathlib/mathlib.h> 67 int res =
_pub_fix2.init(uavcan::TransferPriority::MiddleLower);
70 PX4_WARN(
"GNSS fix2 pub failed %i", res);
77 PX4_WARN(
"GNSS auxiliary sub failed %i", res);
84 PX4_WARN(
"GNSS fix sub failed %i", res);
91 PX4_WARN(
"GNSS fix2 sub failed %i", res);
109 printf(
"RX errors: %d, using old Fix: %d, receiver node id: ",
132 const bool valid_pos_cov = !msg.position_covariance.empty();
133 const bool valid_vel_cov = !msg.velocity_covariance.empty();
136 msg.position_covariance.unpackSquareMatrix(pos_cov);
139 msg.velocity_covariance.unpackSquareMatrix(vel_cov);
141 process_fixx(msg, pos_cov, vel_cov, valid_pos_cov, valid_vel_cov);
148 PX4_INFO(
"GNSS Fix2 message detected, disabling support for the old Fix message");
156 bool valid_covariances =
true;
158 switch (msg.covariance.size()) {
161 const auto x = msg.covariance[0];
175 pos_cov[0] = msg.covariance[0];
176 pos_cov[4] = msg.covariance[1];
177 pos_cov[8] = msg.covariance[2];
179 vel_cov[0] = msg.covariance[3];
180 vel_cov[4] = msg.covariance[4];
181 vel_cov[8] = msg.covariance[5];
197 pos_cov[0] = msg.covariance[0];
198 pos_cov[1] = msg.covariance[1];
199 pos_cov[2] = msg.covariance[2];
200 pos_cov[3] = msg.covariance[1];
201 pos_cov[4] = msg.covariance[6];
202 pos_cov[5] = msg.covariance[7];
203 pos_cov[6] = msg.covariance[2];
204 pos_cov[7] = msg.covariance[7];
205 pos_cov[8] = msg.covariance[11];
207 vel_cov[0] = msg.covariance[15];
208 vel_cov[1] = msg.covariance[16];
209 vel_cov[2] = msg.covariance[17];
210 vel_cov[3] = msg.covariance[16];
211 vel_cov[4] = msg.covariance[18];
212 vel_cov[5] = msg.covariance[19];
213 vel_cov[6] = msg.covariance[17];
214 vel_cov[7] = msg.covariance[19];
215 vel_cov[8] = msg.covariance[20];
229 pos_cov[0] = msg.covariance[0];
230 pos_cov[1] = msg.covariance[1];
231 pos_cov[2] = msg.covariance[2];
232 pos_cov[3] = msg.covariance[6];
233 pos_cov[4] = msg.covariance[7];
234 pos_cov[5] = msg.covariance[8];
235 pos_cov[6] = msg.covariance[12];
236 pos_cov[7] = msg.covariance[13];
237 pos_cov[8] = msg.covariance[14];
239 vel_cov[0] = msg.covariance[21];
240 vel_cov[1] = msg.covariance[22];
241 vel_cov[2] = msg.covariance[23];
242 vel_cov[3] = msg.covariance[27];
243 vel_cov[4] = msg.covariance[28];
244 vel_cov[5] = msg.covariance[29];
245 vel_cov[6] = msg.covariance[33];
246 vel_cov[7] = msg.covariance[34];
247 vel_cov[8] = msg.covariance[35];
253 valid_covariances =
false;
258 process_fixx(msg, pos_cov, vel_cov, valid_covariances, valid_covariances);
261 template <
typename FixType>
263 const float (&pos_cov)[9],
const float (&vel_cov)[9],
264 const bool valid_pos_cov,
const bool valid_vel_cov)
289 report.lat = msg.latitude_deg_1e8 / 10;
290 report.lon = msg.longitude_deg_1e8 / 10;
291 report.alt = msg.height_msl_mm;
292 report.alt_ellipsoid = msg.height_ellipsoid_mm;
296 const float horizontal_pos_variance =
math::max(pos_cov[0], pos_cov[4]);
297 report.eph = (horizontal_pos_variance > 0) ? sqrtf(horizontal_pos_variance) : -1.0F;
300 report.epv = (pos_cov[8] > 0) ? sqrtf(pos_cov[8]) : -1.0F;
320 float vel_n = msg.ned_velocity[0];
321 float vel_e = msg.ned_velocity[1];
322 float vel_n_sq = vel_n * vel_n;
323 float vel_e_sq = vel_e * vel_e;
324 report.c_variance_rad =
325 (vel_e_sq * vel_cov[0] +
326 -2 * vel_n * vel_e * vel_cov[1] +
327 vel_n_sq * vel_cov[4]) / ((vel_n_sq + vel_e_sq) * (vel_n_sq + vel_e_sq));
330 report.s_variance_m_s = -1.0F;
331 report.c_variance_rad = -1.0F;
334 report.fix_type = msg.status;
336 report.vel_n_m_s = msg.ned_velocity[0];
337 report.vel_e_m_s = msg.ned_velocity[1];
338 report.vel_d_m_s = msg.ned_velocity[2];
339 report.vel_m_s = sqrtf(report.vel_n_m_s * report.vel_n_m_s +
340 report.vel_e_m_s * report.vel_e_m_s +
341 report.vel_d_m_s * report.vel_d_m_s);
342 report.cog_rad = atan2f(report.vel_e_m_s, report.vel_n_m_s);
343 report.vel_ned_valid =
true;
345 report.timestamp_time_relative = 0;
347 const uint64_t gnss_ts_usec = uavcan::UtcTime(msg.gnss_timestamp).toUSec();
349 switch (msg.gnss_time_standard) {
350 case FixType::GNSS_TIME_STANDARD_UTC:
351 report.time_utc_usec = gnss_ts_usec;
354 case FixType::GNSS_TIME_STANDARD_GPS:
355 if (msg.num_leap_seconds > 0) {
356 report.time_utc_usec = gnss_ts_usec - msg.num_leap_seconds + 9;
361 case FixType::GNSS_TIME_STANDARD_TAI:
362 if (msg.num_leap_seconds > 0) {
363 report.time_utc_usec = gnss_ts_usec - msg.num_leap_seconds - 10;
377 ts.tv_sec = report.time_utc_usec / 1000000ULL;
380 ts.tv_nsec = (report.time_utc_usec % 1000000ULL) * 1000;
382 px4_clock_settime(CLOCK_REALTIME, &ts);
387 report.satellites_used = msg.sats_used;
396 report.hdop = msg.pdop;
397 report.vdop = msg.pdop;
400 report.heading = NAN;
401 report.heading_offset = NAN;
409 PX4_INFO(
"GNSS ORB->UAVCAN bridge stopped, because there are other GNSS publishers");
423 using uavcan::equipment::gnss::Fix2;
426 msg.gnss_timestamp = uavcan::UtcTime::fromUSec(orb_msg.time_utc_usec);
427 msg.gnss_time_standard = Fix2::GNSS_TIME_STANDARD_UTC;
429 msg.longitude_deg_1e8 = std::int64_t(orb_msg.lon) * 10LL;
430 msg.latitude_deg_1e8 = std::int64_t(orb_msg.lat) * 10LL;
431 msg.height_ellipsoid_mm = orb_msg.alt_ellipsoid;
432 msg.height_msl_mm = orb_msg.alt;
434 msg.ned_velocity[0] = orb_msg.vel_n_m_s;
435 msg.ned_velocity[1] = orb_msg.vel_e_m_s;
436 msg.ned_velocity[2] = orb_msg.vel_d_m_s;
438 msg.sats_used = orb_msg.satellites_used;
439 msg.status = orb_msg.fix_type;
444 msg.covariance.resize(2, orb_msg.eph * orb_msg.eph);
445 msg.covariance.resize(3, orb_msg.epv * orb_msg.epv);
446 msg.covariance.resize(6, orb_msg.s_variance_m_s * orb_msg.s_variance_m_s);
448 msg.pdop = (orb_msg.hdop > orb_msg.vdop) ? orb_msg.hdop : orb_msg.vdop;
void gnss_fix2_sub_cb(const uavcan::ReceivedDataStructure< uavcan::equipment::gnss::Fix2 > &msg)
int init() override
Starts the bridge.
bool _old_fix_subscriber_active
uavcan::MethodBinder< UavcanGnssBridge *, void(UavcanGnssBridge::*)(const uavcan::ReceivedDataStructure< uavcan::equipment::gnss::Auxiliary > &) > AuxiliaryCbBinder
uavcan::Publisher< uavcan::equipment::gnss::Fix2 > _pub_fix2
bool _system_clock_set
Have we set the system clock at least once from GNSS data?
static constexpr unsigned ORB_TO_UAVCAN_FREQUENCY_HZ
UavcanGnssBridge(uavcan::INode &node)
High-resolution timer with callouts and timekeeping.
uORB::Subscription _orb_sub_gnss
uavcan::TimerEventForwarder< TimerCbBinder > _orb_to_uavcan_pub_timer
void broadcast_from_orb(const uavcan::TimerEvent &)
uavcan::MethodBinder< UavcanGnssBridge *, void(UavcanGnssBridge::*)(const uavcan::TimerEvent &)> TimerCbBinder
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
uORB::PublicationMulti< vehicle_gps_position_s > _gps_pub
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
void gnss_fix_sub_cb(const uavcan::ReceivedDataStructure< uavcan::equipment::gnss::Fix > &msg)
uavcan::MethodBinder< UavcanGnssBridge *, void(UavcanGnssBridge::*)(const uavcan::ReceivedDataStructure< uavcan::equipment::gnss::Fix > &) > FixCbBinder
uavcan::Subscriber< uavcan::equipment::gnss::Fix, FixCbBinder > _sub_fix
UAVCAN <–> ORB bridge for GNSS messages: uavcan.equipment.gnss.Fix (deprecated, but still supported ...
uavcan::MethodBinder< UavcanGnssBridge *, void(UavcanGnssBridge::*)(const uavcan::ReceivedDataStructure< uavcan::equipment::gnss::Fix2 > &) > Fix2CbBinder
unsigned get_num_redundant_channels() const override
Returns number of active redundancy channels.
uavcan::Subscriber< uavcan::equipment::gnss::Fix2, Fix2CbBinder > _sub_fix2
void gnss_auxiliary_sub_cb(const uavcan::ReceivedDataStructure< uavcan::equipment::gnss::Auxiliary > &msg)
GNSS fix message will be reported via this callback.
uavcan::Subscriber< uavcan::equipment::gnss::Auxiliary, AuxiliaryCbBinder > _sub_auxiliary
constexpr _Tp max(_Tp a, _Tp b)
float _last_gnss_auxiliary_hdop
static const char *const NAME
float _last_gnss_auxiliary_vdop
uint64_t _last_gnss_auxiliary_timestamp
void print_status() const override
Prints current status in a human readable format to stdout.
bool update(void *dst)
Update the struct.
bool publish(const T &data)
Publish the struct.
void process_fixx(const uavcan::ReceivedDataStructure< FixType > &msg, const float(&pos_cov)[9], const float(&vel_cov)[9], const bool valid_pos_cov, const bool valid_vel_cov)
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).