Skip to content

pashupati_bridge ​

How the handheld talks to the robot without ROS, its video, and where the camera comes from. The bridge never drives the robot itself: the stick is one operator source of Dharma's control mux, which alone publishes the robot's cmd_vel after its envelope, protective field and e-stop.

NodeRole
teleop_udp_nodeUDP gateway of the Pashupati Controller: stick, commands, telemetry, JPEG camera, cloud
video_stream_nodeH.264 of the camera for the handheld's WebRTC video (MediaMTX starts it while watched)
rtsp_camera_nodean RTSP camera as the robot's camera (camera:=rtsp): image, JPEG and camera_info

teleop_udp_node ​

The wire format is PROTOCOL.md (v1, unchanged for the handheld).

HandheldDharma
stick (joy)control/remote/handheld/cmd_vel (remote_source), clamped to max_vx/vy/wz and robot.limits; NaN or text is 0
set_modecontrol/set_mode (auto, or remote with source handheld)
estopcontrol/estop_request at once, then control/estop/engage; estop_release: control/estop/release
nav_*navigation/start, stop, pause, resume
record_*route/start, route/stop, route/mark_stop_point (dharma_mapping)
list_routes, load_routethe taught routes of every site under sites_dir, navigation/load_path
localize, record_tagslocalization/start, localization/record_tags
dock, undockdocking/dock, docking/undock
trip_resetodometry/trip_reset (dharma_odometry): the trip meter back to zero
nav_speedpath_follower_node speed.cruise, between patrol_speed_min and patrol_speed_max (never above robot.limits.max_vx)
inspection_set, people_setlive parameters of anomaly_detector_node, person_detector_node
robot commandsstd_srvs/Trigger /<robot_ns>/<name> of the driver (robot_commands; emergency_stop also latches the software e-stop)

Telemetry comes from the typed status: control/status (mode, e-stop, field), navigation/status, localization/status, health/status with the computer's figures from the health monitor's /diagnostics, the detectors' status, navigation/waypoints, odometry/trip (distance and speeds since trip_reset), and the driver's battery and cmd_vel (remapped to /<robot_ns>/ by the launch) and status (driver_diagnostics_topic, set to /<robot_ns>/diagnostics by the launch: a diagnostics remap would also catch /diagnostics).

Set the same token in the site file and in the handheld; a wrong one is answered with denied. Camera, cloud and TF are subscribed only while a handheld is connected and wants them.

video_stream_node ​

MediaMTX (the pashupati bringup, scripts/setup.sh install webrtc) runs it while the handheld watches the WebRTC video and stops it 10 s after the last viewer. It encodes image_topic (raw rgb8, bgr8, mono8, yuv422, ...) with the first encoder that works (Jetson nvv4l2h264enc, x264, OpenH264) and publishes over RTSP to MediaMTX on the loopback.

rtsp_camera_node ​

An RTSP camera (an IP camera, a gimbal pod, a robot's own camera) in place of a camera driver: camera:=rtsp camera_url:=rtsp://... of the bringup starts it, remapped onto the camera topics every consumer reads (<camera_topics>/image_raw, image_raw/compressed, camera_info). It decodes with GStreamer (Jetson hardware decoder, libav, then FFmpeg), reconnects with a backoff up to 30 s, and with calibration_file publishes the rectified image with a matching camera_info (config/calibration.example.yaml); without one camera_info assumes default_hfov_deg and tag poses are only approximate.

Layout ​

Module
teleop_udp_node.pymessages, commands, the state message
core/protocol.pywire format: JSON, chunked streams, point packing
core/session.pyone driver at a time, acknowledgements, denied rate limit
core/commands.pywhich service each command calls, checks of the arguments
core/summaries.pythe inspection, people and health parts of state
core/routes.pytaught routes inside the sites directory
core/config.pyTeleopConfig, VideoConfig, CameraConfig
core/video.py, core/rtsp.py, core/calibration.pyGStreamer pipelines, the camera calibration
utils/link.pythe UDP socket with its reader thread
utils/clients.pythe service clients, the patrol speed
utils/telemetry.pythe status subscriptions
utils/streams.pycamera, cloud and tags, subscribed only while wanted

Launch and test ​

bash
ros2 launch pashupati_bridge bridge.launch.py robot_ns:=robot
ros2 launch pashupati_bridge bridge.launch.py camera:=rtsp camera_url:=rtsp://192.168.1.120:8554/test
colcon test --packages-select pashupati_bridge && colcon test-result --verbose

Arguments: params_file, robot_params, use_sim_time, log_level, robot_ns, teleop, video_port, camera (driver | rtsp), camera_url, camera_topics (/camera/camera/color). Defaults: config/bridge.yaml.