Skip to main content

Simulation Container

docker pull bedrockdynamics/substrate-sim:ros2-nav2
The container bundles Gazebo Harmonic, ROS 2 Humble, Nav2, and an MCP server with navigation tools.
PortProtocolPurpose
8090HTTPMCP tool server
9090gRPCros2-bridge (odometry streaming + twist relay)

MCP Tools

The MCP server exposes two tools for high-level navigation at 1-3Hz. Sends a goal pose to Nav2’s NavigateToPose action server. Nav2 plans a path and drives the robot to the target, handling obstacle avoidance.
ParameterTypeDescription
x, yfloatTarget position in meters (map frame)
yawfloatTarget heading in radians

follow_waypoints

Sends a sequence of waypoints to Nav2’s FollowWaypoints action server. The robot visits each waypoint in order.
ParameterTypeDescription
waypointsarrayList of {x, y, yaw} objects

WASM Channels

The ChannelManifest::diff_drive() manifest defines 2 twist command channels and 3 odometry state channels at 100Hz.

Command Channels (2)

IndexNameUnitLimitsMax Rate of Change
0base/linear.xm/s-1.0 to 1.00.5 m/s per tick
1base/angular.zrad/s-2.0 to 2.01.0 rad/s per tick
These two channels map directly to the geometry_msgs/Twist message used by differential-drive robots. linear.x is forward/backward velocity, angular.z is rotational velocity (positive = counter-clockwise).

State Channels (3)

IndexNameUnitType
0base/odom.xmPosition
1base/odom.ymPosition
2base/odom.yawradPosition
Odometry is in the odom frame, relative to where the robot started.

Twist Publishing

The gRPC bridge publishes WASM velocity commands as geometry_msgs/Twist messages on the /cmd_vel topic via gz-transport. This bypasses Nav2 — when a WASM controller is active, it has direct control of the robot’s motors.
If both Nav2 and a WASM controller are sending velocity commands, the results are undefined. Use MCP tools or WASM controllers for a given task, not both simultaneously.

Example

A WASM controller that drives the robot in a slow arc:
;; Drive forward at 0.3 m/s
(call $set_command (i32.const 0) (f64.const 0.3))
;; Turn left at 0.5 rad/s
(call $set_command (i32.const 1) (f64.const 0.5))

Source Code