Skip to content

Jeff/feat/g1 raycast ivan#2348

Open
leshy wants to merge 33 commits into
mainfrom
jeff/feat/g1_raycast_ivan
Open

Jeff/feat/g1 raycast ivan#2348
leshy wants to merge 33 commits into
mainfrom
jeff/feat/g1_raycast_ivan

Conversation

@leshy
Copy link
Copy Markdown
Member

@leshy leshy commented Jun 3, 2026

No description provided.

jeff-hykin and others added 30 commits May 27, 2026 00:00
Renames uintree_g1_primitive_no_nav.py to unitree_g1_primitive_no_nav.py,
adds unitree_g1_onboard.py at the corrected path, updates the variable
name and all importers, and regenerates the all_blueprints.py registry
keys (drops the typo'd uintree-g1-primitive-no-nav entry, adds the
correctly-spelled unitree-g1-onboard and unitree-g1-primitive-no-nav).
Prefix with _ so it is not registered as a standalone runnable
blueprint; it stays a shared composition for nav-simple and
nav-onboard. unitree-g1-nav-simple is the only new blueprint.
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 3, 2026

Greptile Summary

This PR introduces a new unitree-g1-nav-simple navigation blueprint for the G1 robot that wires together the FastLio2 onboard LiDAR, a Rust ray-tracing voxel map (now built via Nix), a CostMapper, and A* replanning. It also fixes a long-standing filename typo (uintreeunitree), unifies costmap visualization into a shared costmap_to_rerun helper, and adds deadzone-compensation to the G1 DDS velocity commands.

  • New unitree_g1_nav_simple blueprint composes _unitree_g1_onboard (FastLio2 + DDS SDK), RayTracingVoxelMap, CostMapper with a configurable initial_safe_radius_meters, ReplanningAStarPlanner, and MovementManager; all previously scattered blueprints are refactored to share the new _unitree_g1_onboard sub-blueprint.
  • Ray-tracing Rust module migrates its build from cargo build --release to nix build path:.; the A* planner gains a typed Odometry input and path reconstruction now uses costmap.frame_id instead of the hardcoded string \"world\".
  • G1 DDS SDK adds _boost_above_deadzone to snap sub-threshold velocity commands up to the robot's minimum effective speed, and the mid360 LiDAR pitch in g1.urdf has its sign corrected.

Confidence Score: 3/5

The PR is safe to merge for most of its changes, but the initial_safe_radius_meters feature in CostMapper will silently do nothing useful once the robot leaves its starting position.

The new initial_safe_radius_meters logic clears a disc in the global-frame occupancy grid always centered on world origin (0,0) rather than on the robot's current pose. Because the costmap origin is set to the point-cloud's (min_x, min_y) in world coordinates, the computation is only correct at startup. After the robot moves, the safe zone is misplaced and the feature provides no protection. The Nix flake lock also pins the self-referential dimos-repo input to the feature branch by name, which will cause nix flake update to fail after branch deletion.

dimos/mapping/costmapper.py (the _apply_initial_safe_radius method) and dimos/mapping/ray_tracing/rust/flake.lock (stale branch reference) need attention before or shortly after merge.

Important Files Changed

Filename Overview
dimos/mapping/costmapper.py Adds a prebuilt color lookup table for costmap visualization and a new initial_safe_radius_meters feature; the radius logic incorrectly measures cell distance from the world origin instead of the robot's current position, making it ineffective once the robot moves.
dimos/navigation/replanning_a_star/module.py Adds ReplanningAStarPlannerConfig with per-blueprint robot dimension overrides and a new odometry: In[Odometry] subscription alongside the existing odom: In[PoseStamped] — both call handle_odom, risking double updates if both streams are connected.
dimos/mapping/ray_tracing/rust/flake.lock New Nix flake lock file switches the Rust build to nix; the dimos-repo input is pinned to the feature branch ref which will become stale after merge and branch deletion.
dimos/robot/unitree/g1/blueprints/navigation/unitree_g1_nav_simple.py New blueprint wiring together the onboard sensor stack, ray-tracing voxel map, CostMapper, A* replanning, and movement manager for the G1 robot; parameters look reasonable and the composition is clean.
dimos/robot/unitree/g1/blueprints/primitive/unitree_g1_onboard.py New shared sub-blueprint extracting FastLio2, DDS SDK, and vis into a reusable _unitree_g1_onboard; the remapping of global_map to global_map_fastlio correctly avoids naming conflicts downstream.
dimos/robot/unitree/g1/effectors/high_level/dds_sdk.py Adds deadzone-compensation logic (_boost_above_deadzone) that snaps small non-zero velocity commands to the robot's minimum effective magnitude; the implementation handles zero and sign correctly.
dimos/robot/unitree/g1/g1.urdf Flips the LiDAR pitch mount angle from +0.040 to -0.040 radians to correct the mid360 tilt direction; a single sign change with clear intent.
dimos/msgs/nav_msgs/OccupancyGrid.py Adds an optional color_lookup_table parameter to to_rerun, falling back to the existing LUT builder when not provided; backward-compatible and correctly applied before the clipped index lookup.
dimos/navigation/replanning_a_star/min_cost_astar.py Replaces the hardcoded "world" frame string with costmap.frame_id throughout path reconstruction; straightforward correctness fix.
dimos/robot/unitree/g1/blueprints/primitive/unitree_g1_primitive_no_nav.py Renamed from uintree_g1_primitive_no_nav (fixing the typo) and switches to the centralized costmap_to_rerun function; all references updated consistently.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph _unitree_g1_onboard
        FastLio2 -->|global_map_fastlio| GL_F[global_map_fastlio stream]
        FastLio2 -->|odometry| OdomStream[odometry stream]
        G1DDS[G1HighLevelDdsSdk]
        unitree_g1_vis[unitree_g1_vis]
    end

    subgraph unitree_g1_nav_simple
        _unitree_g1_onboard
        OdomStream --> RayTrace[RayTracingVoxelMap]
        FastLio2 -->|lidar| RayTrace
        RayTrace -->|global_map PointCloud2| CostMapper
        CostMapper -->|global_costmap OccupancyGrid| AStarPlanner[ReplanningAStarPlanner]
        OdomStream --> AStarPlanner
        AStarPlanner -->|nav_cmd_vel Twist| MovementManager
        AStarPlanner -->|path Path| unitree_g1_vis
        CostMapper -->|global_costmap| unitree_g1_vis
        MovementManager -->|cmd_vel Twist| G1DDS
    end
Loading

Comments Outside Diff (1)

  1. dimos/mapping/ray_tracing/rust/flake.lock, line 133-138 (link)

    P2 Lock file pins dimos-repo to the feature branch by name

    The dimos-repo entry is locked to ref: "refs/heads/jeff/feat/g1_raycast". When this branch is deleted after the PR merges, nix flake update will fail to resolve that ref for the git+file:../../../.. dependency, breaking reproducible builds for contributors who run nix flake update afterwards. The lock file should be regenerated after merging pointed at a stable ref such as main.

Reviews (1): Last reviewed commit: "faster angular" | Re-trigger Greptile

Comment on lines +115 to +133
def _apply_initial_safe_radius(self, grid: OccupancyGrid) -> None:
radius_meters = self.config.initial_safe_radius_meters
if radius_meters <= 0 or grid.grid.size == 0:
return

resolution = grid.resolution
origin_x = grid.origin.position.x
origin_y = grid.origin.position.y

rows, columns = np.ogrid[: grid.grid.shape[0], : grid.grid.shape[1]]
cell_world_x = columns * resolution + origin_x
cell_world_y = rows * resolution + origin_y
distance_squared_meters = cell_world_x**2 + cell_world_y**2

# Half-cell tolerance: a cell counts as inside if any part of it overlaps
# the disc. Avoids floating-point boundary flakiness from radius/resolution.
effective_radius_meters = radius_meters + resolution * 0.5
safe_mask = distance_squared_meters <= effective_radius_meters**2
grid.grid[safe_mask] = 0
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 Safe radius centered on world origin, not on the robot

_apply_initial_safe_radius computes each cell's distance from the world origin (0, 0) rather than from the robot's current position. The occupancy grid's origin is set to (min_x, min_y) of the global-frame point cloud, so cell_world_x = columns * resolution + origin_x gives the cell's position in the world frame. Squaring and summing those values gives distance-squared from (0, 0), not from wherever the robot actually is. Once the robot has moved any meaningful distance from its start point, the safe disc sits at the map origin rather than under the robot. CostMapper would need an odometry input to know the robot's current position and compute the correct offset.

Comment on lines 80 to +87
self.register_disposable(Disposable(self.odom.subscribe(self._planner.handle_odom)))
self.register_disposable(
Disposable(
self.odometry.subscribe(
lambda msg: self._planner.handle_odom(msg.to_pose_stamped())
)
)
)
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.

P2 Dual odometry subscriptions can produce double position updates

Both odom (In[PoseStamped]) and odometry (In[Odometry]) are unconditionally subscribed, and both call self._planner.handle_odom. Any blueprint that wires up both streams will drive handle_odom twice per cycle. Guarding each subscription on the transport being non-None (as is done for stop_movement) or making them mutually exclusive would prevent this.

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.

2 participants