diff --git a/distros/humble/patch/dependencies.yaml b/distros/humble/patch/dependencies.yaml index 7213a431f..bef123e72 100644 --- a/distros/humble/patch/dependencies.yaml +++ b/distros/humble/patch/dependencies.yaml @@ -89,9 +89,6 @@ py_trees_ros_tutorials: # PyQt6 (the rqt stack) can't be installed together remove_run: ["pyqt", "pyqt-builder"] add_run: ["pyqt6"] -pybind11_json_vendor: - add_host: ["pybind11_json"] - add_run: ["pybind11_json"] python_qt_binding: # pyside2 has no python 3.14 build; port to PyQt6 instead. remove_host: ["qt-main", "pyqt"] diff --git a/distros/humble/patch/ros2-menge-vendor.win.patch b/distros/humble/patch/ros2-menge-vendor.win.patch new file mode 100644 index 000000000..f76cbbb4b --- /dev/null +++ b/distros/humble/patch/ros2-menge-vendor.win.patch @@ -0,0 +1,27 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7b578b1..5475546 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -60,10 +60,21 @@ add_library( + + target_include_directories( menge_vendor PUBLIC ${TinyXML_INCLUDE_DIRS} ) + +-target_link_libraries ( menge_vendor PUBLIC dl PRIVATE ${TinyXML_LIBRARIES} ) ++if(WIN32) ++ target_link_libraries ( menge_vendor PRIVATE ${TinyXML_LIBRARIES} ) ++else() ++ target_link_libraries ( menge_vendor PUBLIC dl PRIVATE ${TinyXML_LIBRARIES} ) ++endif() + + set_target_properties( menge_vendor PROPERTIES LINKER_LANGUAGE CXX ) + ++if(WIN32) ++ # CoreConfig.h exports MENGE_API symbols only with MENGECORE_EXPORTS (dllimport otherwise, ++ # and MSVC rejects defining dllimport static data members); no libdl on Windows ++ # (SharedLibrary.h uses LoadLibrary there). ++ target_compile_definitions( menge_vendor PRIVATE MENGECORE_EXPORTS ) ++endif() ++ + include(GNUInstallDirs) + + ament_export_include_directories(include) diff --git a/distros/humble/patch/ros2-rmf-api-msgs.win.patch b/distros/humble/patch/ros2-rmf-api-msgs.win.patch new file mode 100644 index 000000000..dbe16fdd3 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-api-msgs.win.patch @@ -0,0 +1,45 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 27156a0..44d4528 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -83,11 +83,20 @@ install( + + # Generate python schemas mode whenever colcon is triggered + message(" Generating schema as py mods") ++# "eval" is a POSIX shell builtin, not a real command -- fails on Windows ++# with "'eval' is not recognized". Pass the command as plain CMake ++# arguments instead of a quoted shell string; portable everywhere. ++# conda-forge's Windows Python is "python.exe", not "python3.exe". ++if(WIN32) ++ set(PY_EXECUTABLE_NAME python) ++else() ++ set(PY_EXECUTABLE_NAME python3) ++endif() + ADD_CUSTOM_TARGET( + py_schemas_gen ALL +- COMMAND eval "python3 generate_py_schemas.py \ +- --schemas_dir ${CMAKE_CURRENT_LIST_DIR}/schemas \ +- --output_file ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/schemas.py" ++ COMMAND ${PY_EXECUTABLE_NAME} generate_py_schemas.py ++ --schemas_dir ${CMAKE_CURRENT_LIST_DIR}/schemas ++ --output_file ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/schemas.py + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/scripts) + + # Generate pydantic models according to schemas +@@ -97,11 +106,11 @@ if(PY_MODELGEN_AVAIL) + message(" Generating py models with 'datamodel-codegen'") + ADD_CUSTOM_TARGET( + py_models_gen ALL +- COMMAND eval "datamodel-codegen \ +- --disable-timestamp \ +- --input-file-type jsonschema \ +- --input ${CMAKE_CURRENT_LIST_DIR}/schemas \ +- --output ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/models" ++ COMMAND datamodel-codegen ++ --disable-timestamp ++ --input-file-type jsonschema ++ --input ${CMAKE_CURRENT_LIST_DIR}/schemas ++ --output ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/models + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/scripts) + else() + message( diff --git a/distros/humble/patch/ros2-rmf-battery.win.patch b/distros/humble/patch/ros2-rmf-battery.win.patch new file mode 100644 index 000000000..3941214e3 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-battery.win.patch @@ -0,0 +1,35 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b00fb4c..bd84a62 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -12,6 +12,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set. Used both in rmf_traffic's installed Interpolate.hpp ++ # (consumed here) and in this package's own test_battery_drain.cpp. ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -36,6 +43,16 @@ add_library(rmf_battery SHARED + ${core_lib_srcs} + ) + ++if(WIN32) ++ # rmf_battery has no dllexport annotations at all. As a shared library ++ # on Windows with nothing explicitly exported, link.exe does not ++ # produce an import .lib, so every consumer fails with LNK1181 ++ # "cannot open input file 'rmf_battery.lib'" even though ++ # rmf_battery.dll itself builds fine. Auto-export everything, same ++ # fix used for rmf_utils/rmf_traffic earlier in this package family. ++ set_target_properties(rmf_battery PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_battery + PUBLIC + rmf_utils::rmf_utils diff --git a/distros/humble/patch/ros2-rmf-building-map-tools.patch b/distros/humble/patch/ros2-rmf-building-map-tools.patch deleted file mode 100644 index bb22014d8..000000000 --- a/distros/humble/patch/ros2-rmf-building-map-tools.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/building_map/transform.py b/building_map/transform.py -index a3980ab..a9286c6 100644 ---- a/building_map/transform.py -+++ b/building_map/transform.py -@@ -29,7 +29,7 @@ class Transform: - def transform_point(self, p): - vec = np.array([[p[0]], [p[1]]]) - transformed = (self.rot_mat @ vec) * self.scale + self.t_vec -- return (np.asscalar(transformed[0]), np.asscalar(transformed[1])) -+ return (transformed.item(0), transformed.item(1)) - - def set_from_fiducials(self, fiducial_pairs, ref_scale): - print(f'Transform.set_from_fiducials()') -@@ -93,8 +93,8 @@ class Transform: - f1x = f_pair[1].x / mean_rel_scale - f1y = f_pair[1].y / mean_rel_scale - rot_f_pair1 = rot_mat @ np.array([[f1x], [f1y]]) -- rot_f1x = np.asscalar(rot_f_pair1[0]) -- rot_f1y = np.asscalar(rot_f_pair1[1]) -+ rot_f1x = rot_f_pair1.item(0) -+ rot_f1y = rot_f_pair1.item(1) - - mean_translation[0] += rot_f1x - f_pair[0].x - mean_translation[1] += rot_f1y - f_pair[0].y diff --git a/distros/humble/patch/ros2-rmf-building-sim-common.win.patch b/distros/humble/patch/ros2-rmf-building-sim-common.win.patch new file mode 100644 index 000000000..bd4a68efe --- /dev/null +++ b/distros/humble/patch/ros2-rmf-building-sim-common.win.patch @@ -0,0 +1,17 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 19810d4..fd41036 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,12 @@ + cmake_minimum_required(VERSION 3.5) + project(rmf_building_sim_common) + ++if(MSVC) ++ # Menge's headers include windows.h: without NOMINMAX its min/max macros break ++ # rclcpp's std::numeric_limits<...>::max() (C2589); M_PI needs _USE_MATH_DEFINES ++ add_compile_definitions(NOMINMAX _USE_MATH_DEFINES) ++endif() ++ + # Default to C99 + if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) diff --git a/distros/humble/patch/ros2-rmf-building-sim-gz-classic-plugins.patch b/distros/humble/patch/ros2-rmf-building-sim-gz-classic-plugins.patch new file mode 100644 index 000000000..f76dc3b02 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-building-sim-gz-classic-plugins.patch @@ -0,0 +1,29 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9ffa144..c890ff0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -148,6 +148,9 @@ target_include_directories(crowd_simulator + ${rmf_building_sim_common_INCLUDE_DIRS} + ) + ++# libgazebo and sdformat (macOS links with -undefined error) ++target_link_libraries(crowd_simulator ${GAZEBO_LIBRARIES}) ++ + ############################### + # install stuff + ############################### +diff --git a/src/thumbnail_generator.cpp b/src/thumbnail_generator.cpp +index 584a92f..c41c8cf 100644 +--- a/src/thumbnail_generator.cpp ++++ b/src/thumbnail_generator.cpp +@@ -21,6 +21,10 @@ + #include + #include + #include ++#if __has_include() ++// OpenCV 5 moved cv::boundingRect to the geometry module ++#include ++#endif + + #include "gazebo/msgs/msgs.hh" + #include "gazebo/transport/transport.hh" diff --git a/distros/humble/patch/ros2-rmf-fleet-adapter.patch b/distros/humble/patch/ros2-rmf-fleet-adapter.patch new file mode 100644 index 000000000..255aa5dca --- /dev/null +++ b/distros/humble/patch/ros2-rmf-fleet-adapter.patch @@ -0,0 +1,140 @@ +diff --git a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp +index 20e0c69..0fae30f 100644 +--- a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp ++++ b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp +@@ -150,7 +150,6 @@ private: + } + on_error_notification(const on_error_notification& o) : ep(o.ep) {} + on_error_notification(const on_error_notification&& o) : ep(std::move(o.ep)) {} +- on_error_notification& operator=(on_error_notification o) { ep = std::move(o.ep); return *this; } + virtual void out(std::ostream& os) const { + os << "on_error("; + os << rxu::what(ep); +diff --git a/src/full_control/main.cpp b/src/full_control/main.cpp +index e979212..6ae1df8 100644 +--- a/src/full_control/main.cpp ++++ b/src/full_control/main.cpp +@@ -1039,8 +1039,12 @@ std::shared_ptr make_fleet( + request_msg->fleet_name.empty()) + return; + +- connections->fleet->open_lanes(request_msg->open_lanes); +- connections->fleet->close_lanes(request_msg->close_lanes); ++ connections->fleet->open_lanes( ++ std::vector( ++ request_msg->open_lanes.begin(), request_msg->open_lanes.end())); ++ connections->fleet->close_lanes( ++ std::vector( ++ request_msg->close_lanes.begin(), request_msg->close_lanes.end())); + + std::unordered_set newly_closed_lanes; + for (const auto& l : request_msg->close_lanes) +@@ -1093,7 +1097,9 @@ std::shared_ptr make_fleet( + requests.push_back(std::move(request)); + } + connections->fleet->limit_lane_speeds(requests); +- connections->fleet->remove_speed_limits(request_msg->remove_limits); ++ connections->fleet->remove_speed_limits( ++ std::vector( ++ request_msg->remove_limits.begin(), request_msg->remove_limits.end())); + }); + + connections->interrupt_request_sub = +diff --git a/src/rmf_fleet_adapter/LegacyTask.cpp b/src/rmf_fleet_adapter/LegacyTask.cpp +index bdbb184..191d04a 100644 +--- a/src/rmf_fleet_adapter/LegacyTask.cpp ++++ b/src/rmf_fleet_adapter/LegacyTask.cpp +@@ -22,7 +22,9 @@ + + #include + ++#if defined(__linux__) + #include ++#endif + + namespace rmf_fleet_adapter { + +@@ -157,7 +159,9 @@ void LegacyTask::_start_next_phase() + // + // TODO(MXG): Remove this when the planner has been made more + // memory-efficient. ++#if defined(__linux__) + malloc_trim(0); ++#endif + + return; + } +diff --git a/src/rmf_fleet_adapter/TaskManager.cpp b/src/rmf_fleet_adapter/TaskManager.cpp +index 6edcf44..e9e8d78 100644 +--- a/src/rmf_fleet_adapter/TaskManager.cpp ++++ b/src/rmf_fleet_adapter/TaskManager.cpp +@@ -344,9 +344,9 @@ nlohmann::json& copy_phase_data( + phase_state["category"] = header.category(); + phase_state["detail"] = header.detail(); + phase_state["original_estimate_millis"] = +- std::max(0l, to_millis(header.original_duration_estimate()).count()); ++ std::max(0, to_millis(header.original_duration_estimate()).count()); + phase_state["estimate_millis"] = +- std::max(0l, to_millis(snapshot.estimate_remaining_time()).count()); ++ std::max(0, to_millis(snapshot.estimate_remaining_time()).count()); + phase_state["final_event_id"] = snapshot.final_event()->id(); + auto& event_states = phase_state["events"]; + +@@ -410,7 +410,7 @@ void copy_phase_data( + phase["category"] = header.category(); + phase["detail"] = header.detail(); + phase["estimate_millis"] = +- std::max(0l, to_millis(header.original_duration_estimate()).count()); ++ std::max(0, to_millis(header.original_duration_estimate()).count()); + } + + //============================================================================== +@@ -484,9 +484,9 @@ void TaskManager::ActiveTask::publish_task_state(TaskManager& mgr) + _state_msg["unix_millis_finish_time"] = + to_millis(finish_estimate.time_since_epoch()).count(); + _state_msg["original_estimate_millis"] = +- std::max(0l, to_millis(header.original_duration_estimate()).count()); ++ std::max(0, to_millis(header.original_duration_estimate()).count()); + _state_msg["estimate_millis"] = +- std::max(0l, to_millis(remaining_time_estimate).count()); ++ std::max(0, to_millis(remaining_time_estimate).count()); + copy_assignment(_state_msg["assigned_to"], *mgr._context); + _state_msg["status"] = + status_to_string(_task->status_overview()); +@@ -1838,7 +1838,7 @@ rmf_task::State TaskManager::_publish_pending_task( + const auto estimate = + pending.finish_state().time().value() - pending.deployment_time(); + pending_json["original_estimate_millis"] = +- std::max(0l, to_millis(estimate).count()); ++ std::max(0, to_millis(estimate).count()); + } + copy_assignment(pending_json["assigned_to"], *_context); + pending_json["status"] = "queued"; +diff --git a/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp b/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp +index 56e8e5a..a27465c 100644 +--- a/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp ++++ b/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp +@@ -73,7 +73,9 @@ + #include + #include + #include ++#if defined(__linux__) + #include ++#endif + + namespace rmf_fleet_adapter { + namespace agv { +@@ -360,7 +362,12 @@ public: + // TODO(MXG): Remove this when the planner has been made more + // memory-efficient. + handle->_pimpl->memory_trim_timer = handle->_pimpl->node->create_wall_timer( +- std::chrono::minutes(5), []() { malloc_trim(0); }); ++ std::chrono::minutes(5), []() ++ { ++#if defined(__linux__) ++ malloc_trim(0); ++#endif ++ }); + + // Create subs and pubs for bidding + auto transient_qos = rclcpp::QoS(10).transient_local(); diff --git a/distros/humble/patch/ros2-rmf-fleet-adapter.win.patch b/distros/humble/patch/ros2-rmf-fleet-adapter.win.patch new file mode 100644 index 000000000..1dfca2c89 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-fleet-adapter.win.patch @@ -0,0 +1,706 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 57ff60f..124093b 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -10,6 +10,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used across rmf_traffic/rmf_utils's installed headers and ++ # this package's own agv/RobotContext.hpp, agv/EasyFullControl.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + find_package(ament_cmake REQUIRED) + find_package(Eigen3 REQUIRED) + find_package(yaml-cpp REQUIRED) +@@ -73,6 +80,18 @@ add_library(rmf_fleet_adapter SHARED + ${rmf_fleet_adapter_srcs} + ) + ++if(MSVC) ++ # agv/Node.cpp exceeds the default object file section limit. ++ target_compile_options(rmf_fleet_adapter PRIVATE /bigobj) ++ ++ # WINDOWS_EXPORT_ALL_SYMBOLS overflows MSVC's import-lib 65535-object ++ # limit (LNK1189) on this heavily Eigen/nlohmann/rxcpp-templated ++ # library, same as rmf_traffic_ros2. Use explicit ++ # RMF_FLEET_ADAPTER_EXPORT annotations (detail/export.hpp) across ++ # the whole public API instead. ++ target_compile_definitions(rmf_fleet_adapter PRIVATE RMF_FLEET_ADAPTER_BUILDING_DLL) ++endif() ++ + target_link_libraries(rmf_fleet_adapter + PUBLIC + rmf_traffic_ros2::rmf_traffic_ros2 +@@ -80,7 +99,7 @@ target_link_libraries(rmf_fleet_adapter + rmf_task::rmf_task + rmf_task_sequence::rmf_task_sequence + rmf_task_ros2::rmf_task_ros2 +- yaml-cpp ++ yaml-cpp::yaml-cpp # the bare name means yaml-cpp.lib to MSVC (LNK1181) + ${rmf_fleet_msgs_LIBRARIES} + ${rclcpp_LIBRARIES} + ${rmf_task_msgs_LIBRARIES} +@@ -206,13 +225,34 @@ target_link_libraries(read_only_blockade + # ----------------------------------------------------------------------------- + + add_executable(full_control src/full_control/main.cpp) ++if(MSVC) ++ # RoboStack: MSVC 14.44 crashes compiling main.cpp (C1001 in its lambda handling, ++ # also unoptimized); full_control isn't built on Windows (newer releases build) ++ set_target_properties(full_control PROPERTIES EXCLUDE_FROM_ALL TRUE) ++ set(_full_control "") ++else() ++ set(_full_control full_control) ++endif() + +-target_link_libraries(full_control +- PRIVATE +- rmf_fleet_adapter +- ${rmf_fleet_msgs_LIBRARIES} +- ${rmf_task_msgs_LIBRARIES} +-) ++if(WIN32) ++ # The raw ${..._LIBRARIES} variables below each recursively re-append ++ # their own dependencies' _LIBRARIES as plain strings with no ++ # deduplication, overflowing link.exe's response-file line limit ++ # (LNK1170) -- same issue and fix as rmf_traffic_ros2/rmf_task_ros2. ++ target_link_libraries(full_control ++ PRIVATE ++ rmf_fleet_adapter ++ rmf_fleet_msgs::rmf_fleet_msgs ++ rmf_task_msgs::rmf_task_msgs ++ ) ++else() ++ target_link_libraries(full_control ++ PRIVATE ++ rmf_fleet_adapter ++ ${rmf_fleet_msgs_LIBRARIES} ++ ${rmf_task_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(full_control + PRIVATE +@@ -224,12 +264,21 @@ target_include_directories(full_control + + add_executable(mock_traffic_light src/mock_traffic_light/main.cpp) + +-target_link_libraries(mock_traffic_light +- PRIVATE +- rmf_fleet_adapter +- ${rmf_task_msgs_LIBRARIES} +- ${rmf_fleet_msgs_LIBRARIES} +-) ++if(WIN32) ++ target_link_libraries(mock_traffic_light ++ PRIVATE ++ rmf_fleet_adapter ++ rmf_task_msgs::rmf_task_msgs ++ rmf_fleet_msgs::rmf_fleet_msgs ++ ) ++else() ++ target_link_libraries(mock_traffic_light ++ PRIVATE ++ rmf_fleet_adapter ++ ${rmf_task_msgs_LIBRARIES} ++ ${rmf_fleet_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(mock_traffic_light + PRIVATE +@@ -265,13 +314,29 @@ add_executable(experimental_lift_watchdog + src/experimental_lift_watchdog/main.cpp + ) + +-target_link_libraries(experimental_lift_watchdog +- PRIVATE +- ${rclcpp_LIBRARIES} +- ${rmf_fleet_msgs_LIBRARIES} +- ${std_msgs_LIBRARIES} +- Threads::Threads +-) ++if(WIN32) ++ # The raw ${..._LIBRARIES} variables below each recursively re-append ++ # their own dependencies' _LIBRARIES as plain strings with no ++ # deduplication, stacking up a lot of repeated full paths. On Windows ++ # CI the concatenated link.exe response-file line exceeded its ++ # ~131071-character limit (LNK1170) -- same issue and same fix as ++ # rmf_traffic_ros2/rmf_task_ros2 hit earlier. ++ target_link_libraries(experimental_lift_watchdog ++ PRIVATE ++ rclcpp::rclcpp ++ rmf_fleet_msgs::rmf_fleet_msgs ++ ${std_msgs_TARGETS} ++ Threads::Threads ++ ) ++else() ++ target_link_libraries(experimental_lift_watchdog ++ PRIVATE ++ ${rclcpp_LIBRARIES} ++ ${rmf_fleet_msgs_LIBRARIES} ++ ${std_msgs_LIBRARIES} ++ Threads::Threads ++ ) ++endif() + + target_include_directories(experimental_lift_watchdog + PRIVATE +@@ -287,12 +352,21 @@ add_executable(door_supervisor + src/door_supervisor/Node.cpp + ) + +-target_link_libraries(door_supervisor +- PRIVATE +- rmf_fleet_adapter +- ${rclcpp_LIBRARIES} +- ${rmf_door_msgs_LIBRARIES} +-) ++if(WIN32) ++ target_link_libraries(door_supervisor ++ PRIVATE ++ rmf_fleet_adapter ++ rclcpp::rclcpp ++ rmf_door_msgs::rmf_door_msgs ++ ) ++else() ++ target_link_libraries(door_supervisor ++ PRIVATE ++ rmf_fleet_adapter ++ ${rclcpp_LIBRARIES} ++ ${rmf_door_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(door_supervisor + PRIVATE +@@ -306,6 +380,15 @@ add_library(robot_state_aggregator_main SHARED + src/robot_state_aggregator/RobotStateAggregator.cpp + ) + ++if(MSVC) ++ # COMPOSITION_BUILDING_DLL below is vestigial -- nothing in this ++ # package's sources actually branches on it for dllexport/dllimport, ++ # so this SHARED target has no explicit export annotations at all, ++ # and MSVC produces the .dll but no import .lib. ++ set_target_properties(robot_state_aggregator_main PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_include_directories(robot_state_aggregator_main + PRIVATE + include +@@ -408,12 +491,21 @@ add_executable(dump_fleet_states + test/dump_fleet_states.cpp + ) + +-target_link_libraries(dump_fleet_states +- PRIVATE +- rmf_fleet_adapter +- ${rclcpp_LIBRARIES} +- ${rmf_fleet_msgs_LIBRARIES} +-) ++if(WIN32) ++ target_link_libraries(dump_fleet_states ++ PRIVATE ++ rmf_fleet_adapter ++ rclcpp::rclcpp ++ rmf_fleet_msgs::rmf_fleet_msgs ++ ) ++else() ++ target_link_libraries(dump_fleet_states ++ PRIVATE ++ rmf_fleet_adapter ++ ${rclcpp_LIBRARIES} ++ ${rmf_fleet_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(dump_fleet_states + PRIVATE +@@ -500,13 +592,22 @@ rmf_api_generate_schema_headers( + ament_export_targets(rmf_fleet_adapter HAS_LIBRARY_TARGET) + ament_export_dependencies(${dep_pkgs}) + ++# RoboStack: the library's DLL goes next to the other DLLs (on PATH on Windows), not ++# with the executables in lib/rmf_fleet_adapter, or rmf_adapter.pyd can't load it ++install( ++ TARGETS rmf_fleet_adapter ++ EXPORT rmf_fleet_adapter ++ RUNTIME DESTINATION bin ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib ++) ++ + install( + TARGETS +- rmf_fleet_adapter + read_only + read_only_blockade + mock_traffic_light +- full_control ++ ${_full_control} + lift_supervisor + experimental_lift_watchdog + door_supervisor +diff --git a/include/rmf_fleet_adapter/agv/Adapter.hpp b/include/rmf_fleet_adapter/agv/Adapter.hpp +index 7360e53..6ec9be4 100644 +--- a/include/rmf_fleet_adapter/agv/Adapter.hpp ++++ b/include/rmf_fleet_adapter/agv/Adapter.hpp +@@ -25,11 +25,13 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class Adapter : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT Adapter : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp b/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp +index 6db7d8b..4af6b69 100644 +--- a/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp ++++ b/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp +@@ -21,11 +21,13 @@ + #include + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class EasyTrafficLight : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT EasyTrafficLight : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp b/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp +index b3b0b69..8e6724b 100644 +--- a/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp ++++ b/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp +@@ -37,11 +37,13 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class FleetUpdateHandle : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT FleetUpdateHandle : public std::enable_shared_from_this + { + public: + +@@ -79,7 +81,7 @@ public: + + /// Confirmation is a class used by the task acceptance callbacks to decide if + /// a task description should be accepted. +- class Confirmation ++ class RMF_FLEET_ADAPTER_EXPORT Confirmation + { + public: + +@@ -209,7 +211,7 @@ public: + void open_lanes(std::vector lane_indices); + + /// A class used to describe speed limit imposed on lanes. +- class SpeedLimitRequest ++ class RMF_FLEET_ADAPTER_EXPORT SpeedLimitRequest + { + public: + /// Constructor +diff --git a/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp b/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp +index 74891f7..fc1a445 100644 +--- a/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp ++++ b/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp +@@ -20,12 +20,14 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== + /// Implement this class to receive robot commands from RMF +-class RobotCommandHandle ++class RMF_FLEET_ADAPTER_EXPORT RobotCommandHandle + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp b/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp +index afd33bd..70b0460 100644 +--- a/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp ++++ b/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp +@@ -32,6 +32,8 @@ + #include + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + +@@ -39,7 +41,7 @@ namespace agv { + /// You will be given an instance of this class every time you add a new robot + /// to your fleet. Use that instance to send updates to RoMi-H about your + /// robot's state. +-class RobotUpdateHandle ++class RMF_FLEET_ADAPTER_EXPORT RobotUpdateHandle + { + public: + +@@ -127,7 +129,7 @@ public: + + /// The ActionExecution class should be used to manage the execution of and + /// provide updates on ongoing actions. +- class ActionExecution ++ class RMF_FLEET_ADAPTER_EXPORT ActionExecution + { + public: + /// Update the amount of time remaining for this action +@@ -198,7 +200,7 @@ public: + + /// An object to maintain an interruption of the current task. When this + /// object is destroyed, the task will resume. +- class Interruption ++ class RMF_FLEET_ADAPTER_EXPORT Interruption + { + public: + /// Call this function to resume the task while providing labels for +@@ -274,7 +276,7 @@ public: + /// An object to maintain an issue that is happening with the robot. When this + /// object is destroyed without calling resolve(), the issue will be + /// "dropped", which issues a warning to the log. +- class IssueTicket ++ class RMF_FLEET_ADAPTER_EXPORT IssueTicket + { + public: + +@@ -332,7 +334,7 @@ public: + + /// This API is experimental and will not be supported in the future. Users + /// are to avoid relying on these feature for any integration. +- class Unstable ++ class RMF_FLEET_ADAPTER_EXPORT Unstable + { + public: + /// True if this robot is allowed to accept new tasks. False if the robot +@@ -375,7 +377,7 @@ public: + /// + /// When the object is destroyed, the stubbornness will automatically be + /// released. +- class Stubbornness ++ class RMF_FLEET_ADAPTER_EXPORT Stubbornness + { + public: + /// Stop being stubborn +diff --git a/include/rmf_fleet_adapter/agv/Waypoint.hpp b/include/rmf_fleet_adapter/agv/Waypoint.hpp +index ffa92de..34a7d5a 100644 +--- a/include/rmf_fleet_adapter/agv/Waypoint.hpp ++++ b/include/rmf_fleet_adapter/agv/Waypoint.hpp +@@ -24,11 +24,13 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class Waypoint ++class RMF_FLEET_ADAPTER_EXPORT Waypoint + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/parse_graph.hpp b/include/rmf_fleet_adapter/agv/parse_graph.hpp +index ad925bd..c6226f0 100644 +--- a/include/rmf_fleet_adapter/agv/parse_graph.hpp ++++ b/include/rmf_fleet_adapter/agv/parse_graph.hpp +@@ -23,6 +23,8 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + +@@ -30,6 +32,7 @@ namespace agv { + /// + /// \warning This will throw a std::runtime_error if the file has a syntax + /// error. ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::agv::Graph parse_graph( + const std::string& filename, + const rmf_traffic::agv::VehicleTraits& vehicle_traits); +diff --git a/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp b/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp +index abca90f..885b853 100644 +--- a/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp ++++ b/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp +@@ -25,6 +25,8 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + namespace test { +@@ -33,7 +35,7 @@ namespace test { + /// This class is an alternative to the Adapter class, but made specifically for + /// testing. It does not try to connect to a Schedule Node or to any Negotiation + /// topics. It keeps its database internal. +-class MockAdapter : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT MockAdapter : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_fleet_adapter/detail/export.hpp b/include/rmf_fleet_adapter/detail/export.hpp +new file mode 100644 +index 0000000..5847ec2 +--- /dev/null ++++ b/include/rmf_fleet_adapter/detail/export.hpp +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2026 Open Source Robotics Foundation ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++*/ ++ ++#ifndef RMF_FLEET_ADAPTER__DETAIL__EXPORT_HPP ++#define RMF_FLEET_ADAPTER__DETAIL__EXPORT_HPP ++ ++// Blanket WINDOWS_EXPORT_ALL_SYMBOLS overflows MSVC's import-lib ++// 65535-object limit for this heavily Eigen/nlohmann/rxcpp-templated ++// library (same pattern rmf_traffic_ros2 hit), so the public API is ++// exported explicitly instead via this macro. ++#if defined(_WIN32) ++ #if defined(RMF_FLEET_ADAPTER_BUILDING_DLL) ++ #define RMF_FLEET_ADAPTER_EXPORT __declspec(dllexport) ++ #else ++ #define RMF_FLEET_ADAPTER_EXPORT __declspec(dllimport) ++ #endif ++#else ++ #define RMF_FLEET_ADAPTER_EXPORT ++#endif ++ ++#endif // RMF_FLEET_ADAPTER__DETAIL__EXPORT_HPP +diff --git a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp +index d76fa76..a7e3628 100644 +--- a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp ++++ b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp +@@ -713,8 +713,12 @@ namespace detail { + + template + inline auto surely(const std::tuple& tpl) +- -> decltype(apply(tpl, detail::surely())) { +- return apply(tpl, detail::surely()); ++ -> decltype(rxcpp::util::apply(tpl, detail::surely())) { ++ // Fully qualified: an unqualified apply(tpl, ...) call here is ++ // subject to ADL bringing in std::apply (tpl is a std::tuple), and ++ // MSVC resolves the resulting ambiguity differently than GCC/Clang, ++ // instantiating std::tuple_size on the wrong type (C2027/C2131). ++ return rxcpp::util::apply(tpl, detail::surely()); + } + + namespace detail { +diff --git a/src/rmf_fleet_adapter/ScheduleManager.hpp b/src/rmf_fleet_adapter/ScheduleManager.hpp +index 8a36911..d0081b1 100644 +--- a/src/rmf_fleet_adapter/ScheduleManager.hpp ++++ b/src/rmf_fleet_adapter/ScheduleManager.hpp +@@ -30,10 +30,12 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + + //============================================================================== +-class ScheduleManager ++class RMF_FLEET_ADAPTER_EXPORT ScheduleManager + { + public: + +@@ -82,6 +84,7 @@ private: + }; + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::future make_schedule_manager( + rclcpp::Node& node, + rmf_traffic_ros2::schedule::Writer& writer, +@@ -89,6 +92,7 @@ std::future make_schedule_manager( + rmf_traffic::schedule::ParticipantDescription description); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void async_make_schedule_manager( + rclcpp::Node& node, + rmf_traffic_ros2::schedule::Writer& writer, +diff --git a/src/rmf_fleet_adapter/estimation.hpp b/src/rmf_fleet_adapter/estimation.hpp +index 479516c..54d8b82 100644 +--- a/src/rmf_fleet_adapter/estimation.hpp ++++ b/src/rmf_fleet_adapter/estimation.hpp +@@ -25,6 +25,8 @@ + + #include + ++#include ++ + //============================================================================== + struct TravelInfo + { +@@ -48,18 +50,21 @@ struct TravelInfo + }; + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void check_path_finish( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::RobotState& state, + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_path_traveling( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::RobotState& state, + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_midlane_state( + const rmf_fleet_msgs::msg::Location& l, + rmf_utils::optional lane_start, +@@ -67,12 +72,14 @@ void estimate_midlane_state( + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_state( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::Location& state, + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_waypoint( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::Location& state, +diff --git a/src/rmf_fleet_adapter/load_param.hpp b/src/rmf_fleet_adapter/load_param.hpp +index 12663d1..2dc8b73 100644 +--- a/src/rmf_fleet_adapter/load_param.hpp ++++ b/src/rmf_fleet_adapter/load_param.hpp +@@ -29,6 +29,8 @@ + #include + #include + ++#include ++ + namespace rmf_fleet_adapter { + + //============================================================================== +@@ -51,15 +53,18 @@ T get_parameter_or_default( + } + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::string get_fleet_name_parameter(rclcpp::Node& node); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::chrono::nanoseconds get_parameter_or_default_time( + rclcpp::Node& node, + const std::string& param_name, + const double default_value); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::agv::VehicleTraits get_traits_or_default( + rclcpp::Node& node, + const double default_v_nom, const double default_w_nom, +@@ -67,12 +72,14 @@ rmf_traffic::agv::VehicleTraits get_traits_or_default( + const double default_r_f, const double default_r_v); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::optional get_battery_system( + rclcpp::Node& node, + const double default_voltage, + const double default_capacity, + const double default_charging_current); + ++RMF_FLEET_ADAPTER_EXPORT + std::optional get_mechanical_system( + rclcpp::Node& node, + const double default_mass, +diff --git a/src/rmf_fleet_adapter/make_trajectory.hpp b/src/rmf_fleet_adapter/make_trajectory.hpp +index a9f775e..3bc0cfd 100644 +--- a/src/rmf_fleet_adapter/make_trajectory.hpp ++++ b/src/rmf_fleet_adapter/make_trajectory.hpp +@@ -24,30 +24,37 @@ + + #include + ++#include ++ + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_trajectory( + const rmf_fleet_msgs::msg::RobotState& state, + const rmf_traffic::agv::VehicleTraits& traits, + bool& is_sitting); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_trajectory( + const rmf_traffic::Time start_time, + const std::vector& path, + const rmf_traffic::agv::VehicleTraits& traits); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_timed_trajectory( + const std::vector& path, + const rmf_traffic::agv::VehicleTraits& traits); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Route make_route( + const rmf_fleet_msgs::msg::RobotState& state, + const rmf_traffic::agv::VehicleTraits& traits, + bool& is_sitting); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_hold( + const rmf_fleet_msgs::msg::Location& location, + const rmf_traffic::Time time, diff --git a/distros/humble/patch/ros2-rmf-robot-sim-gz-plugins.patch b/distros/humble/patch/ros2-rmf-robot-sim-gz-plugins.patch new file mode 100644 index 000000000..3183c1a8f --- /dev/null +++ b/distros/humble/patch/ros2-rmf-robot-sim-gz-plugins.patch @@ -0,0 +1,34 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 352806f..5332f2d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -24,7 +24,7 @@ find_package(rclcpp REQUIRED) + + find_package(ignition-cmake2 REQUIRED) + +-ign_find_package(ignition-gazebo6 REQUIRED) ++ign_find_package(ignition-gazebo6 REQUIRED COMPONENTS gui) + set(IGN_GAZEBO_VER 6) + ign_find_package(ignition-plugin1 REQUIRED COMPONENTS register) + set(IGN_PLUGIN_VER 1) +@@ -173,6 +173,8 @@ ament_target_dependencies(LightTuning + Qt5Quick + rclcpp + ) ++# GuiSystem lives in the gui library (macOS doesn't allow it to stay undefined) ++target_link_libraries(LightTuning ignition-gazebo${IGN_GAZEBO_VER}::ignition-gazebo${IGN_GAZEBO_VER}-gui) + + target_include_directories(LightTuning + PUBLIC +diff --git a/src/LightTuning/LightTuning.cpp b/src/LightTuning/LightTuning.cpp +index 0b23f05..bb52ad7 100644 +--- a/src/LightTuning/LightTuning.cpp ++++ b/src/LightTuning/LightTuning.cpp +@@ -450,7 +450,6 @@ signals: + void markerSelected(QString nm); + + public slots: +- void OnLightTypeSelect(sdf::Light& light, const QString& type); + void OnCreateLightBtnPress( + int idx, bool cast_shadow, const QString& type, + const QString& name, const QString& pose_str, diff --git a/distros/humble/patch/ros2-rmf-task-ros2.win.patch b/distros/humble/patch/ros2-rmf-task-ros2.win.patch new file mode 100644 index 000000000..e5ac431e1 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-task-ros2.win.patch @@ -0,0 +1,53 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 48c9e42..b5b81cf 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -28,14 +28,26 @@ find_package(nlohmann_json_schema_validator REQUIRED) + file(GLOB_RECURSE core_lib_srcs "src/rmf_task_ros2/*.cpp") + add_library(rmf_task_ros2 SHARED ${core_lib_srcs}) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this target, so ++ # without this MSVC produces the .dll but no companion .lib, and ++ # rmf_task_dispatcher/rmf_bidder_node fail with LNK1181. Only 5 ++ # source files here (vs. rmf_traffic_ros2's 26), so the LNK1189 ++ # 65535-object import-lib limit isn't a concern. ++ set_target_properties(rmf_task_ros2 PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_task_ros2 + PUBLIC + rmf_api_msgs::rmf_api_msgs + rmf_traffic::rmf_traffic + rmf_traffic_ros2::rmf_traffic_ros2 + rmf_websocket::rmf_websocket +- ${rmf_task_msgs_LIBRARIES} +- ${rclcpp_LIBRARIES} ++ # (Windows) imported targets instead of ${..._LIBRARIES}: their repeated paths overflowed ++ # link.exe's command line limit (LNK1170) ++ rmf_task_msgs::rmf_task_msgs ++ rclcpp::rclcpp + nlohmann_json::nlohmann_json + nlohmann_json_schema_validator + ) +@@ -109,8 +121,18 @@ install( + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + ++# RoboStack: the library's DLL next to the other DLLs (on PATH on Windows), not with the ++# executables in lib/rmf_task_ros2, where its users couldn't load it ++install( ++ TARGETS rmf_task_ros2 ++ EXPORT rmf_task_ros2 ++ RUNTIME DESTINATION bin ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib ++) ++ + install( +- TARGETS rmf_task_ros2 rmf_task_dispatcher rmf_bidder_node ++ TARGETS rmf_task_dispatcher rmf_bidder_node + EXPORT rmf_task_ros2 + RUNTIME DESTINATION lib/rmf_task_ros2 + LIBRARY DESTINATION lib diff --git a/distros/humble/patch/ros2-rmf-task-sequence.win.patch b/distros/humble/patch/ros2-rmf-task-sequence.win.patch new file mode 100644 index 000000000..df36895aa --- /dev/null +++ b/distros/humble/patch/ros2-rmf-task-sequence.win.patch @@ -0,0 +1,32 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 70eaf0e..9538863 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,6 +13,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used via rmf_traffic's installed agv/Interpolate.hpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -38,6 +44,14 @@ add_library(rmf_task_sequence SHARED + ${lib_srcs} + ) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this target, so ++ # without this MSVC produces the .dll but no companion .lib, and ++ # test_rmf_task_sequence/downstream consumers fail with LNK1181. ++ set_target_properties(rmf_task_sequence PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_task_sequence + PUBLIC + rmf_task::rmf_task diff --git a/distros/humble/patch/ros2-rmf-task.patch b/distros/humble/patch/ros2-rmf-task.patch new file mode 100644 index 000000000..2019760fc --- /dev/null +++ b/distros/humble/patch/ros2-rmf-task.patch @@ -0,0 +1,168 @@ +diff --git a/include/rmf_task/Event.hpp b/include/rmf_task/Event.hpp +index 82a3e60..5771d9a 100644 +--- a/include/rmf_task/Event.hpp ++++ b/include/rmf_task/Event.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__EVENT_HPP + #define RMF_TASK__EVENT_HPP + ++#include + #include + #include + +diff --git a/include/rmf_task/Log.hpp b/include/rmf_task/Log.hpp +index f046442..f62062d 100644 +--- a/include/rmf_task/Log.hpp ++++ b/include/rmf_task/Log.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__LOG_HPP + #define RMF_TASK__LOG_HPP + ++#include + #include + + #include +diff --git a/include/rmf_task/Payload.hpp b/include/rmf_task/Payload.hpp +index 084da6a..f6448f7 100644 +--- a/include/rmf_task/Payload.hpp ++++ b/include/rmf_task/Payload.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__PAYLOAD_HPP + #define RMF_TASK__PAYLOAD_HPP + ++#include + #include + + #include +diff --git a/include/rmf_task/Phase.hpp b/include/rmf_task/Phase.hpp +index 666ca1b..cf024b6 100644 +--- a/include/rmf_task/Phase.hpp ++++ b/include/rmf_task/Phase.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__PHASE_HPP + #define RMF_TASK__PHASE_HPP + ++#include + #include + #include + +diff --git a/include/rmf_task/Task.hpp b/include/rmf_task/Task.hpp +index 6c5f419..3b8d83d 100644 +--- a/include/rmf_task/Task.hpp ++++ b/include/rmf_task/Task.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__TASK_HPP + #define RMF_TASK__TASK_HPP + ++#include + #include + #include + #include +diff --git a/include/rmf_task/TaskPlanner.hpp b/include/rmf_task/TaskPlanner.hpp +index 14488f6..ec5dd10 100644 +--- a/include/rmf_task/TaskPlanner.hpp ++++ b/include/rmf_task/TaskPlanner.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__AGV__TASKPLANNER_HPP + #define RMF_TASK__AGV__TASKPLANNER_HPP + ++#include + #include + #include + #include +diff --git a/include/rmf_task/detail/Backup.hpp b/include/rmf_task/detail/Backup.hpp +index 5a9ad72..c68e959 100644 +--- a/include/rmf_task/detail/Backup.hpp ++++ b/include/rmf_task/detail/Backup.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__DETAIL__BACKUP_HPP + #define RMF_TASK__DETAIL__BACKUP_HPP + ++#include + #include + + #include +diff --git a/include/rmf_task/events/SimpleEventState.hpp b/include/rmf_task/events/SimpleEventState.hpp +index c90d528..1496e2a 100644 +--- a/include/rmf_task/events/SimpleEventState.hpp ++++ b/include/rmf_task/events/SimpleEventState.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__EVENTS__SIMPLEEVENTSTATE_HPP + #define RMF_TASK__EVENTS__SIMPLEEVENTSTATE_HPP + ++#include + #include + + namespace rmf_task { +diff --git a/src/rmf_task/BackupFileManager.cpp b/src/rmf_task/BackupFileManager.cpp +index 7afa25d..992489b 100644 +--- a/src/rmf_task/BackupFileManager.cpp ++++ b/src/rmf_task/BackupFileManager.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + #include + #include +diff --git a/src/rmf_task/Event.cpp b/src/rmf_task/Event.cpp +index 2cb42b8..b5ac0ca 100644 +--- a/src/rmf_task/Event.cpp ++++ b/src/rmf_task/Event.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + namespace rmf_task { +diff --git a/src/rmf_task/Log.cpp b/src/rmf_task/Log.cpp +index 48c5883..84707a7 100644 +--- a/src/rmf_task/Log.cpp ++++ b/src/rmf_task/Log.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + #include +diff --git a/src/rmf_task/Payload.cpp b/src/rmf_task/Payload.cpp +index 8d031ce..8413f1e 100644 +--- a/src/rmf_task/Payload.cpp ++++ b/src/rmf_task/Payload.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + #include + #include +diff --git a/src/rmf_task/detail/Backup.cpp b/src/rmf_task/detail/Backup.cpp +index f353157..9f0e66b 100644 +--- a/src/rmf_task/detail/Backup.cpp ++++ b/src/rmf_task/detail/Backup.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + namespace rmf_task { +diff --git a/src/rmf_task/events/SimpleEventState.cpp b/src/rmf_task/events/SimpleEventState.cpp +index 1af9d68..0bc4bab 100644 +--- a/src/rmf_task/events/SimpleEventState.cpp ++++ b/src/rmf_task/events/SimpleEventState.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + namespace rmf_task { diff --git a/distros/humble/patch/ros2-rmf-task.win.patch b/distros/humble/patch/ros2-rmf-task.win.patch new file mode 100644 index 000000000..4b6b76186 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-task.win.patch @@ -0,0 +1,86 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7e4d9e2..37ca5a7 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,6 +13,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used via rmf_traffic's installed Interpolate.hpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -38,6 +44,16 @@ add_library(rmf_task SHARED + ${lib_srcs} + ) + ++if(WIN32) ++ # rmf_task has no dllexport annotations at all. As a shared library on ++ # Windows with nothing explicitly exported, link.exe does not produce ++ # an import .lib, so every consumer fails with LNK1181 "cannot open ++ # input file 'rmf_task.lib'" even though rmf_task.dll itself builds ++ # fine. Auto-export everything, same fix as rmf_utils/rmf_traffic/ ++ # rmf_battery earlier in this package family. ++ set_target_properties(rmf_task PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_task + PUBLIC + rmf_battery::rmf_battery +diff --git a/src/rmf_task/BackupFileManager.cpp b/src/rmf_task/BackupFileManager.cpp +index 92c62ae..aaa9b82 100644 +--- a/src/rmf_task/BackupFileManager.cpp ++++ b/src/rmf_task/BackupFileManager.cpp +@@ -128,9 +128,14 @@ public: + std::optional last_seq; + const std::string backup_file_name = "backup"; + const std::string pre_backup_file_name = ".backup"; +- const std::string pre_backup_file_path = robot_directory / +- pre_backup_file_name; +- const std::string backup_file_path = robot_directory / backup_file_name; ++ // std::filesystem::path has no implicit conversion to std::string (only ++ // the explicit .string() member) -- GCC/libstdc++ tolerates constructing ++ // a string directly from a path here, but MSVC's STL correctly rejects ++ // it (C2665). Call .string() explicitly; portable everywhere. ++ const std::string pre_backup_file_path = (robot_directory / ++ pre_backup_file_name).string(); ++ const std::string backup_file_path = ++ (robot_directory / backup_file_name).string(); + + void write_if_new(const Task::Active::Backup& backup) + { +diff --git a/test/unit/test_Log.cpp b/test/unit/test_Log.cpp +index f15e519..0c3c69d 100644 +--- a/test/unit/test_Log.cpp ++++ b/test/unit/test_Log.cpp +@@ -95,9 +95,9 @@ SCENARIO("Multi-threaded read/write with synced view") + std::random_device r; + std::default_random_engine eng(r()); + std::uniform_real_distribution entry_dist(0, 1); +- std::uniform_int_distribution tier_dist( +- static_cast(rmf_task::Log::Tier::Info), +- static_cast(rmf_task::Log::Tier::Error)); ++ std::uniform_int_distribution tier_dist( ++ static_cast(rmf_task::Log::Tier::Info), ++ static_cast(rmf_task::Log::Tier::Error)); + + std::size_t counter = 0; + while (!test_finished->load()) +@@ -196,9 +196,9 @@ SCENARIO("Multi-threaded read/write without syncing") + std::random_device r; + std::default_random_engine eng(r()); + std::uniform_real_distribution entry_dist(0, 1); +- std::uniform_int_distribution tier_dist( +- static_cast(rmf_task::Log::Tier::Info), +- static_cast(rmf_task::Log::Tier::Error)); ++ std::uniform_int_distribution tier_dist( ++ static_cast(rmf_task::Log::Tier::Info), ++ static_cast(rmf_task::Log::Tier::Error)); + + std::size_t counter = 0; + while (!test_finished->load()) diff --git a/distros/humble/patch/ros2-rmf-traffic-editor.win.patch b/distros/humble/patch/ros2-rmf-traffic-editor.win.patch new file mode 100644 index 000000000..8b984ff54 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-traffic-editor.win.patch @@ -0,0 +1,59 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index cf1d5e3..ed2a8e3 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -6,17 +6,26 @@ endif() + + project(rmf_traffic_editor) + ++if(MSVC) ++ # M_PI and friends: MSVC defines them only with _USE_MATH_DEFINES; NOGDI keeps windows.h ++ # (pulled in by dependencies) from declaring GDI's Polygon(), which clashes with the editor's ++ add_compile_definitions(_USE_MATH_DEFINES NOGDI) ++endif() ++ + find_package(ament_cmake REQUIRED) + find_package(ament_index_cpp REQUIRED) + find_package(Ceres REQUIRED) + find_package(Eigen3 REQUIRED) + find_package(Qt5 COMPONENTS Widgets Concurrent Test Network REQUIRED) + find_package(yaml-cpp REQUIRED) ++find_package(PROJ CONFIG REQUIRED) + + set(CMAKE_BUILD_TYPE RelWithDebInfo) + # set(CMAKE_VERBOSE_MAKEFILE TRUE) + +-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wshadow -Wextra") ++if(NOT MSVC) # GCC/Clang warning flags; MSVC rejects -Wshadow (D8021) ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wshadow -Wextra") ++endif() + + set(CMAKE_AUTOMOC ON) + set(CMAKE_AUTORCC ON) +@@ -120,8 +129,9 @@ target_link_libraries( + Qt5::Widgets + Qt5::Concurrent + Qt5::Network +- proj +- yaml-cpp ++ # MSVC needs the imported targets (bare names mean proj.lib / yaml-cpp.lib, LNK1181) ++ PROJ::proj ++ yaml-cpp::yaml-cpp + ${ament_index_cpp_LIBRARIES} + ) + +diff --git a/gui/editor.cpp b/gui/editor.cpp +index 5f6eee5..21e8049 100644 +--- a/gui/editor.cpp ++++ b/gui/editor.cpp +@@ -18,9 +18,8 @@ + #include + #include + #include +-#include ++// (Windows) no unistd.h or pwd.h; nothing from them is used + #include +-#include + + #include + diff --git a/distros/humble/patch/ros2-rmf-traffic-examples.win.patch b/distros/humble/patch/ros2-rmf-traffic-examples.win.patch new file mode 100644 index 000000000..21198d91e --- /dev/null +++ b/distros/humble/patch/ros2-rmf-traffic-examples.win.patch @@ -0,0 +1,16 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b71adb5..3ede1a4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.5) + + project(rmf_traffic_examples) + ++if(MSVC) ++ # M_PI and friends: MSVC defines them only with _USE_MATH_DEFINES ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + find_package(rmf_traffic REQUIRED) + + add_executable(three_robots src/three_robots.cpp) diff --git a/distros/humble/patch/ros2-rmf-utils.patch b/distros/humble/patch/ros2-rmf-utils.patch new file mode 100644 index 000000000..59de4cbb8 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-utils.patch @@ -0,0 +1,37 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a93554f..ecf9758 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -14,6 +14,9 @@ include(GNUInstallDirs) + + file(GLOB_RECURSE lib_srcs "src/rmf_utils/*.cpp") + add_library(rmf_utils SHARED ${lib_srcs}) ++if(WIN32) ++ set_target_properties(rmf_utils PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() + + target_include_directories(rmf_utils + PUBLIC +@@ -44,7 +47,9 @@ write_basic_package_version_file( + install( + TARGETS rmf_utils + EXPORT rmf_utils-targets +- DESTINATION lib ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib) ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib + ) + + install( +diff --git a/include/rmf_utils/Modular.hpp b/include/rmf_utils/Modular.hpp +index c994808..ca8397c 100644 +--- a/include/rmf_utils/Modular.hpp ++++ b/include/rmf_utils/Modular.hpp +@@ -19,6 +19,7 @@ + #define RMF_UTILS__MODULAR_HPP + + #include ++#include + #include + #include + diff --git a/distros/humble/patch/ros2-rmf-visualization-floorplans.win.patch b/distros/humble/patch/ros2-rmf-visualization-floorplans.win.patch new file mode 100644 index 000000000..4497462f0 --- /dev/null +++ b/distros/humble/patch/ros2-rmf-visualization-floorplans.win.patch @@ -0,0 +1,17 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6aed5c0..ead378d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -5,6 +5,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI is a non-standard extension MSVC only defines when this is ++ # set (used in src/FloorplanVisualizer.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + include(GNUInstallDirs) + + find_package(eigen3_cmake_module REQUIRED) diff --git a/distros/humble/patch/ros2-rmf-visualization-schedule.win.patch b/distros/humble/patch/ros2-rmf-visualization-schedule.win.patch new file mode 100644 index 000000000..2825b6e0f --- /dev/null +++ b/distros/humble/patch/ros2-rmf-visualization-schedule.win.patch @@ -0,0 +1,52 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 5595472..851de18 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -2,6 +2,19 @@ cmake_minimum_required(VERSION 3.5) + project(rmf_visualization_schedule) + set(CMAKE_EXPORT_COMPILE_COMMANDS on) + ++if(MSVC) ++ # MSVC doesn't update __cplusplus to reflect the actual C++ standard ++ # in use unless told to, so websocketpp's __cplusplus >= 201103L ++ # feature-detection in common/cpp11.hpp always fails, falling back ++ # to boost::is_same -- which recent Boost versions no longer provide ++ # (C2039/C2873 in websocketpp/common/type_traits.hpp). ++ add_compile_options(/Zc:__cplusplus) ++ ++ # M_PI_2 et al. are non-standard extensions MSVC only defines when ++ # this is set (used in test/SubmitTrajectory.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + # Default to C++17 + if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +@@ -48,6 +61,14 @@ endif() + file(GLOB_RECURSE core_lib_srcs "src/rmf_visualization_schedule/*.cpp") + add_library(rmf_visualization_schedule SHARED ${core_lib_srcs}) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this small target ++ # (2 source files), so without this MSVC produces the .dll but no ++ # import .lib, and schedule_visualizer fails with LNK1181. ++ set_target_properties(rmf_visualization_schedule PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_visualization_schedule + PUBLIC + rmf_traffic_ros2::rmf_traffic_ros2 +diff --git a/src/ScheduleVisualizer.cpp b/src/ScheduleVisualizer.cpp +index 961c512..7a7bc2f 100644 +--- a/src/ScheduleVisualizer.cpp ++++ b/src/ScheduleVisualizer.cpp +@@ -107,7 +107,7 @@ ScheduleVisualizer::ScheduleVisualizer( + "Setting parameter port to %d", port + ); + +- uint retained_history_count = this->declare_parameter( ++ unsigned int retained_history_count = this->declare_parameter( + "retained_history_count", 0); + RCLCPP_INFO( + this->get_logger(), diff --git a/distros/humble/patch/ros2-rmf-websocket.patch b/distros/humble/patch/ros2-rmf-websocket.patch new file mode 100644 index 000000000..c48b1a7ab --- /dev/null +++ b/distros/humble/patch/ros2-rmf-websocket.patch @@ -0,0 +1,22 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index abc3bae..2cef478 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -21,7 +21,8 @@ find_package(nlohmann_json REQUIRED) + find_package(nlohmann_json_schema_validator_vendor REQUIRED) + find_package(nlohmann_json_schema_validator REQUIRED) + find_package(websocketpp REQUIRED) +-find_package(Boost COMPONENTS system filesystem REQUIRED) ++# Boost.System is header-only (no boost_system library since Boost 1.89) ++find_package(Boost COMPONENTS filesystem REQUIRED) + find_package(Threads) + + file(GLOB_RECURSE core_lib_srcs "src/rmf_websocket/*.cpp") +@@ -36,7 +37,6 @@ target_link_libraries(rmf_websocket + nlohmann_json_schema_validator + PRIVATE + ${Boost_FILESYSTEM_LIBRARY} +- ${Boost_SYSTEM_LIBRARY} + Threads::Threads + ) + diff --git a/distros/humble/patch/ros2-rmf-websocket.win.patch b/distros/humble/patch/ros2-rmf-websocket.win.patch new file mode 100644 index 000000000..02640a26d --- /dev/null +++ b/distros/humble/patch/ros2-rmf-websocket.win.patch @@ -0,0 +1,41 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index abc3bae..c4b763d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,6 +11,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") + endif() + ++if(MSVC) ++ # websocketpp's C++11 feature detection reads __cplusplus, which MSVC only reports ++ # correctly with /Zc:__cplusplus (otherwise it falls back to boost::is_same, gone from Boost). ++ add_compile_options(/Zc:__cplusplus) ++endif() ++ + include(GNUInstallDirs) + + find_package(ament_cmake REQUIRED) +@@ -27,6 +33,14 @@ find_package(Threads) + file(GLOB_RECURSE core_lib_srcs "src/rmf_websocket/*.cpp") + add_library(rmf_websocket SHARED ${core_lib_srcs}) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this small target, so ++ # without this MSVC produces the .dll but no companion .lib, and ++ # example_client fails with LNK1181. ++ set_target_properties(rmf_websocket PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_websocket + PUBLIC + ${rclcpp_LIBRARIES} +@@ -60,7 +74,7 @@ install( + install( + TARGETS rmf_websocket + EXPORT rmf_websocket +- RUNTIME DESTINATION lib/rmf_websocket ++ RUNTIME DESTINATION bin # RoboStack: the DLL next to the other DLLs (on PATH on Windows) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/humble/pkg_additional_info.yaml b/distros/humble/pkg_additional_info.yaml index 8df60c7e1..84be9abe8 100644 --- a/distros/humble/pkg_additional_info.yaml +++ b/distros/humble/pkg_additional_info.yaml @@ -105,3 +105,5 @@ urdfdom_headers: # Remove build_number fields below on new full rebuild zenoh_cpp_vendor: additional_cmake_args: "-DAMENT_VENDOR_POLICY=NEVER_VENDOR_IGNORE_SATISFIED_CHECK -DUSE_SYSTEM_ZENOH=ON" +rmf_utils: # its DLL moved from lib to bin (Windows) + build_number: 23 diff --git a/distros/humble/vinca.yaml b/distros/humble/vinca.yaml index 30959c787..c2e7520ce 100644 --- a/distros/humble/vinca.yaml +++ b/distros/humble/vinca.yaml @@ -18,12 +18,16 @@ packages_exclude: - mujoco_ros2_control # runtime uses Linux-specific files (as everywhere) - mujoco_ros2_control_demos # readlink and Linux-specific files at runtime (as everywhere) - rclc_examples # MSVC C2055 on rcl_timer_t callbacks; macOS humble-only (no reason recorded) + - rmf_building_sim_gz_classic_plugins # Gazebo Classic (EOL) plugins: macOS link errors against libgazebo/sdformat9; win-64 has no OgreBites.lib (as velodyne_gazebo_plugins) + - rmf_robot_sim_gz_classic_plugins # Gazebo Classic (EOL) plugins, as rmf_building_sim_gz_classic_plugins - if: win then: - gz_ros2_control # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 - gz_ros2_control_demos # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 - hpp-fcl # no ros2-hpp-fcl recipe for win-64; pinocchio wraps conda-forge's pinocchio (coal) anyway + - rmf_building_sim_gz_plugins # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 + - rmf_robot_sim_gz_plugins # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 - ros_gz_sim # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 - ros_gz_sim_demos # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 - ros_ign_gazebo # Ignition Fortress (libignition-gazebo6) isn't installable on win-64 diff --git a/distros/jazzy/patch/ros2-menge-vendor.win.patch b/distros/jazzy/patch/ros2-menge-vendor.win.patch new file mode 100644 index 000000000..7dc45176d --- /dev/null +++ b/distros/jazzy/patch/ros2-menge-vendor.win.patch @@ -0,0 +1,27 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6eaedad..0a28fc4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -57,10 +57,21 @@ add_library( + + target_include_directories( menge_vendor PUBLIC ${tinyxml_INCLUDE_DIRS} ) + +-target_link_libraries ( menge_vendor PUBLIC dl PRIVATE ${tinyxml_LIBRARIES} ) ++if(WIN32) ++ target_link_libraries ( menge_vendor PRIVATE ${tinyxml_LINK_LIBRARIES} ) ++else() ++ target_link_libraries ( menge_vendor PUBLIC dl PRIVATE ${tinyxml_LIBRARIES} ) ++endif() + + set_target_properties( menge_vendor PROPERTIES LINKER_LANGUAGE CXX ) + ++if(WIN32) ++ # CoreConfig.h exports MENGE_API symbols only with MENGECORE_EXPORTS (dllimport otherwise, ++ # and MSVC rejects defining dllimport static data members); no libdl on Windows ++ # (SharedLibrary.h uses LoadLibrary there). ++ target_compile_definitions( menge_vendor PRIVATE MENGECORE_EXPORTS ) ++endif() ++ + include(GNUInstallDirs) + + ament_export_include_directories(include) diff --git a/distros/jazzy/patch/ros2-rmf-api-msgs.win.patch b/distros/jazzy/patch/ros2-rmf-api-msgs.win.patch new file mode 100644 index 000000000..dbe16fdd3 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-api-msgs.win.patch @@ -0,0 +1,45 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 27156a0..44d4528 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -83,11 +83,20 @@ install( + + # Generate python schemas mode whenever colcon is triggered + message(" Generating schema as py mods") ++# "eval" is a POSIX shell builtin, not a real command -- fails on Windows ++# with "'eval' is not recognized". Pass the command as plain CMake ++# arguments instead of a quoted shell string; portable everywhere. ++# conda-forge's Windows Python is "python.exe", not "python3.exe". ++if(WIN32) ++ set(PY_EXECUTABLE_NAME python) ++else() ++ set(PY_EXECUTABLE_NAME python3) ++endif() + ADD_CUSTOM_TARGET( + py_schemas_gen ALL +- COMMAND eval "python3 generate_py_schemas.py \ +- --schemas_dir ${CMAKE_CURRENT_LIST_DIR}/schemas \ +- --output_file ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/schemas.py" ++ COMMAND ${PY_EXECUTABLE_NAME} generate_py_schemas.py ++ --schemas_dir ${CMAKE_CURRENT_LIST_DIR}/schemas ++ --output_file ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/schemas.py + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/scripts) + + # Generate pydantic models according to schemas +@@ -97,11 +106,11 @@ if(PY_MODELGEN_AVAIL) + message(" Generating py models with 'datamodel-codegen'") + ADD_CUSTOM_TARGET( + py_models_gen ALL +- COMMAND eval "datamodel-codegen \ +- --disable-timestamp \ +- --input-file-type jsonschema \ +- --input ${CMAKE_CURRENT_LIST_DIR}/schemas \ +- --output ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/models" ++ COMMAND datamodel-codegen ++ --disable-timestamp ++ --input-file-type jsonschema ++ --input ${CMAKE_CURRENT_LIST_DIR}/schemas ++ --output ${CMAKE_CURRENT_LIST_DIR}/rmf_api_msgs/models + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/scripts) + else() + message( diff --git a/distros/jazzy/patch/ros2-rmf-battery.win.patch b/distros/jazzy/patch/ros2-rmf-battery.win.patch new file mode 100644 index 000000000..3941214e3 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-battery.win.patch @@ -0,0 +1,35 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b00fb4c..bd84a62 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -12,6 +12,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set. Used both in rmf_traffic's installed Interpolate.hpp ++ # (consumed here) and in this package's own test_battery_drain.cpp. ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -36,6 +43,16 @@ add_library(rmf_battery SHARED + ${core_lib_srcs} + ) + ++if(WIN32) ++ # rmf_battery has no dllexport annotations at all. As a shared library ++ # on Windows with nothing explicitly exported, link.exe does not ++ # produce an import .lib, so every consumer fails with LNK1181 ++ # "cannot open input file 'rmf_battery.lib'" even though ++ # rmf_battery.dll itself builds fine. Auto-export everything, same ++ # fix used for rmf_utils/rmf_traffic earlier in this package family. ++ set_target_properties(rmf_battery PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_battery + PUBLIC + rmf_utils::rmf_utils diff --git a/distros/jazzy/patch/ros2-rmf-building-sim-gz-plugins.win.patch b/distros/jazzy/patch/ros2-rmf-building-sim-gz-plugins.win.patch new file mode 100644 index 000000000..fac092bd9 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-building-sim-gz-plugins.win.patch @@ -0,0 +1,57 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index cf3c53a..5819521 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,12 @@ + cmake_minimum_required(VERSION 3.5) + project(rmf_building_sim_gz_plugins) + ++if(MSVC) ++ # windows.h without WIN32_LEAN_AND_MEAN pulls in winsock.h, which then clashes with ++ # winsock2.h (C2011 sockaddr redefinition); NOMINMAX for windows.h's min/max macros ++ add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX _USE_MATH_DEFINES) ++endif() ++ + set (CMAKE_AUTOMOC ON) + + # Default to C99 +diff --git a/include/rmf_building_sim_gz_plugins/components/Door.hpp b/include/rmf_building_sim_gz_plugins/components/Door.hpp +index 4de41c8..137cc7b 100644 +--- a/include/rmf_building_sim_gz_plugins/components/Door.hpp ++++ b/include/rmf_building_sim_gz_plugins/components/Door.hpp +@@ -47,6 +47,9 @@ enum class DoorModeCmp + OPEN = 2 + }; + ++// (MSVC) inside gz-sim's inline version namespace: a separate gz::sim::components next to ++// gz::sim::vN::components is ambiguous there (C2872), and Component/Factory aren't found ++inline namespace GZ_SIM_VERSION_NAMESPACE { + namespace components { + /// \brief A component used to describe an RMF door. + using Door = Component; +@@ -62,4 +65,5 @@ GZ_SIM_REGISTER_COMPONENT("rmf_components.DoorStateComp", DoorStateComp) + } + } + } ++} + #endif +diff --git a/include/rmf_building_sim_gz_plugins/components/Lift.hpp b/include/rmf_building_sim_gz_plugins/components/Lift.hpp +index a68a2b8..6f91357 100644 +--- a/include/rmf_building_sim_gz_plugins/components/Lift.hpp ++++ b/include/rmf_building_sim_gz_plugins/components/Lift.hpp +@@ -57,6 +57,9 @@ struct LiftCommand + DoorModeCmp door_state; + }; + ++// (MSVC) inside gz-sim's inline version namespace: a separate gz::sim::components next to ++// gz::sim::vN::components is ambiguous there (C2872), and Component/Factory aren't found ++inline namespace GZ_SIM_VERSION_NAMESPACE { + namespace components { + /// \brief A component used to describe an RMF lift. + using Lift = Component; +@@ -68,4 +71,5 @@ GZ_SIM_REGISTER_COMPONENT("rmf_components.LiftCmd", LiftCmd) + } + } + } ++} + #endif diff --git a/distros/jazzy/patch/ros2-rmf-fleet-adapter.patch b/distros/jazzy/patch/ros2-rmf-fleet-adapter.patch new file mode 100644 index 000000000..9e3ed2cee --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-fleet-adapter.patch @@ -0,0 +1,154 @@ +diff --git a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp +index 20e0c69..0fae30f 100644 +--- a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp ++++ b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-notification.hpp +@@ -150,7 +150,6 @@ private: + } + on_error_notification(const on_error_notification& o) : ep(o.ep) {} + on_error_notification(const on_error_notification&& o) : ep(std::move(o.ep)) {} +- on_error_notification& operator=(on_error_notification o) { ep = std::move(o.ep); return *this; } + virtual void out(std::ostream& os) const { + os << "on_error("; + os << rxu::what(ep); +diff --git a/src/full_control/main.cpp b/src/full_control/main.cpp +index 6cde76f..e6b50c3 100644 +--- a/src/full_control/main.cpp ++++ b/src/full_control/main.cpp +@@ -1039,8 +1039,12 @@ std::shared_ptr make_fleet( + request_msg->fleet_name.empty()) + return; + +- connections->fleet->open_lanes(request_msg->open_lanes); +- connections->fleet->close_lanes(request_msg->close_lanes); ++ connections->fleet->open_lanes( ++ std::vector( ++ request_msg->open_lanes.begin(), request_msg->open_lanes.end())); ++ connections->fleet->close_lanes( ++ std::vector( ++ request_msg->close_lanes.begin(), request_msg->close_lanes.end())); + + std::unordered_set newly_closed_lanes; + for (const auto& l : request_msg->close_lanes) +@@ -1093,7 +1097,9 @@ std::shared_ptr make_fleet( + requests.push_back(std::move(request)); + } + connections->fleet->limit_lane_speeds(requests); +- connections->fleet->remove_speed_limits(request_msg->remove_limits); ++ connections->fleet->remove_speed_limits( ++ std::vector( ++ request_msg->remove_limits.begin(), request_msg->remove_limits.end())); + }); + + connections->interrupt_request_sub = +diff --git a/src/rmf_fleet_adapter/LegacyTask.cpp b/src/rmf_fleet_adapter/LegacyTask.cpp +index bdbb184..191d04a 100644 +--- a/src/rmf_fleet_adapter/LegacyTask.cpp ++++ b/src/rmf_fleet_adapter/LegacyTask.cpp +@@ -22,7 +22,9 @@ + + #include + ++#if defined(__linux__) + #include ++#endif + + namespace rmf_fleet_adapter { + +@@ -157,7 +159,9 @@ void LegacyTask::_start_next_phase() + // + // TODO(MXG): Remove this when the planner has been made more + // memory-efficient. ++#if defined(__linux__) + malloc_trim(0); ++#endif + + return; + } +diff --git a/src/rmf_fleet_adapter/TaskManager.cpp b/src/rmf_fleet_adapter/TaskManager.cpp +index 38cca49..2651d22 100644 +--- a/src/rmf_fleet_adapter/TaskManager.cpp ++++ b/src/rmf_fleet_adapter/TaskManager.cpp +@@ -322,9 +322,9 @@ nlohmann::json& copy_phase_data( + phase_state["category"] = header.category(); + phase_state["detail"] = header.detail(); + phase_state["original_estimate_millis"] = +- std::max(0l, to_millis(header.original_duration_estimate()).count()); ++ std::max(0, to_millis(header.original_duration_estimate()).count()); + phase_state["estimate_millis"] = +- std::max(0l, to_millis(snapshot.estimate_remaining_time()).count()); ++ std::max(0, to_millis(snapshot.estimate_remaining_time()).count()); + phase_state["final_event_id"] = snapshot.final_event()->id(); + auto& event_states = phase_state["events"]; + +@@ -388,7 +388,7 @@ void copy_phase_data( + phase["category"] = header.category(); + phase["detail"] = header.detail(); + phase["estimate_millis"] = +- std::max(0l, to_millis(header.original_duration_estimate()).count()); ++ std::max(0, to_millis(header.original_duration_estimate()).count()); + } + + //============================================================================== +@@ -467,9 +467,9 @@ void TaskManager::ActiveTask::publish_task_state(TaskManager& mgr) + _state_msg["unix_millis_finish_time"] = + to_millis(finish_estimate.time_since_epoch()).count(); + _state_msg["original_estimate_millis"] = +- std::max(0l, to_millis(header.original_duration_estimate()).count()); ++ std::max(0, to_millis(header.original_duration_estimate()).count()); + _state_msg["estimate_millis"] = +- std::max(0l, to_millis(remaining_time_estimate).count()); ++ std::max(0, to_millis(remaining_time_estimate).count()); + copy_assignment(_state_msg["assigned_to"], *mgr._context); + _state_msg["status"] = + status_to_string(_task->status_overview()); +@@ -2090,7 +2090,7 @@ rmf_task::State TaskManager::_publish_pending_task( + + const auto estimate = + pending.finish_state().time().value() - pending.deployment_time(); +- t.original_estimate_millis = std::max(0l, to_millis(estimate).count()); ++ t.original_estimate_millis = std::max(0, to_millis(estimate).count()); + + pending_json["unix_millis_finish_time"] = t.unix_millis_finish_time; + pending_json["original_estimate_millis"] = t.original_estimate_millis; +diff --git a/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp b/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp +index 7b58004..e7d2024 100644 +--- a/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp ++++ b/src/rmf_fleet_adapter/agv/internal_FleetUpdateHandle.hpp +@@ -75,7 +75,9 @@ + #include + #include + #include ++#if defined(__linux__) + #include ++#endif + + namespace rmf_fleet_adapter { + namespace agv { +@@ -431,7 +433,12 @@ public: + // TODO(MXG): Remove this when the planner has been made more + // memory-efficient. + handle->_pimpl->memory_trim_timer = handle->_pimpl->node->create_wall_timer( +- std::chrono::minutes(5), []() { malloc_trim(0); }); ++ std::chrono::minutes(5), []() ++ { ++#if defined(__linux__) ++ malloc_trim(0); ++#endif ++ }); + + // Create subs and pubs for bidding + auto transient_qos = rclcpp::QoS(10).transient_local(); +diff --git a/src/rmf_fleet_adapter/events/ExecutePlan.cpp b/src/rmf_fleet_adapter/events/ExecutePlan.cpp +index 8e24390..e4484d9 100644 +--- a/src/rmf_fleet_adapter/events/ExecutePlan.cpp ++++ b/src/rmf_fleet_adapter/events/ExecutePlan.cpp +@@ -117,7 +117,8 @@ void truncate_arrival( + std::size_t first_excluded_route = 0; + for (const auto& c : wp.arrival_checkpoints()) + { +- first_excluded_route = std::max(first_excluded_route, c.route_id+1); ++ // route_id is uint64_t, which isn't std::size_t on macOS ++ first_excluded_route = std::max(first_excluded_route, static_cast(c.route_id+1)); + auto& r = previous_itinerary.at(c.route_id); + auto& t = r.trajectory(); + diff --git a/distros/jazzy/patch/ros2-rmf-fleet-adapter.win.patch b/distros/jazzy/patch/ros2-rmf-fleet-adapter.win.patch new file mode 100644 index 000000000..c8d4f9f8a --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-fleet-adapter.win.patch @@ -0,0 +1,879 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ef83cb6..4058d67 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -10,6 +10,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used across rmf_traffic/rmf_utils's installed headers and ++ # this package's own agv/RobotContext.hpp, agv/EasyFullControl.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + find_package(ament_cmake REQUIRED) + find_package(backward_ros REQUIRED) + find_package(Eigen3 REQUIRED) +@@ -91,6 +98,18 @@ ament_target_dependencies(rmf_fleet_adapter + rclcpp + ) + ++if(MSVC) ++ # agv/Node.cpp exceeds the default object file section limit. ++ target_compile_options(rmf_fleet_adapter PRIVATE /bigobj) ++ ++ # WINDOWS_EXPORT_ALL_SYMBOLS overflows MSVC's import-lib 65535-object ++ # limit (LNK1189) on this heavily Eigen/nlohmann/rxcpp-templated ++ # library, same as rmf_traffic_ros2. Use explicit ++ # RMF_FLEET_ADAPTER_EXPORT annotations (detail/export.hpp) across ++ # the whole public API instead. ++ target_compile_definitions(rmf_fleet_adapter PRIVATE RMF_FLEET_ADAPTER_BUILDING_DLL) ++endif() ++ + target_link_libraries(rmf_fleet_adapter + PUBLIC + rmf_task::rmf_task +@@ -203,13 +222,34 @@ target_link_libraries(read_only_blockade + # ----------------------------------------------------------------------------- + + add_executable(full_control src/full_control/main.cpp) ++if(MSVC) ++ # RoboStack: MSVC 14.44 crashes compiling main.cpp (C1001 in its lambda handling, ++ # also unoptimized); full_control isn't built on Windows (newer releases build) ++ set_target_properties(full_control PROPERTIES EXCLUDE_FROM_ALL TRUE) ++ set(_full_control "") ++else() ++ set(_full_control full_control) ++endif() + +-target_link_libraries(full_control +- PRIVATE +- rmf_fleet_adapter +- ${rmf_fleet_msgs_LIBRARIES} +- ${rmf_task_msgs_LIBRARIES} +-) ++if(WIN32) ++ # The raw ${..._LIBRARIES} variables below each recursively re-append ++ # their own dependencies' _LIBRARIES as plain strings with no ++ # deduplication, overflowing link.exe's response-file line limit ++ # (LNK1170) -- same issue and fix as rmf_traffic_ros2/rmf_task_ros2. ++ target_link_libraries(full_control ++ PRIVATE ++ rmf_fleet_adapter ++ rmf_fleet_msgs::rmf_fleet_msgs ++ rmf_task_msgs::rmf_task_msgs ++ ) ++else() ++ target_link_libraries(full_control ++ PRIVATE ++ rmf_fleet_adapter ++ ${rmf_fleet_msgs_LIBRARIES} ++ ${rmf_task_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(full_control + PRIVATE +@@ -221,12 +261,21 @@ target_include_directories(full_control + + add_executable(mock_traffic_light src/mock_traffic_light/main.cpp) + +-target_link_libraries(mock_traffic_light +- PRIVATE +- rmf_fleet_adapter +- ${rmf_task_msgs_LIBRARIES} +- ${rmf_fleet_msgs_LIBRARIES} +-) ++if(WIN32) ++ target_link_libraries(mock_traffic_light ++ PRIVATE ++ rmf_fleet_adapter ++ rmf_task_msgs::rmf_task_msgs ++ rmf_fleet_msgs::rmf_fleet_msgs ++ ) ++else() ++ target_link_libraries(mock_traffic_light ++ PRIVATE ++ rmf_fleet_adapter ++ ${rmf_task_msgs_LIBRARIES} ++ ${rmf_fleet_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(mock_traffic_light + PRIVATE +@@ -281,13 +330,29 @@ add_executable(experimental_lift_watchdog + src/experimental_lift_watchdog/main.cpp + ) + +-target_link_libraries(experimental_lift_watchdog +- PRIVATE +- ${rclcpp_LIBRARIES} +- ${rmf_fleet_msgs_LIBRARIES} +- ${std_msgs_LIBRARIES} +- Threads::Threads +-) ++if(WIN32) ++ # The raw ${..._LIBRARIES} variables below each recursively re-append ++ # their own dependencies' _LIBRARIES as plain strings with no ++ # deduplication, stacking up a lot of repeated full paths. On Windows ++ # CI the concatenated link.exe response-file line exceeded its ++ # ~131071-character limit (LNK1170) -- same issue and same fix as ++ # rmf_traffic_ros2/rmf_task_ros2 hit earlier. ++ target_link_libraries(experimental_lift_watchdog ++ PRIVATE ++ rclcpp::rclcpp ++ rmf_fleet_msgs::rmf_fleet_msgs ++ ${std_msgs_TARGETS} ++ Threads::Threads ++ ) ++else() ++ target_link_libraries(experimental_lift_watchdog ++ PRIVATE ++ ${rclcpp_LIBRARIES} ++ ${rmf_fleet_msgs_LIBRARIES} ++ ${std_msgs_LIBRARIES} ++ Threads::Threads ++ ) ++endif() + + target_include_directories(experimental_lift_watchdog + PRIVATE +@@ -303,12 +368,21 @@ add_executable(door_supervisor + src/door_supervisor/Node.cpp + ) + +-target_link_libraries(door_supervisor +- PRIVATE +- rmf_fleet_adapter +- ${rclcpp_LIBRARIES} +- ${rmf_door_msgs_LIBRARIES} +-) ++if(WIN32) ++ target_link_libraries(door_supervisor ++ PRIVATE ++ rmf_fleet_adapter ++ rclcpp::rclcpp ++ rmf_door_msgs::rmf_door_msgs ++ ) ++else() ++ target_link_libraries(door_supervisor ++ PRIVATE ++ rmf_fleet_adapter ++ ${rclcpp_LIBRARIES} ++ ${rmf_door_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(door_supervisor + PRIVATE +@@ -322,6 +396,15 @@ add_library(robot_state_aggregator_main SHARED + src/robot_state_aggregator/RobotStateAggregator.cpp + ) + ++if(MSVC) ++ # COMPOSITION_BUILDING_DLL below is vestigial -- nothing in this ++ # package's sources actually branches on it for dllexport/dllimport, ++ # so this SHARED target has no explicit export annotations at all, ++ # and MSVC produces the .dll but no import .lib. ++ set_target_properties(robot_state_aggregator_main PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_include_directories(robot_state_aggregator_main + PRIVATE + include +@@ -424,12 +507,21 @@ add_executable(dump_fleet_states + test/dump_fleet_states.cpp + ) + +-target_link_libraries(dump_fleet_states +- PRIVATE +- rmf_fleet_adapter +- ${rclcpp_LIBRARIES} +- ${rmf_fleet_msgs_LIBRARIES} +-) ++if(WIN32) ++ target_link_libraries(dump_fleet_states ++ PRIVATE ++ rmf_fleet_adapter ++ rclcpp::rclcpp ++ rmf_fleet_msgs::rmf_fleet_msgs ++ ) ++else() ++ target_link_libraries(dump_fleet_states ++ PRIVATE ++ rmf_fleet_adapter ++ ${rclcpp_LIBRARIES} ++ ${rmf_fleet_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(dump_fleet_states + PRIVATE +@@ -443,12 +535,22 @@ add_executable(task_aggregator + src/task_aggregator/main.cpp + ) + +-target_link_libraries(task_aggregator +- PRIVATE +- rmf_fleet_adapter +- ${rclcpp_LIBRARIES} +- ${rmf_task_msgs_LIBRARIES} +-) ++if(WIN32) ++ # the raw _LIBRARIES overflow link.exe's response-file line limit (LNK1170), as for full_control ++ target_link_libraries(task_aggregator ++ PRIVATE ++ rmf_fleet_adapter ++ rclcpp::rclcpp ++ rmf_task_msgs::rmf_task_msgs ++ ) ++else() ++ target_link_libraries(task_aggregator ++ PRIVATE ++ rmf_fleet_adapter ++ ${rclcpp_LIBRARIES} ++ ${rmf_task_msgs_LIBRARIES} ++ ) ++endif() + + target_include_directories(task_aggregator + PRIVATE +@@ -516,13 +618,22 @@ rmf_api_generate_schema_headers( + ament_export_targets(rmf_fleet_adapter HAS_LIBRARY_TARGET) + ament_export_dependencies(${dep_pkgs}) + ++# RoboStack: the library's DLL goes next to the other DLLs (on PATH on Windows), not ++# with the executables in lib/rmf_fleet_adapter, or rmf_adapter.pyd can't load it ++install( ++ TARGETS rmf_fleet_adapter ++ EXPORT rmf_fleet_adapter ++ RUNTIME DESTINATION bin ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib ++) ++ + install( + TARGETS +- rmf_fleet_adapter + read_only + read_only_blockade + mock_traffic_light +- full_control ++ ${_full_control} + lift_supervisor + mutex_group_supervisor + experimental_lift_watchdog +diff --git a/include/rmf_fleet_adapter/agv/Adapter.hpp b/include/rmf_fleet_adapter/agv/Adapter.hpp +index c4d90ac..7aa2387 100644 +--- a/include/rmf_fleet_adapter/agv/Adapter.hpp ++++ b/include/rmf_fleet_adapter/agv/Adapter.hpp +@@ -26,11 +26,13 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class Adapter : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT Adapter : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/EasyFullControl.hpp b/include/rmf_fleet_adapter/agv/EasyFullControl.hpp +index c6eb2cd..84a8809 100644 +--- a/include/rmf_fleet_adapter/agv/EasyFullControl.hpp ++++ b/include/rmf_fleet_adapter/agv/EasyFullControl.hpp +@@ -41,6 +41,8 @@ + // System headers + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + +@@ -49,7 +51,7 @@ namespace agv { + /// To disable specific tasks, call the respective consider_*_requests() method + /// on the FleetUpdateHandle that can be accessed within this adapter. + //============================================================================== +-class EasyFullControl : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl : public std::enable_shared_from_this + { + public: + +@@ -143,7 +145,7 @@ private: + using EasyFullControlPtr = std::shared_ptr; + + /// Handle used to update information about one robot +-class EasyFullControl::EasyRobotUpdateHandle ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::EasyRobotUpdateHandle + { + public: + /// Recommended function for updating information about a robot in an +@@ -198,7 +200,7 @@ private: + }; + + /// The current state of a robot, passed into EasyRobotUpdateHandle::update +-class EasyFullControl::RobotState ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::RobotState + { + public: + /// Constructor +@@ -243,7 +245,7 @@ private: + + /// The configuration of a robot. These are parameters that typically do not + /// change over time. +-class EasyFullControl::RobotConfiguration ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::RobotConfiguration + { + public: + +@@ -321,7 +323,7 @@ private: + rmf_utils::impl_ptr _pimpl; + }; + +-class EasyFullControl::RobotCallbacks ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::RobotCallbacks + { + public: + +@@ -364,7 +366,7 @@ private: + + /// Used by system integrators to give feedback on the progress of executing a + /// navigation or docking command. +-class EasyFullControl::CommandExecution ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::CommandExecution + { + public: + +@@ -418,7 +420,7 @@ private: + rmf_utils::impl_ptr _pimpl; + }; + +-class EasyFullControl::Destination ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::Destination + { + public: + /// The name of the map where the destination is located. +@@ -462,7 +464,7 @@ private: + + /// The Configuration class contains parameters necessary to initialize an + /// EasyFullControl fleet instance and add fleets to the adapter. +-class EasyFullControl::FleetConfiguration ++class RMF_FLEET_ADAPTER_EXPORT EasyFullControl::FleetConfiguration + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp b/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp +index 6db7d8b..4af6b69 100644 +--- a/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp ++++ b/include/rmf_fleet_adapter/agv/EasyTrafficLight.hpp +@@ -21,11 +21,13 @@ + #include + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class EasyTrafficLight : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT EasyTrafficLight : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp b/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp +index 9a4c4d9..c9d54f8 100644 +--- a/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp ++++ b/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp +@@ -37,11 +37,13 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class FleetUpdateHandle : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT FleetUpdateHandle : public std::enable_shared_from_this + { + public: + /// Get the name of the fleet that his handle is managing. +@@ -81,7 +83,7 @@ public: + + /// Confirmation is a class used by the task acceptance callbacks to decide if + /// a task description should be accepted. +- class Confirmation ++ class RMF_FLEET_ADAPTER_EXPORT Confirmation + { + public: + +@@ -231,7 +233,7 @@ public: + std::string emergency_level_name); + + /// A class used to describe speed limit imposed on lanes. +- class SpeedLimitRequest ++ class RMF_FLEET_ADAPTER_EXPORT SpeedLimitRequest + { + public: + /// Constructor +@@ -424,6 +426,7 @@ private: + using FleetUpdateHandlePtr = std::shared_ptr; + using ConstFleetUpdateHandlePtr = std::shared_ptr; + ++RMF_FLEET_ADAPTER_EXPORT + FleetUpdateHandle::ConsiderRequest consider_all(); + + } // namespace agv +diff --git a/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp b/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp +index 74891f7..fc1a445 100644 +--- a/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp ++++ b/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp +@@ -20,12 +20,14 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== + /// Implement this class to receive robot commands from RMF +-class RobotCommandHandle ++class RMF_FLEET_ADAPTER_EXPORT RobotCommandHandle + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp b/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp +index 1a7514c..0ff90eb 100644 +--- a/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp ++++ b/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp +@@ -32,6 +32,8 @@ + #include + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + +@@ -39,7 +41,7 @@ namespace agv { + /// You will be given an instance of this class every time you add a new robot + /// to your fleet. Use that instance to send updates to RoMi-H about your + /// robot's state. +-class RobotUpdateHandle ++class RMF_FLEET_ADAPTER_EXPORT RobotUpdateHandle + { + public: + +@@ -132,7 +134,7 @@ public: + + /// Unique identifier for an activity that the robot is performing. Used by + /// the EasyFullControl API. +- class ActivityIdentifier ++ class RMF_FLEET_ADAPTER_EXPORT ActivityIdentifier + { + public: + +@@ -154,7 +156,7 @@ public: + /// + /// When the object is destroyed, the stubbornness will automatically be + /// released. +- class Stubbornness ++ class RMF_FLEET_ADAPTER_EXPORT Stubbornness + { + public: + /// Stop being stubborn +@@ -168,7 +170,7 @@ public: + + /// The ActionExecution class should be used to manage the execution of and + /// provide updates on ongoing actions. +- class ActionExecution ++ class RMF_FLEET_ADAPTER_EXPORT ActionExecution + { + public: + /// Update the amount of time remaining for this action. +@@ -278,7 +280,7 @@ public: + + /// An object to maintain an interruption of the current task. When this + /// object is destroyed, the task will resume. +- class Interruption ++ class RMF_FLEET_ADAPTER_EXPORT Interruption + { + public: + /// Call this function to resume the task while providing labels for +@@ -354,7 +356,7 @@ public: + /// An object to maintain an issue that is happening with the robot. When this + /// object is destroyed without calling resolve(), the issue will be + /// "dropped", which issues a warning to the log. +- class IssueTicket ++ class RMF_FLEET_ADAPTER_EXPORT IssueTicket + { + public: + +@@ -413,7 +415,7 @@ public: + + /// A description of whether the robot should accept dispatched and/or direct + /// tasks. +- class Commission ++ class RMF_FLEET_ADAPTER_EXPORT Commission + { + public: + /// Construct a Commission description with all default values. +@@ -473,7 +475,7 @@ public: + + /// This API is experimental and will not be supported in the future. Users + /// are to avoid relying on these feature for any integration. +- class Unstable ++ class RMF_FLEET_ADAPTER_EXPORT Unstable + { + public: + /// True if this robot is allowed to accept new tasks. False if the robot +diff --git a/include/rmf_fleet_adapter/agv/Transformation.hpp b/include/rmf_fleet_adapter/agv/Transformation.hpp +index 9b8c538..f203f06 100644 +--- a/include/rmf_fleet_adapter/agv/Transformation.hpp ++++ b/include/rmf_fleet_adapter/agv/Transformation.hpp +@@ -22,13 +22,15 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== + /// A Transformation object that stores the transformation data needed to + /// perform transformation between robot and RMF cartesian frames. +-class Transformation ++class RMF_FLEET_ADAPTER_EXPORT Transformation + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/Waypoint.hpp b/include/rmf_fleet_adapter/agv/Waypoint.hpp +index ffa92de..34a7d5a 100644 +--- a/include/rmf_fleet_adapter/agv/Waypoint.hpp ++++ b/include/rmf_fleet_adapter/agv/Waypoint.hpp +@@ -24,11 +24,13 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + + //============================================================================== +-class Waypoint ++class RMF_FLEET_ADAPTER_EXPORT Waypoint + { + public: + +diff --git a/include/rmf_fleet_adapter/agv/parse_graph.hpp b/include/rmf_fleet_adapter/agv/parse_graph.hpp +index ad925bd..c6226f0 100644 +--- a/include/rmf_fleet_adapter/agv/parse_graph.hpp ++++ b/include/rmf_fleet_adapter/agv/parse_graph.hpp +@@ -23,6 +23,8 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + +@@ -30,6 +32,7 @@ namespace agv { + /// + /// \warning This will throw a std::runtime_error if the file has a syntax + /// error. ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::agv::Graph parse_graph( + const std::string& filename, + const rmf_traffic::agv::VehicleTraits& vehicle_traits); +diff --git a/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp b/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp +index abca90f..885b853 100644 +--- a/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp ++++ b/include/rmf_fleet_adapter/agv/test/MockAdapter.hpp +@@ -25,6 +25,8 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace agv { + namespace test { +@@ -33,7 +35,7 @@ namespace test { + /// This class is an alternative to the Adapter class, but made specifically for + /// testing. It does not try to connect to a Schedule Node or to any Negotiation + /// topics. It keeps its database internal. +-class MockAdapter : public std::enable_shared_from_this ++class RMF_FLEET_ADAPTER_EXPORT MockAdapter : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_fleet_adapter/detail/export.hpp b/include/rmf_fleet_adapter/detail/export.hpp +new file mode 100644 +index 0000000..5847ec2 +--- /dev/null ++++ b/include/rmf_fleet_adapter/detail/export.hpp +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2026 Open Source Robotics Foundation ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++*/ ++ ++#ifndef RMF_FLEET_ADAPTER__DETAIL__EXPORT_HPP ++#define RMF_FLEET_ADAPTER__DETAIL__EXPORT_HPP ++ ++// Blanket WINDOWS_EXPORT_ALL_SYMBOLS overflows MSVC's import-lib ++// 65535-object limit for this heavily Eigen/nlohmann/rxcpp-templated ++// library (same pattern rmf_traffic_ros2 hit), so the public API is ++// exported explicitly instead via this macro. ++#if defined(_WIN32) ++ #if defined(RMF_FLEET_ADAPTER_BUILDING_DLL) ++ #define RMF_FLEET_ADAPTER_EXPORT __declspec(dllexport) ++ #else ++ #define RMF_FLEET_ADAPTER_EXPORT __declspec(dllimport) ++ #endif ++#else ++ #define RMF_FLEET_ADAPTER_EXPORT ++#endif ++ ++#endif // RMF_FLEET_ADAPTER__DETAIL__EXPORT_HPP +diff --git a/include/rmf_fleet_adapter/tasks/ParkRobotIndefinitely.hpp b/include/rmf_fleet_adapter/tasks/ParkRobotIndefinitely.hpp +index 01a2d31..569cdb1 100644 +--- a/include/rmf_fleet_adapter/tasks/ParkRobotIndefinitely.hpp ++++ b/include/rmf_fleet_adapter/tasks/ParkRobotIndefinitely.hpp +@@ -20,13 +20,15 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + namespace tasks { + + //============================================================================== + /// Use this task factory to make finisher tasks (idle tasks) that will move the + /// robot to a parking spot. +-class ParkRobotIndefinitely : public rmf_task::RequestFactory ++class RMF_FLEET_ADAPTER_EXPORT ParkRobotIndefinitely : public rmf_task::RequestFactory + { + public: + /// Constructor +diff --git a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp +index d76fa76..a7e3628 100644 +--- a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp ++++ b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp +@@ -713,8 +713,12 @@ namespace detail { + + template + inline auto surely(const std::tuple& tpl) +- -> decltype(apply(tpl, detail::surely())) { +- return apply(tpl, detail::surely()); ++ -> decltype(rxcpp::util::apply(tpl, detail::surely())) { ++ // Fully qualified: an unqualified apply(tpl, ...) call here is ++ // subject to ADL bringing in std::apply (tpl is a std::tuple), and ++ // MSVC resolves the resulting ambiguity differently than GCC/Clang, ++ // instantiating std::tuple_size on the wrong type (C2027/C2131). ++ return rxcpp::util::apply(tpl, detail::surely()); + } + + namespace detail { +diff --git a/src/rmf_fleet_adapter/ScheduleManager.hpp b/src/rmf_fleet_adapter/ScheduleManager.hpp +index 006a9df..3b249ce 100644 +--- a/src/rmf_fleet_adapter/ScheduleManager.hpp ++++ b/src/rmf_fleet_adapter/ScheduleManager.hpp +@@ -30,10 +30,12 @@ + + #include + ++#include ++ + namespace rmf_fleet_adapter { + + //============================================================================== +-class ScheduleManager ++class RMF_FLEET_ADAPTER_EXPORT ScheduleManager + { + public: + +@@ -81,6 +83,7 @@ private: + }; + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::future make_schedule_manager( + rclcpp::Node& node, + rmf_traffic_ros2::schedule::Writer& writer, +@@ -88,6 +91,7 @@ std::future make_schedule_manager( + rmf_traffic::schedule::ParticipantDescription description); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void async_make_schedule_manager( + rclcpp::Node& node, + rmf_traffic_ros2::schedule::Writer& writer, +diff --git a/src/rmf_fleet_adapter/estimation.hpp b/src/rmf_fleet_adapter/estimation.hpp +index 479516c..54d8b82 100644 +--- a/src/rmf_fleet_adapter/estimation.hpp ++++ b/src/rmf_fleet_adapter/estimation.hpp +@@ -25,6 +25,8 @@ + + #include + ++#include ++ + //============================================================================== + struct TravelInfo + { +@@ -48,18 +50,21 @@ struct TravelInfo + }; + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void check_path_finish( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::RobotState& state, + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_path_traveling( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::RobotState& state, + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_midlane_state( + const rmf_fleet_msgs::msg::Location& l, + rmf_utils::optional lane_start, +@@ -67,12 +72,14 @@ void estimate_midlane_state( + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_state( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::Location& state, + TravelInfo& info); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + void estimate_waypoint( + rclcpp::Node* node, + const rmf_fleet_msgs::msg::Location& state, +diff --git a/src/rmf_fleet_adapter/load_param.hpp b/src/rmf_fleet_adapter/load_param.hpp +index 12663d1..2dc8b73 100644 +--- a/src/rmf_fleet_adapter/load_param.hpp ++++ b/src/rmf_fleet_adapter/load_param.hpp +@@ -29,6 +29,8 @@ + #include + #include + ++#include ++ + namespace rmf_fleet_adapter { + + //============================================================================== +@@ -51,15 +53,18 @@ T get_parameter_or_default( + } + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::string get_fleet_name_parameter(rclcpp::Node& node); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::chrono::nanoseconds get_parameter_or_default_time( + rclcpp::Node& node, + const std::string& param_name, + const double default_value); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::agv::VehicleTraits get_traits_or_default( + rclcpp::Node& node, + const double default_v_nom, const double default_w_nom, +@@ -67,12 +72,14 @@ rmf_traffic::agv::VehicleTraits get_traits_or_default( + const double default_r_f, const double default_r_v); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + std::optional get_battery_system( + rclcpp::Node& node, + const double default_voltage, + const double default_capacity, + const double default_charging_current); + ++RMF_FLEET_ADAPTER_EXPORT + std::optional get_mechanical_system( + rclcpp::Node& node, + const double default_mass, +diff --git a/src/rmf_fleet_adapter/make_trajectory.hpp b/src/rmf_fleet_adapter/make_trajectory.hpp +index a9f775e..3bc0cfd 100644 +--- a/src/rmf_fleet_adapter/make_trajectory.hpp ++++ b/src/rmf_fleet_adapter/make_trajectory.hpp +@@ -24,30 +24,37 @@ + + #include + ++#include ++ + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_trajectory( + const rmf_fleet_msgs::msg::RobotState& state, + const rmf_traffic::agv::VehicleTraits& traits, + bool& is_sitting); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_trajectory( + const rmf_traffic::Time start_time, + const std::vector& path, + const rmf_traffic::agv::VehicleTraits& traits); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_timed_trajectory( + const std::vector& path, + const rmf_traffic::agv::VehicleTraits& traits); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Route make_route( + const rmf_fleet_msgs::msg::RobotState& state, + const rmf_traffic::agv::VehicleTraits& traits, + bool& is_sitting); + + //============================================================================== ++RMF_FLEET_ADAPTER_EXPORT + rmf_traffic::Trajectory make_hold( + const rmf_fleet_msgs::msg::Location& location, + const rmf_traffic::Time time, diff --git a/distros/jazzy/patch/ros2-rmf-robot-sim-gz-plugins.patch b/distros/jazzy/patch/ros2-rmf-robot-sim-gz-plugins.patch new file mode 100644 index 000000000..888e45ba6 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-robot-sim-gz-plugins.patch @@ -0,0 +1,34 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 01331b9..279d989 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -23,7 +23,7 @@ find_package(ament_cmake REQUIRED) + find_package(rclcpp REQUIRED) + + find_package(gz_sim_vendor REQUIRED) +-find_package(gz-sim REQUIRED) ++find_package(gz-sim REQUIRED COMPONENTS gui) + find_package(gz_plugin_vendor REQUIRED) + find_package(gz-plugin REQUIRED) + find_package(gz_gui_vendor REQUIRED) +@@ -174,6 +174,8 @@ add_library(LightTuning SHARED ${headers_MOC} + target_link_libraries(LightTuning + gz-gui::core + gz-sim::core ++ # GuiSystem lives in the gui library (macOS doesn't allow it to stay undefined) ++ gz-sim::gui + gz-msgs::core + gz-transport::core + gz-rendering::core +diff --git a/src/LightTuning/LightTuning.cpp b/src/LightTuning/LightTuning.cpp +index 1a78e66..2a9d1c5 100644 +--- a/src/LightTuning/LightTuning.cpp ++++ b/src/LightTuning/LightTuning.cpp +@@ -450,7 +450,6 @@ signals: + void markerSelected(QString nm); + + public slots: +- void OnLightTypeSelect(sdf::Light& light, const QString& type); + void OnCreateLightBtnPress( + int idx, bool cast_shadow, const QString& type, + const QString& name, const QString& pose_str, diff --git a/distros/jazzy/patch/ros2-rmf-robot-sim-gz-plugins.win.patch b/distros/jazzy/patch/ros2-rmf-robot-sim-gz-plugins.win.patch new file mode 100644 index 000000000..25c24bc90 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-robot-sim-gz-plugins.win.patch @@ -0,0 +1,77 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 279d989..7deeab2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,12 @@ + cmake_minimum_required(VERSION 3.5) + project(rmf_robot_sim_gz_plugins) + ++if(MSVC) ++ # windows.h without WIN32_LEAN_AND_MEAN pulls in winsock.h, which then clashes with ++ # winsock2.h (C2011 sockaddr redefinition); NOMINMAX for windows.h's min/max macros ++ add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX _USE_MATH_DEFINES) ++endif() ++ + set (CMAKE_AUTOMOC ON) + + # Default to C99 +diff --git a/src/TeleportDispenser.cpp b/src/TeleportDispenser.cpp +index 4dd81fa..f23f359 100644 +--- a/src/TeleportDispenser.cpp ++++ b/src/TeleportDispenser.cpp +@@ -47,7 +47,9 @@ using namespace rmf_plugins_utils; + + namespace rmf_robot_sim_gz_plugins { + +-class GZ_SIM_VISIBLE TeleportDispenserPlugin ++// (Windows) not GZ_SIM_VISIBLE: that is gz-sim's own export macro, dllimport here (LNK2019 ++// on the vftable); GZ_ADD_PLUGIN exports the plugin ++class TeleportDispenserPlugin + : public System, + public ISystemConfigure, + public ISystemPreUpdate +diff --git a/src/TeleportIngestor.cpp b/src/TeleportIngestor.cpp +index ac1c297..3a7be63 100644 +--- a/src/TeleportIngestor.cpp ++++ b/src/TeleportIngestor.cpp +@@ -46,7 +46,9 @@ using namespace rmf_plugins_utils; + + namespace rmf_robot_sim_gz_plugins { + +-class GZ_SIM_VISIBLE TeleportIngestorPlugin ++// (Windows) not GZ_SIM_VISIBLE: that is gz-sim's own export macro, dllimport here (LNK2019 ++// on the vftable); GZ_ADD_PLUGIN exports the plugin ++class TeleportIngestorPlugin + : public System, + public ISystemConfigure, + public ISystemPreUpdate +diff --git a/src/readonly.cpp b/src/readonly.cpp +index 75384c9..52e9438 100644 +--- a/src/readonly.cpp ++++ b/src/readonly.cpp +@@ -40,7 +40,9 @@ using namespace gz::sim; + + namespace rmf_robot_sim_gz_plugins { + +-class GZ_SIM_VISIBLE ReadonlyPlugin ++// (Windows) not GZ_SIM_VISIBLE: that is gz-sim's own export macro, dllimport here (LNK2019 ++// on the vftable); GZ_ADD_PLUGIN exports the plugin ++class ReadonlyPlugin + : public System, + public ISystemConfigure, + public ISystemPreUpdate +diff --git a/src/slotcar.cpp b/src/slotcar.cpp +index d4fb269..0a8381c 100644 +--- a/src/slotcar.cpp ++++ b/src/slotcar.cpp +@@ -29,7 +29,9 @@ + + using namespace gz::sim; + +-class GZ_SIM_VISIBLE SlotcarPlugin ++// (Windows) not GZ_SIM_VISIBLE: that is gz-sim's own export macro, dllimport here (LNK2019 ++// on the vftable); GZ_ADD_PLUGIN exports the plugin ++class SlotcarPlugin + : public System, + public ISystemConfigure, + public ISystemPreUpdate diff --git a/distros/jazzy/patch/ros2-rmf-task-ros2.win.patch b/distros/jazzy/patch/ros2-rmf-task-ros2.win.patch new file mode 100644 index 000000000..59efba397 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-task-ros2.win.patch @@ -0,0 +1,47 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4f9574c..2091a65 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -29,14 +29,26 @@ find_package(nlohmann_json_schema_validator REQUIRED) + file(GLOB_RECURSE core_lib_srcs "src/rmf_task_ros2/*.cpp") + add_library(rmf_task_ros2 SHARED ${core_lib_srcs}) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this target, so ++ # without this MSVC produces the .dll but no companion .lib, and ++ # rmf_task_dispatcher/rmf_bidder_node fail with LNK1181. Only 5 ++ # source files here (vs. rmf_traffic_ros2's 26), so the LNK1189 ++ # 65535-object import-lib limit isn't a concern. ++ set_target_properties(rmf_task_ros2 PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_task_ros2 + PUBLIC + rmf_api_msgs::rmf_api_msgs + rmf_traffic::rmf_traffic + rmf_traffic_ros2::rmf_traffic_ros2 + rmf_websocket::rmf_websocket +- ${rmf_task_msgs_LIBRARIES} +- ${rclcpp_LIBRARIES} ++ # (Windows) imported targets instead of ${..._LIBRARIES}: their repeated paths overflowed ++ # link.exe's command line limit (LNK1170) ++ rmf_task_msgs::rmf_task_msgs ++ rclcpp::rclcpp + nlohmann_json::nlohmann_json + nlohmann_json_schema_validator + ) +@@ -112,10 +124,12 @@ install( + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + ++# RoboStack: the library's DLL next to the other DLLs (on PATH on Windows), not with the ++# executables in lib/rmf_task_ros2, where its users couldn't load it + install( + TARGETS rmf_task_ros2 + EXPORT rmf_task_ros2 +- RUNTIME DESTINATION lib/rmf_task_ros2 ++ RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/jazzy/patch/ros2-rmf-task-sequence.win.patch b/distros/jazzy/patch/ros2-rmf-task-sequence.win.patch new file mode 100644 index 000000000..df36895aa --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-task-sequence.win.patch @@ -0,0 +1,32 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 70eaf0e..9538863 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,6 +13,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used via rmf_traffic's installed agv/Interpolate.hpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -38,6 +44,14 @@ add_library(rmf_task_sequence SHARED + ${lib_srcs} + ) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this target, so ++ # without this MSVC produces the .dll but no companion .lib, and ++ # test_rmf_task_sequence/downstream consumers fail with LNK1181. ++ set_target_properties(rmf_task_sequence PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_task_sequence + PUBLIC + rmf_task::rmf_task diff --git a/distros/jazzy/patch/ros2-rmf-task.patch b/distros/jazzy/patch/ros2-rmf-task.patch new file mode 100644 index 000000000..2019760fc --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-task.patch @@ -0,0 +1,168 @@ +diff --git a/include/rmf_task/Event.hpp b/include/rmf_task/Event.hpp +index 82a3e60..5771d9a 100644 +--- a/include/rmf_task/Event.hpp ++++ b/include/rmf_task/Event.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__EVENT_HPP + #define RMF_TASK__EVENT_HPP + ++#include + #include + #include + +diff --git a/include/rmf_task/Log.hpp b/include/rmf_task/Log.hpp +index f046442..f62062d 100644 +--- a/include/rmf_task/Log.hpp ++++ b/include/rmf_task/Log.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__LOG_HPP + #define RMF_TASK__LOG_HPP + ++#include + #include + + #include +diff --git a/include/rmf_task/Payload.hpp b/include/rmf_task/Payload.hpp +index 084da6a..f6448f7 100644 +--- a/include/rmf_task/Payload.hpp ++++ b/include/rmf_task/Payload.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__PAYLOAD_HPP + #define RMF_TASK__PAYLOAD_HPP + ++#include + #include + + #include +diff --git a/include/rmf_task/Phase.hpp b/include/rmf_task/Phase.hpp +index 666ca1b..cf024b6 100644 +--- a/include/rmf_task/Phase.hpp ++++ b/include/rmf_task/Phase.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__PHASE_HPP + #define RMF_TASK__PHASE_HPP + ++#include + #include + #include + +diff --git a/include/rmf_task/Task.hpp b/include/rmf_task/Task.hpp +index 6c5f419..3b8d83d 100644 +--- a/include/rmf_task/Task.hpp ++++ b/include/rmf_task/Task.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__TASK_HPP + #define RMF_TASK__TASK_HPP + ++#include + #include + #include + #include +diff --git a/include/rmf_task/TaskPlanner.hpp b/include/rmf_task/TaskPlanner.hpp +index 14488f6..ec5dd10 100644 +--- a/include/rmf_task/TaskPlanner.hpp ++++ b/include/rmf_task/TaskPlanner.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__AGV__TASKPLANNER_HPP + #define RMF_TASK__AGV__TASKPLANNER_HPP + ++#include + #include + #include + #include +diff --git a/include/rmf_task/detail/Backup.hpp b/include/rmf_task/detail/Backup.hpp +index 5a9ad72..c68e959 100644 +--- a/include/rmf_task/detail/Backup.hpp ++++ b/include/rmf_task/detail/Backup.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__DETAIL__BACKUP_HPP + #define RMF_TASK__DETAIL__BACKUP_HPP + ++#include + #include + + #include +diff --git a/include/rmf_task/events/SimpleEventState.hpp b/include/rmf_task/events/SimpleEventState.hpp +index c90d528..1496e2a 100644 +--- a/include/rmf_task/events/SimpleEventState.hpp ++++ b/include/rmf_task/events/SimpleEventState.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TASK__EVENTS__SIMPLEEVENTSTATE_HPP + #define RMF_TASK__EVENTS__SIMPLEEVENTSTATE_HPP + ++#include + #include + + namespace rmf_task { +diff --git a/src/rmf_task/BackupFileManager.cpp b/src/rmf_task/BackupFileManager.cpp +index 7afa25d..992489b 100644 +--- a/src/rmf_task/BackupFileManager.cpp ++++ b/src/rmf_task/BackupFileManager.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + #include + #include +diff --git a/src/rmf_task/Event.cpp b/src/rmf_task/Event.cpp +index 2cb42b8..b5ac0ca 100644 +--- a/src/rmf_task/Event.cpp ++++ b/src/rmf_task/Event.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + namespace rmf_task { +diff --git a/src/rmf_task/Log.cpp b/src/rmf_task/Log.cpp +index 48c5883..84707a7 100644 +--- a/src/rmf_task/Log.cpp ++++ b/src/rmf_task/Log.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + #include +diff --git a/src/rmf_task/Payload.cpp b/src/rmf_task/Payload.cpp +index 8d031ce..8413f1e 100644 +--- a/src/rmf_task/Payload.cpp ++++ b/src/rmf_task/Payload.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + #include + #include +diff --git a/src/rmf_task/detail/Backup.cpp b/src/rmf_task/detail/Backup.cpp +index f353157..9f0e66b 100644 +--- a/src/rmf_task/detail/Backup.cpp ++++ b/src/rmf_task/detail/Backup.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + namespace rmf_task { +diff --git a/src/rmf_task/events/SimpleEventState.cpp b/src/rmf_task/events/SimpleEventState.cpp +index 1af9d68..0bc4bab 100644 +--- a/src/rmf_task/events/SimpleEventState.cpp ++++ b/src/rmf_task/events/SimpleEventState.cpp +@@ -15,6 +15,7 @@ + * + */ + ++#include + #include + + namespace rmf_task { diff --git a/distros/jazzy/patch/ros2-rmf-task.win.patch b/distros/jazzy/patch/ros2-rmf-task.win.patch new file mode 100644 index 000000000..7a40a118b --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-task.win.patch @@ -0,0 +1,86 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7e4d9e2..37ca5a7 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,6 +13,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used via rmf_traffic's installed Interpolate.hpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -38,6 +44,16 @@ add_library(rmf_task SHARED + ${lib_srcs} + ) + ++if(WIN32) ++ # rmf_task has no dllexport annotations at all. As a shared library on ++ # Windows with nothing explicitly exported, link.exe does not produce ++ # an import .lib, so every consumer fails with LNK1181 "cannot open ++ # input file 'rmf_task.lib'" even though rmf_task.dll itself builds ++ # fine. Auto-export everything, same fix as rmf_utils/rmf_traffic/ ++ # rmf_battery earlier in this package family. ++ set_target_properties(rmf_task PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_task + PUBLIC + rmf_battery::rmf_battery +diff --git a/src/rmf_task/BackupFileManager.cpp b/src/rmf_task/BackupFileManager.cpp +index 992489b..ce74e4b 100644 +--- a/src/rmf_task/BackupFileManager.cpp ++++ b/src/rmf_task/BackupFileManager.cpp +@@ -128,9 +128,14 @@ public: + std::optional last_seq; + const std::string backup_file_name = "backup"; + const std::string pre_backup_file_name = ".backup"; +- const std::string pre_backup_file_path = robot_directory / +- pre_backup_file_name; +- const std::string backup_file_path = robot_directory / backup_file_name; ++ // std::filesystem::path has no implicit conversion to std::string (only ++ // the explicit .string() member) -- GCC/libstdc++ tolerates constructing ++ // a string directly from a path here, but MSVC's STL correctly rejects ++ // it (C2665). Call .string() explicitly; portable everywhere. ++ const std::string pre_backup_file_path = (robot_directory / ++ pre_backup_file_name).string(); ++ const std::string backup_file_path = ++ (robot_directory / backup_file_name).string(); + + void write_if_new(const Task::Active::Backup& backup) + { +diff --git a/test/unit/test_Log.cpp b/test/unit/test_Log.cpp +index f15e519..0c3c69d 100644 +--- a/test/unit/test_Log.cpp ++++ b/test/unit/test_Log.cpp +@@ -95,9 +95,9 @@ SCENARIO("Multi-threaded read/write with synced view") + std::random_device r; + std::default_random_engine eng(r()); + std::uniform_real_distribution entry_dist(0, 1); +- std::uniform_int_distribution tier_dist( +- static_cast(rmf_task::Log::Tier::Info), +- static_cast(rmf_task::Log::Tier::Error)); ++ std::uniform_int_distribution tier_dist( ++ static_cast(rmf_task::Log::Tier::Info), ++ static_cast(rmf_task::Log::Tier::Error)); + + std::size_t counter = 0; + while (!test_finished->load()) +@@ -196,9 +196,9 @@ SCENARIO("Multi-threaded read/write without syncing") + std::random_device r; + std::default_random_engine eng(r()); + std::uniform_real_distribution entry_dist(0, 1); +- std::uniform_int_distribution tier_dist( +- static_cast(rmf_task::Log::Tier::Info), +- static_cast(rmf_task::Log::Tier::Error)); ++ std::uniform_int_distribution tier_dist( ++ static_cast(rmf_task::Log::Tier::Info), ++ static_cast(rmf_task::Log::Tier::Error)); + + std::size_t counter = 0; + while (!test_finished->load()) diff --git a/distros/jazzy/patch/ros2-rmf-traffic-editor.win.patch b/distros/jazzy/patch/ros2-rmf-traffic-editor.win.patch new file mode 100644 index 000000000..e6415d824 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-traffic-editor.win.patch @@ -0,0 +1,59 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 330da79..6cf1e01 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -6,17 +6,26 @@ endif() + + project(rmf_traffic_editor) + ++if(MSVC) ++ # M_PI and friends: MSVC defines them only with _USE_MATH_DEFINES; NOGDI keeps windows.h ++ # (pulled in by dependencies) from declaring GDI's Polygon(), which clashes with the editor's ++ add_compile_definitions(_USE_MATH_DEFINES NOGDI) ++endif() ++ + find_package(ament_cmake REQUIRED) + find_package(ament_index_cpp REQUIRED) + find_package(Ceres REQUIRED) + find_package(Eigen3 REQUIRED) + find_package(Qt5 COMPONENTS Widgets Concurrent Test Network REQUIRED) + find_package(yaml-cpp REQUIRED) ++find_package(PROJ CONFIG REQUIRED) + + set(CMAKE_BUILD_TYPE RelWithDebInfo) + # set(CMAKE_VERBOSE_MAKEFILE TRUE) + +-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wshadow -Wextra") ++if(NOT MSVC) # GCC/Clang warning flags; MSVC rejects -Wshadow (D8021) ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wshadow -Wextra") ++endif() + + set(CMAKE_AUTOMOC ON) + set(CMAKE_AUTORCC ON) +@@ -120,8 +129,9 @@ target_link_libraries( + Qt5::Widgets + Qt5::Concurrent + Qt5::Network +- proj +- yaml-cpp ++ # MSVC needs the imported targets (bare names mean proj.lib / yaml-cpp.lib, LNK1181) ++ PROJ::proj ++ yaml-cpp::yaml-cpp + ${ament_index_cpp_LIBRARIES} + ) + +diff --git a/gui/editor.cpp b/gui/editor.cpp +index 4b80f05..d658ddb 100644 +--- a/gui/editor.cpp ++++ b/gui/editor.cpp +@@ -18,9 +18,8 @@ + #include + #include + #include +-#include ++// (Windows) no unistd.h or pwd.h; nothing from them is used + #include +-#include + + #include + diff --git a/distros/jazzy/patch/ros2-rmf-traffic-examples.win.patch b/distros/jazzy/patch/ros2-rmf-traffic-examples.win.patch new file mode 100644 index 000000000..21198d91e --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-traffic-examples.win.patch @@ -0,0 +1,16 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b71adb5..3ede1a4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.5) + + project(rmf_traffic_examples) + ++if(MSVC) ++ # M_PI and friends: MSVC defines them only with _USE_MATH_DEFINES ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + find_package(rmf_traffic REQUIRED) + + add_executable(three_robots src/three_robots.cpp) diff --git a/distros/jazzy/patch/ros2-rmf-utils.win.patch b/distros/jazzy/patch/ros2-rmf-utils.win.patch index 767245108..41f090f5f 100644 --- a/distros/jazzy/patch/ros2-rmf-utils.win.patch +++ b/distros/jazzy/patch/ros2-rmf-utils.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a93554f..956d1ea 100644 +index a93554f..c3783a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,10 @@ include(GNUInstallDirs) @@ -13,3 +13,14 @@ index a93554f..956d1ea 100644 target_include_directories(rmf_utils PUBLIC +@@ -44,7 +48,9 @@ write_basic_package_version_file( + install( + TARGETS rmf_utils + EXPORT rmf_utils-targets +- DESTINATION lib ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib) ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib + ) + + install( diff --git a/distros/jazzy/patch/ros2-rmf-visualization-floorplans.patch b/distros/jazzy/patch/ros2-rmf-visualization-floorplans.patch new file mode 100644 index 000000000..4e6edd8bc --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-visualization-floorplans.patch @@ -0,0 +1,14 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a4a50fa..3e74cd5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -38,6 +38,9 @@ ament_target_dependencies(floorplan_visualizer + ) + + ++# Eigen 5's config doesn't set the Eigen3_INCLUDE_DIRS that ament_target_dependencies uses ++target_link_libraries(floorplan_visualizer PUBLIC Eigen3::Eigen) ++ + target_include_directories(floorplan_visualizer + PRIVATE + $ diff --git a/distros/jazzy/patch/ros2-rmf-visualization-floorplans.win.patch b/distros/jazzy/patch/ros2-rmf-visualization-floorplans.win.patch new file mode 100644 index 000000000..e4bacebd8 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-visualization-floorplans.win.patch @@ -0,0 +1,17 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3e74cd5..1d48faf 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -5,6 +5,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI is a non-standard extension MSVC only defines when this is ++ # set (used in src/FloorplanVisualizer.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + include(GNUInstallDirs) + + find_package(eigen3_cmake_module REQUIRED) diff --git a/distros/jazzy/patch/ros2-rmf-visualization-schedule.patch b/distros/jazzy/patch/ros2-rmf-visualization-schedule.patch new file mode 100644 index 000000000..e065859f2 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-visualization-schedule.patch @@ -0,0 +1,14 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 036ae74..2f9e406 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -63,6 +63,9 @@ target_include_directories(rmf_visualization_schedule + PUBLIC + $ + ) ++# ament_target_dependencies looks for OpenSSL_LIBRARIES, but FindOpenSSL only sets ++# OPENSSL_LIBRARIES, so nothing was linked (macOS doesn't allow the symbols to stay undefined) ++target_link_libraries(rmf_visualization_schedule PUBLIC OpenSSL::SSL OpenSSL::Crypto) + + ament_export_dependencies( + rmf_traffic diff --git a/distros/jazzy/patch/ros2-rmf-visualization-schedule.win.patch b/distros/jazzy/patch/ros2-rmf-visualization-schedule.win.patch new file mode 100644 index 000000000..1413c59e7 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-visualization-schedule.win.patch @@ -0,0 +1,59 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 2f9e406..feb1c71 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -2,6 +2,19 @@ cmake_minimum_required(VERSION 3.5) + project(rmf_visualization_schedule) + set(CMAKE_EXPORT_COMPILE_COMMANDS on) + ++if(MSVC) ++ # MSVC doesn't update __cplusplus to reflect the actual C++ standard ++ # in use unless told to, so websocketpp's __cplusplus >= 201103L ++ # feature-detection in common/cpp11.hpp always fails, falling back ++ # to boost::is_same -- which recent Boost versions no longer provide ++ # (C2039/C2873 in websocketpp/common/type_traits.hpp). ++ add_compile_options(/Zc:__cplusplus) ++ ++ # M_PI_2 et al. are non-standard extensions MSVC only defines when ++ # this is set (used in test/SubmitTrajectory.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + # Default to C++17 + if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +@@ -48,6 +61,11 @@ endif() + file(GLOB_RECURSE core_lib_srcs "src/rmf_visualization_schedule/*.cpp") + add_library(rmf_visualization_schedule SHARED ${core_lib_srcs}) + ++if(MSVC) ++ # no dllexport annotations: without this there's no import library (LNK1181) ++ set_target_properties(rmf_visualization_schedule PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + ament_target_dependencies(rmf_visualization_schedule + PUBLIC + rmf_traffic +@@ -124,6 +142,8 @@ install( + ARCHIVE DESTINATION lib + ) + +-add_subdirectory(test) ++if(BUILD_TESTING) # RoboStack: its link command is too long for the Windows linker (LNK1170) ++ add_subdirectory(test) ++endif() + + ament_package() +diff --git a/src/ScheduleVisualizer.cpp b/src/ScheduleVisualizer.cpp +index 961c512..7a7bc2f 100644 +--- a/src/ScheduleVisualizer.cpp ++++ b/src/ScheduleVisualizer.cpp +@@ -107,7 +107,7 @@ ScheduleVisualizer::ScheduleVisualizer( + "Setting parameter port to %d", port + ); + +- uint retained_history_count = this->declare_parameter( ++ unsigned int retained_history_count = this->declare_parameter( + "retained_history_count", 0); + RCLCPP_INFO( + this->get_logger(), diff --git a/distros/jazzy/patch/ros2-rmf-websocket.patch b/distros/jazzy/patch/ros2-rmf-websocket.patch new file mode 100644 index 000000000..283fe4f4d --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-websocket.patch @@ -0,0 +1,162 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6c6745a..4d5c35d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -21,7 +21,8 @@ find_package(nlohmann_json REQUIRED) + find_package(nlohmann_json_schema_validator_vendor REQUIRED) + find_package(nlohmann_json_schema_validator REQUIRED) + find_package(websocketpp REQUIRED) +-find_package(Boost COMPONENTS system REQUIRED) ++# Boost.System is header-only (no boost_system library since Boost 1.89) ++find_package(Boost REQUIRED) + find_package(Threads) + + +@@ -39,7 +40,7 @@ target_link_libraries(rmf_websocket + nlohmann_json::nlohmann_json + nlohmann_json_schema_validator + PRIVATE +- Boost::system ++ Boost::headers + Threads::Threads + ) + +@@ -113,7 +114,7 @@ if(BUILD_TESTING) + target_link_libraries(test_ring_buffer + PRIVATE + rmf_utils::rmf_utils +- Boost::system ++ Boost::headers + ) + + #integration test +@@ -126,7 +127,7 @@ if(BUILD_TESTING) + ${websocketpp_LIBRARIES} + ${rclcpp_LIBRARIES} + rmf_utils::rmf_utils +- Boost::system ++ Boost::headers + rmf_websocket + PRIVATE + Threads::Threads +@@ -149,7 +150,7 @@ if(BUILD_TESTING) + ${websocketpp_LIBRARIES} + ${rclcpp_LIBRARIES} + rmf_utils::rmf_utils +- Boost::system ++ Boost::headers + rmf_websocket + PRIVATE + Threads::Threads +@@ -171,7 +172,7 @@ if(BUILD_TESTING) + ${websocketpp_LIBRARIES} + ${rclcpp_LIBRARIES} + rmf_utils::rmf_utils +- Boost::system ++ Boost::headers + rmf_websocket + PRIVATE + Threads::Threads +diff --git a/src/rmf_websocket/BroadcastClient.cpp b/src/rmf_websocket/BroadcastClient.cpp +index 01d3ac1..d2950e0 100644 +--- a/src/rmf_websocket/BroadcastClient.cpp ++++ b/src/rmf_websocket/BroadcastClient.cpp +@@ -53,7 +53,7 @@ public: + _io_service.run(); + }); + +- _io_service.dispatch([this]() ++ boost::asio::dispatch(_io_service, [this]() + { + _endpoint.connect(); + }); +@@ -113,7 +113,7 @@ public: + RCLCPP_INFO( + this->_node->get_logger(), + "Attempting queue flush if connected"); +- _io_service.dispatch([this]() ++ boost::asio::dispatch(_io_service, [this]() + { + _flush_queue_if_connected(); + }); +@@ -134,7 +134,7 @@ public: + { + /// _queue is thread safe. No need to lock. + _queue.push(msg); +- _io_service.dispatch([this]() ++ boost::asio::dispatch(_io_service, [this]() + { + _flush_queue_if_connected(); + }); +@@ -151,7 +151,7 @@ public: + log("Buffer full dropping oldest message"); + } + } +- _io_service.dispatch([this]() ++ boost::asio::dispatch(_io_service, [this]() + { + _flush_queue_if_connected(); + }); +@@ -217,7 +217,8 @@ private: + } + // create pimpl + std::string _uri; +- boost::asio::io_service _io_service; ++ // Boost 1.90 removed io_service (and its post/dispatch members) ++ boost::asio::io_context _io_service; + std::shared_ptr _node; + RingBuffer _queue; + ProvideJsonUpdates _get_json_updates_cb; +diff --git a/src/rmf_websocket/client/ClientWebSocketEndpoint.cpp b/src/rmf_websocket/client/ClientWebSocketEndpoint.cpp +index 99a823b..0aad552 100644 +--- a/src/rmf_websocket/client/ClientWebSocketEndpoint.cpp ++++ b/src/rmf_websocket/client/ClientWebSocketEndpoint.cpp +@@ -41,7 +41,7 @@ void ConnectionMetadata::on_fail(WsClient* c, websocketpp::connection_hdl hdl) + WsClient::connection_ptr con = c->get_con_from_hdl(hdl); + _server = con->get_response_header("Server"); + _error_reason = con->get_ec().message(); +- c->get_io_service().post(_reconnection_cb); ++ asio::post(c->get_io_context(), _reconnection_cb); + } + + //============================================================================= +@@ -54,7 +54,7 @@ void ConnectionMetadata::on_close(WsClient* c, websocketpp::connection_hdl hdl) + << websocketpp::close::status::get_string(con->get_remote_close_code()) + << "), close reason: " << con->get_remote_close_reason(); + _error_reason = s.str(); +- c->get_io_service().post(_reconnection_cb); ++ asio::post(c->get_io_context(), _reconnection_cb); + } + + //============================================================================= +@@ -108,7 +108,7 @@ websocketpp::connection_hdl ConnectionMetadata::get_hdl() const + //============================================================================= + ClientWebSocketEndpoint::ClientWebSocketEndpoint( + std::string const& uri, std::shared_ptr node, +- asio::io_service* io_service, ++ asio::io_context* io_service, + ConnectionCallback cb) + : _uri(uri), _node(node), _init{false}, _reconnect_enqueued(false), + _connection_cb(std::move(cb)) +@@ -144,7 +144,7 @@ websocketpp::lib::error_code ClientWebSocketEndpoint::connect() + "> Reconnecting in 1s\n" + "> Host: %s", _uri.c_str()); + _endpoint->stop_perpetual(); +- auto io_service = &_endpoint->get_io_service(); ++ auto io_service = &_endpoint->get_io_context(); + _endpoint = std::make_unique(); + _endpoint->clear_access_channels(websocketpp::log::alevel::all); + _endpoint->clear_error_channels(websocketpp::log::elevel::all); +diff --git a/src/rmf_websocket/client/ClientWebSocketEndpoint.hpp b/src/rmf_websocket/client/ClientWebSocketEndpoint.hpp +index 55f7105..1d79b6f 100644 +--- a/src/rmf_websocket/client/ClientWebSocketEndpoint.hpp ++++ b/src/rmf_websocket/client/ClientWebSocketEndpoint.hpp +@@ -101,7 +101,7 @@ public: + ClientWebSocketEndpoint( + std::string const& uri, + std::shared_ptr node, +- boost::asio::io_service* io_service, ++ boost::asio::io_context* io_service, + ConnectionCallback cb); + + /// Delete move constructor diff --git a/distros/jazzy/patch/ros2-rmf-websocket.win.patch b/distros/jazzy/patch/ros2-rmf-websocket.win.patch new file mode 100644 index 000000000..ce5f7f923 --- /dev/null +++ b/distros/jazzy/patch/ros2-rmf-websocket.win.patch @@ -0,0 +1,41 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6c6745a..8593ff6 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,6 +11,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") + endif() + ++if(MSVC) ++ # websocketpp's C++11 feature detection reads __cplusplus, which MSVC only reports ++ # correctly with /Zc:__cplusplus (otherwise it falls back to boost::is_same, gone from Boost). ++ add_compile_options(/Zc:__cplusplus) ++endif() ++ + include(GNUInstallDirs) + + find_package(ament_cmake REQUIRED) +@@ -31,6 +37,14 @@ add_library(rmf_websocket SHARED + src/rmf_websocket/BroadcastServer.cpp + ) + ++if(MSVC) ++ # No explicit dllexport annotations anywhere in this small target, so ++ # without this MSVC produces the .dll but no companion .lib, and ++ # example_client fails with LNK1181. ++ set_target_properties(rmf_websocket PROPERTIES ++ WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + target_link_libraries(rmf_websocket + PUBLIC + ${rclcpp_LIBRARIES} +@@ -83,7 +97,7 @@ install( + install( + TARGETS rmf_websocket + EXPORT rmf_websocket +- RUNTIME DESTINATION lib/rmf_websocket ++ RUNTIME DESTINATION bin # RoboStack: the DLL next to the other DLLs (on PATH on Windows) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/jazzy/pkg_additional_info.yaml b/distros/jazzy/pkg_additional_info.yaml index 3d1759753..9970403be 100644 --- a/distros/jazzy/pkg_additional_info.yaml +++ b/distros/jazzy/pkg_additional_info.yaml @@ -133,3 +133,5 @@ zenoh_cpp_vendor: additional_cmake_args: "-DAMENT_VENDOR_POLICY=NEVER_VENDOR_IGNORE_SATISFIED_CHECK -DUSE_SYSTEM_ZENOH=ON" gz_ogre_next_vendor: build_number: 28 +rmf_utils: # its DLL moved from lib to bin (Windows) + build_number: 28 diff --git a/distros/lyrical/patch/dependencies.yaml b/distros/lyrical/patch/dependencies.yaml index 1e0b683b6..2baff0313 100644 --- a/distros/lyrical/patch/dependencies.yaml +++ b/distros/lyrical/patch/dependencies.yaml @@ -135,9 +135,6 @@ py_trees_ros_tutorials: add_run: ["pyqt6"] py_trees_ros_viewer: add_host: ["poetry-core"] -pybind11_json_vendor: - add_host: ["pybind11_json"] - add_run: ["pybind11_json"] python_qt_binding: add_host: ["pyqt-builder", "qt6-main", "pyqt6"] add_run: ["pyqt-builder", "qt6-main", "pyqt6"] diff --git a/distros/lyrical/patch/ros2-rmf-building-map-tools.patch b/distros/lyrical/patch/ros2-rmf-building-map-tools.patch deleted file mode 100644 index 46ce77f3c..000000000 --- a/distros/lyrical/patch/ros2-rmf-building-map-tools.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/building_map/level.py b/building_map/level.py -index b602ed6..68767cf 100644 ---- a/building_map/level.py -+++ b/building_map/level.py -@@ -430,7 +430,9 @@ class Level: - b.append(verts[i-1] - verts[i]) - # cross products of the four pairs of vectors. If the four cross - # products have the same sign, then the point is inside the rectangle -- cross = np.cross(a, np.array(b)) -+ b = np.array(b) -+ # np.cross no longer accepts 2D vectors as of NumPy 2.4. -+ cross = a[:, 0] * b[:, 1] - a[:, 1] * b[:, 0] - if np.all(cross >= 0) or np.all(cross <= 0): - return True - else: diff --git a/distros/lyrical/patch/ros2-rmf-fleet-adapter.win.patch b/distros/lyrical/patch/ros2-rmf-fleet-adapter.win.patch index 40b839872..4b4252587 100644 --- a/distros/lyrical/patch/ros2-rmf-fleet-adapter.win.patch +++ b/distros/lyrical/patch/ros2-rmf-fleet-adapter.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index c037339..9319d50 100644 +index c037339..c2741f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -204,6 +204,15 @@ index c037339..9319d50 100644 target_include_directories(dump_fleet_states PRIVATE +@@ -498,7 +582,7 @@ install( + TARGETS + rmf_fleet_adapter + EXPORT export_rmf_fleet_adapter +- RUNTIME DESTINATION lib/rmf_fleet_adapter ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_fleet_adapter) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/include/rmf_fleet_adapter/agv/Adapter.hpp b/include/rmf_fleet_adapter/agv/Adapter.hpp index c4d90ac..7aa2387 100644 --- a/include/rmf_fleet_adapter/agv/Adapter.hpp diff --git a/distros/lyrical/patch/ros2-rmf-task-ros2.win.patch b/distros/lyrical/patch/ros2-rmf-task-ros2.win.patch index 751d37996..d9421aad9 100644 --- a/distros/lyrical/patch/ros2-rmf-task-ros2.win.patch +++ b/distros/lyrical/patch/ros2-rmf-task-ros2.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8d3ecf9..403d67f 100644 +index 8d3ecf9..442cdec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,16 @@ find_package(nlohmann_json_schema_validator REQUIRED) @@ -54,3 +54,12 @@ index 8d3ecf9..403d67f 100644 target_include_directories(rmf_task_ros2 PUBLIC $ +@@ -117,7 +147,7 @@ install( + install( + TARGETS rmf_task_ros2 + EXPORT export_rmf_task_ros2 +- RUNTIME DESTINATION lib/rmf_task_ros2 ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_task_ros2) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/lyrical/patch/ros2-rmf-traffic-ros2.win.patch b/distros/lyrical/patch/ros2-rmf-traffic-ros2.win.patch index 67b8830a5..35800896d 100644 --- a/distros/lyrical/patch/ros2-rmf-traffic-ros2.win.patch +++ b/distros/lyrical/patch/ros2-rmf-traffic-ros2.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a05ec3e2..409ae76f 100644 +index a05ec3e..9e7f32b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -161,6 +161,15 @@ index a05ec3e2..409ae76f 100644 # TODO(MXG): Change these executables into shared libraries that can act as # ROS2 node components +@@ -280,7 +370,7 @@ install( + TARGETS + rmf_traffic_ros2 + EXPORT export_rmf_traffic_ros2 +- RUNTIME DESTINATION lib/rmf_traffic_ros2 ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_traffic_ros2) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/include/rmf_traffic_ros2/detail/export.hpp b/include/rmf_traffic_ros2/detail/export.hpp new file mode 100644 index 00000000..a8117028 diff --git a/distros/lyrical/patch/ros2-rmf-utils.win.patch b/distros/lyrical/patch/ros2-rmf-utils.win.patch index fe4c98e9b..12050ad01 100644 --- a/distros/lyrical/patch/ros2-rmf-utils.win.patch +++ b/distros/lyrical/patch/ros2-rmf-utils.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a08c67a..f4b60c0 100644 +index a08c67a..ad6b4ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,16 @@ if(WIN32) @@ -19,3 +19,14 @@ index a08c67a..f4b60c0 100644 target_include_directories(rmf_utils PUBLIC $ +@@ -47,7 +57,9 @@ write_basic_package_version_file( + install( + TARGETS rmf_utils + EXPORT rmf_utils-targets +- DESTINATION lib ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib) ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib + ) + + install( diff --git a/distros/lyrical/patch/ros2-rmf-websocket.win.patch b/distros/lyrical/patch/ros2-rmf-websocket.win.patch index 461e893d7..dc8acbcdc 100644 --- a/distros/lyrical/patch/ros2-rmf-websocket.win.patch +++ b/distros/lyrical/patch/ros2-rmf-websocket.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a23ef26..23c4822 100644 +index a23ef26..237fa6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,15 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -33,3 +33,12 @@ index a23ef26..23c4822 100644 target_link_libraries(rmf_websocket PUBLIC ${rclcpp_LIBRARIES} +@@ -89,7 +106,7 @@ install( + install( + TARGETS rmf_websocket + EXPORT export_rmf_websocket +- RUNTIME DESTINATION lib/rmf_websocket ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_websocket) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/lyrical/pkg_additional_info.yaml b/distros/lyrical/pkg_additional_info.yaml index e54cad0ca..56457c86f 100644 --- a/distros/lyrical/pkg_additional_info.yaml +++ b/distros/lyrical/pkg_additional_info.yaml @@ -115,3 +115,15 @@ urdfdom_headers: zenoh_cpp_vendor: additional_cmake_args: "-DAMENT_VENDOR_POLICY=NEVER_VENDOR_IGNORE_SATISFIED_CHECK -DUSE_SYSTEM_ZENOH=ON" # Remove build_number fields below on new full rebuild +rmf_fleet_adapter: # its DLL moved to bin (Windows) + build_number: 31 +rmf_fleet_adapter_python: # rmf_adapter as a Python MODULE (shared patch) + build_number: 31 +rmf_task_ros2: # its DLL moved to bin (Windows) + build_number: 31 +rmf_traffic_ros2: # its DLL moved to bin (Windows) + build_number: 31 +rmf_utils: # its DLL moved to bin (Windows) + build_number: 31 +rmf_websocket: # its DLL moved to bin (Windows) + build_number: 31 diff --git a/distros/rolling/patch/ros2-rmf-fleet-adapter-python.win.patch b/distros/rolling/patch/ros2-rmf-fleet-adapter-python.win.patch deleted file mode 100644 index c43b7e574..000000000 --- a/distros/rolling/patch/ros2-rmf-fleet-adapter-python.win.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index f71ed979..c28faa14 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -14,6 +14,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) - endif() - -+if(MSVC) -+ # M_PI et al. are non-standard extensions MSVC only defines when this -+ # is set (used via rmf_traffic's installed agv/Interpolate.hpp). -+ add_compile_definitions(_USE_MATH_DEFINES) -+endif() -+ - if(NOT CMAKE_BUILD_TYPE) - # Use the Release build type by default if the user has not specified one - set(CMAKE_BUILD_TYPE Release) diff --git a/distros/rolling/patch/ros2-rmf-fleet-adapter.win.patch b/distros/rolling/patch/ros2-rmf-fleet-adapter.win.patch index d1edac885..0e8f81c99 100644 --- a/distros/rolling/patch/ros2-rmf-fleet-adapter.win.patch +++ b/distros/rolling/patch/ros2-rmf-fleet-adapter.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 0588eeac..7155d63c 100644 +index 0588eea..be41017 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -204,6 +204,15 @@ index 0588eeac..7155d63c 100644 target_include_directories(dump_fleet_states PRIVATE +@@ -499,7 +583,7 @@ install( + TARGETS + rmf_fleet_adapter + EXPORT export_rmf_fleet_adapter +- RUNTIME DESTINATION lib/rmf_fleet_adapter ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_fleet_adapter) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp b/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp index d76fa76a..a7e36281 100644 --- a/rmf_rxcpp/RxCpp-4.1.0/Rx/v2/src/rxcpp/rx-util.hpp diff --git a/distros/rolling/patch/ros2-rmf-task-ros2.win.patch b/distros/rolling/patch/ros2-rmf-task-ros2.win.patch index c12276f53..7df37038c 100644 --- a/distros/rolling/patch/ros2-rmf-task-ros2.win.patch +++ b/distros/rolling/patch/ros2-rmf-task-ros2.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 9dc2b82c..1d248be7 100644 +index 9dc2b82..c35ac96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,16 @@ find_package(nlohmann_json_schema_validator REQUIRED) @@ -54,3 +54,12 @@ index 9dc2b82c..1d248be7 100644 target_include_directories(rmf_task_ros2 PUBLIC $ +@@ -117,7 +147,7 @@ install( + install( + TARGETS rmf_task_ros2 + EXPORT export_rmf_task_ros2 +- RUNTIME DESTINATION lib/rmf_task_ros2 ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_task_ros2) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/rolling/patch/ros2-rmf-traffic-ros2.win.patch b/distros/rolling/patch/ros2-rmf-traffic-ros2.win.patch index 67b8830a5..35800896d 100644 --- a/distros/rolling/patch/ros2-rmf-traffic-ros2.win.patch +++ b/distros/rolling/patch/ros2-rmf-traffic-ros2.win.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a05ec3e2..409ae76f 100644 +index a05ec3e..9e7f32b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -161,6 +161,15 @@ index a05ec3e2..409ae76f 100644 # TODO(MXG): Change these executables into shared libraries that can act as # ROS2 node components +@@ -280,7 +370,7 @@ install( + TARGETS + rmf_traffic_ros2 + EXPORT export_rmf_traffic_ros2 +- RUNTIME DESTINATION lib/rmf_traffic_ros2 ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_traffic_ros2) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/include/rmf_traffic_ros2/detail/export.hpp b/include/rmf_traffic_ros2/detail/export.hpp new file mode 100644 index 00000000..a8117028 diff --git a/distros/rolling/patch/ros2-rmf-utils.win.patch b/distros/rolling/patch/ros2-rmf-utils.win.patch index 9c79859cc..e1ba619fe 100644 --- a/distros/rolling/patch/ros2-rmf-utils.win.patch +++ b/distros/rolling/patch/ros2-rmf-utils.win.patch @@ -1,21 +1,15 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index a93554f..3ec361d 100644 +index a08c67a..ecf9758 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -15,6 +15,16 @@ include(GNUInstallDirs) - file(GLOB_RECURSE lib_srcs "src/rmf_utils/*.cpp") - add_library(rmf_utils SHARED ${lib_srcs}) +@@ -47,7 +47,9 @@ write_basic_package_version_file( + install( + TARGETS rmf_utils + EXPORT rmf_utils-targets +- DESTINATION lib ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib) ++ LIBRARY DESTINATION lib ++ ARCHIVE DESTINATION lib + ) -+if(WIN32) -+ # rmf_utils has no dllexport annotations at all. As a shared library on -+ # Windows with nothing explicitly exported, link.exe does not produce -+ # an import .lib, so every consumer (rmf-traffic here) fails with -+ # LNK1181 "cannot open input file 'rmf_utils.lib'" even though -+ # rmf_utils.dll itself builds fine. Auto-export everything, same fix -+ # used for every other Windows shared-library target this session. -+ set_target_properties(rmf_utils PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) -+endif() -+ - target_include_directories(rmf_utils - PUBLIC - $ + install( diff --git a/distros/rolling/patch/ros2-rmf-websocket.win.patch b/distros/rolling/patch/ros2-rmf-websocket.win.patch index aaacbb548..e2fdff38c 100644 --- a/distros/rolling/patch/ros2-rmf-websocket.win.patch +++ b/distros/rolling/patch/ros2-rmf-websocket.win.patch @@ -1,9 +1,9 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 38a92790..9db1d821 100644 +index 32172de..702989f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -7,6 +7,15 @@ project(rmf_websocket) - # RoboStack/ros-lyrical#41's fix), which still provides io_service. +@@ -8,6 +8,15 @@ project(rmf_websocket) + # standalone Asio 1.33.0, github.com/chriskohlhoff/asio@49fcd034). add_compile_definitions(ASIO_STANDALONE) +if(MSVC) @@ -18,7 +18,7 @@ index 38a92790..9db1d821 100644 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) endif() -@@ -35,6 +44,14 @@ add_library(rmf_websocket SHARED +@@ -36,6 +45,14 @@ add_library(rmf_websocket SHARED src/rmf_websocket/BroadcastServer.cpp ) @@ -33,3 +33,12 @@ index 38a92790..9db1d821 100644 target_link_libraries(rmf_websocket PUBLIC ${rclcpp_LIBRARIES} +@@ -87,7 +104,7 @@ install( + install( + TARGETS rmf_websocket + EXPORT export_rmf_websocket +- RUNTIME DESTINATION lib/rmf_websocket ++ RUNTIME DESTINATION bin # RoboStack: the DLL on PATH on Windows (was lib/rmf_websocket) + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + ) diff --git a/distros/rolling/pkg_additional_info.yaml b/distros/rolling/pkg_additional_info.yaml index ee9014bf6..edc5bf49d 100644 --- a/distros/rolling/pkg_additional_info.yaml +++ b/distros/rolling/pkg_additional_info.yaml @@ -73,3 +73,15 @@ urdfdom_headers: override_version: '3.0.0' zenoh_cpp_vendor: additional_cmake_args: "-DAMENT_VENDOR_POLICY=NEVER_VENDOR_IGNORE_SATISFIED_CHECK -DUSE_SYSTEM_ZENOH=ON" +rmf_fleet_adapter: # its DLL moved to bin (Windows) + build_number: 33 +rmf_fleet_adapter_python: # rmf_adapter as a Python MODULE (shared patch) + build_number: 33 +rmf_task_ros2: # its DLL moved to bin (Windows) + build_number: 33 +rmf_traffic_ros2: # its DLL moved to bin (Windows) + build_number: 33 +rmf_utils: # its DLL moved to bin (Windows) + build_number: 33 +rmf_websocket: # its DLL moved to bin (Windows) + build_number: 33 diff --git a/shared/patch/dependencies.yaml b/shared/patch/dependencies.yaml index 06fe3b647..b1dd64dda 100644 --- a/shared/patch/dependencies.yaml +++ b/shared/patch/dependencies.yaml @@ -110,6 +110,10 @@ plotjuggler_ros: add_host: ["${{ 'libgl-devel' if linux }}", "${{ 'libopengl-devel' if linux }}"] popf: add_host: ["perl"] +pybind11_json_vendor: + # the shared NEVER_VENDOR policy (pkg_additional_info.yaml) needs conda-forge's pybind11_json + add_host: ["pybind11_json"] + add_run: ["pybind11_json"] pybind11_vendor: add_host: ["pybind11"] add_run: ["pybind11"] diff --git a/shared/patch/ros2-nlohmann-json-schema-validator-vendor.patch b/shared/patch/ros2-nlohmann-json-schema-validator-vendor.patch new file mode 100644 index 000000000..a2a503cde --- /dev/null +++ b/shared/patch/ros2-nlohmann-json-schema-validator-vendor.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 2115dd4..5d0ea5f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -7,7 +7,7 @@ find_package(ament_cmake REQUIRED) + macro(build_nlohmann_json_schema_validator) + + set(cmake_commands) +- set(cmake_configure_args -Wno-dev) ++ set(cmake_configure_args -Wno-dev -DCMAKE_POLICY_VERSION_MINIMUM=3.5) + + if(WIN32) + if(DEFINED CMAKE_GENERATOR) diff --git a/shared/patch/ros2-nlohmann-json-schema-validator-vendor.win.patch b/shared/patch/ros2-nlohmann-json-schema-validator-vendor.win.patch new file mode 100644 index 000000000..0271a3ac2 --- /dev/null +++ b/shared/patch/ros2-nlohmann-json-schema-validator-vendor.win.patch @@ -0,0 +1,45 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 5d0ea5f..cb42546 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -20,8 +20,9 @@ macro(build_nlohmann_json_schema_validator) + + if(DEFINED CMAKE_BUILD_TYPE) + if(WIN32) +- build_command(_build_command CONFIGURATION ${CMAKE_BUILD_TYPE}) +- list(APPEND cmake_commands "BUILD_COMMAND ${_build_command}") ++ # build_command() gives one pre-quoted string, which the VS generator quotes once ++ # more ("... is not recognized as an internal or external command"): tokens instead ++ list(APPEND cmake_commands BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}) + else() + list(APPEND cmake_configure_args -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}) + endif() +@@ -59,10 +60,13 @@ macro(build_nlohmann_json_schema_validator) + include(ExternalProject) + # HEAD of `main` branch on 2022-10-07 + set(nlohmann_json_schema_validator_version "5ef4f903af055550e06955973a193e17efded896") +- externalproject_add(nlohmann_json_schema_validator-${nlohmann_json_schema_validator_version} ++ # short name and prefix: the default layout repeats the 40-character hash, which with ++ # rattler-build's work directory exceeds MAX_PATH ("'$GIT_DIR' too big") ++ externalproject_add(nlohmann_json_schema_validator_ext ++ PREFIX ${CMAKE_CURRENT_BINARY_DIR}/ext + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator.git + GIT_TAG ${nlohmann_json_schema_validator_version} +- GIT_CONFIG advice.detachedHead=false ++ GIT_CONFIG advice.detachedHead=false core.longpaths=true + # Suppress git update due to https://gitlab.kitware.com/cmake/cmake/-/issues/16419 + UPDATE_COMMAND "" + TIMEOUT 6000 +@@ -71,6 +75,12 @@ macro(build_nlohmann_json_schema_validator) + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${json_external_project_dir}/install/ + -DBUILD_SHARED_LIBS:BOOL=ON ++ # no dllexport annotations: without this there's no import library (LNK1181) ++ -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS:BOOL=ON ++ # options of this (older) validator; JSON_VALIDATOR_BUILD_* below are the newer names. Its test ++ # links the data symbol draft7_schema_builtin, which export-all does not export (LNK2019). ++ -DBUILD_TESTS:BOOL=OFF ++ -DBUILD_EXAMPLES:BOOL=OFF + -DJSON_VALIDATOR_BUILD_TESTS:BOOL=OFF + -DJSON_VALIDATOR_BUILD_EXAMPLES:BOOL=OFF + ${cmake_configure_args} diff --git a/distros/rolling/patch/ros2-rmf-building-map-tools.patch b/shared/patch/ros2-rmf-building-map-tools.patch similarity index 100% rename from distros/rolling/patch/ros2-rmf-building-map-tools.patch rename to shared/patch/ros2-rmf-building-map-tools.patch diff --git a/shared/patch/ros2-rmf-fleet-adapter-python.patch b/shared/patch/ros2-rmf-fleet-adapter-python.patch new file mode 100644 index 000000000..085c90c2d --- /dev/null +++ b/shared/patch/ros2-rmf-fleet-adapter-python.patch @@ -0,0 +1,11 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 914a737..9be2883 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -38,3 +38,5 @@ find_package(pybind11_json REQUIRED) + +-pybind11_add_module(rmf_adapter SHARED ++# A Python extension module, not a SHARED library: SHARED makes pybind11 link pybind11::embed, ++# i.e. libpython, and on macOS importing it then crashes (a second, uninitialised interpreter) ++pybind11_add_module(rmf_adapter MODULE + src/adapter.cpp diff --git a/distros/lyrical/patch/ros2-rmf-fleet-adapter-python.win.patch b/shared/patch/ros2-rmf-fleet-adapter-python.win.patch similarity index 100% rename from distros/lyrical/patch/ros2-rmf-fleet-adapter-python.win.patch rename to shared/patch/ros2-rmf-fleet-adapter-python.win.patch diff --git a/shared/patch/ros2-rmf-robot-sim-common.patch b/shared/patch/ros2-rmf-robot-sim-common.patch new file mode 100644 index 000000000..e369277ed --- /dev/null +++ b/shared/patch/ros2-rmf-robot-sim-common.patch @@ -0,0 +1,39 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 250bb9a..ff56169 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -18,6 +18,10 @@ endif() + + find_package(eigen3_cmake_module REQUIRED) + find_package(Eigen3 REQUIRED) ++if(NOT EIGEN3_INCLUDE_DIRS) ++ # Eigen 5's CMake config only provides the Eigen3::Eigen target ++ get_target_property(EIGEN3_INCLUDE_DIRS Eigen3::Eigen INTERFACE_INCLUDE_DIRECTORIES) ++endif() + find_package(ament_cmake REQUIRED) + find_package(rclcpp REQUIRED) + find_package(geometry_msgs REQUIRED) +diff --git a/include/rmf_robot_sim_common/readonly_common.hpp b/include/rmf_robot_sim_common/readonly_common.hpp +index 3621daf..b3f493f 100644 +--- a/include/rmf_robot_sim_common/readonly_common.hpp ++++ b/include/rmf_robot_sim_common/readonly_common.hpp +@@ -122,7 +122,8 @@ void ReadonlyCommon::read_sdf(SdfPtrT& sdf) + RCLCPP_INFO(logger(), "Setting level name to: %s", _level_name.c_str()); + + if (sdf->HasElement("graph_index")) +- _nav_graph_index = sdf->template Get("graph_index"); ++ // sdformat has no std::size_t parameter type where it is unsigned long (macOS) ++ _nav_graph_index = static_cast(sdf->template Get("graph_index")); + RCLCPP_INFO(logger(), "Setting nav graph index: %d", _nav_graph_index); + + if (sdf->HasElement("spawn_waypoint")) +@@ -130,7 +131,8 @@ void ReadonlyCommon::read_sdf(SdfPtrT& sdf) + RCLCPP_INFO(logger(), "Setting start wp name: %s", _start_wp_name.c_str()); + + if (sdf->HasElement("look_ahead")) +- _lookahead = sdf->template Get("look_ahead"); ++ // sdformat has no std::size_t parameter type where it is unsigned long (macOS) ++ _lookahead = static_cast(sdf->template Get("look_ahead")); + _lookahead = _lookahead < 1 ? 1 : _lookahead; + _next_wp.resize(_lookahead); + _path.resize(_lookahead); diff --git a/shared/patch/ros2-rmf-robot-sim-common.win.patch b/shared/patch/ros2-rmf-robot-sim-common.win.patch new file mode 100644 index 000000000..f43f6e6e7 --- /dev/null +++ b/shared/patch/ros2-rmf-robot-sim-common.win.patch @@ -0,0 +1,16 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ff56169..e797946 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,11 @@ + cmake_minimum_required(VERSION 3.5) + project(rmf_robot_sim_common) + ++if(MSVC) ++ # M_PI and friends: MSVC defines them only with _USE_MATH_DEFINES ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + # Default to C99 + if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) diff --git a/shared/patch/ros2-rmf-traffic-editor-test-maps.win.patch b/shared/patch/ros2-rmf-traffic-editor-test-maps.win.patch new file mode 100644 index 000000000..0c3ac692d --- /dev/null +++ b/shared/patch/ros2-rmf-traffic-editor-test-maps.win.patch @@ -0,0 +1,17 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a0546f2..089ef9b 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,6 +11,12 @@ install(DIRECTORY + + ament_package() + ++if(WIN32) ++ # building_map_model_downloader logs "error: ..." for the missing crowd_sim models, which ++ # MSBuild takes for a failed custom command (MSB8066); it also needs Gazebo Fuel at build time ++ set(NO_DOWNLOAD_MODELS ON) ++endif() ++ + file(GLOB_RECURSE traffic_editor_paths "maps/*.building.yaml") + + foreach(path ${traffic_editor_paths}) diff --git a/shared/patch/ros2-rmf-traffic-ros2.patch b/shared/patch/ros2-rmf-traffic-ros2.patch new file mode 100644 index 000000000..51425713d --- /dev/null +++ b/shared/patch/ros2-rmf-traffic-ros2.patch @@ -0,0 +1,39 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9bfd3b5..a05ec3e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -180,6 +180,7 @@ add_library(rmf_traffic_ros2 SHARED ${core_lib_srcs}) + target_link_libraries(rmf_traffic_ros2 + PUBLIC + rmf_traffic::rmf_traffic ++ Eigen3::Eigen + nlohmann_json::nlohmann_json + ${rmf_traffic_msgs_LIBRARIES} + ${rmf_site_map_msgs_LIBRARIES} +diff --git a/cmake/FindLibUUID.cmake b/cmake/FindLibUUID.cmake +index 9bd1663..f1bccd7 100644 +--- a/cmake/FindLibUUID.cmake ++++ b/cmake/FindLibUUID.cmake +@@ -42,6 +42,22 @@ They may be set by end users to point at LibUUID components. + #]=======================================================================] + + #----------------------------------------------------------------------------- ++if(APPLE) ++ # macOS provides uuid_generate() etc. and uuid/uuid.h directly via the SDK's ++ # default system search paths (libSystem) -- there is no standalone ++ # libuuid.dylib to link, and no extra include dir is needed (adding the SDK's ++ # own usr/include explicitly confuses libc++'s header self-checks). Just ++ # declare an empty INTERFACE target so callers' target_link_libraries still ++ # resolves. ++ set(LibUUID_FOUND TRUE) ++ set(LIBUUID_FOUND TRUE) ++ set(LibUUID_INCLUDE_DIRS "") ++ set(LibUUID_LIBRARIES "") ++ if(NOT TARGET LibUUID::LibUUID) ++ add_library(LibUUID::LibUUID INTERFACE IMPORTED) ++ endif() ++ return() ++endif() + if(CYGWIN) + # Note: on current version of Cygwin, linking to libuuid.dll.a doesn't + # import the right symbols sometimes. Fix this by linking directly diff --git a/shared/patch/ros2-rmf-traffic-ros2.win.patch b/shared/patch/ros2-rmf-traffic-ros2.win.patch new file mode 100644 index 000000000..87237a57f --- /dev/null +++ b/shared/patch/ros2-rmf-traffic-ros2.win.patch @@ -0,0 +1,1005 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9e46c52..d9ddf34 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,6 +11,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (used via rmf_traffic's installed Moderator.hpp and this ++ # package's own blockade/Node.cpp). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake) + + include(GNUInstallDirs) +@@ -26,13 +33,22 @@ find_package(rclcpp REQUIRED) + find_package(yaml-cpp REQUIRED) + find_package(nlohmann_json REQUIRED) + find_package(ZLIB REQUIRED) +-find_package(LibUUID REQUIRED) ++if(NOT WIN32) ++ # libuuid is Linux/macOS-only; schedule/Node.cpp uses Windows' RPC UUID API instead. ++ find_package(LibUUID REQUIRED) ++endif() + + # NOTE(MXG): libproj-dev does not currently distribute its cmake config-files + # in Debian, so we can't use find_package and need to rely on pkg-config. + # find_package(PROJ REQUIRED) +-find_package(PkgConfig REQUIRED) +-pkg_check_modules(PROJ REQUIRED IMPORTED_TARGET proj) ++if(WIN32) ++ # conda-forge's proj has a CMake config with PROJ::proj; pkg-config gives a bare ++ # "proj_9" that MSVC's linker can't find (LNK1181). ++ find_package(PROJ CONFIG REQUIRED) ++else() ++ find_package(PkgConfig REQUIRED) ++ pkg_check_modules(PROJ REQUIRED IMPORTED_TARGET proj) ++endif() + + if (rmf_traffic_FOUND) + message(STATUS "found rmf_traffic") +@@ -169,6 +185,33 @@ endif() + file(GLOB_RECURSE core_lib_srcs "src/rmf_traffic_ros2/*.cpp") + add_library(rmf_traffic_ros2 SHARED ${core_lib_srcs}) + ++if(MSVC) ++ # schedule/Node.cpp exceeds the default object file section limit. ++ target_compile_options(rmf_traffic_ros2 PRIVATE /bigobj) ++ # WINDOWS_EXPORT_ALL_SYMBOLS overflows the import library's 65535-object limit ++ # (LNK1189): explicit RMF_TRAFFIC_ROS2_EXPORT annotations (detail/export.hpp) instead. ++ target_compile_definitions(rmf_traffic_ros2 PRIVATE RMF_TRAFFIC_ROS2_BUILDING_DLL) ++endif() ++ ++if(WIN32) ++ # MSVC needs the imported targets (a bare "yaml-cpp" means yaml-cpp.lib, LNK1181), and ++ # the :: targets keep the link line under link.exe's limit (LNK1170). ++ target_link_libraries(rmf_traffic_ros2 ++ PUBLIC ++ rmf_traffic::rmf_traffic ++ Eigen3::Eigen ++ nlohmann_json::nlohmann_json ++ rmf_traffic_msgs::rmf_traffic_msgs ++ rmf_site_map_msgs::rmf_site_map_msgs ++ rmf_building_map_msgs::rmf_building_map_msgs ++ rclcpp::rclcpp ++ yaml-cpp::yaml-cpp ++ ZLIB::ZLIB ++ PRIVATE ++ PROJ::proj ++ rpcrt4 ++ ) ++else() + target_link_libraries(rmf_traffic_ros2 + PUBLIC + rmf_traffic::rmf_traffic +@@ -184,6 +227,7 @@ target_link_libraries(rmf_traffic_ros2 + PRIVATE + LibUUID::LibUUID + ) ++endif() + + target_include_directories(rmf_traffic_ros2 + PUBLIC +@@ -209,6 +253,12 @@ ament_export_dependencies( + ZLIB + ) + ++if(WIN32) ++ # rmf_building_map_msgs::rmf_building_map_msgs is in the PUBLIC link interface on Windows ++ # (above), so find_package(rmf_traffic_ros2) has to find it first. ++ ament_export_dependencies(rmf_building_map_msgs) ++endif() ++ + # TODO(MXG): Change these executables into shared libraries that can act as + # ROS2 node components + +@@ -268,6 +318,12 @@ install( + ARCHIVE DESTINATION lib + ) + ++if(WIN32) ++ # RoboStack: the DLL also next to the other DLLs (on PATH): the RUNTIME destination above, ++ # lib/rmf_traffic_ros2, is for the executables, so its users couldn't load it ++ install(FILES $ DESTINATION bin) ++endif() ++ + ament_package( + CONFIG_EXTRAS + cmake/proj_dependency.cmake +diff --git a/include/rmf_traffic_ros2/Profile.hpp b/include/rmf_traffic_ros2/Profile.hpp +index d4c040a..c6d7a64 100644 +--- a/include/rmf_traffic_ros2/Profile.hpp ++++ b/include/rmf_traffic_ros2/Profile.hpp +@@ -22,12 +22,16 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::Profile convert(const rmf_traffic_msgs::msg::Profile& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::Profile convert(const rmf_traffic::Profile& from); + + } // namespace rmf_traffic_ros2 +diff --git a/include/rmf_traffic_ros2/Route.hpp b/include/rmf_traffic_ros2/Route.hpp +index 1974734..f15a83b 100644 +--- a/include/rmf_traffic_ros2/Route.hpp ++++ b/include/rmf_traffic_ros2/Route.hpp +@@ -19,19 +19,25 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::Route convert(const rmf_traffic_msgs::msg::Route& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::Route convert(const rmf_traffic::Route& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + std::vector convert( + const std::vector& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + std::vector convert( + const std::vector& from); + +diff --git a/include/rmf_traffic_ros2/Time.hpp b/include/rmf_traffic_ros2/Time.hpp +index 3467531..963bc6d 100644 +--- a/include/rmf_traffic_ros2/Time.hpp ++++ b/include/rmf_traffic_ros2/Time.hpp +@@ -23,24 +23,32 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + builtin_interfaces::msg::Time convert(rmf_traffic::Time time); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::Time convert(builtin_interfaces::msg::Time time); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rclcpp::Time to_ros2(rmf_traffic::Time time); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::Time convert(rclcpp::Time time); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rclcpp::Duration convert(rmf_traffic::Duration duration); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::Duration convert(rclcpp::Duration duration); + + } // namespace rmf_traffic_ros2 +diff --git a/include/rmf_traffic_ros2/Trajectory.hpp b/include/rmf_traffic_ros2/Trajectory.hpp +index 660d220..7c86184 100644 +--- a/include/rmf_traffic_ros2/Trajectory.hpp ++++ b/include/rmf_traffic_ros2/Trajectory.hpp +@@ -22,6 +22,8 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== +@@ -31,10 +33,12 @@ namespace rmf_traffic_ros2 { + /// describing the issue. + // TODO(MXG): Consider making conversion functions that do not require any + // allocation. ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::Trajectory convert(const rmf_traffic_msgs::msg::Trajectory& from); + + //============================================================================== + /// Convert from a Trajectory instance to a Trajectory message. ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::Trajectory convert(const rmf_traffic::Trajectory& from); + + } // namespace rmf_traffic_ros2 +diff --git a/include/rmf_traffic_ros2/agv/Graph.hpp b/include/rmf_traffic_ros2/agv/Graph.hpp +index 9603ab9..8959df4 100644 +--- a/include/rmf_traffic_ros2/agv/Graph.hpp ++++ b/include/rmf_traffic_ros2/agv/Graph.hpp +@@ -26,9 +26,12 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::agv::Graph convert(const rmf_site_map_msgs::msg::SiteMap& from, + int graph_idx = 0, double wp_tolerance = 1e-3); + +@@ -36,6 +39,7 @@ rmf_traffic::agv::Graph convert(const rmf_site_map_msgs::msg::SiteMap& from, + /// Convert a valid rmf_building_map_msgs::msg::Graph message to an + /// rmf_traffic::agv::Graph object. + /// Returns nullopt if required fields are missing. ++RMF_TRAFFIC_ROS2_EXPORT + std::optional convert( + const rmf_building_map_msgs::msg::Graph& from); + +@@ -43,6 +47,7 @@ std::optional convert( + /// Convert a valid rmf_traffic::agv::Graph object to an + /// rmf_building_map_msgs::msg::Graph message. + /// Returns nullptr if required fields are missing or fleet_name is empty. ++RMF_TRAFFIC_ROS2_EXPORT + std::unique_ptr convert( + const rmf_traffic::agv::Graph& from, const std::string& fleet_name); + +diff --git a/include/rmf_traffic_ros2/blockade/Node.hpp b/include/rmf_traffic_ros2/blockade/Node.hpp +index dd6379a..0075c6d 100644 +--- a/include/rmf_traffic_ros2/blockade/Node.hpp ++++ b/include/rmf_traffic_ros2/blockade/Node.hpp +@@ -20,14 +20,18 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace blockade { + + /// Make a blockade node instance ++RMF_TRAFFIC_ROS2_EXPORT + std::shared_ptr make_node( + const rclcpp::NodeOptions& options = rclcpp::NodeOptions()); + + /// Make a blockade node instance, specifying a node name ++RMF_TRAFFIC_ROS2_EXPORT + std::shared_ptr make_node( + const std::string& node_name, + const rclcpp::NodeOptions& options = rclcpp::NodeOptions()); +diff --git a/include/rmf_traffic_ros2/blockade/Writer.hpp b/include/rmf_traffic_ros2/blockade/Writer.hpp +index f6b771b..70b7e87 100644 +--- a/include/rmf_traffic_ros2/blockade/Writer.hpp ++++ b/include/rmf_traffic_ros2/blockade/Writer.hpp +@@ -22,13 +22,15 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace blockade { + + //============================================================================== + /// The Writer class provides an API that allows a Node to create blockade + /// Participants. +-class Writer : public std::enable_shared_from_this ++class RMF_TRAFFIC_ROS2_EXPORT Writer : public std::enable_shared_from_this + { + public: + +diff --git a/include/rmf_traffic_ros2/detail/export.hpp b/include/rmf_traffic_ros2/detail/export.hpp +new file mode 100644 +index 0000000..a811702 +--- /dev/null ++++ b/include/rmf_traffic_ros2/detail/export.hpp +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2026 Open Source Robotics Foundation ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++*/ ++ ++#ifndef RMF_TRAFFIC_ROS2__DETAIL__EXPORT_HPP ++#define RMF_TRAFFIC_ROS2__DETAIL__EXPORT_HPP ++ ++// Blanket WINDOWS_EXPORT_ALL_SYMBOLS overflows MSVC's import-lib ++// 65535-object limit for this heavily Eigen/nlohmann-templated library ++// (LNK1189), so the small set of symbols actually needed by this ++// package's own executables are exported explicitly instead. ++#if defined(_WIN32) ++ #if defined(RMF_TRAFFIC_ROS2_BUILDING_DLL) ++ #define RMF_TRAFFIC_ROS2_EXPORT __declspec(dllexport) ++ #else ++ #define RMF_TRAFFIC_ROS2_EXPORT __declspec(dllimport) ++ #endif ++#else ++ #define RMF_TRAFFIC_ROS2_EXPORT ++#endif ++ ++#endif // RMF_TRAFFIC_ROS2__DETAIL__EXPORT_HPP +diff --git a/include/rmf_traffic_ros2/geometry/Circle.hpp b/include/rmf_traffic_ros2/geometry/Circle.hpp +index cb3d888..b3813ec 100644 +--- a/include/rmf_traffic_ros2/geometry/Circle.hpp ++++ b/include/rmf_traffic_ros2/geometry/Circle.hpp +@@ -22,13 +22,17 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::Circle convert( + const rmf_traffic::geometry::Circle& circle); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::geometry::Circle convert( + const rmf_traffic_msgs::msg::Circle& circle); + +diff --git a/include/rmf_traffic_ros2/geometry/ConvexShape.hpp b/include/rmf_traffic_ros2/geometry/ConvexShape.hpp +index 403b2e6..2f33ac1 100644 +--- a/include/rmf_traffic_ros2/geometry/ConvexShape.hpp ++++ b/include/rmf_traffic_ros2/geometry/ConvexShape.hpp +@@ -23,11 +23,13 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace geometry { + + //============================================================================== +-class ConvexShapeContext ++class RMF_TRAFFIC_ROS2_EXPORT ConvexShapeContext + { + public: + +@@ -47,10 +49,12 @@ private: + } // namespace geometry + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + geometry::ConvexShapeContext convert( + const rmf_traffic_msgs::msg::ConvexShapeContext& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ConvexShapeContext convert( + const geometry::ConvexShapeContext& from); + +diff --git a/include/rmf_traffic_ros2/geometry/Shape.hpp b/include/rmf_traffic_ros2/geometry/Shape.hpp +index 4b5ec19..f926cc2 100644 +--- a/include/rmf_traffic_ros2/geometry/Shape.hpp ++++ b/include/rmf_traffic_ros2/geometry/Shape.hpp +@@ -23,11 +23,13 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace geometry { + + //============================================================================== +-class ShapeContext ++class RMF_TRAFFIC_ROS2_EXPORT ShapeContext + { + public: + +@@ -47,10 +49,12 @@ private: + } // namespace geometry + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + geometry::ShapeContext convert( + const rmf_traffic_msgs::msg::ShapeContext& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ShapeContext convert( + const geometry::ShapeContext& from); + +diff --git a/include/rmf_traffic_ros2/schedule/Change.hpp b/include/rmf_traffic_ros2/schedule/Change.hpp +index 644d7ee..8d1485b 100644 +--- a/include/rmf_traffic_ros2/schedule/Change.hpp ++++ b/include/rmf_traffic_ros2/schedule/Change.hpp +@@ -25,41 +25,52 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Change::Add::Item convert( + const rmf_traffic_msgs::msg::ScheduleChangeAddItem& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleChangeAddItem convert( + const rmf_traffic::schedule::Change::Add::Item& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Change::Add convert( + const rmf_traffic_msgs::msg::ScheduleChangeAdd& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleChangeAdd convert( + const rmf_traffic::schedule::Change::Add& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Change::Delay convert( + const rmf_traffic_msgs::msg::ScheduleChangeDelay& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleChangeDelay convert( + const rmf_traffic::schedule::Change::Delay& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::ParticipantId convert( + const rmf_traffic::schedule::Change::UnregisterParticipant& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Change::Cull convert( + const rmf_traffic_msgs::msg::ScheduleChangeCull& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleChangeCull convert( + const rmf_traffic::schedule::Change::Cull& from); + +diff --git a/include/rmf_traffic_ros2/schedule/Inconsistencies.hpp b/include/rmf_traffic_ros2/schedule/Inconsistencies.hpp +index aea4d02..bbc0e39 100644 +--- a/include/rmf_traffic_ros2/schedule/Inconsistencies.hpp ++++ b/include/rmf_traffic_ros2/schedule/Inconsistencies.hpp +@@ -22,9 +22,12 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleInconsistency convert( + const rmf_traffic::schedule::Inconsistencies::Element& from, + const rmf_traffic::schedule::ProgressVersion progress_version); +diff --git a/include/rmf_traffic_ros2/schedule/Itinerary.hpp b/include/rmf_traffic_ros2/schedule/Itinerary.hpp +index 90d74c8..7a420d9 100644 +--- a/include/rmf_traffic_ros2/schedule/Itinerary.hpp ++++ b/include/rmf_traffic_ros2/schedule/Itinerary.hpp +@@ -23,17 +23,22 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + std::vector convert( + const rmf_traffic::schedule::Itinerary& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + std::vector convert( + const std::vector& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + std::vector convert( + const std::vector& from); + +diff --git a/include/rmf_traffic_ros2/schedule/MirrorManager.hpp b/include/rmf_traffic_ros2/schedule/MirrorManager.hpp +index d3153c9..857c453 100644 +--- a/include/rmf_traffic_ros2/schedule/MirrorManager.hpp ++++ b/include/rmf_traffic_ros2/schedule/MirrorManager.hpp +@@ -23,16 +23,18 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + + //============================================================================== +-class MirrorManager ++class RMF_TRAFFIC_ROS2_EXPORT MirrorManager + { + public: + + /// Options for the MirrorManager +- class Options ++ class RMF_TRAFFIC_ROS2_EXPORT Options + { + public: + +@@ -96,7 +98,7 @@ private: + }; + + //============================================================================== +-class MirrorManagerFuture ++class RMF_TRAFFIC_ROS2_EXPORT MirrorManagerFuture + { + public: + +@@ -153,6 +155,7 @@ private: + /// + // TODO(MXG): Use std::optional here instead of std::unique_ptr when C++17 can + // be supported. ++RMF_TRAFFIC_ROS2_EXPORT + MirrorManagerFuture make_mirror( + const std::shared_ptr& node, + rmf_traffic::schedule::Query query, +diff --git a/include/rmf_traffic_ros2/schedule/MonitorNode.hpp b/include/rmf_traffic_ros2/schedule/MonitorNode.hpp +index 18da3ca..8317445 100644 +--- a/include/rmf_traffic_ros2/schedule/MonitorNode.hpp ++++ b/include/rmf_traffic_ros2/schedule/MonitorNode.hpp +@@ -23,6 +23,8 @@ + #include + #include + ++#include ++ + using namespace std::chrono_literals; + + namespace rmf_traffic_ros2 { +@@ -30,6 +32,7 @@ namespace schedule { + + /// Make a monitor node to monitor a heartbeat and restart a node when + /// the heartbeat is lost ++RMF_TRAFFIC_ROS2_EXPORT + std::shared_ptr make_monitor_node( + std::function)> callback, + const rclcpp::NodeOptions& options = rclcpp::NodeOptions(), +diff --git a/include/rmf_traffic_ros2/schedule/Negotiation.hpp b/include/rmf_traffic_ros2/schedule/Negotiation.hpp +index 318939e..018f3bb 100644 +--- a/include/rmf_traffic_ros2/schedule/Negotiation.hpp ++++ b/include/rmf_traffic_ros2/schedule/Negotiation.hpp +@@ -26,12 +26,14 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + + //============================================================================== + /// A ROS2 interface for negotiating solutions to schedule conflicts +-class Negotiation ++class RMF_TRAFFIC_ROS2_EXPORT Negotiation + { + public: + +@@ -109,7 +111,7 @@ public: + /// + /// \param[in] count + /// The number of negotiations to retain +- void set_retained_history_count(uint count); ++ void set_retained_history_count(unsigned int count); + + /// Register a negotiator with this Negotiation manager. + /// +diff --git a/include/rmf_traffic_ros2/schedule/Node.hpp b/include/rmf_traffic_ros2/schedule/Node.hpp +index 0ae4ccb..8bf6d98 100644 +--- a/include/rmf_traffic_ros2/schedule/Node.hpp ++++ b/include/rmf_traffic_ros2/schedule/Node.hpp +@@ -20,10 +20,13 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + + /// Make a ScheduleNode instance ++RMF_TRAFFIC_ROS2_EXPORT + std::shared_ptr make_node( + const rclcpp::NodeOptions& options = rclcpp::NodeOptions()); + +diff --git a/include/rmf_traffic_ros2/schedule/ParticipantDescription.hpp b/include/rmf_traffic_ros2/schedule/ParticipantDescription.hpp +index 6536cc2..ac62c06 100644 +--- a/include/rmf_traffic_ros2/schedule/ParticipantDescription.hpp ++++ b/include/rmf_traffic_ros2/schedule/ParticipantDescription.hpp +@@ -23,21 +23,27 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::ParticipantDescription convert( + const rmf_traffic_msgs::msg::ParticipantDescription& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ParticipantDescription convert( + const rmf_traffic::schedule::ParticipantDescription& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::ParticipantDescriptionsMap convert( + const rmf_traffic_msgs::msg::Participants& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::Participants convert( + const rmf_traffic::schedule::ParticipantDescriptionsMap& from); + +diff --git a/include/rmf_traffic_ros2/schedule/ParticipantRegistry.hpp b/include/rmf_traffic_ros2/schedule/ParticipantRegistry.hpp +index 6601639..c7536ce 100644 +--- a/include/rmf_traffic_ros2/schedule/ParticipantRegistry.hpp ++++ b/include/rmf_traffic_ros2/schedule/ParticipantRegistry.hpp +@@ -26,6 +26,8 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + +@@ -48,7 +50,7 @@ struct AtomicOperation + + //============================================================================= + /// This is the base class for the persistence logger. +-class AbstractParticipantLogger ++class RMF_TRAFFIC_ROS2_EXPORT AbstractParticipantLogger + { + public: + /// Called when we wish to commit an operation to disk +@@ -64,7 +66,7 @@ public: + + //============================================================================= + /// YAML logger class. Logs everything to YAML buffers on disk +-class YamlLogger : public AbstractParticipantLogger ++class RMF_TRAFFIC_ROS2_EXPORT YamlLogger : public AbstractParticipantLogger + { + public: + /// Constructor +@@ -97,7 +99,7 @@ private: + /// Internally, this class implements a an append only journal. This makes it + /// independent of any id generation inside the database, as long as the said + /// database id generation algorithm is deterministic. +-class ParticipantRegistry ++class RMF_TRAFFIC_ROS2_EXPORT ParticipantRegistry + { + public: + /// Constructor +diff --git a/include/rmf_traffic_ros2/schedule/Patch.hpp b/include/rmf_traffic_ros2/schedule/Patch.hpp +index 63915f3..5bc62fb 100644 +--- a/include/rmf_traffic_ros2/schedule/Patch.hpp ++++ b/include/rmf_traffic_ros2/schedule/Patch.hpp +@@ -22,21 +22,27 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleParticipantPatch convert( + const rmf_traffic::schedule::Patch::Participant& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Patch::Participant convert( + const rmf_traffic_msgs::msg::ScheduleParticipantPatch& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::SchedulePatch convert( + const rmf_traffic::schedule::Patch& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Patch convert( + const rmf_traffic_msgs::msg::SchedulePatch& from); + +diff --git a/include/rmf_traffic_ros2/schedule/Query.hpp b/include/rmf_traffic_ros2/schedule/Query.hpp +index 43ccb53..8b13f0c 100644 +--- a/include/rmf_traffic_ros2/schedule/Query.hpp ++++ b/include/rmf_traffic_ros2/schedule/Query.hpp +@@ -22,29 +22,37 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Query::Spacetime convert( + const rmf_traffic_msgs::msg::ScheduleQuerySpacetime& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleQuerySpacetime convert( + const rmf_traffic::schedule::Query::Spacetime& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Query::Participants convert( + const rmf_traffic_msgs::msg::ScheduleQueryParticipants& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleQueryParticipants convert( + const rmf_traffic::schedule::Query::Participants& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic::schedule::Query convert( + const rmf_traffic_msgs::msg::ScheduleQuery& from); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + rmf_traffic_msgs::msg::ScheduleQuery convert( + const rmf_traffic::schedule::Query& from); + +diff --git a/include/rmf_traffic_ros2/schedule/ScheduleIdentity.hpp b/include/rmf_traffic_ros2/schedule/ScheduleIdentity.hpp +index 168f5d3..4550fc5 100644 +--- a/include/rmf_traffic_ros2/schedule/ScheduleIdentity.hpp ++++ b/include/rmf_traffic_ros2/schedule/ScheduleIdentity.hpp +@@ -21,6 +21,8 @@ + #include + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + +@@ -30,12 +32,14 @@ namespace schedule { + /// the data of the new incoming message and the function will return true. If + /// no reconnection should happen then the previous argument will not be + /// modified and the function will return false. ++RMF_TRAFFIC_ROS2_EXPORT + bool reconnect_schedule( + rmf_traffic_msgs::msg::ScheduleIdentity& previous, + const rmf_traffic_msgs::msg::ScheduleIdentity& incoming); + + /// Same as its overload, but it accepts an optional for previous. When previous + /// is nullopt, this will save incoming and return true. ++RMF_TRAFFIC_ROS2_EXPORT + bool reconnect_schedule( + std::optional& previous, + const rmf_traffic_msgs::msg::ScheduleIdentity& incoming); +@@ -43,6 +47,7 @@ bool reconnect_schedule( + //============================================================================== + /// Equivalent to reconnect_schedule, but it does not modify the previous + /// argument. ++RMF_TRAFFIC_ROS2_EXPORT + bool need_reconnection( + const rmf_traffic_msgs::msg::ScheduleIdentity& previous, + const rmf_traffic_msgs::msg::ScheduleIdentity& incoming); +diff --git a/include/rmf_traffic_ros2/schedule/Writer.hpp b/include/rmf_traffic_ros2/schedule/Writer.hpp +index cf0cf62..13e1777 100644 +--- a/include/rmf_traffic_ros2/schedule/Writer.hpp ++++ b/include/rmf_traffic_ros2/schedule/Writer.hpp +@@ -23,13 +23,15 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + + //============================================================================== + /// The Writer class provides an API that allows a Node to create schedule + /// Participants. +-class Writer : public std::enable_shared_from_this ++class RMF_TRAFFIC_ROS2_EXPORT Writer : public std::enable_shared_from_this + { + public: + +diff --git a/src/rmf_traffic_ros2/schedule/MonitorNode.cpp b/src/rmf_traffic_ros2/schedule/MonitorNode.cpp +index daf4e1d..8bde4ca 100644 +--- a/src/rmf_traffic_ros2/schedule/MonitorNode.cpp ++++ b/src/rmf_traffic_ros2/schedule/MonitorNode.cpp +@@ -19,6 +19,7 @@ + + #include "internal_Node.hpp" + ++#include + #include + #include + +diff --git a/src/rmf_traffic_ros2/schedule/Negotiation.cpp b/src/rmf_traffic_ros2/schedule/Negotiation.cpp +index 80fe47c..a71ee91 100644 +--- a/src/rmf_traffic_ros2/schedule/Negotiation.cpp ++++ b/src/rmf_traffic_ros2/schedule/Negotiation.cpp +@@ -303,7 +303,7 @@ public: + std::function; + StatusConclusionCallback conclusion_callback; + +- uint retained_history_count = 0; ++ unsigned int retained_history_count = 0; + std::map history; + + Implementation( +@@ -1032,7 +1032,7 @@ public: + for_participant, negotiators, failure_callbacks); + } + +- void set_retained_history_count(uint count) ++ void set_retained_history_count(unsigned int count) + { + retained_history_count = count; + } +@@ -1131,7 +1131,7 @@ Negotiation::TableViewPtr Negotiation::table_view( + } + + //============================================================================== +-void Negotiation::set_retained_history_count(uint count) ++void Negotiation::set_retained_history_count(unsigned int count) + { + return _pimpl->set_retained_history_count(count); + } +diff --git a/src/rmf_traffic_ros2/schedule/Node.cpp b/src/rmf_traffic_ros2/schedule/Node.cpp +index 1418a86..448e215 100644 +--- a/src/rmf_traffic_ros2/schedule/Node.cpp ++++ b/src/rmf_traffic_ros2/schedule/Node.cpp +@@ -17,6 +17,8 @@ + + #include "internal_Node.hpp" + ++#include ++ + #include + + #include +@@ -37,7 +39,26 @@ + #include + + #include ++#ifdef _WIN32 ++// libuuid (uuid/uuid.h) is Linux/macOS-only; use Windows' native RPC ++// UUID API instead (linked against rpcrt4 in CMakeLists.txt). ++// NOMINMAX/WIN32_LEAN_AND_MEAN/NOGDI keep windows.h (pulled in by rpc.h) ++// from defining min/max (collides with std::numeric_limits::max) and, ++// via wingdi.h, an ERROR macro (collides with ++// RequestChanges::Response::ERROR used later in this file). ++#ifndef NOMINMAX ++#define NOMINMAX ++#endif ++#ifndef WIN32_LEAN_AND_MEAN ++#define WIN32_LEAN_AND_MEAN ++#endif ++#ifndef NOGDI ++#define NOGDI ++#endif ++#include ++#else + #include ++#endif + + namespace rmf_traffic_ros2 { + namespace schedule { +@@ -46,17 +67,27 @@ namespace { + //============================================================================== + ScheduleNode::ScheduleId generate_node_id() + { ++#ifdef _WIN32 ++ UUID raw_uuid; ++ UuidCreate(&raw_uuid); ++ RPC_CSTR uuid_cstr = nullptr; ++ UuidToStringA(&raw_uuid, &uuid_cstr); ++ const std::string uuid(reinterpret_cast(uuid_cstr)); ++ RpcStringFreeA(&uuid_cstr); ++#else + uuid_t raw_uuid; + uuid_generate(raw_uuid); + // According to these docs, the size of the uuid string will be + // 36 bytes + '\n' so we make a buffer of 37. +- char uuid[37]; +- uuid_unparse(raw_uuid, uuid); ++ char uuid_buf[37]; ++ uuid_unparse(raw_uuid, uuid_buf); ++ const std::string uuid(uuid_buf); ++#endif + const rclcpp::Time time( + std::chrono::system_clock::now().time_since_epoch().count()); + + return rmf_traffic_msgs::build() +- .node_uuid(std::string(uuid)) ++ .node_uuid(uuid) + .timestamp(time); + } + +diff --git a/src/rmf_traffic_ros2/schedule/internal_MonitorNode.hpp b/src/rmf_traffic_ros2/schedule/internal_MonitorNode.hpp +index 8d666fe..807aa97 100644 +--- a/src/rmf_traffic_ros2/schedule/internal_MonitorNode.hpp ++++ b/src/rmf_traffic_ros2/schedule/internal_MonitorNode.hpp +@@ -42,7 +42,7 @@ using namespace std::chrono_literals; + class MonitorNode : public rclcpp::Node + { + public: +- static struct NoAutomaticSetup{} no_automatic_setup; ++ inline static struct NoAutomaticSetup{} no_automatic_setup; + + MonitorNode( + std::function)> callback, +diff --git a/src/rmf_traffic_ros2/schedule/internal_Node.hpp b/src/rmf_traffic_ros2/schedule/internal_Node.hpp +index c5c7a7a..f835172 100644 +--- a/src/rmf_traffic_ros2/schedule/internal_Node.hpp ++++ b/src/rmf_traffic_ros2/schedule/internal_Node.hpp +@@ -83,7 +83,7 @@ public: + using ScheduleId = rmf_traffic_msgs::msg::ScheduleIdentity; + ScheduleId node_id; + +- static struct NoAutomaticSetup{} no_automatic_setup; ++ inline static struct NoAutomaticSetup{} no_automatic_setup; + + ScheduleNode( + ScheduleId id, +diff --git a/src/rmf_traffic_ros2/schedule/internal_YamlSerialization.hpp b/src/rmf_traffic_ros2/schedule/internal_YamlSerialization.hpp +index 028d6dc..dc7cdc2 100644 +--- a/src/rmf_traffic_ros2/schedule/internal_YamlSerialization.hpp ++++ b/src/rmf_traffic_ros2/schedule/internal_YamlSerialization.hpp +@@ -25,6 +25,8 @@ + + #include + ++#include ++ + namespace rmf_traffic_ros2 { + namespace schedule { + +@@ -41,6 +43,7 @@ rmf_traffic_msgs::msg::ConvexShapeContext shape_context(YAML::Node node); + rmf_traffic::Profile profile(YAML::Node node); + + //============================================================================== ++RMF_TRAFFIC_ROS2_EXPORT + ParticipantDescription participant_description(YAML::Node node); + + //============================================================================== diff --git a/shared/patch/ros2-rmf-traffic.patch b/shared/patch/ros2-rmf-traffic.patch new file mode 100644 index 000000000..76a4792be --- /dev/null +++ b/shared/patch/ros2-rmf-traffic.patch @@ -0,0 +1,362 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8d341d0..324322f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -96,6 +96,7 @@ endif() + + target_link_libraries(rmf_traffic + PUBLIC ++ Eigen3::Eigen + rmf_utils::rmf_utils + Threads::Threads + PRIVATE +diff --git a/include/rmf_traffic/schedule/Database.hpp b/include/rmf_traffic/schedule/Database.hpp +index 6318012..2d27b4b 100644 +--- a/include/rmf_traffic/schedule/Database.hpp ++++ b/include/rmf_traffic/schedule/Database.hpp +@@ -113,7 +113,7 @@ public: + + // Documentation inherited from Viewer + std::shared_ptr get_participant( +- std::size_t participant_id) const final; ++ ParticipantId participant_id) const final; + + // Documentation inherited from Viewer + Version latest_version() const; +@@ -125,11 +125,11 @@ public: + + // Documentation inherited from ItineraryViewer + std::optional get_itinerary( +- std::size_t participant_id) const final; ++ ParticipantId participant_id) const final; + + // Documentation inherited from ItineraryViewer + std::optional get_current_plan_id( +- std::size_t participant_id) const final; ++ ParticipantId participant_id) const final; + + // Documentation inherited from ItineraryViewer + const std::vector* get_current_progress( +diff --git a/include/rmf_traffic/schedule/Mirror.hpp b/include/rmf_traffic/schedule/Mirror.hpp +index 14c3c9e..f6a6108 100644 +--- a/include/rmf_traffic/schedule/Mirror.hpp ++++ b/include/rmf_traffic/schedule/Mirror.hpp +@@ -51,11 +51,11 @@ public: + + // Documentation inherited from Viewer + std::shared_ptr get_participant( +- std::size_t participant_id) const final; ++ ParticipantId participant_id) const final; + + // Documentation inherited from Viewer + std::optional get_itinerary( +- std::size_t participant_id) const final; ++ ParticipantId participant_id) const final; + + // Documentation inherited from Viewer + std::optional latest_version() const; +diff --git a/include/rmf_traffic/schedule/ParticipantDescription.hpp b/include/rmf_traffic/schedule/ParticipantDescription.hpp +index 74d272c..3ce72cd 100644 +--- a/include/rmf_traffic/schedule/ParticipantDescription.hpp ++++ b/include/rmf_traffic/schedule/ParticipantDescription.hpp +@@ -18,6 +18,7 @@ + #ifndef RMF_TRAFFIC__SCHEDULE__PARTICIPANTDESCRIPTION_HPP + #define RMF_TRAFFIC__SCHEDULE__PARTICIPANTDESCRIPTION_HPP + ++#include + #include + #include + +diff --git a/src/rmf_traffic/blockade/geometry.cpp b/src/rmf_traffic/blockade/geometry.cpp +index 049351e..0817edb 100644 +--- a/src/rmf_traffic/blockade/geometry.cpp ++++ b/src/rmf_traffic/blockade/geometry.cpp +@@ -15,8 +15,10 @@ + * + */ + ++#include + #include "geometry.hpp" + ++#include + #include + + namespace rmf_traffic { +diff --git a/src/rmf_traffic/schedule/Database.cpp b/src/rmf_traffic/schedule/Database.cpp +index 3f6dd48..2377692 100644 +--- a/src/rmf_traffic/schedule/Database.cpp ++++ b/src/rmf_traffic/schedule/Database.cpp +@@ -1303,7 +1303,7 @@ const std::unordered_set& Database::participant_ids() const + + //============================================================================== + std::shared_ptr Database::get_participant( +- std::size_t participant_id) const ++ ParticipantId participant_id) const + { + const auto state_it = _pimpl->descriptions.find(participant_id); + if (state_it == _pimpl->descriptions.end()) +@@ -1320,7 +1320,7 @@ Version Database::latest_version() const + + //============================================================================== + std::optional Database::get_itinerary( +- const std::size_t participant_id) const ++ const ParticipantId participant_id) const + { + const auto state_it = _pimpl->states.find(participant_id); + if (state_it == _pimpl->states.end()) +@@ -1345,7 +1345,7 @@ std::optional Database::get_itinerary( + + //============================================================================== + std::optional Database::get_current_plan_id( +- const std::size_t participant_id) const ++ const ParticipantId participant_id) const + { + const auto state_it = _pimpl->states.find(participant_id); + if (state_it == _pimpl->states.end()) +diff --git a/src/rmf_traffic/schedule/Mirror.cpp b/src/rmf_traffic/schedule/Mirror.cpp +index 4c1d710..e84006a 100644 +--- a/src/rmf_traffic/schedule/Mirror.cpp ++++ b/src/rmf_traffic/schedule/Mirror.cpp +@@ -255,7 +255,7 @@ const std::unordered_set& Mirror::participant_ids() const + + //============================================================================== + std::shared_ptr Mirror::get_participant( +- std::size_t participant_id) const ++ ParticipantId participant_id) const + { + const auto p = _pimpl->descriptions.find(participant_id); + if (p == _pimpl->descriptions.end()) +@@ -272,7 +272,7 @@ std::optional Mirror::latest_version() const + + //============================================================================== + std::optional Mirror::get_itinerary( +- const std::size_t participant_id) const ++ const ParticipantId participant_id) const + { + const auto p = _pimpl->states.find(participant_id); + if (p == _pimpl->states.end()) +@@ -297,7 +297,7 @@ std::optional Mirror::get_itinerary( + + //============================================================================== + std::optional Mirror::get_current_plan_id( +- const std::size_t participant_id) const ++ const ParticipantId participant_id) const + { + const auto p = _pimpl->states.find(participant_id); + if (p == _pimpl->states.end()) +diff --git a/test/unit/schedule/test_Spacetime.cpp b/test/unit/schedule/test_Spacetime.cpp +index e96cfb6..140ac52 100644 +--- a/test/unit/schedule/test_Spacetime.cpp ++++ b/test/unit/schedule/test_Spacetime.cpp +@@ -41,8 +41,8 @@ SCENARIO("Testing intersection of spacetime with trajectories") + const auto region_box_shape = rmf_traffic::geometry::make_final_convex< + rmf_traffic::geometry::Box>(10.0, 1.0); + +- std::chrono::_V2::steady_clock::time_point lower_time_bound = time; +- std::chrono::_V2::steady_clock::time_point upper_time_bound = time+10s; ++ std::chrono::steady_clock::time_point lower_time_bound = time; ++ std::chrono::steady_clock::time_point upper_time_bound = time+10s; + + rmf_traffic::internal::Spacetime region = { + &lower_time_bound, +@@ -117,8 +117,8 @@ SCENARIO("Testing intersction of various spacetimes and trajectories") + using namespace std::chrono_literals; + auto time = std::chrono::steady_clock::now(); + Eigen::Isometry2d tf = Eigen::Isometry2d::Identity(); +- std::chrono::_V2::steady_clock::time_point lower_time_bound; +- std::chrono::_V2::steady_clock::time_point upper_time_bound; ++ std::chrono::steady_clock::time_point lower_time_bound; ++ std::chrono::steady_clock::time_point upper_time_bound; + + const auto region_box_shape = rmf_traffic::geometry::make_final_convex< + rmf_traffic::geometry::Box>(10.0, 1.0); +@@ -1210,8 +1210,8 @@ SCENARIO("Testing intersection of curved trajectory with various spacetimes") + GIVEN("spacetime that encompasses the trajectory in space and time") + { + //creating space to create spacetime +- std::chrono::_V2::steady_clock::time_point lower_time_bound = time; +- std::chrono::_V2::steady_clock::time_point upper_time_bound = time+10s; ++ std::chrono::steady_clock::time_point lower_time_bound = time; ++ std::chrono::steady_clock::time_point upper_time_bound = time+10s; + Eigen::Isometry2d tf = Eigen::Isometry2d::Identity(); + + rmf_traffic::internal::Spacetime region = { +@@ -1227,8 +1227,8 @@ SCENARIO("Testing intersection of curved trajectory with various spacetimes") + GIVEN("spacetime that encompasses the trajectory in space but not time") + { + //creating space to create spacetime +- std::chrono::_V2::steady_clock::time_point lower_time_bound = time+20s; +- std::chrono::_V2::steady_clock::time_point upper_time_bound = time+30s; ++ std::chrono::steady_clock::time_point lower_time_bound = time+20s; ++ std::chrono::steady_clock::time_point upper_time_bound = time+30s; + Eigen::Isometry2d tf = Eigen::Isometry2d::Identity(); + + rmf_traffic::internal::Spacetime region = { +@@ -1244,8 +1244,8 @@ SCENARIO("Testing intersection of curved trajectory with various spacetimes") + GIVEN("spacetime that partially intersects the trajectory in space and time") + { + //creating space to create spacetime +- std::chrono::_V2::steady_clock::time_point lower_time_bound = time; +- std::chrono::_V2::steady_clock::time_point upper_time_bound = time+10s; ++ std::chrono::steady_clock::time_point lower_time_bound = time; ++ std::chrono::steady_clock::time_point upper_time_bound = time+10s; + Eigen::Isometry2d tf = Eigen::Isometry2d::Identity(); + + rmf_traffic::internal::Spacetime region = { +@@ -1263,8 +1263,8 @@ SCENARIO("Testing intersection of curved trajectory with various spacetimes") + SCENARIO("Testing multi-waypoint trajectories with various spacetimes") + { + using namespace std::chrono_literals; +- std::chrono::_V2::steady_clock::time_point lower_time_bound; +- std::chrono::_V2::steady_clock::time_point upper_time_bound; ++ std::chrono::steady_clock::time_point lower_time_bound; ++ std::chrono::steady_clock::time_point upper_time_bound; + + const auto small_circle_shape = rmf_traffic::geometry::make_final_convex< + rmf_traffic::geometry::Circle>(0.5); +diff --git a/thirdparty/fcl/include/fcl/broadphase/default_broadphase_callbacks.h b/thirdparty/fcl/include/fcl/broadphase/default_broadphase_callbacks.h +index 1c9b4fe..76f3bde 100644 +--- a/thirdparty/fcl/include/fcl/broadphase/default_broadphase_callbacks.h ++++ b/thirdparty/fcl/include/fcl/broadphase/default_broadphase_callbacks.h +@@ -37,6 +37,7 @@ + #ifndef FCL_BROADPHASE_DEFAULTBROADPHASECALLBACKS_H + #define FCL_BROADPHASE_DEFAULTBROADPHASECALLBACKS_H + ++#include + #include "fcl/narrowphase/collision.h" + #include "fcl/narrowphase/collision_request.h" + #include "fcl/narrowphase/collision_result.h" +diff --git a/thirdparty/fcl/include/fcl/geometry/octree/octree-inl.h b/thirdparty/fcl/include/fcl/geometry/octree/octree-inl.h +index f50fe81..04781f8 100644 +--- a/thirdparty/fcl/include/fcl/geometry/octree/octree-inl.h ++++ b/thirdparty/fcl/include/fcl/geometry/octree/octree-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_OCTREE_INL_H + #define FCL_OCTREE_INL_H + ++#include + #include "fcl/geometry/octree/octree.h" + + #include "fcl/config.h" +diff --git a/thirdparty/fcl/include/fcl/geometry/shape/convex-inl.h b/thirdparty/fcl/include/fcl/geometry/shape/convex-inl.h +index 10adc69..c50b53f 100644 +--- a/thirdparty/fcl/include/fcl/geometry/shape/convex-inl.h ++++ b/thirdparty/fcl/include/fcl/geometry/shape/convex-inl.h +@@ -39,6 +39,7 @@ + #ifndef FCL_SHAPE_CONVEX_INL_H + #define FCL_SHAPE_CONVEX_INL_H + ++#include + #include + #include + #include +diff --git a/thirdparty/fcl/include/fcl/math/motion/taylor_model/taylor_model-inl.h b/thirdparty/fcl/include/fcl/math/motion/taylor_model/taylor_model-inl.h +index 861f72d..c54f5d6 100644 +--- a/thirdparty/fcl/include/fcl/math/motion/taylor_model/taylor_model-inl.h ++++ b/thirdparty/fcl/include/fcl/math/motion/taylor_model/taylor_model-inl.h +@@ -41,6 +41,9 @@ + #ifndef FCL_CCD_TAYLOR_MODEL_INL_H + #define FCL_CCD_TAYLOR_MODEL_INL_H + ++#include ++ ++#include + #include "fcl/math/motion/taylor_model/taylor_model.h" + + namespace fcl +diff --git a/thirdparty/fcl/include/fcl/math/rng-inl.h b/thirdparty/fcl/include/fcl/math/rng-inl.h +index 1ba9da7..0e04dcd 100644 +--- a/thirdparty/fcl/include/fcl/math/rng-inl.h ++++ b/thirdparty/fcl/include/fcl/math/rng-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_MATH_RNG_INL_H + #define FCL_MATH_RNG_INL_H + ++#include + #include "fcl/math/rng.h" + + namespace fcl +diff --git a/thirdparty/fcl/include/fcl/narrowphase/detail/convexity_based_algorithm/gjk_libccd-inl.h b/thirdparty/fcl/include/fcl/narrowphase/detail/convexity_based_algorithm/gjk_libccd-inl.h +index 60fd0ad..0ddc589 100644 +--- a/thirdparty/fcl/include/fcl/narrowphase/detail/convexity_based_algorithm/gjk_libccd-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/detail/convexity_based_algorithm/gjk_libccd-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_NARROWPHASE_DETAIL_GJKLIBCCD_INL_H + #define FCL_NARROWPHASE_DETAIL_GJKLIBCCD_INL_H + ++#include + #include "fcl/narrowphase/detail/convexity_based_algorithm/gjk_libccd.h" + #include "fcl/narrowphase/detail/failed_at_this_configuration.h" + +diff --git a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/capsule_capsule-inl.h b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/capsule_capsule-inl.h +index b316c95..10af788 100644 +--- a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/capsule_capsule-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/capsule_capsule-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_NARROWPHASE_DETAIL_CAPSULECAPSULE_INL_H + #define FCL_NARROWPHASE_DETAIL_CAPSULECAPSULE_INL_H + ++#include + #include "fcl/narrowphase/detail/primitive_shape_algorithm/capsule_capsule.h" + + namespace fcl +diff --git a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/plane-inl.h b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/plane-inl.h +index 1373dce..dd19a87 100755 +--- a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/plane-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/plane-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_NARROWPHASE_DETAIL_PLANE_INL_H + #define FCL_NARROWPHASE_DETAIL_PLANE_INL_H + ++#include + #include "fcl/narrowphase/detail/primitive_shape_algorithm/plane.h" + + namespace fcl +diff --git a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_box-inl.h b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_box-inl.h +index 77e0a66..a82f049 100644 +--- a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_box-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_box-inl.h +@@ -37,6 +37,7 @@ + #ifndef FCL_NARROWPHASE_DETAIL_SPHEREBOX_INL_H + #define FCL_NARROWPHASE_DETAIL_SPHEREBOX_INL_H + ++#include + #include "fcl/narrowphase/detail/primitive_shape_algorithm/sphere_box.h" + + namespace fcl { +diff --git a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_cylinder-inl.h b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_cylinder-inl.h +index abda262..793f278 100644 +--- a/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_cylinder-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/detail/primitive_shape_algorithm/sphere_cylinder-inl.h +@@ -37,6 +37,7 @@ + #ifndef FCL_NARROWPHASE_DETAIL_SPHERECYLINDER_INL_H + #define FCL_NARROWPHASE_DETAIL_SPHERECYLINDER_INL_H + ++#include + #include "fcl/narrowphase/detail/primitive_shape_algorithm/sphere_cylinder.h" + + namespace fcl { +diff --git a/thirdparty/fcl/include/fcl/narrowphase/detail/traversal/distance/mesh_conservative_advancement_traversal_node-inl.h b/thirdparty/fcl/include/fcl/narrowphase/detail/traversal/distance/mesh_conservative_advancement_traversal_node-inl.h +index 44ddde5..2e63bee 100644 +--- a/thirdparty/fcl/include/fcl/narrowphase/detail/traversal/distance/mesh_conservative_advancement_traversal_node-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/detail/traversal/distance/mesh_conservative_advancement_traversal_node-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_TRAVERSAL_MESHCONSERVATIVEADVANCEMENTTRAVERSALNODE_INL_H + #define FCL_TRAVERSAL_MESHCONSERVATIVEADVANCEMENTTRAVERSALNODE_INL_H + ++#include + #include "fcl/narrowphase/detail/traversal/distance/mesh_conservative_advancement_traversal_node.h" + + #include "fcl/math/bv/RSS.h" +diff --git a/thirdparty/fcl/include/fcl/narrowphase/distance-inl.h b/thirdparty/fcl/include/fcl/narrowphase/distance-inl.h +index 115b710..7011975 100644 +--- a/thirdparty/fcl/include/fcl/narrowphase/distance-inl.h ++++ b/thirdparty/fcl/include/fcl/narrowphase/distance-inl.h +@@ -38,6 +38,7 @@ + #ifndef FCL_DISTANCE_INL_H + #define FCL_DISTANCE_INL_H + ++#include + #include "fcl/narrowphase/distance.h" + + #include "fcl/narrowphase/collision.h" diff --git a/shared/patch/ros2-rmf-traffic.win.patch b/shared/patch/ros2-rmf-traffic.win.patch new file mode 100644 index 000000000..87f509a5f --- /dev/null +++ b/shared/patch/ros2-rmf-traffic.win.patch @@ -0,0 +1,195 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7e40537..db7d641 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,6 +13,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + ++if(MSVC) ++ # M_PI et al. are non-standard extensions MSVC only defines when this ++ # is set (Spline.cpp uses M_PI unconditionally). ++ add_compile_definitions(_USE_MATH_DEFINES) ++endif() ++ + if(NOT CMAKE_BUILD_TYPE) + # Use the Release build type by default if the user has not specified one + set(CMAKE_BUILD_TYPE Release) +@@ -50,6 +56,17 @@ add_library(rmf_traffic SHARED + ${core_lib_srcs} + ) + ++if(WIN32) ++ # rmf_traffic has no dllexport annotations at all. As a shared library ++ # on Windows with nothing explicitly exported, link.exe does not ++ # produce an import .lib, so every consumer fails with LNK1181 ++ # "cannot open input file 'rmf_traffic.lib'" even though ++ # rmf_traffic.dll itself builds fine. Auto-export everything, same ++ # fix used for every other Windows shared-library target this ++ # session (including rmf_utils earlier in this same package family). ++ set_target_properties(rmf_traffic PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) ++endif() ++ + find_package(ament_cmake_catch2 QUIET) + find_package(ament_cmake_uncrustify QUIET) + if(BUILD_TESTING AND ament_cmake_catch2_FOUND AND ament_cmake_uncrustify_FOUND) +diff --git a/src/rmf_traffic/Trajectory.cpp b/src/rmf_traffic/Trajectory.cpp +index 3f29c7d..be98311 100644 +--- a/src/rmf_traffic/Trajectory.cpp ++++ b/src/rmf_traffic/Trajectory.cpp +@@ -798,7 +798,12 @@ bool Trajectory::base_iterator::operator>=( + + //============================================================================== + template +-Trajectory::base_iterator::operator const_iterator() const ++// MSVC fails to resolve the unqualified "const_iterator" here (a member ++// alias of the enclosing Trajectory class, not of base_iterator itself) ++// in this out-of-line nested-class-template conversion operator (C2833). ++// GCC/Clang already resolve it via the enclosing scope; qualifying it ++// explicitly is equivalent and portable everywhere. ++Trajectory::base_iterator::operator Trajectory::const_iterator() const + { + return _pimpl->make_iterator(_pimpl->raw_iterator); + } +diff --git a/src/rmf_traffic/agv/Planner.cpp b/src/rmf_traffic/agv/Planner.cpp +index 5bd91d4..746fccc 100644 +--- a/src/rmf_traffic/agv/Planner.cpp ++++ b/src/rmf_traffic/agv/Planner.cpp +@@ -25,9 +25,11 @@ namespace rmf_traffic { + namespace agv { + + //============================================================================== +-// This line tells the linker to take care of defining the value of this field +-// inside of this translation unit. +-const Duration Planner::Options::DefaultMinHoldingTime; ++// C++17's static constexpr members are implicitly inline, so this ++// out-of-class definition (needed pre-C++17 for ODR-use) is redundant ++// now that this project targets C++17 -- and MSVC rejects it outright ++// (C2734: "'const' object must be initialized if not 'extern'"), even ++// though GCC/Clang tolerate the redundant redeclaration. Just remove it. + + //============================================================================== + class Planner::Configuration::Implementation +diff --git a/src/rmf_traffic/agv/SimpleNegotiator.cpp b/src/rmf_traffic/agv/SimpleNegotiator.cpp +index 7657152..7aee6d8 100644 +--- a/src/rmf_traffic/agv/SimpleNegotiator.cpp ++++ b/src/rmf_traffic/agv/SimpleNegotiator.cpp +@@ -26,9 +26,11 @@ namespace rmf_traffic { + namespace agv { + + //============================================================================== +-// This line tells the linker to take care of defining the value of this field +-// inside of this translation unit. +-const double SimpleNegotiator::Options::DefaultMaxCostLeeway; ++// C++17's static constexpr members are implicitly inline, so this ++// out-of-class definition (needed pre-C++17 for ODR-use) is redundant ++// now that this project targets C++17 -- and MSVC rejects it outright ++// (C2734: "'const' object must be initialized if not 'extern'"), even ++// though GCC/Clang tolerate the redundant redeclaration. Just remove it. + + //============================================================================== + class SimpleNegotiator::Options::Implementation +diff --git a/src/rmf_traffic/agv/planning/CacheManager.hpp b/src/rmf_traffic/agv/planning/CacheManager.hpp +index fb5f8fd..1f4974e 100644 +--- a/src/rmf_traffic/agv/planning/CacheManager.hpp ++++ b/src/rmf_traffic/agv/planning/CacheManager.hpp +@@ -184,7 +184,26 @@ private: + + CacheManager( + std::shared_ptr generator, +- std::function storage_initializer = []() { return Storage(); }); ++ // MSVC cannot compile a lambda used as a default argument value ++ // here when the lambda references this class template's dependent ++ // Storage member alias: unqualified "Storage" fails to resolve ++ // (C3861), fully qualifying as CacheManager::Storage ++ // fails because CacheArg itself isn't found in that context ++ // (C2065), and the injected-class-name form CacheManager::Storage ++ // is rejected outright ("requires template argument list", C2955). ++ // Default to nullptr (no name lookup needed at all) and resolve ++ // the real default inside default_storage_initializer()'s body ++ // instead, where normal class/template scoping applies with none ++ // of these restrictions. ++ std::function storage_initializer = nullptr); ++ ++ static std::function default_storage_initializer( ++ std::function storage_initializer) ++ { ++ if (storage_initializer) ++ return storage_initializer; ++ return []() { return Storage(); }; ++ } + + template friend class Cache; + std::shared_ptr _upstream; +@@ -210,7 +229,18 @@ public: + + CacheManagerMap( + std::shared_ptr factory, +- std::function storage_initializer = []() { return Storage(); }); ++ // Same MSVC default-argument-lambda restriction as CacheManager's ++ // constructor above -- default to nullptr and resolve the real ++ // default inside default_storage_initializer()'s body instead. ++ std::function storage_initializer = nullptr); ++ ++ static std::function default_storage_initializer( ++ std::function storage_initializer) ++ { ++ if (storage_initializer) ++ return storage_initializer; ++ return []() { return Storage(); }; ++ } + + CacheManagerPtr get(std::size_t goal_index) const; + +@@ -284,8 +314,10 @@ CacheManager::CacheManager( + std::shared_ptr generator, + std::function storage_initializer) + : _upstream( +- std::make_shared(storage_initializer, std::move(generator))), +- _storage_initializer(std::move(storage_initializer)) ++ std::make_shared( ++ default_storage_initializer(storage_initializer), std::move(generator))), ++ _storage_initializer( ++ default_storage_initializer(std::move(storage_initializer))) + { + // Do nothing + } +@@ -311,7 +343,8 @@ CacheManagerMap::CacheManagerMap( + std::shared_ptr factory, + std::function storage_initializer) + : _generator_factory(std::move(factory)), +- _storage_initializer(std::move(storage_initializer)) ++ _storage_initializer( ++ default_storage_initializer(std::move(storage_initializer))) + { + // Do nothing + } +diff --git a/src/rmf_traffic/agv/planning/DifferentialDriveMap.hpp b/src/rmf_traffic/agv/planning/DifferentialDriveMap.hpp +index 27e3df8..bca545d 100644 +--- a/src/rmf_traffic/agv/planning/DifferentialDriveMap.hpp ++++ b/src/rmf_traffic/agv/planning/DifferentialDriveMap.hpp +@@ -213,6 +213,14 @@ struct DifferentialDriveMapTypes + + struct KeyHash + { ++ // MSVC's / implementation instantiates ++ // code paths requiring the hasher to be default-constructible even ++ // though real usage always passes N_lanes explicitly (GCC/Clang's ++ // libstdc++/libc++ don't need this). The members are left ++ // uninitialized here since this constructor is never actually ++ // invoked in practice. ++ KeyHash() = default; ++ + KeyHash(std::size_t N_lanes) + { + const std::size_t lane_shift = std::ceil(std::log2(N_lanes)); +@@ -245,6 +253,9 @@ struct DifferentialDriveMapTypes + + struct EntryHash + { ++ // Same MSVC default-constructibility requirement as KeyHash above. ++ EntryHash() = default; ++ + EntryHash(std::size_t N_lanes) + { + _orientation_shift = std::ceil(std::log2(N_lanes)); diff --git a/shared/pkg_additional_info.yaml b/shared/pkg_additional_info.yaml index 4db4b4fd2..630af5acb 100644 --- a/shared/pkg_additional_info.yaml +++ b/shared/pkg_additional_info.yaml @@ -130,6 +130,18 @@ pybind11_json_vendor: additional_cmake_args: "-DAMENT_VENDOR_POLICY=NEVER_VENDOR" pybind11_vendor: additional_cmake_args: "-DAMENT_VENDOR_POLICY=NEVER_VENDOR" +rmf_building_sim_common: # shared libraries without dllexport annotations (Windows: no import library) + additional_cmake_args: "-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON" +rmf_robot_sim_common: # shared libraries without dllexport annotations (Windows: no import library) + additional_cmake_args: "-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON" +rmf_visualization_rviz2_plugins: # Windows: uses the alternative operator tokens (`or`), which MSVC only has with + additional_cmake_args: + if: win + then: '-DCMAKE_CXX_FLAGS_INIT=/FIiso646.h' +rmf_visualization_schedule: # Windows: its test's link command exceeds the linker's line limit (LNK1170) + additional_cmake_args: + if: win + then: '-DBUILD_TESTING=OFF' robot_state_publisher: additional_cmake_args: "-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON" rosx_introspection: diff --git a/shared/robostack.yaml b/shared/robostack.yaml index c2880a076..92294f994 100644 --- a/shared/robostack.yaml +++ b/shared/robostack.yaml @@ -175,6 +175,11 @@ ignition-cmake2: robostack: [libignition-cmake2] ignition-common4: robostack: [libignition-common4] +ignition-fortress: + robostack: + linux: [libignition-cmake2, libignition-common4, libignition-gazebo6, libignition-gui6, libignition-math6, libignition-msgs8, libignition-plugin1, libignition-rendering6, libignition-transport11, libgl-devel] + osx: [libignition-cmake2, libignition-common4, libignition-gazebo6, libignition-gui6, libignition-math6, libignition-msgs8, libignition-plugin1, libignition-rendering6, libignition-transport11] + win64: [libignition-cmake2, libignition-common4, libignition-gazebo6, libignition-gui6, libignition-math6, libignition-msgs8, libignition-plugin1, libignition-rendering6, libignition-transport11] ignition-gazebo3: robostack: [libignition-gazebo5] ignition-gazebo5: diff --git a/shared/tests/ros2-rmf-fleet-adapter-python.yaml b/shared/tests/ros2-rmf-fleet-adapter-python.yaml new file mode 100644 index 000000000..574ac338d --- /dev/null +++ b/shared/tests/ros2-rmf-fleet-adapter-python.yaml @@ -0,0 +1,8 @@ +tests: + # Regression test: rmf_adapter must import and work. Built as a SHARED library instead of + # a Python module, it links libpython, and on macOS `import rmf_adapter` then aborts + # ("PyInterpreterState_Get: the function must be called with the GIL held"): it initialises + # a second interpreter (see shared/patch/ros2-rmf-fleet-adapter-python.patch). + - script: + # submodules as attributes: older versions (humble's) don't make rmf_adapter a package + - python -c "import rmf_adapter; assert rmf_adapter.graph.Graph().num_waypoints == 0" diff --git a/shared/vinca.yaml b/shared/vinca.yaml index 39ac5936a..f6c6dddd2 100644 --- a/shared/vinca.yaml +++ b/shared/vinca.yaml @@ -261,6 +261,7 @@ packages_select_by_deps: - realsense2_description - realtime_tools - rmf_demos + - rmf_dev # Open RMF; requested in https://github.com/RoboStack/ros-humble/pull/298 - rmw - rmw_stats_shim - rmw_zenoh_cpp