Sign inSign up

olorobotics/olo-appliance

By olorobotics

•Updated 13 days ago

Image
Developer tools
0

50K+

olorobotics/olo-appliance repository overview

⁠OLO Appliance Docker image

This image runs the OLO Appliance. This guide tells you how to start the image and which settings you can change.


⁠Supported tags

We publish each release with one version tag for each ROS 2 distribution.

TagExampleWhat it gives you
{distro}-X.Y.Z (also {distro}-vX.Y.Z)jazzy-2.4.2One fixed release
{distro}-X.Yjazzy-2.4The newest patch release of a minor version
{distro}-latestjazzy-latestThe newest release

For a production install, use the {distro}-X.Y.Z tag. Then the image changes only when you change the tag.

Replace {distro} with humble or jazzy. The distribution must be the same as the ROS 2 distribution on your robot.

The Tags tab shows the current release. The examples in this guide use X.Y.Z. Replace X.Y.Z with a real version number.

⁠Image variants
VariantTag prefixArchitecturesUse it on
Standardhumble-, jazzy-amd64, arm64Most hosts, including hosts with NVIDIA GPUs (see NVIDIA GPUs⁠)
Hexagon NPUjazzy-npu-arm64Arduino Ventuno Q

A tag that ends in -amd64 or -arm64 contains only one architecture. Our build system makes these tags. Do not use them. Use the tags in the tables above.


⁠Quick start: one container with host networking

These steps use Humble. For Jazzy, replace humble with jazzy in the tag.

docker pull olorobotics/olo-appliance:humble-X.Y.Z

docker run -d \
  --net=host \
  --name olo-appliance \
  -e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
  -e OLO_APL_APPLIANCE_NAME="My Appliance" \
  -v olo-data:/data \
  olorobotics/olo-appliance:humble-X.Y.Z

This command starts the appliance. The appliance keeps its data in the olo-data Docker volume. At the first start, the appliance gets its robot identity from the OLO server.


⁠Minimal Docker Compose example

services:
  olo-appliance:
    image: olorobotics/olo-appliance:humble-X.Y.Z
    container_name: olo-appliance
    network_mode: host
    environment:
      OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
      OLO_APL_APPLIANCE_NAME: "My Appliance"
    volumes:
      - olo-data:/data
    restart: unless-stopped

volumes:
  olo-data:
    driver: local

⁠Configuration

⁠Authentication

We recommend that you authenticate with a device API key. You get a device API key from the OLO portal when you register a new appliance.

  • OLO_APL_DEVICE_API_KEY: The device API key. The key starts with apl_. If you do not set this variable, the appliance starts the device authorization flow⁠.
  • OLO_APL_APPLIANCE_NAME: The name of this appliance, for example My Appliance.

Optional:

  • OLO_APL_ROBOT_ID: The robot ID. If you do not set it, the appliance gets the robot ID from the OLO server at the first start. If you set it, the appliance does not send this request.
⁠Device authorization flow

The device authorization flow lets you connect an appliance without a device API key. The flow uses OAuth 2.0 device authorization (RFC 8628). Use it for a first setup, or when you cannot give the appliance a key before it starts.

If OLO_APL_DEVICE_API_KEY has no value, the appliance starts the flow automatically:

  1. The appliance gets a device code from the OLO backend.
  2. The appliance writes a verification URL and a user code to the container logs.
  3. Open the URL in a browser.
  4. Enter the user code.
  5. The appliance saves the API key in /data/.appliance.json.

After step 5, the appliance uses the saved key each time it starts.

To see the URL and the user code, read the container logs:

docker logs olo-appliance

The flow stops after 30 minutes. If the flow stops before you enter the code, restart the container.

To start the appliance without an API key:

docker run -d \
  --net=host \
  --name olo-appliance \
  -e OLO_APL_APPLIANCE_NAME="My Appliance" \
  -v olo-data:/data \
  olorobotics/olo-appliance:humble-X.Y.Z

# Read the logs to get the URL and the user code
docker logs -f olo-appliance

⁠Optional configuration

⁠Authentication settings
  • OLO_APL_FORCE_DEVICE_FLOW: Set to true to start the device authorization flow when the appliance already has a saved API key. Use this setting to move an appliance to a different account or organization.
  • OLO_APL_MANAGEMENT_SECRET: A shared secret that protects these management endpoints: /device-flow/start, /device-flow/status, and /device-flow/cancel. If you set it, each request to these endpoints must send the secret as a Bearer token in the Authorization header. Most installs do not need this setting.
⁠ROS transport

The appliance connects to ROS 2 from inside its own process, through rclnodejs.

  • Cloud clients connect through the /rosbridge WebSocket on the OLO server, and through WebRTC data channels.
  • LAN clients and code execution connect to ws://localhost:<port>/local-rosbridge. <port> is the HTTP port of the appliance.
⁠Simulation time
  • OLO_APL_USE_SIM_TIME: Set to true to use simulation time. The default is false.
⁠ROS domain ID
  • ROS_DOMAIN_ID: The ROS 2 domain ID for DDS communication. The default is 0.
⁠Topic throttling

Throttling limits the rate at which the appliance sends topic messages. Use it to decrease bandwidth.

  • OLO_APL_TOPIC_DEFAULT_THROTTLE_HZ: The maximum rate in Hz for all topics. To send all messages without a limit, set it to 0 or do not set it.
  • OLO_APL_TOPIC_HANDLING_JSON: The full topic handling configuration, as JSON.

Example:

docker run -d \
  --net=host \
  --name olo-appliance \
  -e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
  -e OLO_APL_APPLIANCE_NAME="My Appliance" \
  -e OLO_APL_TOPIC_HANDLING_JSON='{"defaultThrottleFrequency": 20, "throttleTopics": {"/odom": 10, "/camera/image_raw": 5}, "throttleDataTypes": {"sensor_msgs/msg/PointCloud2": 2}}' \
  -v olo-data:/data \
  olorobotics/olo-appliance:humble-X.Y.Z

The JSON configuration has these fields:

  • defaultThrottleFrequency: The maximum rate in Hz for all topics.
  • throttleTopics: A maximum rate for each named topic.
  • throttleDataTypes: A maximum rate for each message type.

If more than one field applies to a topic, the appliance uses the first match in this order:

  1. throttleTopics
  2. throttleDataTypes
  3. defaultThrottleFrequency

⁠External ROS 2 workspace

Your robot can use custom messages, services, and actions. The appliance cannot read these types until it loads the ROS 2 workspace that defines them.

⁠How it works

Set ROS2_WS_PATH to the path of a ROS 2 workspace inside the container. When the appliance starts, it loads the base ROS distribution first. Then it loads $ROS2_WS_PATH/install/setup.bash.

⁠Share a workspace between containers

We recommend a shared Docker volume that contains your built ROS 2 workspace. The robot driver container writes its workspace to the volume. The appliance reads the workspace from the volume.

services:
  olo-appliance:
    image: olorobotics/olo-appliance:humble-X.Y.Z
    network_mode: host
    environment:
      OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
      OLO_APL_APPLIANCE_NAME: "My Appliance"
      ROS2_WS_PATH: /shared/workspace
    volumes:
      - olo-data:/data
      - ros-workspace:/shared/workspace:ro  # The appliance reads the workspace

  my-robot-driver:
    image: my-robot-driver:humble-latest
    network_mode: host
    environment:
      EXPORT_WORKSPACE: "1"  # The driver writes its workspace at startup
    volumes:
      - ros-workspace:/shared/workspace:rw  # The driver writes the workspace

volumes:
  olo-data:
    driver: local
  ros-workspace:
    driver: local

In this example:

  • The robot driver mounts the shared volume as read-write (rw). The driver writes its built workspace to the volume.
  • The appliance mounts the same volume as read-only (ro). The appliance loads the workspace from ROS2_WS_PATH.
  • The appliance can then read the custom messages, services, and actions of your robot.

⁠Robot drivers in Docker containers

You can run the appliance with one or more robot drivers in containers. All the containers must use host networking. Without host networking, ROS 2 DDS discovery does not work between the containers.

⁠Example with more than one container

This example runs the appliance with one robot driver. The two containers share a ROS 2 workspace volume.

services:
  olo-appliance:
    image: olorobotics/olo-appliance:humble-X.Y.Z
    init: true
    restart: unless-stopped
    stop_signal: SIGINT
    stop_grace_period: 40s
    network_mode: host
    ipc: host
    environment:
      OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
      OLO_APL_APPLIANCE_NAME: "My Appliance"
      ROS_DOMAIN_ID: 55
      ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET
      ROS_LOCALHOST_ONLY: 0
      ROS2_WS_PATH: /shared/workspace
    volumes:
      - olo-appliance-data:/data
      - ros-workspace:/shared/workspace:ro
      - /dev/shm:/dev/shm:rw

  my-robot-driver:
    image: your-robot-driver:humble-latest
    init: true
    restart: unless-stopped
    stop_signal: SIGINT
    stop_grace_period: 40s
    network_mode: host
    ipc: host
    environment:
      ROS_DOMAIN_ID: 55
      ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET
      ROS_LOCALHOST_ONLY: 0
    volumes:
      - ros-workspace:/shared/workspace:rw
      - /dev/shm:/dev/shm:rw
    # If your driver needs access to hardware:
    # devices:
    #   - "/dev/ttyUSB0:/dev/ttyUSB0"

volumes:
  ros-workspace:
    driver: local
  olo-appliance-data:
    driver: local
⁠Important settings
  • network_mode: host: ROS 2 DDS discovery needs this setting. Without it, the containers cannot find each other or the nodes on the host and the LAN.
  • ipc: host and the /dev/shm bind mount: Set both on every container. The shared-memory transport of Fast DDS needs them. See Topics are discovered but no messages arrive⁠.
  • ROS_DOMAIN_ID: Use the same value on all containers and all external ROS nodes.
  • ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET: Lets ROS 2 find nodes on the local subnet.
  • ros-workspace volume: The shared workspace that contains the custom message types.
  • init: true: Sends stop signals correctly, so that each container stops cleanly.
⁠Start the services
# Start all services
docker compose up -d

# Start only the appliance
docker compose up -d olo-appliance

# Show the logs
docker compose logs -f

⁠Networking and ports

With host networking, the container uses the network of the host directly. To use it, add --net=host to docker run, or network_mode: host to Docker Compose.

Use host networking for most installs. ROS 2 DDS finds nodes with multicast packets. The default Docker bridge network blocks multicast packets. Thus, without host networking, the appliance cannot find a robot that runs on a different computer on the same network.

With host networking, do not use -p port mappings. The container already uses the ports of the host.

⁠Health endpoint (bridge networking only)

You can run the appliance without host networking, on the Docker bridge network. In this mode, the appliance has an HTTP endpoint on port 8443 inside the container.

To do health checks from outside the container, publish the port:

docker run -d \
  --name olo-appliance \
  -e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
  -e OLO_APL_APPLIANCE_NAME="My Appliance" \
  -v olo-data:/data \
  -p 9443:8443 \
  olorobotics/olo-appliance:humble-X.Y.Z

Then send a request to the endpoint:

curl http://localhost:9443/health

The appliance operates normally without this port. Publish it only if you need health checks.


⁠NVIDIA GPUs

The standard image operates on hosts with NVIDIA GPUs. On an x86_64 host with an NVIDIA GPU, the appliance can encode WebRTC video on the GPU (NVENC). To use the GPU, the container must have access to it.

  1. Install the NVIDIA driver on the host.

  2. Install the NVIDIA Container Toolkit⁠ on the host.

  3. Configure Docker to use the toolkit, then restart Docker:

    sudo nvidia-ctk runtime configure --runtime=docker
    sudo systemctl restart docker
    
  4. Start the appliance with access to the GPU and with the video driver capability:

    docker run -d \
      --net=host \
      --ipc=host \
      --gpus all \
      --name olo-appliance \
      -e NVIDIA_DRIVER_CAPABILITIES=compute,utility,video \
      -e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
      -e OLO_APL_APPLIANCE_NAME="My Appliance" \
      -v olo-data:/data \
      --restart unless-stopped \
      olorobotics/olo-appliance:jazzy-X.Y.Z
    

    With Docker Compose:

    services:
      olo-appliance:
        image: olorobotics/olo-appliance:jazzy-X.Y.Z
        network_mode: host
        ipc: host
        gpus: all
        environment:
          NVIDIA_DRIVER_CAPABILITIES: compute,utility,video
          OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
          OLO_APL_APPLIANCE_NAME: "My Appliance"
        volumes:
          - olo-data:/data
        restart: unless-stopped
    
    volumes:
      olo-data:
    
  5. Start a camera stream.

  6. Find the encoder that the appliance selected:

    docker logs olo-appliance 2>&1 | grep "encoder preflight"
    
    • If the log shows selected nvautogpuh264enc, the appliance encodes video on the GPU.
    • If the log shows selected x264enc, the appliance encodes video on the CPU. Make sure that you started the container with --gpus all and with the video capability.
⁠Encoder setting

