ROS embodiment adapter for Inspect Robots over the rosbridge websocket protocol.
Project description
inspect-robots-ros
Safety
Warning: This adapter sends commands to physical hardware. Keep a tested emergency stop within reach, and do not run an unsupervised evaluation until the full command path has been checked on your robot.
- Verify every arm and gripper bound against the robot URDF, manufacturer datasheet, and controller configuration.
- Start with a low policy speed limit such as a low
max_speed_frac, then increase it only after reviewing commanded and measured motion. - Supervise first runs with the workspace clear and the robot at reduced hardware speed.
- Confirm that loss of rosbridge communication stops motion safely at the controller or robot level.
The package registers the ros Inspect Robots embodiment. It connects directly
to rosbridge_server, so the evaluation machine needs no ROS installation,
ROS message packages, or robot-vendor SDK.
Install
pip install inspect-robots-ros
The embodiment then appears in inspect-robots list embodiments.
Robot-side bringup
Install rosbridge_server in the robot's ROS environment and start its
websocket endpoint. Port 9090 is the rosbridge default.
ROS 1:
roslaunch rosbridge_server rosbridge_websocket.launch
ROS 2:
ros2 launch rosbridge_server rosbridge_websocket_launch.xml
The evaluation host must be able to reach the websocket URL. Restrict network access to trusted hosts because rosbridge exposes ROS topics and services. The plugin does not launch rosbridge or install anything on the robot.
Quickstart
This six-joint example publishes JointTrajectory commands, reads a wrist
camera, and uses explicit joint limits:
inspect-robots run --task my-task --policy agent --embodiment ros \
-E url=ws://robot:9090 \
-E joints=joint1,joint2,joint3,joint4,joint5,joint6 \
-E command_topic=/joint_trajectory_controller/joint_trajectory \
-E cameras=wrist:/camera/wrist/image_raw/compressed:640x480 \
-E action_low=-3.1,-2.2,-2.9,-3.1,-2.9,-3.1 \
-E action_high=3.1,2.2,2.9,3.1,2.9,3.1
The embodiment composes with any compatible policy. The same robot configuration evaluates an XPolicyLab-served VLA (any of the 40+ policies behind inspect-robots-xpolicylab) instead of an LLM:
inspect-robots run --task my-task --embodiment ros \
--policy xpolicylab -P url=ws://gpu-box:19000 -P cameras=cam_head:wrist \
-E url=ws://robot:9090 \
-E joints=joint1,joint2,joint3,joint4,joint5,joint6 \
-E command_topic=/joint_trajectory_controller/joint_trajectory \
-E cameras=wrist:/camera/wrist/image_raw/compressed:640x480 \
-E action_low=-3.1,-2.2,-2.9,-3.1,-2.9,-3.1 \
-E action_high=3.1,2.2,2.9,3.1,2.9,3.1
-P arguments go to the policy and -E arguments go to the embodiment, so
the robot half of the command never changes when you swap policies.
Construction and .info are network-free. The websocket connects on the first
reset(), after compatibility and guardrail checks have inspected the declared
spaces.
Configuration
Pass values as -E key=value arguments or as keyword arguments to
RosEmbodiment. Compact lists use commas. Camera entries use
name:topic:WxH; 640x480 means width 640 and height 480.
| Argument | Default | Meaning |
|---|---|---|
url |
ws://localhost:9090 |
rosbridge websocket URL. |
ros_version |
2 |
1 or 2. Selects message type strings and JointTrajectory duration keys. |
joints |
required | Ordered arm joint names. This order defines arm actions and joint_pos. |
joint_states_topic |
/joint_states |
sensor_msgs/JointState source. Arm and configured gripper names must appear in this topic. |
command_topic |
required | Arm controller command topic. |
command_type |
joint_trajectory |
joint_trajectory or float64_multi_array. |
action_low |
required | One lower command bound per arm joint. |
action_high |
required | One upper command bound per arm joint. |
gripper_topic |
None |
Optional gripper command topic. Adds one final action dimension. |
gripper_command_type |
ROS 1: float64; ROS 2: float64_multi_array |
Gripper wire message type. |
gripper_joint |
None |
JointState name for measured gripper position. Required exactly when gripper_topic is set. |
gripper_low |
None |
Native lower gripper command bound. Required with gripper_topic. |
gripper_high |
None |
Native upper gripper command bound. Required with gripper_topic and must exceed gripper_low. |
gripper_closed_at |
low |
low or high, identifying which native bound means closed. |
eef_pose_topic |
None |
Optional geometry_msgs/PoseStamped source for eef_pose. |
cameras |
none | Camera name to compressed topic and resolution. Compact form: wrist:/camera/compressed:640x480. |
control_hz |
10.0 |
Command rate. The adapter sleep-gates each arm publish to this rate. |
fresh_obs_timeout_s |
2/control_hz |
Maximum step-time wait for a sequence-newer joint-state message. |
camera_throttle_ms |
1000/control_hz |
Camera subscription throttle in milliseconds. Set 0 for unthrottled. |
reset_service |
None |
Optional empty-argument service called on every reset. It must return result: true. |
operator_reset_confirm |
False |
Print the scene instruction and require Enter on every reset. EOF stops the run. |
obs_timeout_s |
5.0 |
Reset-time wait for initial and post-reset messages on every configured topic. |
staleness_s |
2.0 |
Maximum cached sample age and cross-modal skew bound during observation assembly. |
simulated |
False |
Set true for a simulator such as Gazebo behind rosbridge. |
name |
ros |
Embodiment name recorded in logs, for example ros:ur5e. |
connect_timeout_s |
10 |
Websocket connection timeout. |
request_timeout_s |
30 |
Service response timeout. |
Arm bounds and gripper bounds form the action Box, so the default Inspect
Robots clamp and delta-limit guardrails can reject unsafe policy output before
it reaches rosbridge.
Controller mapping
Choose settings that match the controller's subscribed ROS message type.
| ROS controller family | Plugin setting | Typical topic and message |
|---|---|---|
ROS 1 joint_trajectory_controller/JointTrajectoryController |
command_type=joint_trajectory |
<controller>/command, trajectory_msgs/JointTrajectory |
ROS 1 position_controllers/JointGroupPositionController |
command_type=float64_multi_array |
<controller>/command, std_msgs/Float64MultiArray |
ROS 2 joint_trajectory_controller/JointTrajectoryController |
command_type=joint_trajectory |
<controller>/joint_trajectory, trajectory_msgs/msg/JointTrajectory |
ROS 2 forward_command_controller/ForwardCommandController |
command_type=float64_multi_array |
<controller>/commands, std_msgs/msg/Float64MultiArray |
| ROS 1 single-joint position controller for a gripper | gripper_command_type=float64 |
<controller>/command, std_msgs/Float64 |
| ROS 2 forward command controller for a gripper joint | gripper_command_type=float64_multi_array |
<controller>/commands, one-element std_msgs/msg/Float64MultiArray |
The stock ROS 2 gripper_action_controller is action-only and is not supported
by this publish-based adapter. Configure a forward_command_controller on the
gripper joint instead. The plugin does not send ROS action goals.
Observation and timing contract
joint_posfollows the configured arm joint order. With a gripper, its raw measured position is folded into the last element so proprioception matches the action dimension.- Arm joint positions are normally radians. The folded gripper element remains
in its controller's native unit, commonly radians or metres. Do not assume
every element of a gripper-equipped
joint_posvector has the same unit. gripperis a separate normalized field with shape(1,): 0 means closed and 1 means open.gripper_closed_at=highflips the native range.eef_poseis[x, y, z, qw, qx, qy, qz]. ROS supplies quaternion fields as xyzw, and the adapter reorders them to wxyz.state_timeis the monotonic receive time of the oldest state message used for an observation.image_times[name]records each camera frame's receive time.- A fresh joint state may be combined with an end-effector pose or camera frame
up to
staleness_sold. This is the explicit cross-modal skew bound.
The adapter subscribes to joint state at twice control_hz. On the first
reset, it measures the unthrottled native rate and warns when the publisher is
slower than that target. Each step captures the joint-state sequence just
before the arm publish and waits for a greater sequence afterward. A message
sampled just before the command but received just after it can satisfy this
check; this is a receive-time approximation intended for low-latency links.
Reset behavior
The first reset advertises command topics, performs the native-rate preflight,
subscribes with queue length 1, and verifies every configured topic and camera
resolution. Every reset then calls reset_service when configured, prompts the
operator when requested, and waits for newer messages with obs_timeout_s.
If neither reset path is configured, the adapter warns once on the second
reset because it cannot change the physical scene between trials. An operator
confirmation on non-interactive stdin raises EOFError and halts the run.
Troubleshooting
- Connection failures name the URL and both rosbridge launch commands. Confirm the server is listening, port 9090 is reachable, and no proxy intercepts the websocket.
- A missing-joint error lists all names present in
JointState. Version 0.1 requires arm and gripper state on the same topic. - Fresh-observation timeouts usually mean the native joint-state publisher is
slower than twice
control_hz. Lowercontrol_hzor raisefresh_obs_timeout_s. - Staleness errors mean a configured state or camera topic stopped arriving.
Check the publisher and consider a larger
staleness_sonly after confirming that older cross-modal pairing is acceptable. - Compressed images are base64-encoded inside rosbridge JSON. Reduce JPEG size
or increase
camera_throttle_mswhen image traffic queues behind state. - Camera resolution is written as width by height, but images are represented
as
(height, width, 3)RGB arrays. - A rosbridge
status:errorafter publishing usually indicates a mismatchedros_version,command_type, or controller message type. The first error is latched and all later client calls fail. - A 7-dimensional action space cannot also declare
eef_posein this release. This includes a seven-joint arm and a six-joint arm with a gripper. Omiteef_pose_topicuntil core supports key-priority reference matching.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inspect_robots_ros-0.1.0.tar.gz.
File metadata
- Download URL: inspect_robots_ros-0.1.0.tar.gz
- Upload date:
- Size: 38.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5c41958d209b37359b725436152b5c2836c231e0fc88a799cf466ff0d28da76
|
|
| MD5 |
7b004e55bb4252313a85c1db85913edc
|
|
| BLAKE2b-256 |
baaedad5ea28099f6b435d6362fffed4209b5e0d2f23c24cbf3895b353a6a17f
|
Provenance
The following attestation bundles were made for inspect_robots_ros-0.1.0.tar.gz:
Publisher:
release.yml on robocurve/inspect-robots
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inspect_robots_ros-0.1.0.tar.gz -
Subject digest:
c5c41958d209b37359b725436152b5c2836c231e0fc88a799cf466ff0d28da76 - Sigstore transparency entry: 2175836831
- Sigstore integration time:
-
Permalink:
robocurve/inspect-robots@d7b5a1a282b58aad5424e160163ad1e885c3a219 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/robocurve
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d7b5a1a282b58aad5424e160163ad1e885c3a219 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file inspect_robots_ros-0.1.0-py3-none-any.whl.
File metadata
- Download URL: inspect_robots_ros-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bba5857eb0fc099dda25cac4bf1a1f114edd0a7a23f935ca1e8b7d705d05ea72
|
|
| MD5 |
dae866bff101fcf01cee7137a277f17a
|
|
| BLAKE2b-256 |
a45cb2888f5c0b456e8e169af4a8d8f9b79ad7aadc1176ef7b888dcecc00c14f
|
Provenance
The following attestation bundles were made for inspect_robots_ros-0.1.0-py3-none-any.whl:
Publisher:
release.yml on robocurve/inspect-robots
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inspect_robots_ros-0.1.0-py3-none-any.whl -
Subject digest:
bba5857eb0fc099dda25cac4bf1a1f114edd0a7a23f935ca1e8b7d705d05ea72 - Sigstore transparency entry: 2175836840
- Sigstore integration time:
-
Permalink:
robocurve/inspect-robots@d7b5a1a282b58aad5424e160163ad1e885c3a219 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/robocurve
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d7b5a1a282b58aad5424e160163ad1e885c3a219 -
Trigger Event:
workflow_dispatch
-
Statement type: