Skip to content

fix(gps): split RTCM corrections and moving-baseline uORB topics#27097

Draft
dakejahl wants to merge 1 commit intomainfrom
dakejahl/rtcm-topic-split
Draft

fix(gps): split RTCM corrections and moving-baseline uORB topics#27097
dakejahl wants to merge 1 commit intomainfrom
dakejahl/rtcm-topic-split

Conversation

@dakejahl
Copy link
Copy Markdown
Contributor

Summary

Fixes #27088.

gps_inject_data was being used for two unrelated purposes — external fixed-base RTCM corrections (MAVLink GPS_RTCM_DATA, UAVCAN RTCMStream) and moving-base-to-rover RTCM 4072. In a dual-GPS (moving base + rover) plus fixed-base setup, the two streams collided on the same 8-deep queue, and the FMU UAVCAN bridge mirrored fixed-base RTCM onto the MovingBaselineData CAN message, breaking rover heading or RTK fix depending on timing.

Split by role:

  • rtcm_corrections (renamed from gps_inject_data, MAX_INSTANCES = 4): external RTCM into the vehicle. Producers: MAVLink receiver, UAVCAN RTCMStream subscriber, GPS drivers in dump mode.
  • rtcm_moving_baseline (new, single-publisher): moving-base GPS output intended for a rover. Producers: on-FMU moving-base GPS or CANnode MovingBaselineData subscriber.

Key changes

  • GPSHelper::isMovingBase() virtual added in PX4/PX4-GPSDrivers#206 (submodule bump included here). GPS::publishRTCMCorrections() uses it to pick the destination topic.
  • Septentrio publish_rtcm_corrections() always publishes to rtcm_moving_baseline (only the Secondary moving base decodes RTCM).
  • Rover consumers (gps, septentrio, FMU UavcanGnssBridge) drain both topics independently, each with its own stale-link switchover state. The FMU bridge no longer dual-publishes a single message onto both CAN streams.
  • CANnode MovingBaselineDataPub subscribes to rtcm_moving_baseline, drops the bus_type == UAVCAN workaround.
  • CANnode RTCMStream subscriber → PublicationMulti so multiple CAN RTCM sources coexist (e.g. dual rovers outputting MSM7 for logging plus a fixed-base feed).
  • MAVLink GPS_RTCM_DATA stream stays sourced from rtcm_corrections only — no more upstream echo of moving-base RTCM 4072 to the GCS.
  • zenoh Kconfig.topics updated.

Dependencies

  • Submodule PR PX4/PX4-GPSDrivers#206 adds isMovingBase(). This PR bumps the submodule; needs the submodule PR merged before this can merge.

Builds

  • px4_fmu-v6x_default
  • ark_can-rtk-gps_default

