The ROS2 Foundation
OLO exists to make robot programming easier and faster. While ROS2 is powerful, it has a steep learning curve and requires significant infrastructure setup. OLO wraps ROS2 complexity behind a simple SDK, letting you program robots in JavaScript or Python without needing to understand DDS, message serialization, or ROS2 build systems. The OLO Portal provides development tools (visualization, simulation, deployment), while the OLO Appliance runs your code locally on - or on the same network as - the robot itself.
The Developer Experience Gap
If you're coming from web development, mobile apps, or general software engineering, your first encounter with ROS2 can be frustrating. You might think: "I just want the robot to move forward. Why do I need to set up a workspace, understand DDS domains, define message types, configure QoS policies, and source environment files before I can send a simple velocity command?"
This isn't a criticism of ROS2 - it's designed for building complex, production-grade robotic systems where that infrastructure matters. But when you're learning, prototyping, or just want to get something working quickly, the gap between "I have an idea" and "the robot is moving" can feel unnecessarily wide.
ROS2 also isn't structured like a typical API. There's no robot.moveForward() method you can call. Instead, you work with a distributed system of nodes publishing and subscribing to topics. To move a robot, you create a publisher, construct a properly-typed Twist message, and publish it to /cmd_vel - repeatedly, because most robot bases expect continuous velocity commands. Understanding why this architecture exists (and its benefits for complex systems) takes time.
OLO provides a different entry point. The SDK gives you that moveForward() style of interface - await oloClient.core.moveFor({ linear: 0.5 }, 2000) moves your robot forward for 2 seconds - while the Portal shows you what topics exist, what data is flowing, and what your robot is doing. You can start simple, see results immediately, and learn ROS2 concepts as you need them rather than all at once upfront.
The underlying ROS2 system is still there. Every node, topic, service, parameter and action - you have full access to all of it through the SDK. OLO doesn't hide ROS2; it provides a more approachable way to work with it.
What You Need to Know About ROS2
ROS2 is the industry-standard middleware for robotics. It provides a structured way for different parts of a robot system to communicate - sensors, actuators, planning algorithms, and user interfaces all exchange data through ROS2.
Two Core Concepts:
1. Topics - Named channels for streaming data
Topics are publish/subscribe channels where data flows continuously. Any node can publish messages to a topic, and any number of nodes can subscribe to receive those messages.
Examples of common topics:
/camera/image_raw - Camera frames (sensor_msgs/Image)
/scan - LiDAR distance readings (sensor_msgs/LaserScan)
/odom - Robot position/velocity (nav_msgs/Odometry)
/cmd_vel - Movement commands (geometry_msgs/Twist)
/joint_states - Arm joint positions (sensor_msgs/JointState)
/tf - Coordinate transforms (tf2_msgs/TFMessage)2. Nodes - Independent processes that do work
Nodes are individual programs that perform specific functions. A typical robot has many nodes running simultaneously:
Example robot system:
camera_node - Captures and publishes images
lidar_node - Reads laser scanner, publishes /scan
navigation_node - Subscribes to /scan, plans paths
motor_controller - Subscribes to /cmd_vel, drives wheels
arm_controller - Manages joint trajectories
state_publisher - Broadcasts robot transforms to /tfNodes communicate exclusively through topics, services, and actions - they don't call each other directly. This loose coupling means you can add, remove, or replace nodes without affecting others.
Traditional ROS2 Development
For context, here's what traditional ROS2 development typically involves:
Traditional ROS2 Development Workflow
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 1. Set up ROS2 workspace colcon build, source setup.bash │
│ 2. Define message types .msg/.srv files, rebuild │
│ 3. Write C++/Python nodes rclcpp/rclpy, callbacks, executors │
│ 4. Configure launch files XML/Python launch system │
│ 5. Manage dependencies package.xml, CMakeLists.txt │
│ 6. Handle QoS policies Reliability, durability, history │
│ 7. Set up simulation Gazebo/Isaac Sim, URDF/SDF models, │
│ world files, sensor plugins │
│ 8. Debug with CLI tools ros2 topic echo, ros2 node list │
│ │
└─────────────────────────────────────────────────────────────────────────┘This workflow is well-suited for building production robot systems but requires understanding ROS2's build system, message definitions, and execution model, and you are mandated to use Linux and the ROS2 suite of desktop tools that have been created by the open source community. OLO provides an alternative approach for rapid development and scripting, all through a friendly web browser.
How OLO Simplifies ROS2 Programming
OLO addresses these challenges with two components working together:
1. The OLO SDK - A simple programming interface that wraps ROS2 complexity:
// OLO SDK - Simple, async JavaScript/Python
const topics = await oloClient.core.listTopics();
await oloClient.core.sendVelocity('/cmd_vel', { linear: 0.5 });
await oloClient.navigation.navigateTo({ x: 2, y: 1, yaw: 0 });2. The OLO Appliance - Software that runs on or near your robot:
┌─────────────────────────────────────────────────────────────────────────┐
│ ROBOT SIDE │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ OLO APPLIANCE │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ SCRIPT EXECUTION ENGINE │ │ │
│ │ │ │ │ │
│ │ │ Your JavaScript/Python code runs locally │ │ │
│ │ │ - Optional scheduled execution, script chaining │ │ │
│ │ │ │ │ │
│ │ └──────────────────────────┬──────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────────────────┴──────────────────────────────────┐ │ │
│ │ │ OLO SDK (Local) │ │ │
│ │ │ Wraps ROS2 complexity into simple async API calls │ │ │
│ │ └──────────────────────────┬──────────────────────────────────┘ │ │
│ │ │ │ │
│ └─────────────────────────────┼─────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ ROS2 / DDS │ │
│ │ /camera/image_raw /scan /cmd_vel /tf /joint_states │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Sensors │ │ Actuators│ │ Planning │ │
│ └─────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘Once code is deployed to the appliance, it runs locally with direct ROS2 access. The robot can navigate, manipulate objects, and execute behaviors without an internet connection.
The OLO Portal - Development and Deployment
The OLO Portal is where you develop, test, and deploy code.
┌────────────────────────────────────────────────────────────────────────┐
│ OLO PORTAL (Cloud) │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ SDK Playground │ │ Visualization │ │ Cloud Sim │ │
│ │ │ │ │ │ │ │
│ │ - Write code │ │ - 3D URDF view │ │ - Test without │ │
│ │ - AI assistant │ │ - Camera feeds │ │ real robot │ │
│ │ - Live testing │ │ - Sensor data │ │ - Iterate quickly │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ Deployment │ │ Scheduling │ │ Fleet Management │ │
│ │ │ │ │ │ │ │
│ │ - Save scripts │ │ - Timed runs │ │ - Multiple robots │ │
│ │ - Push to robot│ │ - Recurring │ │ - Remote monitoring│ │
│ │ - Version ctrl │ │ tasks │ │ - Team access │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘
│
Internet (for development workflow)
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ OLO APPLIANCE (Robot) │
│ Receives deployed scripts, runs them locally, reports status back │
└────────────────────────────────────────────────────────────────────────┘When Internet Connectivity Matters:
| Activity | Requires Internet? |
|---|---|
| Writing and testing code in SDK Playground | Yes |
| Visualizing robot state remotely | Yes |
| Running Cloud Sim | Yes |
| Deploying scripts to the appliance | Yes |
| Robot executing deployed scripts | No |
| Robot navigating autonomously | No |
| Robot running scheduled tasks | No |
How Remote Connectivity Works
When you do need remote access (development, monitoring, remote control), OLO handles the networking complexity:
| Protocol | Used For | Why |
|---|---|---|
| WebSocket | Control messages, topic data, services | Reliable delivery through firewalls; JSON-based rosbridge protocol |
| WebRTC | Video streaming, high-bandwidth topics | Peer-to-peer when possible, adaptive bitrate, hardware-accelerated encoding |
WebSocket (via ROSBridge):
- Provides a standard JSON-RPC interface to ROS2
- Handles topic subscriptions, publishing, service calls, and parameters
- Works through any firewall that allows outbound HTTPS
- Includes intelligent throttling to manage bandwidth
WebRTC (for Video and Large Data):
- Establishes peer-to-peer connections when network topology allows
- Falls back to TURN relay servers when direct connection isn't possible
- Hardware-accelerated H.264/VP8/VP9 video encoding
- Adaptive bitrate adjusts quality based on network conditions
ROS2 Domains - Isolation and Organization
ROS2 uses Domain IDs to isolate communication. Nodes on the same domain can discover and communicate with each other; nodes on different domains cannot.
Domain 0 (Default) Domain 1 Domain 2
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Robot A │ │ Robot B │ │ Simulation │
│ - /cmd_vel │ │ - /cmd_vel │ │ - /cmd_vel │
│ - /scan │ │ - /scan │ │ - /scan │
│ - /odom │ │ - /odom │ │ - /odom │
└─────────────────┘ └─────────────────┘ └─────────────────┘
No cross-domain communication - topics are isolatedKey Points:
- The OLO Appliance connects to a specific ROS2 domain (configurable, default is 0)
- Topics, nodes, and services are only visible within their domain
- Use different domains to run multiple isolated robot systems on the same network
- Set via
ROS_DOMAIN_IDenvironment variable
Namespaces - Multiple Robots, One Domain
While domains provide hard isolation, namespaces allow multiple robots to coexist within the same domain with organized, prefixed topic names:
Single Domain with Namespaced Robots
┌─────────────────────────────────────────────────────────────────────────┐
│ Domain 0 │
│ │
│ Robot 1 (namespace: /robot1) Robot 2 (namespace: /robot2) │
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
│ │ /robot1/cmd_vel │ │ /robot2/cmd_vel │ │
│ │ /robot1/scan │ │ /robot2/scan │ │
│ │ /robot1/odom │ │ /robot2/odom │ │
│ │ /robot1/camera/image │ │ /robot2/camera/image │ │
│ └──────────────────────────┘ └──────────────────────────┘ │
│ │
│ Shared Topics (no namespace) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ /tf /tf_static (transforms from ALL robots) │ │
│ │ /clock (simulation time, if used) │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘Benefits of Namespaces:
- Multiple robots share one ROS2 domain without topic name conflicts
- Shared topics like
/tfaggregate data from all robots - One appliance can access all robots in its domain
- The OLO SDK's
discoverRobots()function automatically detects namespaced robots
How OLO Handles Namespaces:
When you call discoverRobots(), OLO analyzes TF frames and topics to identify distinct robot instances:
// Discover all robots in the ROS environment
const robots = await oloClient.core.discoverRobots();
// Example output:
// [
// { namespace: 'robot_1', name: 'Robot 1', type: 'mobile_robot', signals: { hasCmdVel: true, ... } },
// { namespace: 'robot_2', name: 'Robot 2', type: 'mobile_robot', signals: { hasCmdVel: true, ... } },
// { namespace: '', name: 'Global', type: 'robot_arm', signals: { hasJointStates: true, ... } }
// ]
// Control a specific robot by including its namespace in topic names
await oloClient.core.sendVelocity('/robot1/cmd_vel', { linear: 0.5 });
await oloClient.core.sendVelocity('/robot2/cmd_vel', { linear: -0.5 });Why the OLO SDK Wraps ROS2
The OLO SDK provides a higher-level API over ROS2 operations:
1. Async/Await Patterns - All operations return promises for clean sequential code:
const topics = await oloClient.core.listTopics();
await oloClient.core.subscribe('/scan', (msg) => console.log(msg));
await oloClient.core.publish('/cmd_vel', { linear: 0.5, angular: 0 });2. Automatic Topic Type Resolution - No need to specify message types:
// Message type detected automatically from the ROS2 topic
await oloClient.core.publish('/cmd_vel', { linear: 0.5, angular: 0 });3. Built-in Safety Patterns - Robot control with automatic cleanup:
// Velocity hold - stops automatically if script is cancelled
const handle = await oloClient.core.startVelocityHold(
{ linear: 0.5 },
{ abortSignal }
);
// Timed movement - robot stops after duration OR if aborted
await oloClient.core.moveFor({ linear: 0.5 }, 3000, { abortSignal });4. Cross-Language Consistency - Same API in JavaScript and Python:
await oloClient.core.sendVelocity('/cmd_vel', { linear: 0.5, angular: 0 });
await oloClient.navigation.navigateTo({ x: 2, y: 1, yaw: 0 });Appliances and Load Distribution
A single OLO Appliance connects to one ROS2 domain and provides access to all robots (namespaces) within that domain. For advanced deployments, multiple appliances can distribute load:
INTERNET
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Browser │ │ OLO Portal │ │ Your App │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└──────────────────────┼─────────────────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Appliance A │ │ Appliance B │
│ │ │ │
│ Handles: │ │ Handles: │
│ - Navigation │ │ - Arm Control │
│ - Base movement │ │ - Gripper │
│ - LiDAR/Cameras │ │ - Vision AI │
└────────┬────────┘ └────────┬────────┘
│ │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ ROS2 Domain 0 │
│ │
│ /cmd_vel /scan /tf │
│ /joint_states /camera │
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ Mobile Manipulator │
│ (Base + Arm) │
└─────────────────────────┘When to Use Multiple Appliances:
| Scenario | Configuration |
|---|---|
| Single robot, simple tasks | One appliance handles everything |
| Complex robot (mobile base + arm) | Separate appliances for navigation vs manipulation |
| High video bandwidth | Dedicated appliance for video streaming |
| Redundancy requirements | Multiple appliances for failover |
| Team isolation | Different teams connect to different appliances |
Key Points:
- All appliances in the same domain see the same topics
- Each appliance can run scripts independently
- No special configuration needed - appliances automatically share the ROS2 topic space
Using Multiple Domains for Isolation:
Another approach is to run separate ROS2 domains, each with its own appliance. This provides complete isolation - robots in different domains cannot see each other's topics, even if they're on the same network. This is useful for running independent robot systems, separating production from testing, or isolating different customer deployments:
OLO Portal
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Appliance A │ │ Appliance B │ │ Appliance C │
│ (Domain 0) │ │ (Domain 1) │ │ (Domain 2) │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ ROS2 Domain 0 │ │ ROS2 Domain 1 │ │ ROS2 Domain 2 │
│ │ │ │ │ │
│ Warehouse │ │ Lab Testing │ │ Customer X │
│ Fleet │ │ Environment │ │ Deployment │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
No cross-domain communication - complete isolationEach appliance is configured with a ROS_DOMAIN_ID in its settings that determines which ROS2 domain it joins. You set this through the appliance configuration.
Summary: How It All Fits Together
┌─────────────────────────────────────────────────────────────────────────┐
│ DEVELOPMENT TIME │
│ │
│ Your Browser OLO Portal │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ SDK Playground│ ◄──────────► │ Cloud Services│ │
│ │ Write code │ Internet │ - Sim │ │
│ │ Test & debug │ │ - Viz │ │
│ └───────────────┘ └──────┬────────┘ │
│ │ │
│ Deploy scripts │
│ │ │
└─────────────────────────────────────────┼───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ RUNTIME (Robot) │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ OLO APPLIANCE │ │
│ │ │ │
│ │ Your Code ──► OLO SDK ──► ROS2 ──► Motors/Sensors │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘With this foundation, you're ready to understand how the OLO Appliance works and start programming robots!
