From 6095a79eab674be7474af367751dff2e6a625305 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 11:19:14 +1000 Subject: [PATCH 01/15] Map the cli11 rosdep key to conda-forge cli11 mola_launcher, mp2p_icp_core/viz and mola_metric_maps find_package(CLI11) for their command-line tools; the key was unmapped, so the dependency was dropped and configure failed. gz_utils_vendor and ros_gz_sim also declare it and pick it up now. Co-Authored-By: Claude Opus 5.5 --- shared/robostack.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/robostack.yaml b/shared/robostack.yaml index e1dd8aeac..3b8c5db59 100644 --- a/shared/robostack.yaml +++ b/shared/robostack.yaml @@ -56,6 +56,8 @@ clang-format: robostack: [clang-format] clang-tidy: robostack: [clang-tools] +cli11: + robostack: [cli11] cmake: robostack: [cmake] coinor-libcbc-dev: From 2f9a0847ee8ebd381ea857bad8d59b557faad5b5 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 11:19:14 +1000 Subject: [PATCH 02/15] mrpt_common, mrpt_gui: add missing host dependencies - mrpt_common calls find_package(ament_cmake) when ROS_VERSION=2, but its package.xml (build_type cmake) does not declare it. - mrpt_gui links libwx_*; the wxwidgets/wx-common keys map to wxpython, so wxwidgets was only a transitive host dependency and its (weak) run_exports never reached the run requirements (libmrpt_gui.so and libmola_viz.so then failed to load). Co-Authored-By: Claude Opus 5.5 --- shared/patch/dependencies.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shared/patch/dependencies.yaml b/shared/patch/dependencies.yaml index 0a42505a2..5b7c1e4ef 100644 --- a/shared/patch/dependencies.yaml +++ b/shared/patch/dependencies.yaml @@ -86,6 +86,14 @@ moveit_setup_framework: add_host: ["${{ 'libgl-devel' if linux }}", "${{ 'libopengl-devel' if linux }}"] moveit_setup_srdf_plugins: add_host: ["${{ 'libgl-devel' if linux }}", "${{ 'libopengl-devel' if linux }}"] +mrpt_common: + # CMakeLists.txt calls find_package(ament_cmake) when ROS_VERSION=2 (set by ros_environment), + # but package.xml (build_type cmake) does not declare it + add_host: ["ros2-ament-cmake"] +mrpt_gui: + # links libwx_*; the wxwidgets/wx-common keys map to wxpython, so wxwidgets is only a + # transitive host dep and its (weak) run_exports never reach the run requirements + add_host: ["wxwidgets"] mujoco_ros2_control_plugins: add_host: - if: linux From d7a7a6f08e775b2f26fc1e5f1a3d537d374716f4 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 11:19:14 +1000 Subject: [PATCH 03/15] mrpt_gui: find the bundled nanogui fonts outside the find root find_file() for the fonts in 3rdparty/nanogui/resources is re-rooted under CMAKE_FIND_ROOT_PATH by the conda toolchain flags, so the source tree files are never found. Search them with NO_CMAKE_FIND_ROOT_PATH. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mrpt-gui.patch | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 shared/patch/ros2-mrpt-gui.patch diff --git a/shared/patch/ros2-mrpt-gui.patch b/shared/patch/ros2-mrpt-gui.patch new file mode 100644 index 000000000..edabfc815 --- /dev/null +++ b/shared/patch/ros2-mrpt-gui.patch @@ -0,0 +1,16 @@ +diff --git a/3rdparty/nanogui/CMakeLists.txt b/3rdparty/nanogui/CMakeLists.txt +--- a/3rdparty/nanogui/CMakeLists.txt ++++ b/3rdparty/nanogui/CMakeLists.txt +@@ -64,9 +64,9 @@ + # ------------------------------------------------------------------------- + # Resource / Font Compilation + # ------------------------------------------------------------------------- +-find_file(ENTYPO_TTF_FILE entypo.ttf PATHS "${CMAKE_CURRENT_SOURCE_DIR}/resources" REQUIRED) +-find_file(ROBOTO_BOLD_TTF_FILE Roboto-Bold.ttf PATHS /usr/share/fonts/truetype/roboto-fontface/roboto/ "${CMAKE_CURRENT_SOURCE_DIR}/resources" REQUIRED) +-find_file(ROBOTO_REGULAR_TTF_FILE Roboto-Regular.ttf PATHS /usr/share/fonts/truetype/roboto-fontface/roboto/ "${CMAKE_CURRENT_SOURCE_DIR}/resources" REQUIRED) ++find_file(ENTYPO_TTF_FILE entypo.ttf PATHS "${CMAKE_CURRENT_SOURCE_DIR}/resources" NO_CMAKE_FIND_ROOT_PATH REQUIRED) ++find_file(ROBOTO_BOLD_TTF_FILE Roboto-Bold.ttf PATHS /usr/share/fonts/truetype/roboto-fontface/roboto/ "${CMAKE_CURRENT_SOURCE_DIR}/resources" NO_CMAKE_FIND_ROOT_PATH REQUIRED) ++find_file(ROBOTO_REGULAR_TTF_FILE Roboto-Regular.ttf PATHS /usr/share/fonts/truetype/roboto-fontface/roboto/ "${CMAKE_CURRENT_SOURCE_DIR}/resources" NO_CMAKE_FIND_ROOT_PATH REQUIRED) + + set(resources ${ENTYPO_TTF_FILE} ${ROBOTO_BOLD_TTF_FILE} ${ROBOTO_REGULAR_TTF_FILE}) + message(STATUS "Font resources: ${resources}") From 9d15651f662ebc61945a1f4a78635ff784bf2c0a Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 11:19:15 +1000 Subject: [PATCH 04/15] mrpt_imgui_vendor: link CMAKE_DL_LIBS The static vendor library's GLFW/OpenGL3 backends call dlopen()/dlsym(), which live in libdl on the glibc 2.28 sysroot; mp2p_icp_viz's mm-viewer failed to link. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mrpt-imgui-vendor.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 shared/patch/ros2-mrpt-imgui-vendor.patch diff --git a/shared/patch/ros2-mrpt-imgui-vendor.patch b/shared/patch/ros2-mrpt-imgui-vendor.patch new file mode 100644 index 000000000..10614efb9 --- /dev/null +++ b/shared/patch/ros2-mrpt-imgui-vendor.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -141,6 +141,9 @@ + # Always PIC: a static vendor library gets linked into MRPT shared libraries. + set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE TRUE) + ++# The GLFW/OpenGL3 backends call dlopen()/dlsym(), which live in libdl on glibc < 2.34. ++target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS}) ++ + # Upstream headers are included unqualified (`#include "imgui.h"`), so the + # directory holding them must itself be on the interface include path. SYSTEM + # keeps third-party warnings out of consumers' builds. From 932ad74d95f236658eaa18cd63b31de5f3156f4f Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 11:19:15 +1000 Subject: [PATCH 05/15] mola_launcher: find modules in conda environments mola-cli only searches MOLA_MODULES_LIB_PATH and LD_LIBRARY_PATH for module libraries; neither is set in a conda/pixi environment, so no module was ever loaded. Also search /lib for each AMENT_PREFIX_PATH entry, and skip *__rosidl_* libraries (mola_msgs), which are never modules and whose Python ones cannot be dlopen()ed from a non-Python process. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mola-launcher.patch | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 shared/patch/ros2-mola-launcher.patch diff --git a/shared/patch/ros2-mola-launcher.patch b/shared/patch/ros2-mola-launcher.patch new file mode 100644 index 000000000..b72d789d2 --- /dev/null +++ b/shared/patch/ros2-mola-launcher.patch @@ -0,0 +1,31 @@ +diff --git a/src/MolaDLL_Loader.cpp b/src/MolaDLL_Loader.cpp +--- a/src/MolaDLL_Loader.cpp ++++ b/src/MolaDLL_Loader.cpp +@@ -59,6 +59,9 @@ + for (const auto& lib : lst) + { + if (lib.name.find("mola") == std::string::npos) continue; // skip ++ // ROS interface libraries (e.g. mola_msgs) are never MOLA modules, and the ++ // Python ones cannot be dlopen()ed from a non-Python process: ++ if (lib.name.find("__rosidl_") != std::string::npos) continue; // skip + + // Already loaded? + if (loaded_lib_handled.count(lib.name) != 0) continue; // skip +diff --git a/src/MolaLauncherApp.cpp b/src/MolaLauncherApp.cpp +--- a/src/MolaLauncherApp.cpp ++++ b/src/MolaLauncherApp.cpp +@@ -119,6 +119,14 @@ + // do not filter these ones by *directory* name, since *filenames* will be + // filtered later on: + from_env_var_to_list("LD_LIBRARY_PATH", lib_search_paths_); ++ ++ // conda/RoboStack environments do not set LD_LIBRARY_PATH: also search ++ // /lib for every prefix in AMENT_PREFIX_PATH. ++ { ++ std::vector prefixes; ++ from_env_var_to_list("AMENT_PREFIX_PATH", prefixes); ++ for (const auto& prefix : prefixes) safe_add_to_list(prefix + "/lib", lib_search_paths_); ++ } + } + + MolaLauncherApp::~MolaLauncherApp() From f115922f72687d15698269ce3c16451d90f0722a Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 11:19:15 +1000 Subject: [PATCH 06/15] Select mola on Linux [skip ci] Requested in https://github.com/RoboStack/robostack/issues/106. On lyrical this is MOLA 3.3.0 on MRPT 3 (mrpt3-release 3.3.1) and mp2p_icp 3.0.0 (mp2p_icp_core/mp2p_icp_viz), all released in the snapshot. Co-authored-by: Wolf Vollprecht <885054+wolfv@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 --- shared/vinca.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/vinca.yaml b/shared/vinca.yaml index c93bc0853..f24496cd6 100644 --- a/shared/vinca.yaml +++ b/shared/vinca.yaml @@ -448,6 +448,7 @@ packages_select_by_deps: - easynav_tools - easynav_vff_controller - libcamera + - mola # requested in https://github.com/RoboStack/robostack/issues/106 - mujoco_ros2_control # Isaac ROS deploy / Unitree G1 simulation; runtime uses Linux-specific files; mujoco_ros2_control_plugins needs EGL - mujoco_ros2_control_demos # Use readlink and access at runtime linux-specific file - navmap_core From 53ceab8bf25ddd240cabfc27fa536d024d67f78d Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 12:14:38 +1000 Subject: [PATCH 07/15] mrpt_maps: fix Bonxai Grid move assignment for clang Grid::operator=(Grid&&) move-assigns a Bonxai::Mask, which has const members and so no assignment operator. GCC never instantiates the operator, clang rejects it at definition. Re-construct the mask in place. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mrpt-maps.patch | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 shared/patch/ros2-mrpt-maps.patch diff --git a/shared/patch/ros2-mrpt-maps.patch b/shared/patch/ros2-mrpt-maps.patch new file mode 100644 index 000000000..a1a92f6a7 --- /dev/null +++ b/shared/patch/ros2-mrpt-maps.patch @@ -0,0 +1,15 @@ +diff --git a/include/mrpt/maps/bonxai/bonxai.hpp b/include/mrpt/maps/bonxai/bonxai.hpp +--- a/include/mrpt/maps/bonxai/bonxai.hpp ++++ b/include/mrpt/maps/bonxai/bonxai.hpp +@@ -538,7 +538,10 @@ + { + dim_ = other.dim_; + size_ = other.size_; +- mask_ = std::move(other.mask_); ++ // Mask has const members, so it is not assignable (clang rejects this even if ++ // the operator is never instantiated): re-construct it in place instead. ++ mask_.~Mask(); ++ new (&mask_) Bonxai::Mask(std::move(other.mask_)); + std::swap(data_, other.data_); + return *this; + } From 11b84759ae6c8bb61ad08d82017ab8f904671a7c Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 12:14:38 +1000 Subject: [PATCH 08/15] mrpt_gui: build the bundled nanogui on macOS too MRPT turns MRPT_WITH_NANOGUI off by default on Apple, which drops CDisplayWindowGUI; mola_viz requires it unconditionally. nanogui builds against GLFW and OpenGL.framework there. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mrpt-gui.patch | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/shared/patch/ros2-mrpt-gui.patch b/shared/patch/ros2-mrpt-gui.patch index edabfc815..d7bb49827 100644 --- a/shared/patch/ros2-mrpt-gui.patch +++ b/shared/patch/ros2-mrpt-gui.patch @@ -1,7 +1,7 @@ diff --git a/3rdparty/nanogui/CMakeLists.txt b/3rdparty/nanogui/CMakeLists.txt --- a/3rdparty/nanogui/CMakeLists.txt +++ b/3rdparty/nanogui/CMakeLists.txt -@@ -64,9 +64,9 @@ +@@ -64,9 +64,9 @@ endif() # ------------------------------------------------------------------------- # Resource / Font Compilation # ------------------------------------------------------------------------- @@ -14,3 +14,21 @@ diff --git a/3rdparty/nanogui/CMakeLists.txt b/3rdparty/nanogui/CMakeLists.txt set(resources ${ENTYPO_TTF_FILE} ${ROBOTO_BOLD_TTF_FILE} ${ROBOTO_REGULAR_TTF_FILE}) message(STATUS "Font resources: ${resources}") +diff --git a/cmake/script_nanogui.cmake b/cmake/script_nanogui.cmake +--- a/cmake/script_nanogui.cmake ++++ b/cmake/script_nanogui.cmake +@@ -4,11 +4,9 @@ + set(CMAKE_MRPT_HAS_NANOGUI 0) + set(CMAKE_MRPT_HAS_NANOGUI_SYSTEM 0) + +-if (APPLE) +- set(def_ OFF) +-else() +- set(def_ ON) +-endif() ++# RoboStack: also build nanogui on macOS (needed by mola_viz); it builds with GLFW and ++# OpenGL.framework. ++set(def_ ON) + set(MRPT_WITH_NANOGUI ${def_} CACHE BOOL "Build an embedded version of nanogui (OpenGL GUIs)") + unset(def_) + From f0728080873c9adcdf3ae69da184eae5fc8d09d8 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 12:14:39 +1000 Subject: [PATCH 09/15] mp2p_icp_core: build and load plugins on macOS - load_plugin(): use dlopen() on Apple too (it only did under __unix__, so macOS fell into the Windows LoadLibrary() branch), map the usual "lib.so" plugin names to .dylib there, and also search /lib for each AMENT_PREFIX_PATH entry (conda environments do not set LD_LIBRARY_PATH). - Serialize std::size_t values as uint64_t: MRPT's CArchive only accepts fixed-width integers and size_t is unsigned long, not uint64_t, on macOS. No change on Linux, where the two are the same type. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mp2p-icp-core.patch | 108 ++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 shared/patch/ros2-mp2p-icp-core.patch diff --git a/shared/patch/ros2-mp2p-icp-core.patch b/shared/patch/ros2-mp2p-icp-core.patch new file mode 100644 index 000000000..42c17e283 --- /dev/null +++ b/shared/patch/ros2-mp2p-icp-core.patch @@ -0,0 +1,108 @@ +diff --git a/mp2p_icp/include/mp2p_icp/LogRecord.h b/mp2p_icp/include/mp2p_icp/LogRecord.h +--- a/mp2p_icp/include/mp2p_icp/LogRecord.h ++++ b/mp2p_icp/include/mp2p_icp/LogRecord.h +@@ -80,7 +80,7 @@ class LogRecord : public mrpt::serialization::CSerializable + + DECLARE_TTYPENAME_CLASSNAME(mp2p_icp::LogRecord::DebugInfoPerIteration) + }; +- using iteration_idx_t = std::size_t; ++ using iteration_idx_t = std::uint64_t; + using IterationsDetails = std::map; + + std::optional iterationsDetails; +diff --git a/mp2p_icp/src/Pairings.cpp b/mp2p_icp/src/Pairings.cpp +--- a/mp2p_icp/src/Pairings.cpp ++++ b/mp2p_icp/src/Pairings.cpp +@@ -57,7 +57,7 @@ void Pairings::serializeFrom(mrpt::serialization::CArchive& in) + { + // Removed in v3: per-point weights. Read and discard, for backward + // compatibility with older serialized icplog files. +- std::vector> unusedPointWeights; ++ std::vector> unusedPointWeights; + in >> unusedPointWeights; + } + if (readVersion >= 1) +diff --git a/mp2p_icp/src/Results.cpp b/mp2p_icp/src/Results.cpp +--- a/mp2p_icp/src/Results.cpp ++++ b/mp2p_icp/src/Results.cpp +@@ -25,7 +25,7 @@ static const uint8_t SERIALIZATION_VERSION = 1; + void Results::serializeTo(mrpt::serialization::CArchive& out) const + { + out.WriteAs(SERIALIZATION_VERSION); +- out << optimal_tf << optimalScale << nIterations; ++ out << optimal_tf << optimalScale << static_cast(nIterations); + out << static_cast(terminationReason); + out << quality; + finalPairings.serializeTo(out); +@@ -37,7 +37,8 @@ void Results::serializeFrom(mrpt::serialization::CArchive& in) + + ASSERT_LE_(readVersion, SERIALIZATION_VERSION); + +- in >> optimal_tf >> optimalScale >> nIterations; ++ in >> optimal_tf >> optimalScale; ++ nIterations = static_cast(in.ReadAs()); + terminationReason = static_cast(in.ReadAs()); + in >> quality; + finalPairings.serializeFrom(in); +diff --git a/mp2p_icp_common/src/load_plugin.cpp b/mp2p_icp_common/src/load_plugin.cpp +--- a/mp2p_icp_common/src/load_plugin.cpp ++++ b/mp2p_icp_common/src/load_plugin.cpp +@@ -27,7 +27,7 @@ + #include + namespace fs = std::filesystem; + +-#if defined(__unix__) ++#if defined(__unix__) || defined(__APPLE__) + #include + #endif + +@@ -72,6 +72,14 @@ void mp2p_icp::load_plugin( + { + std::string absPath; + ++#if defined(__APPLE__) ++ // Plugin names are usually given as "lib.so": use the macOS suffix. ++ if (fs::path(moduleToLoad).extension() == ".so") ++ { ++ return load_plugin(fs::path(moduleToLoad).replace_extension(".dylib").string(), logger); ++ } ++#endif ++ + if (!fs::path(moduleToLoad).is_relative()) + { + // already absolute: +@@ -83,6 +91,13 @@ void mp2p_icp::load_plugin( + // search for it: + std::vector lstPath; + from_env_var_to_list("LD_LIBRARY_PATH", lstPath); ++ // conda/RoboStack environments do not set LD_LIBRARY_PATH: also search ++ // /lib for every prefix in AMENT_PREFIX_PATH. ++ { ++ std::vector prefixes; ++ from_env_var_to_list("AMENT_PREFIX_PATH", prefixes); ++ for (const auto& prefix : prefixes) safe_add_to_list(prefix + "/lib", lstPath); ++ } + + for (const auto& p : lstPath) + { +@@ -101,7 +116,7 @@ void mp2p_icp::load_plugin( + } + } + +-#if defined(__unix__) ++#if defined(__unix__) || defined(__APPLE__) + // Check if already loaded? + { + void* handle = dlopen(absPath.c_str(), RTLD_NOLOAD); +diff --git a/tests/test-mp2p_Pairings.cpp b/tests/test-mp2p_Pairings.cpp +--- a/tests/test-mp2p_Pairings.cpp ++++ b/tests/test-mp2p_Pairings.cpp +@@ -149,7 +149,7 @@ void test_Pairings_BackwardCompatDeserialization() + MatchedLineList ln2ln; + MatchedPlaneList pl2pl; + // Old-format per-point weights block, no longer used by current code: +- std::vector> point_weights; ++ std::vector> point_weights; + point_weights.emplace_back(1, 2.5); + const uint64_t potential_pairings = 42; + MatchedPointWithCovList cov2cov; From d1c9c53c2e8c3035bd96019b1668a994ce12d9d8 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 12:14:39 +1000 Subject: [PATCH 10/15] mp2p_icp_viz: link CoreServices on macOS libcfgpath calls FSFindFolder()/FSRefMakePath() on Apple; mm-viewer and icp-log-viewer failed to link. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mp2p-icp-viz.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 shared/patch/ros2-mp2p-icp-viz.patch diff --git a/shared/patch/ros2-mp2p-icp-viz.patch b/shared/patch/ros2-mp2p-icp-viz.patch new file mode 100644 index 000000000..f7a6c7b61 --- /dev/null +++ b/shared/patch/ros2-mp2p-icp-viz.patch @@ -0,0 +1,13 @@ +diff --git a/apps/imgui_app_common/CMakeLists.txt b/apps/imgui_app_common/CMakeLists.txt +--- a/apps/imgui_app_common/CMakeLists.txt ++++ b/apps/imgui_app_common/CMakeLists.txt +@@ -20,4 +20,9 @@ find_package(Threads REQUIRED) + + target_link_libraries(${PROJECT_NAME} PUBLIC imgui::imgui Threads::Threads) + ++# libcfgpath (used here and by the apps) calls FSFindFolder() on macOS: ++if(APPLE) ++ target_link_libraries(${PROJECT_NAME} PUBLIC "-framework CoreServices") ++endif() ++ + target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) From e5e3d5f8022f7e130323c2f24e301a77af257850 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 12:14:39 +1000 Subject: [PATCH 11/15] mola_launcher: load modules on macOS MolaDLL_Loader only used dlopen() under __unix__, which Apple clang does not define, so macOS took the Windows LoadLibrary() branch. Use dlopen() on Apple too and look for .dylib modules there. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mola-launcher.patch | 37 ++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/shared/patch/ros2-mola-launcher.patch b/shared/patch/ros2-mola-launcher.patch index b72d789d2..63b3e3da3 100644 --- a/shared/patch/ros2-mola-launcher.patch +++ b/shared/patch/ros2-mola-launcher.patch @@ -1,7 +1,27 @@ diff --git a/src/MolaDLL_Loader.cpp b/src/MolaDLL_Loader.cpp --- a/src/MolaDLL_Loader.cpp +++ b/src/MolaDLL_Loader.cpp -@@ -59,6 +59,9 @@ +@@ -24,7 +24,7 @@ + + #include + +-#if defined(__unix__) ++#if defined(__unix__) || defined(__APPLE__) + #include + #endif + +@@ -39,7 +39,9 @@ + { + MRPT_TRY_START + +-#if defined(__unix__) ++#if defined(__APPLE__) ++#define DLL_EXT "dylib" ++#elif defined(__unix__) + #define DLL_EXT "so" + #else + #define DLL_EXT "dll" +@@ -59,11 +61,14 @@ for (const auto& lib : lst) { if (lib.name.find("mola") == std::string::npos) continue; // skip @@ -11,6 +31,21 @@ diff --git a/src/MolaDLL_Loader.cpp b/src/MolaDLL_Loader.cpp // Already loaded? if (loaded_lib_handled.count(lib.name) != 0) continue; // skip + +-#if defined(__unix__) ++#if defined(__unix__) || defined(__APPLE__) + // Check if already loaded? + { + void* handle = dlopen(lib.wholePath.c_str(), RTLD_NOLOAD); +@@ -109,7 +114,7 @@ + { + // printf("[mola-launcher] Unloading: %s\n", + // lib.second.lib_path.c_str()); +-#if defined(__unix__) ++#if defined(__unix__) || defined(__APPLE__) + dlclose(lib.second.handle); + #else + FreeLibrary(lib.second.handle); diff --git a/src/MolaLauncherApp.cpp b/src/MolaLauncherApp.cpp --- a/src/MolaLauncherApp.cpp +++ b/src/MolaLauncherApp.cpp From 8ef8e587e0fcf8038132211c0fbfd6290c3cd182 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 12:14:47 +1000 Subject: [PATCH 12/15] Select mola on macOS too [skip ci] The whole MOLA / MRPT 3 / mp2p_icp tree builds on osx-arm64 with the previous fixes, and mola-cli loads all modules. Windows not tried yet. Co-Authored-By: Claude Opus 5.5 --- shared/vinca.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/vinca.yaml b/shared/vinca.yaml index f24496cd6..8cc5b2468 100644 --- a/shared/vinca.yaml +++ b/shared/vinca.yaml @@ -448,7 +448,6 @@ packages_select_by_deps: - easynav_tools - easynav_vff_controller - libcamera - - mola # requested in https://github.com/RoboStack/robostack/issues/106 - mujoco_ros2_control # Isaac ROS deploy / Unitree G1 simulation; runtime uses Linux-specific files; mujoco_ros2_control_plugins needs EGL - mujoco_ros2_control_demos # Use readlink and access at runtime linux-specific file - navmap_core @@ -564,6 +563,7 @@ packages_select_by_deps: - med14_moveit_config - med7_moveit_config - mobile_robot_simulator + - mola # requested in https://github.com/RoboStack/robostack/issues/106; Windows not tried yet - octomap_server - openvdb_vendor - orbbec_camera_msgs From c233120878d06ef0dc65b035e6b1b59d7770c4a1 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 13:10:35 +1000 Subject: [PATCH 13/15] jazzy, humble: let mrpt_gui pick a wxwidgets compatible with qt-main 5.15 These distributions map Qt to qt-main 5.15, whose builds need gstreamer <1.27 on Linux, while the pinned wxwidgets 3.3.3 needs gstreamer 1.28, so mrpt_gui's host environment (shared: add_host wxwidgets) could not be solved. A version spec bypasses the variant pin: on linux-64 the solver now takes wxwidgets 3.2.8.1 (with wxpython 4.2.4, which the wx rosdep keys map to), and its run_exports still reach the run requirements. lyrical and rolling (qt6-main) keep the shared entry. Co-Authored-By: Claude Opus 5.5 --- distros/humble/patch/dependencies.yaml | 5 +++++ distros/jazzy/patch/dependencies.yaml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/distros/humble/patch/dependencies.yaml b/distros/humble/patch/dependencies.yaml index 3f8d989cd..3d864d913 100644 --- a/distros/humble/patch/dependencies.yaml +++ b/distros/humble/patch/dependencies.yaml @@ -66,6 +66,11 @@ mrpt2: add_host: ["assimp", "octomap", "tinyxml2", "libboost-devel", "jsoncpp", "gtest", "libboost-python-devel", "libdc1394", "xorg-libxcomposite", "libftdi", "ros2-octomap"] add_run: ["assimp", "octomap", "tinyxml2", "libboost-devel", "jsoncpp", "gtest", "libboost-python-devel", "libdc1394", "xorg-libxcomposite", "libftdi", "ros2-octomap"] add_build: ["${{ cdt('libxcomposite-devel') if linux }}"] +mrpt_gui: + # Overrides shared/: this distribution maps Qt to qt-main 5.15, whose builds need + # gstreamer <1.27, while the pinned wxwidgets (3.3.3) needs gstreamer 1.28. A version + # spec bypasses that pin, so the solver picks a wxwidgets that coexists with qt-main. + add_host: ["wxwidgets >=3.2"] nav2_constrained_smoother: add_host: ["${{ 'openblas' if win }}"] nav2_util: diff --git a/distros/jazzy/patch/dependencies.yaml b/distros/jazzy/patch/dependencies.yaml index 756b4bdf4..daf9cdfa9 100644 --- a/distros/jazzy/patch/dependencies.yaml +++ b/distros/jazzy/patch/dependencies.yaml @@ -102,6 +102,11 @@ mrpt2: add_host: ["assimp", "octomap", "tinyxml2", "libboost-devel", "jsoncpp", "gtest", "libboost-python-devel", "libdc1394", "xorg-libxcomposite", "libftdi", "ros2-octomap"] add_run: ["assimp", "octomap", "tinyxml2", "libboost-devel", "jsoncpp", "gtest", "libboost-python-devel", "libdc1394", "xorg-libxcomposite", "libftdi", "ros2-octomap"] add_build: ["${{ cdt('libxcomposite-devel') if linux }}"] +mrpt_gui: + # Overrides shared/: this distribution maps Qt to qt-main 5.15, whose builds need + # gstreamer <1.27, while the pinned wxwidgets (3.3.3) needs gstreamer 1.28. A version + # spec bypasses that pin, so the solver picks a wxwidgets that coexists with qt-main. + add_host: ["wxwidgets >=3.2"] nav2_constrained_smoother: add_host: ["${{ 'openblas' if win }}"] nav2_mppi_controller: From 8af9ccdb849fa175ad645bfc48299e4fe908f00d Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 14:20:16 +1000 Subject: [PATCH 14/15] mrpt_gui: don't include the wx headers in error_box.cpp when Qt 5 is used [skip ci] showErrorMessage() only uses wx when Qt is not available, but the file includes WxUtils.h whenever wx is found. With Qt 5 (jazzy, humble) on macOS, the wx and Qt headers clash: "typedef 'NSData' cannot be referenced with the 'struct' specifier". No change on Linux or with Qt 6. Co-Authored-By: Claude Opus 5.5 --- shared/patch/ros2-mrpt-gui.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/shared/patch/ros2-mrpt-gui.patch b/shared/patch/ros2-mrpt-gui.patch index d7bb49827..42b22cb5d 100644 --- a/shared/patch/ros2-mrpt-gui.patch +++ b/shared/patch/ros2-mrpt-gui.patch @@ -32,3 +32,17 @@ diff --git a/cmake/script_nanogui.cmake b/cmake/script_nanogui.cmake set(MRPT_WITH_NANOGUI ${def_} CACHE BOOL "Build an embedded version of nanogui (OpenGL GUIs)") unset(def_) +diff --git a/src/error_box.cpp b/src/error_box.cpp +--- a/src/error_box.cpp ++++ b/src/error_box.cpp +@@ -22,7 +22,9 @@ + #else + #include + #endif // MRPT_HAS_Qt5 +-#if MRPT_HAS_WXWIDGETS ++// Only needed without Qt (see showErrorMessage()); on macOS the wx and Qt 5 headers ++// clash (NSData/NSString forward declarations). ++#if MRPT_HAS_WXWIDGETS && !MRPT_HAS_Qt5 + #include + #endif + From 00a537398b74fe5762e86fa7ca0d1d7cc296cda1 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Mon, 19 Oct 2026 18:33:24 +1000 Subject: [PATCH 15/15] mola: recipe test that mola-cli finds the modules and their classes [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-mola.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 shared/tests/ros2-mola.yaml diff --git a/shared/tests/ros2-mola.yaml b/shared/tests/ros2-mola.yaml new file mode 100644 index 000000000..ded29b8fd --- /dev/null +++ b/shared/tests/ros2-mola.yaml @@ -0,0 +1,7 @@ +tests: + # mola-cli must find the module libraries of a conda environment without any environment + # variable (shared/patch/ros2-mola-launcher.patch) and register their classes. + - if: unix + then: + script: + - python -c "import subprocess; out = subprocess.run(['mola-cli', '--rtti-list-all'], capture_output=True, text=True).stdout; missing = [c for c in ('mola::MolaViz', 'mola::BridgeROS2', 'mola::Rosbag2Dataset', 'mola::KeyframePointCloudMap') if c not in out]; assert not missing, missing"