ROS 2 (Robot Operating System): concepts, tutorials and how-to guides for the current LTS
Covers ROS 2 Lyrical Luth (the current LTS): nodes, topics, services, actions, parameters and QoS policies with their compatibility rules, tf2 transforms, executors and callback groups, lifecycle (managed) nodes, DDS/RMW middleware and discovery (ROS_DOMAIN_ID, ROS_AUTOMATIC_DISCOVERY_RANGE, discovery server), colcon workspaces, launch files, SROS2 security, real-time programming, and migration from ROS 1 with ros1_bridge, together with the exact release dates, end-of-life dates and supported platforms of each distribution (Humble, Jazzy, Kilted, Lyrical). Built for robotics engineers, students and integrators who need exact command syntax, environment variables and version-specific facts rather than a general overview. Curated by Kopik from public sources: ROS 2 Documentation by Open Robotics and contributors (CC BY 4.0).
Ask your question
Free account requiredAnswers are written by a language model solely from this base's documents, with numbered sources. They can be wrong and aren't legal, medical or financial advice: check the sources before any important decision.
This assistant answers practical questions about ROS 2, the Robot Operating System, with a focus on Lyrical Luth, the current Long Term Support release. It is built for robotics engineers, students and integrators who need exact commands, environment variables and version-specific facts. Every answer comes from the official ROS 2 Documentation by Open Robotics and contributors, published under CC BY 4.0.
The building blocks: nodes, topics, services and actions
A ROS 2 system is made of nodes that exchange data in several ways. Topics carry a continuous stream of messages from publishers to subscriptions, while services use a single call-and-response: a client sends a request and receives one response.
Actions are meant for long-running procedures, where an action client waits for an action server to carry out a task and return a result. Actions are built on topics and services and are defined in .action files.
Parameters also work differently from ROS 1: in ROS 2 they are associated with each node and can be changed at runtime through ROS services. There is no global parameter server.
When a robot has several moving parts, tf2 keeps track of a tree of coordinate frames over time, so you can ask where one frame is relative to another. The assistant can walk you through writing a broadcaster or adding a new frame to the tree.
Discovery and network isolation
By default, ROS 2 tries to find all nodes on all hosts of the same subnet. The ROS_AUTOMATIC_DISCOVERY_RANGE variable controls this: SUBNET is the default, LOCALHOST limits discovery to the same machine, OFF disables automatic discovery even locally, and SYSTEM_DEFAULT leaves your middleware settings untouched.
ROS_STATIC_PEERS accepts a semicolon-separated list of addresses to reach specific machines, as long as the discovery range is not OFF. Note that neither variable is supported by rmw_zenoh, which has its own configuration.
To keep separate groups of nodes apart on a shared network, set ROS_DOMAIN_ID. The default is zero, and the documentation recommends choosing an integer between 0 and 101, inclusive, that no other ROS user on your network is using.
For larger networks, or where multicast is not available, the Fast DDS Discovery Server offers a centralized, client-server alternative to the distributed discovery used by DDS by default. Each node acts as a discovery client and points to a server through ROS_DISCOVERY_SERVER, for example 127.0.0.1:11811. This reduces discovery traffic, and several servers can be duplicated or connected for redundancy.
Installing Lyrical and choosing a middleware
Binary packages for Lyrical Luth are provided for Ubuntu 26.04 Resolute Raccoon (amd64 and aarch64), Red Hat Enterprise Linux 10 (amd64) and Windows 11 (amd64). On other systems you may need to build from source or use a container.
The default middleware is Fast DDS, but the RMW implementation can be replaced, for example by exporting RMW_IMPLEMENTATION=rmw_cyclonedds_cpp before starting your nodes.
After installation, each new terminal needs the environment: run source /opt/ros/lyrical/setup.bash, or add that line to your ~/.bashrc so it runs automatically.
To encrypt and authenticate traffic, SROS2 relies on a keystore. You point ROS_SECURITY_KEYSTORE to it, set ROS_SECURITY_ENABLE=true, and use ROS_SECURITY_STRATEGY=Enforce so that nodes without valid security files cannot start.
Launch files and execution model
Launch files describe which nodes to start and how to configure them. In ROS 2 they can be written in XML, YAML or Python. Because the launch libraries are written in Python, a Python launch file gives lower level access to launch features that XML and YAML may not expose.
Callbacks are run by executors. Calling spin(node) creates a Single-Threaded Executor, the simplest one, and a MultiThreadedExecutor is also available. Callback groups control concurrency: callbacks in a mutually exclusive group must never run in parallel. Callbacks in a reentrant group may run in parallel.
The EventsExecutor, introduced in Iron, uses a push-based model and moves timer management into a separate thread, which can give more accurate results and lower overhead, especially with many timers.
Frequently asked questions
What does ROS_AUTOMATIC_DISCOVERY_RANGE default to?
If you do not set it, the value is SUBNET. With DDS-based middleware, this means a node will discover any other node reachable via multicast. Set it to LOCALHOST to keep nodes on one machine, which is useful when several robots share a network and should not talk to each other.
Which ROS_DOMAIN_ID should I pick?
The default domain ID is zero. To pick a safe value without studying the underlying port calculation, choose an integer between 0 and 101, inclusive, that nobody else on your network uses.
Should I use a service or an action?
A service is a single request followed by one response. An action suits long-running tasks, since there is overhead in setting up and monitoring the connection, and the client waits for the server to act and return a result. Services, like topics, use reliable delivery by default.
Can I change the middleware without rebuilding?
Yes. The documentation states that Fast DDS is the default and that the RMW can be replaced at runtime, for example with the RMW_IMPLEMENTATION environment variable. Other examples given in the documentation include rmw_gurumdds_cpp and rmw_connextdds. Keep in mind that discovery variables such as ROS_STATIC_PEERS are not supported by rmw_zenoh.
What states does a lifecycle (managed) node go through?
The rclcpp_lifecycle::LifecycleNode class includes functions for transitions involving the Unconfigured, Inactive, Active and Finalized states. The assistant can explain each transition in detail from the documentation.
Do I have to source ROS 2 in every terminal?
Yes, each new shell needs the setup file to find ROS 2 commands. Adding source /opt/ros/lyrical/setup.bash to your shell startup file avoids repeating it.
Embed / API / MCP
Connect this base to Claude, Cursor, ChatGPT or your own app. Each API or MCP request costs β¬0.10, charged to your Kopik credit (not charged if nothing is found). You need an API key: create one from your dashboard.
MCP for your agents
This base's MCP server URL (tools ask_base and search_base):
https://kopik.io/api/mcp?base=ros2-robotics-documentationClaude Code, Cursor and other clients
claude mcp add --transport http kopik-ros2-robotics-documentation "https://kopik.io/api/mcp?base=ros2-robotics-documentation" --header "Authorization: Bearer kpk_β¦"{
"mcpServers": {
"kopik-ros2-robotics-documentation": {
"url": "https://kopik.io/api/mcp?base=ros2-robotics-documentation",
"headers": {
"Authorization": "Bearer kpk_β¦"
}
}
}
}REST API for your apps
mode is "answer" (written answer + sources) or "passages" (raw passages only). Add an optional maxPriceCents to cap the price: if the base costs more, the call is refused and nothing is charged.
curl -X POST https://kopik.io/api/v1/bases/ros2-robotics-documentation/query \
-H "Authorization: Bearer kpk_β¦" \
-H "Content-Type: application/json" \
-d '{"question": "Your question here", "mode": "answer"}'Getting started
- Create a key in your dashboard and top up your credit.
- Replace
kpk_β¦with your key. - Full details (responses, errors, JS and Python examples): developer docs.