Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/Tools/AP_Periph/gps.cpp
Views: 1798
#include "AP_Periph.h"12#ifdef HAL_PERIPH_ENABLE_GPS34/*5GPS support6*/78#include <dronecan_msgs.h>9#include <AP_GPS/RTCM3_Parser.h>1011#define DEBUG_PRINTS 01213#if DEBUG_PRINTS14# define Debug(fmt, args ...) do {can_printf(fmt "\n", ## args);} while(0)15#else16# define Debug(fmt, args ...)17#endif1819/*20handle gnss::RTCMStream21*/22void AP_Periph_FW::handle_RTCMStream(CanardInstance* canard_instance, CanardRxTransfer* transfer)23{24uavcan_equipment_gnss_RTCMStream req;25if (uavcan_equipment_gnss_RTCMStream_decode(transfer, &req)) {26return;27}28gps.handle_gps_rtcm_fragment(0, req.data.data, req.data.len);29}3031/*32handle gnss::MovingBaselineData33*/34#if GPS_MOVING_BASELINE35void AP_Periph_FW::handle_MovingBaselineData(CanardInstance* canard_instance, CanardRxTransfer* transfer)36{37ardupilot_gnss_MovingBaselineData msg;38if (ardupilot_gnss_MovingBaselineData_decode(transfer, &msg)) {39return;40}41gps.inject_MBL_data(msg.data.data, msg.data.len);42Debug("MovingBaselineData: len=%u\n", msg.data.len);43}44#endif // GPS_MOVING_BASELINE4546/*47convert large values to NaN for float1648*/49static void check_float16_range(float *v, uint8_t len)50{51for (uint8_t i=0; i<len; i++) {52const float f16max = 65519;53if (isinf(v[i]) || v[i] <= -f16max || v[i] >= f16max) {54v[i] = nanf("");55}56}57}5859/*60update CAN GPS61*/62void AP_Periph_FW::can_gps_update(void)63{64if (gps.get_type(0) == AP_GPS::GPS_Type::GPS_TYPE_NONE) {65return;66}67gps.update();68send_moving_baseline_msg();69send_relposheading_msg();70if (last_gps_update_ms == gps.last_message_time_ms()) {71return;72}73last_gps_update_ms = gps.last_message_time_ms();7475{76/*77send Fix2 packet78*/79uavcan_equipment_gnss_Fix2 pkt {};80const Location &loc = gps.location();81const Vector3f &vel = gps.velocity();82if (gps.status() < AP_GPS::GPS_OK_FIX_2D && !saw_gps_lock_once) {83pkt.timestamp.usec = AP_HAL::micros64();84pkt.gnss_timestamp.usec = 0;85} else {86saw_gps_lock_once = true;87pkt.timestamp.usec = gps.time_epoch_usec();88pkt.gnss_timestamp.usec = gps.last_message_epoch_usec();89}90if (pkt.gnss_timestamp.usec == 0) {91pkt.gnss_time_standard = UAVCAN_EQUIPMENT_GNSS_FIX_GNSS_TIME_STANDARD_NONE;92} else {93pkt.gnss_time_standard = UAVCAN_EQUIPMENT_GNSS_FIX_GNSS_TIME_STANDARD_UTC;94}95pkt.longitude_deg_1e8 = uint64_t(loc.lng) * 10ULL;96pkt.latitude_deg_1e8 = uint64_t(loc.lat) * 10ULL;97pkt.height_ellipsoid_mm = loc.alt * 10;98pkt.height_msl_mm = loc.alt * 10;99float undulation;100if (gps.get_undulation(undulation)) {101pkt.height_ellipsoid_mm -= undulation*1000;102}103for (uint8_t i=0; i<3; i++) {104pkt.ned_velocity[i] = vel[i];105}106pkt.sats_used = gps.num_sats();107switch (gps.status()) {108case AP_GPS::GPS_Status::NO_GPS:109case AP_GPS::GPS_Status::NO_FIX:110pkt.status = UAVCAN_EQUIPMENT_GNSS_FIX2_STATUS_NO_FIX;111pkt.mode = UAVCAN_EQUIPMENT_GNSS_FIX2_MODE_SINGLE;112pkt.sub_mode = UAVCAN_EQUIPMENT_GNSS_FIX2_SUB_MODE_DGPS_OTHER;113break;114case AP_GPS::GPS_Status::GPS_OK_FIX_2D:115pkt.status = UAVCAN_EQUIPMENT_GNSS_FIX2_STATUS_2D_FIX;116pkt.mode = UAVCAN_EQUIPMENT_GNSS_FIX2_MODE_SINGLE;117pkt.sub_mode = UAVCAN_EQUIPMENT_GNSS_FIX2_SUB_MODE_DGPS_OTHER;118break;119case AP_GPS::GPS_Status::GPS_OK_FIX_3D:120pkt.status = UAVCAN_EQUIPMENT_GNSS_FIX2_STATUS_3D_FIX;121pkt.mode = UAVCAN_EQUIPMENT_GNSS_FIX2_MODE_SINGLE;122pkt.sub_mode = UAVCAN_EQUIPMENT_GNSS_FIX2_SUB_MODE_DGPS_OTHER;123break;124case AP_GPS::GPS_Status::GPS_OK_FIX_3D_DGPS:125pkt.status = UAVCAN_EQUIPMENT_GNSS_FIX2_STATUS_3D_FIX;126pkt.mode = UAVCAN_EQUIPMENT_GNSS_FIX2_MODE_DGPS;127pkt.sub_mode = UAVCAN_EQUIPMENT_GNSS_FIX2_SUB_MODE_DGPS_SBAS;128break;129case AP_GPS::GPS_Status::GPS_OK_FIX_3D_RTK_FLOAT:130pkt.status = UAVCAN_EQUIPMENT_GNSS_FIX2_STATUS_3D_FIX;131pkt.mode = UAVCAN_EQUIPMENT_GNSS_FIX2_MODE_RTK;132pkt.sub_mode = UAVCAN_EQUIPMENT_GNSS_FIX2_SUB_MODE_RTK_FLOAT;133break;134case AP_GPS::GPS_Status::GPS_OK_FIX_3D_RTK_FIXED:135pkt.status = UAVCAN_EQUIPMENT_GNSS_FIX2_STATUS_3D_FIX;136pkt.mode = UAVCAN_EQUIPMENT_GNSS_FIX2_MODE_RTK;137pkt.sub_mode = UAVCAN_EQUIPMENT_GNSS_FIX2_SUB_MODE_RTK_FIXED;138break;139}140141pkt.covariance.len = 6;142143float hacc;144if (gps.horizontal_accuracy(hacc)) {145pkt.covariance.data[0] = pkt.covariance.data[1] = sq(hacc);146}147148float vacc;149if (gps.vertical_accuracy(vacc)) {150pkt.covariance.data[2] = sq(vacc);151}152153float sacc;154if (gps.speed_accuracy(sacc)) {155float vc3 = sq(sacc);156pkt.covariance.data[3] = pkt.covariance.data[4] = pkt.covariance.data[5] = vc3;157}158159check_float16_range(pkt.covariance.data, pkt.covariance.len);160161uint8_t buffer[UAVCAN_EQUIPMENT_GNSS_FIX2_MAX_SIZE];162uint16_t total_size = uavcan_equipment_gnss_Fix2_encode(&pkt, buffer, !canfdout());163164canard_broadcast(UAVCAN_EQUIPMENT_GNSS_FIX2_SIGNATURE,165UAVCAN_EQUIPMENT_GNSS_FIX2_ID,166CANARD_TRANSFER_PRIORITY_LOW,167&buffer[0],168total_size);169}170171/*172send aux packet173*/174{175uavcan_equipment_gnss_Auxiliary aux {};176aux.hdop = gps.get_hdop() * 0.01;177aux.vdop = gps.get_vdop() * 0.01;178179uint8_t buffer[UAVCAN_EQUIPMENT_GNSS_AUXILIARY_MAX_SIZE];180uint16_t total_size = uavcan_equipment_gnss_Auxiliary_encode(&aux, buffer, !canfdout());181canard_broadcast(UAVCAN_EQUIPMENT_GNSS_AUXILIARY_SIGNATURE,182UAVCAN_EQUIPMENT_GNSS_AUXILIARY_ID,183CANARD_TRANSFER_PRIORITY_LOW,184&buffer[0],185total_size);186}187188// send the gnss status packet189{190ardupilot_gnss_Status status {};191192status.healthy = gps.is_healthy();193if (gps.logging_present() && gps.logging_enabled() && !gps.logging_failed()) {194status.status |= ARDUPILOT_GNSS_STATUS_STATUS_LOGGING;195}196uint8_t idx; // unused197if (status.healthy && !gps.first_unconfigured_gps(idx)) {198status.status |= ARDUPILOT_GNSS_STATUS_STATUS_ARMABLE;199}200201uint32_t error_codes;202if (gps.get_error_codes(error_codes)) {203status.error_codes = error_codes;204}205206uint8_t buffer[ARDUPILOT_GNSS_STATUS_MAX_SIZE];207const uint16_t total_size = ardupilot_gnss_Status_encode(&status, buffer, !canfdout());208canard_broadcast(ARDUPILOT_GNSS_STATUS_SIGNATURE,209ARDUPILOT_GNSS_STATUS_ID,210CANARD_TRANSFER_PRIORITY_LOW,211&buffer[0],212total_size);213214}215216// send Heading message if we are not sending RelPosHeading messages and have yaw217if (gps.have_gps_yaw() && last_relposheading_ms == 0) {218float yaw_deg, yaw_acc_deg;219uint32_t yaw_time_ms;220if (gps.gps_yaw_deg(yaw_deg, yaw_acc_deg, yaw_time_ms) && yaw_time_ms != last_gps_yaw_ms) {221last_gps_yaw_ms = yaw_time_ms;222223ardupilot_gnss_Heading heading {};224heading.heading_valid = true;225heading.heading_accuracy_valid = is_positive(yaw_acc_deg);226heading.heading_rad = radians(yaw_deg);227heading.heading_accuracy_rad = radians(yaw_acc_deg);228uint8_t buffer[ARDUPILOT_GNSS_HEADING_MAX_SIZE];229const uint16_t total_size = ardupilot_gnss_Heading_encode(&heading, buffer, !canfdout());230canard_broadcast(ARDUPILOT_GNSS_HEADING_SIGNATURE,231ARDUPILOT_GNSS_HEADING_ID,232CANARD_TRANSFER_PRIORITY_LOW,233&buffer[0],234total_size);235}236}237}238239240void AP_Periph_FW::send_moving_baseline_msg()241{242#if GPS_MOVING_BASELINE243const uint8_t *data = nullptr;244uint16_t len = 0;245if (!gps.get_RTCMV3(data, len)) {246return;247}248if (len == 0 || data == nullptr) {249return;250}251252/*253send the packet from Moving Base to be used RelPosHeading calc by GPS module254for long RTCMv3 packets we may need to split it up255*/256257uint8_t iface_mask = 0;258#if HAL_NUM_CAN_IFACES >= 2 && CANARD_MULTI_IFACE259if (gps_mb_can_port != -1 && (gps_mb_can_port < HAL_NUM_CAN_IFACES)) {260iface_mask = 1U<<gps_mb_can_port;261}262#endif263264// get the data from the moving base and send as MovingBaselineData message265while (len > 0) {266ardupilot_gnss_MovingBaselineData mbldata {};267268const uint16_t n = MIN(len, sizeof(mbldata.data.data));269270mbldata.data.len = n;271memcpy(mbldata.data.data, data, n);272273uint8_t buffer[ARDUPILOT_GNSS_MOVINGBASELINEDATA_MAX_SIZE];274const uint16_t total_size = ardupilot_gnss_MovingBaselineData_encode(&mbldata, buffer, !canfdout());275276canard_broadcast(ARDUPILOT_GNSS_MOVINGBASELINEDATA_SIGNATURE,277ARDUPILOT_GNSS_MOVINGBASELINEDATA_ID,278CANARD_TRANSFER_PRIORITY_LOW,279&buffer[0],280total_size,281iface_mask);282len -= n;283data += n;284}285286gps.clear_RTCMV3();287#endif // GPS_MOVING_BASELINE288}289290void AP_Periph_FW::send_relposheading_msg() {291#if GPS_MOVING_BASELINE292float reported_heading;293float relative_distance;294float relative_down_pos;295float reported_heading_acc;296uint32_t curr_timestamp = 0;297if (!gps.get_RelPosHeading(curr_timestamp, reported_heading, relative_distance, relative_down_pos, reported_heading_acc) ||298last_relposheading_ms == curr_timestamp) {299return;300}301last_relposheading_ms = curr_timestamp;302ardupilot_gnss_RelPosHeading relpos {};303relpos.timestamp.usec = uint64_t(curr_timestamp)*1000LLU;304relpos.reported_heading_deg = reported_heading;305relpos.relative_distance_m = relative_distance;306relpos.relative_down_pos_m = relative_down_pos;307relpos.reported_heading_acc_deg = reported_heading_acc;308relpos.reported_heading_acc_available = !is_zero(relpos.reported_heading_acc_deg);309uint8_t buffer[ARDUPILOT_GNSS_RELPOSHEADING_MAX_SIZE];310const uint16_t total_size = ardupilot_gnss_RelPosHeading_encode(&relpos, buffer, !canfdout());311canard_broadcast(ARDUPILOT_GNSS_RELPOSHEADING_SIGNATURE,312ARDUPILOT_GNSS_RELPOSHEADING_ID,313CANARD_TRANSFER_PRIORITY_LOW,314&buffer[0],315total_size);316#endif // GPS_MOVING_BASELINE317}318319#endif // HAL_PERIPH_ENABLE_GPS320321322