OLO_GSTREAMER_H264_ENCODER selects the H.264 encoder.

  • auto (the default): The appliance uses the first hardware encoder that operates correctly. If no hardware encoder operates, the appliance uses x264enc on the CPU.
  • x264enc: The appliance always encodes video on the CPU.
⁠AI inference

The appliance runs AI inference on the CPU on all hosts. It does not use the GPU for inference.

⁠NVIDIA Jetson

On a Jetson, use the standard arm64 image. Do not add --gpus. The image cannot use the hardware video encoder of the Jetson. Thus, the appliance encodes video on the CPU.


⁠Data storage

The appliance keeps all its data in /data inside the container:

  • /data/recordings/rosbags: ROS bag recordings.
  • /data/script-logs: Logs from script runs.
  • /data/cached-scripts: Cached scripts.
  • /data/scheduled-scripts: Data for scheduled scripts.

We recommend a named volume, so that the data stays when the container restarts:

docker volume create olo-data

docker run -d \
  --net=host \
  --name olo-appliance \
  -e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
  -e OLO_APL_APPLIANCE_NAME="My Appliance" \
  -v olo-data:/data \
  olorobotics/olo-appliance:humble-X.Y.Z

With Docker Compose:

services:
  olo-appliance:
    image: olorobotics/olo-appliance:humble-X.Y.Z
    network_mode: host
    environment:
      OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
      OLO_APL_APPLIANCE_NAME: "My Appliance"
    volumes:
      - olo-data:/data

volumes:
  olo-data:
    driver: local

⁠Troubleshooting

⁠ROS 2 nodes cannot find each other

Symptoms: topics do not show, or services are not found. To correct this, make Fast DDS use only the UDPv4 transport:

environment:
  FASTDDS_BUILTIN_TRANSPORTS: UDPv4

Or on the command line:

docker run -d \
  --net=host \
  --name olo-appliance \
  -e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
  -e OLO_APL_APPLIANCE_NAME="My Appliance" \
  -e FASTDDS_BUILTIN_TRANSPORTS="UDPv4" \
  -v olo-data:/data \
  olorobotics/olo-appliance:humble-X.Y.Z

This setting helps most in these conditions:

  • More than one container runs on the same host.
  • A container cannot see the topics of other containers or of the host.
  • The network uses a VPN or a special configuration.
⁠Topics are discovered but no messages arrive

Symptoms: ros2 topic list and ros2 topic info show the topic with a publisher and a subscriber. But no messages arrive on the topic.

This problem is different from the problem above. FASTDDS_BUILTIN_TRANSPORTS: UDPv4 alone does not correct it.

The usual cause: the containers do not share /dev/shm. To correct it, set ipc: host and the /dev/shm bind mount on every container. See the example with more than one container⁠.

Why no error shows:

  1. Without a shared /dev/shm, each container has its own private /dev/shm.
  2. Discovery uses UDP multicast. Host networking shares multicast, so discovery still works.
  3. Each side tells the other side to send messages through shared memory.
  4. Each side writes to a new buffer that the other side never reads.
  5. No messages arrive, and no component logs an error.
⁠More DDS settings

These settings give you more control of ROS 2 discovery:

environment:
  ROS_DOMAIN_ID: 55                          # Use the same value on all nodes
  ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET      # Find nodes on the local subnet
  ROS_LOCALHOST_ONLY: 0                      # Allow communication with other computers
  FASTDDS_BUILTIN_TRANSPORTS: UDPv4          # Use only the UDP transport
⁠Authentication problems
  • Make sure that OLO_APL_DEVICE_API_KEY is correct. The key must start with apl_.
  • If you did not set an API key, read docker logs olo-appliance. The logs show the verification URL and the user code.
  • If the device flow stops after 30 minutes, restart the container. The appliance starts a new flow.
  • If the device flow shows "access denied", make sure that the user who authorizes the appliance has the correct permissions in the OLO portal.
  • To connect an appliance that already has a saved key to a different account, set OLO_APL_FORCE_DEVICE_FLOW=true.
  • Make sure that the appliance can connect to the OLO backend.
  • To read the logs, run docker logs olo-appliance.
⁠Port conflicts
  • With bridge networking: if a different service uses host port 8443, map a different host port, for example -p 9443:8443.
  • With host networking: make sure that no other service uses port 8443.

Tag summary

Content type

Image

Digest

sha256:aa86842a5…

Size

1.9 GB

Last updated

13 days ago

docker pull olorobotics/olo-appliance:jazzy-npu-latest