The single gps_inject_data topic served two unrelated purposes:
external fixed-base RTCM corrections (from MAVLink GPS_RTCM_DATA or
UAVCAN RTCMStream) and moving-base-to-rover RTCM 4072. In a
dual-GPS-with-moving-base plus fixed-base setup, the two streams
collided on the same queue and the FMU UAVCAN bridge mirrored
fixed-base RTCM onto the MovingBaselineData CAN message, breaking
rover heading or RTK fix (see #27088).

Split by role:
- rtcm_corrections    (renamed from gps_inject_data): external RTCM
                       flowing into the vehicle; producers are
                       MAVLink, UAVCAN RTCMStream, and GPS drivers in
                       dump mode.
- rtcm_moving_baseline (new): moving-base GPS output intended for a
                       rover; single producer per vehicle.

GPS driver routes publishRTCMCorrections() based on a new
GPSHelper::isMovingBase() virtual (overridden in UBX). Septentrio's
publish_rtcm_corrections() always publishes to rtcm_moving_baseline
(only the Secondary moving base calls it). Rover-side consumers
(gps, septentrio, uavcan bridge) drain both topics independently;
each gets its own stale-link switchover state.

FMU UAVCAN bridge: two independent drain loops, one per topic. No
more dual-publish of a single uORB message onto both RTCMStream and
MovingBaselineData CAN streams.

CANnode MovingBaselineDataPub subscribes to rtcm_moving_baseline and
drops the bus_type == UAVCAN heuristic that was papering over the
conflation. CANnode RTCMStream subscriber switches to
PublicationMulti so multiple CAN RTCM sources coexist (e.g. dual
rovers outputting MSM7 for logging plus a fixed-base feed).

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
} else {
gps_inject_data.flags = 0;
}
const size_t capacity = sizeof(moving_baseline.data) / sizeof(moving_baseline.data[0]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[error] bugprone-sizeof-expression [error]
suspicious usage of sizeof pointer sizeof(T)/sizeof(T)

#define GPS_RTCM_DATA_HPP

#include <uORB/topics/gps_inject_data.h>
#include <uORB/topics/rtcm_corrections.h>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[error] clang-diagnostic-error [error]
uORB/topics/rtcm_corrections.h file not found

Comment thread src/drivers/gps/gps.cpp
} else {
gps_inject_data.flags = 0;
}
const size_t capacity = sizeof(corrections.data) / sizeof(corrections.data[0]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[error] bugprone-sizeof-expression [error]
suspicious usage of sizeof pointer sizeof(T)/sizeof(T)

@github-actions
Copy link
Copy Markdown

🔎 FLASH Analysis

px4_fmu-v5x [Total VM Diff: 976 byte (0.05 %)]
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +984  +0.0%    +984    .text
    [NEW]    +524  [NEW]    +524    GPS::drainRtcmSubscriptions<>()
    [NEW]    +484  [NEW]    +484    drain_rtcm_to_can<>()
     +17%    +112   +17%    +112    GPS::GPS()
     +75%    +108   +75%    +108    GPS::publishRTCMCorrections()
     +14%    +104   +14%    +104    UavcanGnssBridge::UavcanGnssBridge()
    +0.2%     +32  +0.2%     +32    uORB::compressed_fields
     +12%     +28   +12%     +28    GPS::~GPS()
    [NEW]     +22  [NEW]     +22    GPSDriverUBX::isMovingBase()
     +11%     +20   +11%     +20    UavcanGnssBridge::~UavcanGnssBridge()
    [NEW]     +16  [NEW]     +16    __orb_rtcm_corrections
    [NEW]     +16  [NEW]     +16    __orb_rtcm_moving_baseline
     +12%      +4   +12%      +4    GPSDriverAshtech
    +9.1%      +4  +9.1%      +4    GPSDriverEmlidReach
     +12%      +4   +12%      +4    GPSDriverFemto
     +12%      +4   +12%      +4    GPSDriverMTK
     +12%      +4   +12%      +4    GPSDriverNMEA
   +10.0%      +4 +10.0%      +4    GPSDriverUBX
   -100.0%      +2 -100.0%      +2    [12 Others]
    [DEL]     -16  [DEL]     -16    __orb_gps_inject_data
   -58.1%    -216 -58.1%    -216    UavcanGnssBridge::handleInjectDataTopic()
   -63.9%    -276 -63.9%    -276    GPS::handleInjectDataTopic()
  +0.1% +1.09Ki  [ = ]       0    .debug_abbrev
  +0.1%    +152  [ = ]       0    .debug_aranges
  +0.1%    +480  [ = ]       0    .debug_frame
  +0.1% +20.2Ki  [ = ]       0    .debug_info
  +0.1% +2.80Ki  [ = ]       0    .debug_line
   -16.7%      -1  [ = ]       0    [Unmapped]
    +0.1% +2.80Ki  [ = ]       0    [section .debug_line]
  +0.1% +2.33Ki  [ = ]       0    .debug_loclists
  +0.1%    +352  [ = ]       0    .debug_rnglists
   -66.7%      -2  [ = ]       0    [Unmapped]
    +0.1%    +354  [ = ]       0    [section .debug_rnglists]
  +0.1% +2.06Ki  [ = ]       0    .debug_str
  -0.4%      -1  [ = ]       0    .shstrtab
  +0.1%    +601  [ = ]       0    .strtab
    [NEW]    +210  [ = ]       0    GPS::drainRtcmSubscriptions<>()
   -54.8%     -40  [ = ]       0    GPS::handleInjectDataTopic()
    [NEW]     +35  [ = ]       0    GPSDriverUBX::isMovingBase()
    [NEW]     +31  [ = ]       0    GPSHelper::isMovingBase()
    +0.1%     +26  [ = ]       0    [section .strtab]
     +47%     +16  [ = ]       0    __nxsched_resume_scheduler_veneer
    [DEL]     -22  [ = ]       0    __orb_gps_inject_data
    [NEW]     +23  [ = ]       0    __orb_rtcm_corrections
    [NEW]     +27  [ = ]       0    __orb_rtcm_moving_baseline
   -44.4%     -16  [ = ]       0    __sq_addlast_veneer
    [NEW]    +311  [ = ]       0    drain_rtcm_to_can<>()
  +0.0%    +256  [ = ]       0    .symtab
     +20%     +16  [ = ]       0    GPS::callback()
    [NEW]     +96  [ = ]       0    GPS::drainRtcmSubscriptions<>()
   -66.7%     -64  [ = ]       0    GPS::handleInjectDataTopic()
   -10.0%     -16  [ = ]       0    GPS::instantiate()
    +100%     +16  [ = ]       0    GPS::pollOrRead()
     +50%     +16  [ = ]       0    GPS::publishRTCMCorrections()
   -50.0%     -16  [ = ]       0    GPS::publishRelativePosition()
   -33.3%     -16  [ = ]       0    GPSDriverAshtech::receive()
    [NEW]     +16  [ = ]       0    GPSDriverUBX::isMovingBase()
    +200%     +32  [ = ]       0    GPSDriverUBX::shouldInjectRTCM()
    [NEW]     +32  [ = ]       0    GPSHelper::isMovingBase()
    [NEW]     +96  [ = ]       0    [1 Others]
   -25.0%     -16  [ = ]       0    ___ZN4ListIP13MavlinkStreamE8IteratorppEv.isra.0_veneer
     +33%     +16  [ = ]       0    __getpid_veneer
     +67%     +32  [ = ]       0    __nxsched_resume_scheduler_veneer
   -33.3%     -16  [ = ]       0    __nxsem_boost_priority_veneer
     +50%     +16  [ = ]       0    __nxsem_tickwait_uninterruptible_veneer
    [DEL]     -48  [ = ]       0    __orb_gps_inject_data
    [NEW]     +48  [ = ]       0    __orb_rtcm_corrections
    [NEW]     +48  [ = ]       0    __orb_rtcm_moving_baseline
   -40.0%     -32  [ = ]       0    __sq_addlast_veneer
  -8.4%    -976  [ = ]       0    [Unmapped]
  -0.1%      -8  -0.1%      -8    .ramfunc
     +14%      +1   +14%      +1    __nxsem_tickwait_uninterruptible_veneer
   -12.5%      -1 -12.5%      -1    __nxsem_boost_priority_veneer
    -1.2%      -4  -1.2%      -4    Ekf::measurementUpdate()
   -16.7%      -4 -16.7%      -4    get_orb_meta()
  +0.1% +30.3Ki  +0.0%    +976    TOTAL

px4_fmu-v6x [Total VM Diff: 1288 byte (0.07 %)]
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +1.26Ki  +0.1% +1.26Ki    .text
    [NEW]    +524  [NEW]    +524    GPS::drainRtcmSubscriptions<>()
    [NEW]    +484  [NEW]    +484    drain_rtcm_to_can<>()
    [NEW]    +396  [NEW]    +396    septentrio::SeptentrioDriver::drain_rtcm_subscriptions<>()
     +17%    +112   +17%    +112    GPS::GPS()
     +75%    +108   +75%    +108    GPS::publishRTCMCorrections()
     +14%    +104   +14%    +104    UavcanGnssBridge::UavcanGnssBridge()
     +10%     +92   +10%     +92    septentrio::SeptentrioDriver::SeptentrioDriver()
   -97.3%     +70 -97.3%     +70    [26 Others]
    [NEW]     +40  [NEW]     +40    CSWTCH.289
    +0.2%     +32  +0.2%     +32    uORB::compressed_fields
     +12%     +28   +12%     +28    GPS::~GPS()
    [NEW]     +22  [NEW]     +22    GPSDriverUBX::isMovingBase()
     +11%     +20   +11%     +20    UavcanGnssBridge::~UavcanGnssBridge()
    +0.0%     +20  +0.0%     +20    [section .text]
     +10%     +20   +10%     +20    septentrio::SeptentrioDriver::~SeptentrioDriver()
    [DEL]     -16  [DEL]     -16    CSWTCH.279
    [DEL]     -16  [DEL]     -16    CSWTCH.280
    [DEL]     -40  [DEL]     -40    CSWTCH.278
   -58.1%    -216 -58.1%    -216    UavcanGnssBridge::handleInjectDataTopic()
   -82.1%    -220 -82.1%    -220    septentrio::SeptentrioDriver::handle_inject_data_topic()
   -63.9%    -276 -63.9%    -276    GPS::handleInjectDataTopic()
  +0.1% +1.11Ki  [ = ]       0    .debug_abbrev
  +0.1%    +184  [ = ]       0    .debug_aranges
  +0.1%    +616  [ = ]       0    .debug_frame
  +0.1% +22.4Ki  [ = ]       0    .debug_info
  +0.1% +3.43Ki  [ = ]       0    .debug_line
   -33.3%      -1  [ = ]       0    [Unmapped]
    +0.1% +3.43Ki  [ = ]       0    [section .debug_line]
  +0.1% +3.10Ki  [ = ]       0    .debug_loclists
  +0.1%    +445  [ = ]       0    .debug_rnglists
    [DEL]      -3  [ = ]       0    [Unmapped]
    +0.1%    +448  [ = ]       0    [section .debug_rnglists]
  +0.1% +2.41Ki  [ = ]       0    .debug_str
  +0.4%      +1  [ = ]       0    .shstrtab
  +0.1%    +867  [ = ]       0    .strtab
    [DEL]     -11  [ = ]       0    CSWTCH.278
    [DEL]     -11  [ = ]       0    CSWTCH.279
    [DEL]     -11  [ = ]       0    CSWTCH.280
    [NEW]     +11  [ = ]       0    CSWTCH.289
    [NEW]     +11  [ = ]       0    CSWTCH.290
    [NEW]     +11  [ = ]       0    CSWTCH.291
    [NEW]    +210  [ = ]       0    GPS::drainRtcmSubscriptions<>()
   -54.8%     -40  [ = ]       0    GPS::handleInjectDataTopic()
    [NEW]     +35  [ = ]       0    GPSDriverUBX::isMovingBase()
    [NEW]     +31  [ = ]       0    GPSHelper::isMovingBase()
    +0.1%     +26  [ = ]       0    [section .strtab]
    [DEL]     -22  [ = ]       0    __orb_gps_inject_data
    [NEW]     +23  [ = ]       0    __orb_rtcm_corrections
    [NEW]     +27  [ = ]       0    __orb_rtcm_moving_baseline
    [NEW]    +311  [ = ]       0    drain_rtcm_to_can<>()
    [NEW]    +266  [ = ]       0    septentrio::SeptentrioDriver::drain_rtcm_subscriptions<>()
  +0.1%    +352  [ = ]       0    .symtab
    [DEL]     -32  [ = ]       0    CSWTCH.278
    [DEL]     -32  [ = ]       0    CSWTCH.279
    [DEL]     -32  [ = ]       0    CSWTCH.280
    [NEW]     +32  [ = ]       0    CSWTCH.289
    [NEW]     +32  [ = ]       0    CSWTCH.290
    [NEW]     +32  [ = ]       0    CSWTCH.291
     +20%     +16  [ = ]       0    GPS::callback()
    [NEW]     +96  [ = ]       0    GPS::drainRtcmSubscriptions<>()
   -66.7%     -64  [ = ]       0    GPS::handleInjectDataTopic()
   -10.0%     -16  [ = ]       0    GPS::instantiate()
    +100%     +16  [ = ]       0    GPS::pollOrRead()
     +50%     +16  [ = ]       0    GPS::publishRTCMCorrections()
   -50.0%     -16  [ = ]       0    GPS::publishRelativePosition()
   -33.3%     -16  [ = ]       0    GPSDriverAshtech::receive()
    [NEW]     +16  [ = ]       0    GPSDriverUBX::isMovingBase()
    +200%     +32  [ = ]       0    GPSDriverUBX::shouldInjectRTCM()
    [NEW]     +32  [ = ]       0    GPSHelper::isMovingBase()
   -53.6%    +208  [ = ]       0    [12 Others]
    +0.3%     +32  [ = ]       0    [section .symtab]
    [DEL]     -48  [ = ]       0    __orb_gps_inject_data
    [NEW]     +48  [ = ]       0    __orb_rtcm_corrections
 -16.6% -1.26Ki  [ = ]       0    [Unmapped]
  +0.1% +34.8Ki  +0.1% +1.26Ki    TOTAL

Updated: 2026-04-16T01:33:32

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR resolves RTCM stream collisions by splitting the former gps_inject_data uORB topic into two role-specific topics: external RTCM corrections vs moving-baseline RTCM intended for a rover, preventing cross-pollination in dual-GPS + fixed-base configurations.

Changes:

  • Replace gps_inject_data with rtcm_corrections (multi-instance) and introduce rtcm_moving_baseline (moving-base→rover).
  • Update MAVLink, GPS drivers, and UAVCAN FMU/CANnode bridges to publish/consume the new topics independently.
  • Add new uORB message definitions and update build/Kconfig topic selections accordingly.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/modules/zenoh/Kconfig.topics Replaces Zenoh selection for gps_inject_data with the new RTCM topics.
src/modules/mavlink/streams/GPS_RTCM_DATA.hpp MAVLink stream now sources RTCM from rtcm_corrections.
src/modules/mavlink/mavlink_receiver.h Receiver publishes incoming GPS_RTCM_DATA into rtcm_corrections.
src/modules/mavlink/mavlink_receiver.cpp Implements the GPS_RTCM_DATArtcm_corrections publication path.
src/drivers/uavcannode/Subscribers/RTCMStream.hpp CANnode RTCMStream subscriber republishes into rtcm_corrections using multi-publication.
src/drivers/uavcannode/Subscribers/MovingBaselineData.hpp CANnode MovingBaselineData subscriber republishes into rtcm_moving_baseline.
src/drivers/uavcannode/Publishers/MovingBaselineData.hpp CANnode publishes rtcm_moving_baseline out as CAN MovingBaselineData.
src/drivers/uavcan/sensors/gnss.hpp FMU UAVCAN GNSS bridge subscribes to both new RTCM topics with independent state.
src/drivers/uavcan/sensors/gnss.cpp Splits forwarding to distinct CAN messages and deduplicates drain logic via a helper.
src/drivers/gps/gps.cpp GPS driver now drains both RTCM topics and routes published RTCM based on moving-base role.
src/drivers/gnss/septentrio/septentrio.h Septentrio driver wiring updated to new RTCM topics and new drain helper.
src/drivers/gnss/septentrio/septentrio.cpp Implements separate draining paths and publishes moving-baseline RTCM to the new topic.
msg/RtcmMovingBaseline.msg Introduces rtcm_moving_baseline uORB message definition.
msg/RtcmCorrections.msg Introduces rtcm_corrections uORB message definition.
msg/GpsInjectData.msg Removes the conflated legacy message definition.
msg/CMakeLists.txt Registers the new message files and removes the old one from the build.

Comment on lines +2741 to 2742
rtcm_corrections_topic.timestamp = hrt_absolute_time();

Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rtcm_corrections_topic.timestamp is assigned twice; the first assignment is redundant since it is overwritten just before publish. Consider keeping only a single timestamp assignment (ideally once, close to publish).

Suggested change
rtcm_corrections_topic.timestamp = hrt_absolute_time();

Copilot uses AI. Check for mistakes.

uint8 ORB_QUEUE_LENGTH = 16

uint8 MAX_INSTANCES = 2
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_INSTANCES is set to 2, and multiple consumers now implement multi-instance selection logic, but all publishers in this PR use single-instance uORB::Publication for rtcm_moving_baseline. If the topic is intended to be single-source, consider setting MAX_INSTANCES = 1 (and possibly using non-multi subscriptions); if multiple sources are expected, consider switching publishers to PublicationMulti so instances don’t collide on instance 0.

Suggested change
uint8 MAX_INSTANCES = 2
uint8 MAX_INSTANCES = 1

Copilot uses AI. Check for mistakes.
Comment thread src/drivers/gps/gps.cpp
Comment on lines 576 to +578
// If there has not been a valid RTCM message for a while, try to switch to a different RTCM link
if (now > _last_rtcm_injection_time + 5_s) {

for (int instance = 0; instance < _orb_inject_data_sub.size(); instance++) {
const bool exists = _orb_inject_data_sub[instance].advertised();

if (exists && _orb_inject_data_sub[instance].copy(&msg)) {
for (int instance = 0; instance < subs.size(); instance++) {
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drainRtcmSubscriptions() uses the shared member _last_rtcm_injection_time to decide when a subscription has gone stale. Now that handleInjectDataTopic() drains both rtcm_corrections and rtcm_moving_baseline, activity on one stream will keep _last_rtcm_injection_time fresh and can prevent stale-link switchover (and even injection) on the other stream. Track last-injection time per stream (e.g. separate members for corrections vs moving-baseline, or pass hrt_abstime& last_injection_time into drainRtcmSubscriptions()).

Copilot uses AI. Check for mistakes.
Comment on lines 1632 to +1634
// If there has not been a valid RTCM message for a while, try to switch to a different RTCM link
if (now > _last_rtcm_injection_time + 5_s) {
for (int instance = 0; instance < _gps_inject_data_sub.size(); instance++) {
const bool exists = _gps_inject_data_sub[instance].advertised();

if (exists) {
if (_gps_inject_data_sub[instance].copy(&msg)) {
if (now < msg.timestamp + 5_s) {
// Remember that we already did a copy on this instance.
already_copied = true;
_selected_rtcm_instance = instance;
break;
}
for (int instance = 0; instance < subs.size(); instance++) {
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drain_rtcm_subscriptions() uses the shared _last_rtcm_injection_time for stale-link switchover. Since handle_inject_data_topic() now drains both rtcm_corrections and rtcm_moving_baseline, injection on one stream can mask staleness on the other and prevent instance re-selection. Consider keeping separate last-injection timestamps per stream (or pass a last_injection_time reference into drain_rtcm_subscriptions()).

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +70
msg.len = corrections.len;
msg.flags = corrections.flags;
memcpy(msg.data, corrections.data, sizeof(msg.data));
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MAVLink message is zero-initialized, but this copies sizeof(msg.data) bytes regardless of msg.len. If the uORB publisher doesn't clear bytes beyond len, this can leak stale bytes over MAVLink. Copy only msg.len bytes (and optionally leave the remainder zero) rather than always copying the full array.

Suggested change
msg.len = corrections.len;
msg.flags = corrections.flags;
memcpy(msg.data, corrections.data, sizeof(msg.data));
const size_t payload_len = (corrections.len < sizeof(msg.data)) ? corrections.len : sizeof(msg.data);
msg.len = payload_len;
msg.flags = corrections.flags;
memcpy(msg.data, corrections.data, payload_len);

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

@dakejahl dakejahl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few non-blocking observations.

Inline: on MovingBaselineDataPub dropping the bus_type == UAVCAN filter, and on RtcmCorrections queue length staying at 8 while MAX_INSTANCES doubled.

Diagnostic parity — not anchorable to a changed line, so noting here: gps.cpp still sets only _sensor_gps.selected_rtcm_instance; consider adding _sensor_gps.selected_moving_baseline_instance so flight logs can tell which moving-baseline instance the rover is actually pulling from when debugging dual-CAN moving-base setups. Related: _rtcm_injection_rate now aggregates both streams (UavcanGnssBridge passes the same _rtcm_injection_rate_message_count into both drains — gnss.cpp:637 and :643). Separate rates would be more useful for diagnosing which side is flaky, but that's sensor_gps schema churn — reasonable as a follow-up rather than this PR.

Docs: docs/en/msg_docs/GpsInjectData.md should be deleted and RtcmCorrections.md / RtcmMovingBaseline.md regenerated (auto-gen, not hand-written).


Posted by Claude (Opus 4.7) on behalf of @dakejahl.

// gps_inject_data -> ardupilot::gnss::MovingBaselineData
gps_inject_data_s gps_inject_data = {};
// rtcm_moving_baseline -> ardupilot::gnss::MovingBaselineData
rtcm_moving_baseline_s moving_baseline = {};
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bus_type == UAVCAN filter that used to sit a few lines below this was doing double duty: gps_inject_data role disambiguation (now solved by splitting the topic) and defensive loop-break — a CANnode that both subscribes and publishes MovingBaselineData wouldn't re-broadcast what it just received from the bus. The PR solves the first purpose but drops the second. If a future deployment ever has two CANnodes each running a moving-base publisher, they'd ping-pong each other's traffic over CAN indefinitely (neither self-filter — that's source-node-ID — catches a relayed message).

Suggest either keeping the one-line filter, or leaving a comment stating "only one CANnode may run MovingBaselineDataPub per bus" so the invariant is visible to future readers.

Comment thread msg/RtcmCorrections.msg
uint8 flags # LSB: 1=fragmented
uint8[300] data # RTCM3 correction data (from a fixed base, or another GPS)

uint8 ORB_QUEUE_LENGTH = 8
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_INSTANCES doubled from 2 → 4 (good — covers MAVLink + multiple CAN sources), but ORB_QUEUE_LENGTH stays at 8. With four active publishers each writing to their own instance, per-instance depth of 8 is tight when bursts arrive (RTCM often comes in 4-message clusters covering GPS/GLONASS/BeiDou/Galileo). Consider 16 to match RtcmMovingBaseline.msg, or a comment explaining why 8 is sufficient here. Nit.

Comment thread msg/RtcmCorrections.msg
@@ -0,0 +1,11 @@
uint64 timestamp # time since system start (microseconds)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document all uorb topics to standard https://docs.px4.io/main/en/uorb/uorb_documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] gps_inject_data topic conflates external RTCM and moving-baseline RTCM, breaks dual GPS + fixed base

3 participants