<aside> ⌚

Time to complete: about 60–90 min, including the first container build

</aside>

Planned outcomes

After completing this guide, you will have a UR5e mock-hardware stack built on the TalTech ROS Desktop Jazzy image on the ROS computer and Unity 6000.3.23f1 on the Unity computer. ROS 2 stays inside the container: the host only needs Docker. You will build the application layer yourself, so there are no mystery layers to debug later.

UR mock hardware + joint_trajectory_controller
  → /joint_states (sensor_msgs/JointState)
  → ROS TCP Endpoint :10002
  → ROSConnection in Unity
  → RobotJointStatesListener
      validates and maps by exact joint name
  → RobotJointStateMirror
      forwards each newly accepted immutable snapshot
  → UrdfRobotMotionController
      revalidates robot metadata and actuates ArticulationBody joints
Layer Owns Does not own
UR driver / ros2_control Robot state and trajectory execution Unity rendering
ROS TCP Endpoint ROS ↔ TCP message bridge Robot semantics
ROSConnection Socket lifecycle and ROS serialization Joint mapping
RobotJointStatesListener Validation, name mapping, telemetry, accepted snapshots Actuation
RobotJointStateMirror Snapshot handoff and failure isolation Transport or kinematics
UrdfRobotMotionController Metadata-bound articulation targets ROS subscription

Prerequisites

Pick one unused ROS_DOMAIN_ID for this stack. The examples use 72.

Steps

1. Build the ROS application image

Create a small project on the ROS computer:

mkdir -p ~/ur5e-ros2-unity
cd ~/ur5e-ros2-unity

mkdir -p ~/.config/ur5e-unity
umask 077
openssl rand -base64 24 > ~/.config/ur5e-unity/selkies-password
chmod 600 ~/.config/ur5e-unity/selkies-password

Create Dockerfile:

FROM taltechivarlab/ros-desktop:jazzy@sha256:119849d6fd85af83ced74b80a2988c864546fa72446d92f0a39c33fa3f25a27a

ARG ROS_TCP_ENDPOINT_REV=54c1a64b6d5ef6ffa0a0431570bb74329b79b15b

USER root
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
      git \
      ros-jazzy-ros2controlcli \
      ros-jazzy-ur && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir -p /opt/ros2_unity_ws/src/ros_tcp_endpoint && \
    git -C /opt/ros2_unity_ws/src/ros_tcp_endpoint init && \
    git -C /opt/ros2_unity_ws/src/ros_tcp_endpoint remote add origin \
      <https://github.com/Unity-Technologies/ROS-TCP-Endpoint.git> && \
    git -C /opt/ros2_unity_ws/src/ros_tcp_endpoint fetch --depth=1 origin \
      "${ROS_TCP_ENDPOINT_REV}" && \
    git -C /opt/ros2_unity_ws/src/ros_tcp_endpoint checkout --detach FETCH_HEAD && \
    test "$(git -C /opt/ros2_unity_ws/src/ros_tcp_endpoint rev-parse HEAD)" = \
      "${ROS_TCP_ENDPOINT_REV}" && \
    bash -lc 'source /opt/ros/jazzy/setup.bash && cd /opt/ros2_unity_ws && colcon build --merge-install --packages-select ros_tcp_endpoint'

This keeps TalTech's tested Jazzy environment as the base, then adds the Universal Robots ROS 2 Driver and the exact validated ROS TCP Endpoint revision as a reproducible application layer.

<aside> 💡

The base-image digest is pinned deliberately. Update it only after validating a newer jazzy image; do not silently turn the tutorial into a moving target.

</aside>

2. Launch the container

Create compose.yaml: