From aed1365a3569a644533ace82cbbcbd37978120e2 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 9 Nov 2026 17:52:42 +1000 Subject: [PATCH 1/3] Docs: bridge ROS 1 and ROS 2 with ros1_bridge A short page on building ros1_bridge in a pixi project with separate Noetic and Humble environments (Humble using Noetic as an underlay), tested on Ubuntu 22.04 aarch64 with the current builds of both. Requested in #106. Co-Authored-By: Claude Opus 5.5 --- astro.config.mjs | 1 + src/content/docs/Ros1Bridge.md | 84 ++++++++++++++++++++++++++++++++++ src/data/nav.ts | 2 +- 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/content/docs/Ros1Bridge.md diff --git a/astro.config.mjs b/astro.config.mjs index aa7b0c4c..1f21ed5e 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -76,6 +76,7 @@ export default defineConfig({ ], }, { label: "JupyterRos", slug: "JupyterRos" }, + { label: "Bridging ROS 1 and ROS 2", slug: "Ros1Bridge" }, ], }, { diff --git a/src/content/docs/Ros1Bridge.md b/src/content/docs/Ros1Bridge.md new file mode 100644 index 00000000..d46825a1 --- /dev/null +++ b/src/content/docs/Ros1Bridge.md @@ -0,0 +1,84 @@ +--- +title: Bridging ROS 1 and ROS 2 +slug: Ros1Bridge +description: Connect ROS 1 Noetic and ROS 2 Humble nodes with ros1_bridge, built from source in a pixi project. +--- + +[`ros1_bridge`](https://github.com/ros2/ros1_bridge) passes topics and services between ROS 1 and ROS 2, for example between a robot running ROS 1 Noetic and a computer running ROS 2 Humble. It isn't packaged, but builds from source in a pixi project. Tested on Linux (x86_64 and aarch64). + +:::caution[Keep Noetic and Humble in separate environments] +Both distributions have packages with the same names (`std_msgs`, `rosgraph_msgs`, ...). In one environment, their Python modules and CMake files overwrite each other, which breaks `roscore` and building the bridge. +::: + +## Set up + +One pixi project with two environments, `noetic` and `humble`. The `humble` environment uses `noetic` as an underlay, like sourcing `/opt/ros/noetic` before `/opt/ros/humble` on Ubuntu. + +`pixi.toml`: + +```toml +[workspace] +name = "ros1-bridge" +channels = ["https://prefix.dev/robostack-noetic", "https://prefix.dev/robostack-humble", "https://prefix.dev/conda-forge"] +platforms = ["linux-64", "linux-aarch64"] + +[feature.noetic.dependencies] +ros-noetic-ros-base = "*" +ros-noetic-rospy-tutorials = "*" + +[feature.humble.dependencies] +ros-humble-ros-base = "*" +ros-humble-demo-nodes-cpp = "*" +ros-humble-rmw-implementation-cmake = "*" +compilers = "*" +cmake = "*" +ninja = "*" +pkg-config = "*" +colcon-common-extensions = "*" + +[feature.humble.activation] +scripts = ["noetic-underlay.sh"] + +[environments] +noetic = { features = ["noetic"], no-default-feature = true } +humble = { features = ["humble"], no-default-feature = true } +``` + +`noetic-underlay.sh`, next to it: + +```sh +NOETIC="$PIXI_PROJECT_ROOT/.pixi/envs/noetic" +export ROS1_INSTALL_PATH="$NOETIC" +export PKG_CONFIG_PATH="${PKG_CONFIG_PATH:+$PKG_CONFIG_PATH:}$NOETIC/lib/pkgconfig" +export ROS_PACKAGE_PATH="$NOETIC/share" +export ROS_MASTER_URI="${ROS_MASTER_URI:-http://localhost:11311}" +export PYTHONPATH="${PYTHONPATH:+$PYTHONPATH:}$NOETIC/lib/python3.12/site-packages" +export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH:+$CMAKE_PREFIX_PATH:}$CONDA_PREFIX:$NOETIC" +# the bridge finds the ROS 1 libraries through an rpath; LD_LIBRARY_PATH would put them +# ahead of the ROS 2 libraries for every program run in this environment +export LDFLAGS="${LDFLAGS:+$LDFLAGS }-Wl,-rpath,$NOETIC/lib" +``` + +## Build + +```sh +pixi install -a +git clone https://github.com/ros2/ros1_bridge.git ws/src/ros1_bridge +cd ws +pixi run -e humble colcon build --cmake-args -G Ninja -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DPython3_FIND_VIRTUALENV=ONLY +``` + +The bridge supports the message types present in both environments; `ros-base` gives about 130 (`std_msgs`, `geometry_msgs`, `sensor_msgs`, `nav_msgs`, ...). For more, add the message packages to both features (e.g. `ros-noetic-tf2-msgs` and `ros-humble-tf2-msgs`) and build again. + +## Run + +Each command in its own terminal, in `ws`: + +```sh +pixi run -e noetic roscore +pixi run -e humble bash -c "source install/setup.bash && ros2 run ros1_bridge dynamic_bridge --bridge-all-topics" +pixi run -e noetic rosrun rospy_tutorials talker +pixi run -e humble ros2 run demo_nodes_cpp listener +``` + +The listener prints the messages of the ROS 1 talker. To use an existing ROS 1 master, e.g. on a robot, set `ROS_MASTER_URI` instead of running `roscore`. diff --git a/src/data/nav.ts b/src/data/nav.ts index 953bf659..ff91b009 100644 --- a/src/data/nav.ts +++ b/src/data/nav.ts @@ -17,7 +17,7 @@ export const NAV_TABS: NavTab[] = [ label: "Docs", href: "/GettingStarted.html", match: - /^\/(GettingStarted|micromamba|conda|JupyterRos|FAQ|support|CommunityMeeting|Contributing|Monorepo)/, + /^\/(GettingStarted|micromamba|conda|JupyterRos|Ros1Bridge|FAQ|support|CommunityMeeting|Contributing|Monorepo)/, }, { label: "Packages", From f65dcb7d554b00964594a0a2ca5096c6db124cc0 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 9 Nov 2026 18:27:16 +1000 Subject: [PATCH 2/3] Docs: ros1_bridge on macOS Tested on osx-arm64 too: add the platform, build with C++23 (clang rejects the bridge's static_asserts in older modes) and CMAKE_INSTALL_RPATH_USE_LINK_PATH (CMake's install dropped the LDFLAGS rpath to the ROS 1 libraries on macOS), and note ROS_HOSTNAME / ROS_LOCALHOST_ONLY for a single machine. Retested on Ubuntu 22.04 aarch64 with the same flags. Co-Authored-By: Claude Opus 5.5 --- src/content/docs/Ros1Bridge.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/content/docs/Ros1Bridge.md b/src/content/docs/Ros1Bridge.md index d46825a1..9fcdbdf0 100644 --- a/src/content/docs/Ros1Bridge.md +++ b/src/content/docs/Ros1Bridge.md @@ -4,7 +4,7 @@ slug: Ros1Bridge description: Connect ROS 1 Noetic and ROS 2 Humble nodes with ros1_bridge, built from source in a pixi project. --- -[`ros1_bridge`](https://github.com/ros2/ros1_bridge) passes topics and services between ROS 1 and ROS 2, for example between a robot running ROS 1 Noetic and a computer running ROS 2 Humble. It isn't packaged, but builds from source in a pixi project. Tested on Linux (x86_64 and aarch64). +[`ros1_bridge`](https://github.com/ros2/ros1_bridge) passes topics and services between ROS 1 and ROS 2, for example between a robot running ROS 1 Noetic and a computer running ROS 2 Humble. It isn't packaged, but builds from source in a pixi project. Tested on Linux (aarch64) and macOS (Apple silicon). :::caution[Keep Noetic and Humble in separate environments] Both distributions have packages with the same names (`std_msgs`, `rosgraph_msgs`, ...). In one environment, their Python modules and CMake files overwrite each other, which breaks `roscore` and building the bridge. @@ -20,7 +20,7 @@ One pixi project with two environments, `noetic` and `humble`. The `humble` envi [workspace] name = "ros1-bridge" channels = ["https://prefix.dev/robostack-noetic", "https://prefix.dev/robostack-humble", "https://prefix.dev/conda-forge"] -platforms = ["linux-64", "linux-aarch64"] +platforms = ["linux-64", "linux-aarch64", { platform = "osx-arm64", macos = "14.0" }] [feature.noetic.dependencies] ros-noetic-ros-base = "*" @@ -54,9 +54,6 @@ export ROS_PACKAGE_PATH="$NOETIC/share" export ROS_MASTER_URI="${ROS_MASTER_URI:-http://localhost:11311}" export PYTHONPATH="${PYTHONPATH:+$PYTHONPATH:}$NOETIC/lib/python3.12/site-packages" export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH:+$CMAKE_PREFIX_PATH:}$CONDA_PREFIX:$NOETIC" -# the bridge finds the ROS 1 libraries through an rpath; LD_LIBRARY_PATH would put them -# ahead of the ROS 2 libraries for every program run in this environment -export LDFLAGS="${LDFLAGS:+$LDFLAGS }-Wl,-rpath,$NOETIC/lib" ``` ## Build @@ -65,9 +62,12 @@ export LDFLAGS="${LDFLAGS:+$LDFLAGS }-Wl,-rpath,$NOETIC/lib" pixi install -a git clone https://github.com/ros2/ros1_bridge.git ws/src/ros1_bridge cd ws -pixi run -e humble colcon build --cmake-args -G Ninja -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DPython3_FIND_VIRTUALENV=ONLY +pixi run -e humble colcon build --cmake-args -G Ninja -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DPython3_FIND_VIRTUALENV=ONLY \ + -DCMAKE_CXX_STANDARD=23 -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON ``` +`CMAKE_INSTALL_RPATH_USE_LINK_PATH` lets the bridge find the ROS 1 libraries without `LD_LIBRARY_PATH`, and C++23 is needed for clang on macOS. + The bridge supports the message types present in both environments; `ros-base` gives about 130 (`std_msgs`, `geometry_msgs`, `sensor_msgs`, `nav_msgs`, ...). For more, add the message packages to both features (e.g. `ros-noetic-tf2-msgs` and `ros-humble-tf2-msgs`) and build again. ## Run @@ -82,3 +82,5 @@ pixi run -e humble ros2 run demo_nodes_cpp listener ``` The listener prints the messages of the ROS 1 talker. To use an existing ROS 1 master, e.g. on a robot, set `ROS_MASTER_URI` instead of running `roscore`. + +On macOS, set `ROS_HOSTNAME=localhost` for the ROS 1 nodes when everything runs on one machine, and `ROS_LOCALHOST_ONLY=1` if ROS 2 nodes on the same machine don't see each other. From f861d20de25b30e5c9f4cf62ceb4997605aff129 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 9 Nov 2026 19:31:33 +1000 Subject: [PATCH 3/3] Docs: capitalise Pixi in the ros1_bridge page Co-Authored-By: Claude Opus 5.5 --- src/content/docs/Ros1Bridge.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/Ros1Bridge.md b/src/content/docs/Ros1Bridge.md index 9fcdbdf0..6900874a 100644 --- a/src/content/docs/Ros1Bridge.md +++ b/src/content/docs/Ros1Bridge.md @@ -1,10 +1,10 @@ --- title: Bridging ROS 1 and ROS 2 slug: Ros1Bridge -description: Connect ROS 1 Noetic and ROS 2 Humble nodes with ros1_bridge, built from source in a pixi project. +description: Connect ROS 1 Noetic and ROS 2 Humble nodes with ros1_bridge, built from source in a Pixi project. --- -[`ros1_bridge`](https://github.com/ros2/ros1_bridge) passes topics and services between ROS 1 and ROS 2, for example between a robot running ROS 1 Noetic and a computer running ROS 2 Humble. It isn't packaged, but builds from source in a pixi project. Tested on Linux (aarch64) and macOS (Apple silicon). +[`ros1_bridge`](https://github.com/ros2/ros1_bridge) passes topics and services between ROS 1 and ROS 2, for example between a robot running ROS 1 Noetic and a computer running ROS 2 Humble. It isn't packaged, but builds from source in a Pixi project. Tested on Linux (aarch64) and macOS (Apple silicon). :::caution[Keep Noetic and Humble in separate environments] Both distributions have packages with the same names (`std_msgs`, `rosgraph_msgs`, ...). In one environment, their Python modules and CMake files overwrite each other, which breaks `roscore` and building the bridge. @@ -12,7 +12,7 @@ Both distributions have packages with the same names (`std_msgs`, `rosgraph_msgs ## Set up -One pixi project with two environments, `noetic` and `humble`. The `humble` environment uses `noetic` as an underlay, like sourcing `/opt/ros/noetic` before `/opt/ros/humble` on Ubuntu. +One Pixi project with two environments, `noetic` and `humble`. The `humble` environment uses `noetic` as an underlay, like sourcing `/opt/ros/noetic` before `/opt/ros/humble` on Ubuntu. `pixi.toml`: