Skip to content

fix: now publishes z=0 to odom in DroneConnectionModule for 2D navigation stack#2381

Open
knikou01 wants to merge 3 commits into
dimensionalOS:mainfrom
knikou01:fix/drone-odom-z-axis-2d-navigation
Open

fix: now publishes z=0 to odom in DroneConnectionModule for 2D navigation stack#2381
knikou01 wants to merge 3 commits into
dimensionalOS:mainfrom
knikou01:fix/drone-odom-z-axis-2d-navigation

Conversation

@knikou01
Copy link
Copy Markdown
Contributor

@knikou01 knikou01 commented Jun 6, 2026

The A* planner checks arrival using 3D distance. DroneConnectionModule was publishing real altitude in odom, so the drone was never arriving at the destination, that always had z=0. It failed to find a path there because 3D pathfinding isn't implemented. With this change it publishes z=0 to odom and keeps real z only for visualization, so it can at least run a 2D pathfinding, and the developers can handle the drone's z axis movements independently.

…tion stack

The A* planner checks arrival using 3D distance. DroneConnectionModule was publishing real altitude in odom, so the drone was never arriving at the destination. Now it publishes z=0 to odom and keeps real z only for visualization.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 6, 2026

Greptile Summary

This PR fixes the 2D navigation stack by zeroing the z-coordinate in the odometry message published by DroneConnectionModule, so the A* planner's 3D arrival check can match waypoints that always have z=0. Real altitude is preserved only in the TF base_link transform for Rerun visualization.

  • _publish_tf now stores and publishes a z=0 PoseStamped for navigation while passing the original msg.position (with real z) to the TF transform — an intentional split documented in a code comment.
  • The nav_msg = self._odom intermediate variable is a no-op alias and can be inlined, but this is a trivial style point.

Confidence Score: 5/5

The change is narrowly scoped to a single method and achieves its stated goal cleanly.

The odom/TF split is intentional and clearly documented with a code comment. The telemetry loop's default-pose path already used z=0, so the zeroing is consistent throughout. No new data paths are introduced; existing callers of the odom stream get exactly what the 2D nav stack needs.

No files require special attention.

Important Files Changed

Filename Overview
dimos/robot/drone/connection_module.py Zeroes z in the odometry message stored and published for the 2D navigation stack, while keeping real z in the TF base_link transform for Rerun visualization.

Sequence Diagram

sequenceDiagram
    participant Drone as Drone (MAVLink)
    participant DCM as DroneConnectionModule
    participant OdomStream as odom stream (z=0)
    participant TF as TF stream (real z)
    participant NavStack as A* Nav Stack
    participant Rerun as Rerun Visualization

    Drone->>DCM: PoseStamped(x, y, real_z)
    DCM->>DCM: _publish_tf(msg)
    DCM->>DCM: "self._odom = PoseStamped(x, y, 0.0)"
    DCM->>OdomStream: "publish(nav_msg) [z=0.0]"
    DCM->>TF: publish(base_link Transform) [real z from msg.position]
    OdomStream->>NavStack: PoseStamped(x, y, 0.0)
    TF->>Rerun: base_link at real altitude
    NavStack->>NavStack: "A* arrival check (3D dist with z=0 vs goal z=0)"
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into fix/drone-odom-..." | Re-trigger Greptile

Comment thread dimos/robot/drone/connection_module.py Outdated
Comment on lines +175 to +178
self._odom = msg

# Publish odometry
self.odom.publish(msg)
nav_msg = PoseStamped(
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.

P1 get_odom() returns self._odom, which still holds the original PoseStamped with the real altitude. Any caller using get_odom() over RPC will see a different z than what was published on the odom stream, silently breaking the z=0 contract that this PR introduces for the 2D navigation stack.

Suggested change
self._odom = msg
# Publish odometry
self.odom.publish(msg)
nav_msg = PoseStamped(
self._odom = PoseStamped(
position=Vector3(msg.position.x, msg.position.y, 0.0),
orientation=msg.orientation,
frame_id=msg.frame_id,
ts=msg.ts,
)
# Publish odometry
nav_msg = PoseStamped(

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@knikou01
Copy link
Copy Markdown
Contributor Author

knikou01 commented Jun 6, 2026

A test can't reach huggingface, and a required one is skipped

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.

1 participant