> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeroruntime.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Connect your ROS 2 robot and control it from another machine.

This guide connects your ROS 2 robot to an operator machine. When you're done,
moving the leader arm on one machine moves the robot on the other.

Using SO-101 arms? Follow the [SO-101](/robotics/integrations/ros2/so101) guide
instead.

## Prerequisites

* Ubuntu 24.04 and ROS 2 Jazzy on both machines
* An [access token](https://app.videosdk.live/signup) and a room id.

<Steps>
  <Step title="Install the SDK" icon="download">
    On both machines:

    ```bash theme={null}
    sudo apt install python3-venv
    source /opt/ros/jazzy/setup.bash
    python3 -m venv --system-site-packages ~/ros2-venv
    source ~/ros2-venv/bin/activate
    pip install "zeroruntime-teleops[ros2]"
    ```

    Check the install: `which zrt-teleops-ros2-leader` should print a path.
  </Step>

  <Step title="Set your environment" icon="key">
    Both machines need your token and the same room id
    (`ZERORUNTIME_MEETING_ID`). To create a room id, run this once on either
    machine and copy the result:

    ```bash theme={null}
    export ZERORUNTIME_AUTH_TOKEN="your-token-here"
    python3 -c "from zeroruntime.teleops.rooms import create_room; print(create_room())"
    ```

    Then, on both machines:

    ```bash theme={null}
    export ZERORUNTIME_AUTH_TOKEN="your-token-here"
    export ZERORUNTIME_MEETING_ID="abcd-efgh-ijkl"
    ```

    <Note>
      Repeat this setup in every new terminal: `source /opt/ros/jazzy/setup.bash`,
      `source ~/ros2-venv/bin/activate`, and the two exports.
    </Note>
  </Step>

  <Step title="Create a params file" icon="file">
    Create `params.yaml` on both machines, with your robot's joints and topics:

    ```yaml params.yaml theme={null}
    /**:
      ros__parameters:
        joint_names: [j1, j2, j3]

        # how far each joint on THIS machine's arm can move
        joint_min: [-3.14, -1.57, -2.0]
        joint_max: [ 3.14,  1.57,  2.0]

        leader_states_topic: /leader/joint_states
        follower_states_topic: /follower/joint_states
        follower_commands_topic: /follower/forward_controller/commands
    ```

    <Warning>
      Use the same `joint_names`, in the same order, on both machines. Set
      `joint_min` and `joint_max` for each machine's own arm.

      `joint_names` must also be in the same order as your controller's
      `joints`: the bridge sends a `std_msgs/Float64MultiArray` in that order.
    </Warning>
  </Step>

  <Step title="Start the bridges" icon="play">
    Start your drivers first, then one bridge on each machine:

    ```bash theme={null}
    # robot machine
    zrt-teleops-ros2-follower --ros-args --params-file params.yaml -r __ns:=/follower

    # operator machine
    zrt-teleops-ros2-leader --ros-args --params-file params.yaml -r __ns:=/leader
    ```
  </Step>

  <Step title="Take control" icon="gamepad">
    In a new terminal on the operator machine:

    ```bash theme={null}
    ros2 service call /leader/zrt_teleop_bridge/take_control std_srvs/srv/Trigger
    ```

    Move the leader arm. The robot follows it.

    If it's refused and names a joint, the two arms are too far apart. Move the
    leader to match the robot, or set `max_misalignment: 0.0` to let the robot
    move to the leader.
  </Step>
</Steps>

## Stop the robot

| To | Run on | Command |
| - | - | - |
| Stop and hold position | operator machine | `ros2 service call /leader/zrt_teleop_bridge/release_control std_srvs/srv/Trigger` |
| Emergency stop | operator machine | `ros2 service call /leader/zrt_teleop_bridge/estop std_srvs/srv/Trigger` |
| Emergency stop | robot machine | `ros2 service call /follower/zrt_teleop_bridge/estop std_srvs/srv/Trigger` |
| Clear an emergency stop | robot machine | `ros2 service call /follower/zrt_teleop_bridge/clear_estop std_srvs/srv/Trigger` |

After clearing an emergency stop, run `take_control` again.

## Troubleshooting

| Problem | Fix |
| - | - |
| `zrt-teleops-ros2-leader: command not found` | The virtual environment isn't active, or the installed version predates the ROS 2 bridge (check with `pip show zeroruntime-teleops`). A conda or pyenv Python won't work with ROS. |
| `nothing publishes <topic>` | A topic name in `params.yaml` doesn't match your driver. Check with `ros2 topic list`. |
| `no grant within 5.0s` | The follower bridge isn't running or is still joining, the two machines use different room ids, or the token and room id are from different environments. |
| `schema mismatch` (in the reply or the leader log) | `joint_names` is different on the two machines. |
| `the follower is e-stopped` | Clear the emergency stop on the robot machine. |
| Taking control fails and names a joint | Move the leader closer to the robot's position. |

## What's next

<CardGroup cols={2}>
  <Card title="Reference" icon="sliders" href="/robotics/integrations/ros2/reference">
    Settings, services, recording, and more.
  </Card>

  <Card title="SO-101" icon="gears" href="/robotics/integrations/ros2/so101">
    Set up two SO-101 arms.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.