From a6891eedb05e0adec3f5e5ab00ebb9b45b0d4d00 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 13:05:47 +1000 Subject: [PATCH 1/4] Add rko_lio [skip ci] Ports RoboStack/ros-kilted#104: rko_lio (PRBonn's KISS-ICP-based LiDAR-inertial odometry). It's released as 0.4.2 in humble, jazzy, lyrical and rolling, so no additional recipe is needed. Maps robin-map-dev to conda-forge's tsl_robin_map, and drops rko_lio's Eigen 3.4 minimum version, which Eigen 5's config (SameMajorVersion) rejects. Co-authored-by: Sattwik Kumar Sahu <98335434+sattwik-sahu@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-rko-lio.patch | 14 ++++++++++++++ shared/robostack.yaml | 2 ++ shared/vinca.yaml | 1 + 3 files changed, 17 insertions(+) create mode 100644 shared/patch/ros2-rko-lio.patch diff --git a/shared/patch/ros2-rko-lio.patch b/shared/patch/ros2-rko-lio.patch new file mode 100644 index 000000000..4e7fb1cb9 --- /dev/null +++ b/shared/patch/ros2-rko-lio.patch @@ -0,0 +1,14 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index cfef6f3..f227839 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -29,7 +29,8 @@ option(RKO_LIO_FETCH_CONTENT_DEPS "Fetch dependencies via FetchContent instead o + include(cmake/dependencies.cmake) + include(cmake/compat_target_sources.cmake) + +-find_package(Eigen3 3.4 REQUIRED CONFIG) ++# no minimum version: Eigen 5 (conda-forge) rejects a 3.x request (SameMajorVersion) ++find_package(Eigen3 REQUIRED CONFIG) + find_package(Sophus REQUIRED CONFIG) + find_package(TBB REQUIRED CONFIG) + find_package(tsl-robin-map REQUIRED CONFIG) diff --git a/shared/robostack.yaml b/shared/robostack.yaml index e1dd8aeac..49dc36faa 100644 --- a/shared/robostack.yaml +++ b/shared/robostack.yaml @@ -1212,6 +1212,8 @@ rapidjson-dev: robostack: [rapidjson] rmw_opensplice_cpp: robostack: [] +robin-map-dev: + robostack: [tsl_robin_map] roboticstoolbox-python: robostack: [roboticstoolbox-python] rsync: diff --git a/shared/vinca.yaml b/shared/vinca.yaml index c93bc0853..044e98aab 100644 --- a/shared/vinca.yaml +++ b/shared/vinca.yaml @@ -266,6 +266,7 @@ packages_select_by_deps: - realsense2_camera # IntelRealSense - realsense2_description # IntelRealSense - realtime_tools + - rko_lio # LiDAR-inertial odometry (PRBonn); requested in https://github.com/RoboStack/ros-kilted/pull/104 - rmf_demos - rmw - rmw_stats_shim From b05b3b273095f919f4117e55d16c8acff51a9c3f Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 18:33:18 +1000 Subject: [PATCH 2/4] rko_lio: recipe test that the online node starts [skip ci] Turns the local checks of this PR into a recipe test, so later rebuilds keep them. Co-Authored-By: Claude Opus 5.5 --- shared/tests/ros2-rko-lio.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 shared/tests/ros2-rko-lio.yaml diff --git a/shared/tests/ros2-rko-lio.yaml b/shared/tests/ros2-rko-lio.yaml new file mode 100644 index 000000000..4bec639b1 --- /dev/null +++ b/shared/tests/ros2-rko-lio.yaml @@ -0,0 +1,6 @@ +tests: + # Smoke test: `rko_lio/online_node` (the odometry node) starts (loads its libraries and the RMW) and is still running after 5 s. + - if: unix + then: + script: + - python -c "import os, subprocess, sys, time; p = subprocess.Popen([os.path.join(os.environ['PREFIX'], 'lib', 'rko_lio', 'online_node')]); time.sleep(5); r = p.poll(); p.terminate(); sys.exit(0 if r is None else 1)" From d72953911238bc4ee7948b3767ff2d067d4911e1 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Sun, 25 Oct 2026 07:39:31 +1000 Subject: [PATCH 3/4] rko_lio: recipe test passes the node's required parameters online_node throws UninitializedStaticallyTypedParameterException without imu_topic, lidar_topic and base_frame (CI, linux-64 and osx-arm64). Co-Authored-By: Claude Opus 5.5 --- shared/tests/ros2-rko-lio.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/tests/ros2-rko-lio.yaml b/shared/tests/ros2-rko-lio.yaml index 4bec639b1..a14eea2f9 100644 --- a/shared/tests/ros2-rko-lio.yaml +++ b/shared/tests/ros2-rko-lio.yaml @@ -1,6 +1,6 @@ tests: - # Smoke test: `rko_lio/online_node` (the odometry node) starts (loads its libraries and the RMW) and is still running after 5 s. + # Smoke test: `rko_lio/online_node` (the odometry node), given its required parameters, starts (loads its libraries and the RMW) and is still running after 5 s. - if: unix then: script: - - python -c "import os, subprocess, sys, time; p = subprocess.Popen([os.path.join(os.environ['PREFIX'], 'lib', 'rko_lio', 'online_node')]); time.sleep(5); r = p.poll(); p.terminate(); sys.exit(0 if r is None else 1)" + - python -c "import os, subprocess, sys, time; p = subprocess.Popen([os.path.join(os.environ['PREFIX'], 'lib', 'rko_lio', 'online_node'), '--ros-args', '-p', 'imu_topic:=/imu', '-p', 'lidar_topic:=/lidar', '-p', 'base_frame:=base_link']); time.sleep(5); r = p.poll(); p.terminate(); sys.exit(0 if r is None else 1)" From b082f6cddb5c8fa327ac5c72a1c24fb96c2e578b Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Sun, 25 Oct 2026 15:15:28 +1000 Subject: [PATCH 4/4] rko_lio recipe test: stop online_node for sure On macOS the test ran for hours: after SIGTERM the node kept running and held the test's output open, so rattler-build waited for it. Kill it after 3 s and wait. Co-Authored-By: Claude Opus 5.5 --- shared/tests/ros2-rko-lio.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/tests/ros2-rko-lio.yaml b/shared/tests/ros2-rko-lio.yaml index a14eea2f9..1544cae7b 100644 --- a/shared/tests/ros2-rko-lio.yaml +++ b/shared/tests/ros2-rko-lio.yaml @@ -1,6 +1,6 @@ tests: - # Smoke test: `rko_lio/online_node` (the odometry node), given its required parameters, starts (loads its libraries and the RMW) and is still running after 5 s. + # Smoke test: `rko_lio/online_node` (the odometry node), given its required parameters, starts (loads its libraries and the RMW) and is still running after 5 s. It's stopped (killed if SIGTERM doesn't end it) before the test exits, or the test runner waits for it. - if: unix then: script: - - python -c "import os, subprocess, sys, time; p = subprocess.Popen([os.path.join(os.environ['PREFIX'], 'lib', 'rko_lio', 'online_node'), '--ros-args', '-p', 'imu_topic:=/imu', '-p', 'lidar_topic:=/lidar', '-p', 'base_frame:=base_link']); time.sleep(5); r = p.poll(); p.terminate(); sys.exit(0 if r is None else 1)" + - python -c "import os, subprocess, sys, time; p = subprocess.Popen([os.path.join(os.environ['PREFIX'], 'lib', 'rko_lio', 'online_node'), '--ros-args', '-p', 'imu_topic:=/imu', '-p', 'lidar_topic:=/lidar', '-p', 'base_frame:=base_link']); time.sleep(5); r = p.poll(); p.terminate(); time.sleep(3); p.kill(); p.wait(); sys.exit(0 if r is None else 1)"