cmake_minimum_required(VERSION 3.0.2) project(move_base2 VERSION 0.1.0 LANGUAGES CXX) # ======================================================== # Build mode detection # ======================================================== if(DEFINED CATKIN_DEVEL_PREFIX OR DEFINED CATKIN_TOPLEVEL) set(BUILDING_WITH_CATKIN TRUE) message(STATUS "Building move_base2 with Catkin") else() set(BUILDING_WITH_CATKIN FALSE) message(STATUS "Building move_base2 with Standalone CMake") endif() # ======================================================== # C++ Standard # ======================================================== set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # ======================================================== # Common dependencies # ======================================================== find_package(Boost REQUIRED COMPONENTS system thread filesystem ) find_package(Threads REQUIRED) find_package(yaml-cpp REQUIRED) # ======================================================== # Standalone configuration # ======================================================== if(NOT BUILDING_WITH_CATKIN) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}") # Test/ -> src/AMR_T800/pnkx_nav_core/src set(PNKX_NAV_CORE_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../pnkx_nav_core/src" ) # Test/ -> T800_ws/devel/lib set(WORKSPACE_DEVEL_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../devel/lib" ) file(GLOB STANDALONE_PACKAGE_INCLUDE_DIRS LIST_DIRECTORIES true ${PNKX_NAV_CORE_SRC_DIR}/*/include ${PNKX_NAV_CORE_SRC_DIR}/*/*/include ${PNKX_NAV_CORE_SRC_DIR}/*/*/*/include ${PNKX_NAV_CORE_SRC_DIR}/*/*/*/*/include ) find_package(PCL QUIET COMPONENTS common io) set(STANDALONE_INCLUDE_DIRS ${STANDALONE_PACKAGE_INCLUDE_DIRS} ${PCL_INCLUDE_DIRS} # These runtime packages are siblings while they still live below Test/. # The explicit paths keep `cmake ..` in move_base2 working before the # packages are moved below pnkx_nav_core/src. ${CMAKE_CURRENT_SOURCE_DIR}/../recovery_core/include ${CMAKE_CURRENT_SOURCE_DIR}/../action_core/include ${CMAKE_CURRENT_SOURCE_DIR}/../mission_adapters/include ${CMAKE_CURRENT_SOURCE_DIR}/../nav_test_harness/include /usr/local/include ) if(PCL_FOUND) add_definitions(${PCL_DEFINITIONS}) endif() set(PACKAGES_DIR robot_costmap_2d robot_nav_2d_utils robot_cpp robot_time robot_xmlrpcpp # move_base2 public headers and runners use these packages directly. # When configured from the pnkx_nav_core root, these names resolve to # CMake targets and propagate their public include directories. recovery_core action_core mission_adapters nav_test_harness ) find_library(TF3_LIBRARY NAMES tf3 PATHS /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu ) if(NOT TF3_LIBRARY) message(FATAL_ERROR "tf3 not found — install tf3 (/usr/local/lib/libtf3.so) before building") endif() if(EXISTS ${WORKSPACE_DEVEL_LIB_DIR}) link_directories(${WORKSPACE_DEVEL_LIB_DIR}) endif() link_directories(/usr/local/lib) # ======================================================== # Catkin configuration # ======================================================== else() find_package(catkin REQUIRED COMPONENTS move_base_core robot_nav_core robot_costmap_2d robot_cpp robot_time robot_geometry_msgs robot_std_msgs robot_nav_msgs robot_nav_2d_msgs robot_nav_2d_utils robot_sensor_msgs robot_map_msgs robot_protocol_msgs robot_xmlrpcpp # SensorGateway là chỗ duy nhất trong gói này lọc laser trước khi vào costmap. laser_filter # RecoveryRunner include thẳng recovery_core: đó là chỗ duy nhất trong gói này biết tới nó. recovery_core # ActionRunner include thẳng action_core: chỗ duy nhất trong gói này biết tới nó. action_core # `bridges/` include thẳng mission_adapters: biên duy nhất trong gói này biết tới nó # (MissionAdapterBridge dịch contract, MissionLayer lắp ráp framework). mission_adapters # scenario_test chạy kịch bản khai báo qua khung của nav_test_harness. nav_test_harness ) find_library(TF3_LIBRARY NAMES tf3 PATHS /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu ) if(NOT TF3_LIBRARY) message(FATAL_ERROR "tf3 not found — install tf3 (/usr/local/lib/libtf3.so) before building") endif() catkin_package( INCLUDE_DIRS include LIBRARIES move_base2_core move_base2 CATKIN_DEPENDS move_base_core robot_nav_core robot_costmap_2d robot_cpp robot_time robot_geometry_msgs robot_std_msgs robot_nav_msgs robot_nav_2d_msgs robot_nav_2d_utils robot_sensor_msgs robot_map_msgs robot_protocol_msgs robot_xmlrpcpp DEPENDS Boost ) include_directories(include) # Dependency vào dạng SYSTEM: `robot/robot.h` kéo theo `console.h`, file này khai vài chục hằng màu # ở namespace scope và sinh đúng số đó warning -Wunused-variable. Để chúng lẫn vào output sẽ chôn # mất warning THẬT của gói — mà cờ -Wall -Wextra ở dưới có mặt chính là để thấy những warning đó. include_directories(SYSTEM ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) endif() # ======================================================== # Core library — logic thuần, không I/O. # # Tách riêng khỏi plugin để test lõi không phải kéo theo contract host, và để bất kỳ ai muốn nhúng # state machine vào runtime khác cũng dùng lại được. # ======================================================== add_library(move_base2_core SHARED src/navigation_state.cpp src/state_machine.cpp src/velocity_arbiter.cpp src/control_loop.cpp src/config/move_base2_config.cpp src/runners/recovery_runner.cpp src/runners/action_runner.cpp src/runners/planner_runner.cpp src/runners/controller_runner.cpp src/io/runtime_stats.cpp src/io/sensor_gateway.cpp src/io/costmap_exporter.cpp src/bridges/mission_adapter_bridge.cpp src/bridges/mission_layer.cpp src/navigation_runtime.cpp ) # Gói này KHÔNG kế thừa cờ -w của pnkx_nav_core: warning ở đây phải nhìn thấy được. target_compile_options(move_base2_core PRIVATE -Wall -Wextra) target_include_directories(move_base2_core PUBLIC $ $ ) # ======================================================== # Plugin library — facade BaseNavigation + export Boost.DLL. # ======================================================== add_library(move_base2 SHARED src/navigation_server.cpp src/move_base2_plugin.cpp ) target_compile_options(move_base2 PRIVATE -Wall -Wextra) target_include_directories(move_base2 PUBLIC $ $ ) set_target_properties(move_base2 PROPERTIES POSITION_INDEPENDENT_CODE ON) # ======================================================== # Linking # ======================================================== if(BUILDING_WITH_CATKIN) add_dependencies(move_base2_core ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS} ) add_dependencies(move_base2 move_base2_core ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS} ) target_link_libraries(move_base2_core PUBLIC ${catkin_LIBRARIES} PRIVATE Boost::boost Threads::Threads ${TF3_LIBRARY} ) target_link_libraries(move_base2 PUBLIC move_base2_core ${catkin_LIBRARIES} PRIVATE Boost::boost Boost::system Boost::filesystem Threads::Threads ${CMAKE_DL_LIBS} ${TF3_LIBRARY} ) else() target_include_directories(move_base2_core PRIVATE ${STANDALONE_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) target_include_directories(move_base2 PRIVATE ${STANDALONE_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) target_link_libraries(move_base2_core PUBLIC ${PACKAGES_DIR} PRIVATE Boost::boost Threads::Threads ${TF3_LIBRARY} ) target_link_libraries(move_base2 PUBLIC move_base2_core ${PACKAGES_DIR} PRIVATE Boost::boost Boost::system Boost::filesystem Threads::Threads ${CMAKE_DL_LIBS} ${TF3_LIBRARY} ) set_target_properties(move_base2_core move_base2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} BUILD_RPATH "${CMAKE_BINARY_DIR}" INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" ) endif() # ======================================================== # Install # ======================================================== if(BUILDING_WITH_CATKIN) install(TARGETS move_base2_core move_base2 ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} ) install(DIRECTORY include/${PROJECT_NAME}/ DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} FILES_MATCHING PATTERN "*.h" ) install(DIRECTORY launch config DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} ) else() install(TARGETS move_base2_core move_base2 EXPORT ${PROJECT_NAME}-targets ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin ) install(EXPORT ${PROJECT_NAME}-targets FILE ${PROJECT_NAME}-targets.cmake NAMESPACE ${PROJECT_NAME}:: DESTINATION lib/cmake/${PROJECT_NAME} ) install(DIRECTORY include/${PROJECT_NAME}/ DESTINATION include FILES_MATCHING PATTERN "*.h" ) endif() # ======================================================== # Tests # ======================================================== option(BUILD_MOVE_BASE2_TESTS "Build move_base2 tests" ON) if(BUILD_MOVE_BASE2_TESTS AND BUILDING_WITH_CATKIN) if(NOT COMMAND catkin_add_gtest) message(FATAL_ERROR "catkin_add_gtest NOT FOUND") endif() # Plugin global planner chỉ dùng cho test — nạp qua Boost.DLL đúng đường runtime đi, không link # thẳng. Đặt trong nhánh test để không bao giờ lọt vào bản cài đặt. foreach(test_plugin move_base2_test_global_planner move_base2_test_local_planner) if(test_plugin STREQUAL "move_base2_test_global_planner") set(test_plugin_src test/plugins/test_global_planner.cpp) else() set(test_plugin_src test/plugins/test_local_planner.cpp) endif() add_library(${test_plugin} SHARED ${test_plugin_src}) target_compile_options(${test_plugin} PRIVATE -Wall -Wextra) target_include_directories(${test_plugin} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ) set_target_properties(${test_plugin} PROPERTIES POSITION_INDEPENDENT_CODE ON) target_link_libraries(${test_plugin} PRIVATE ${catkin_LIBRARIES} Boost::boost ${CMAKE_DL_LIBS} ) endforeach() set(MOVE_BASE2_TESTS state_machine_test velocity_arbiter_test walking_skeleton_test config_validation_test action_runner_test recovery_runner_test sensor_gateway_test runtime_stats_test navigation_server_test planner_runner_test controller_runner_test mission_adapter_bridge_test mission_layer_test move_base2_scenario_test # tên có tiền tố gói: nav_test_harness đã có target scenario_test ) foreach(test_name ${MOVE_BASE2_TESTS}) catkin_add_gtest(${test_name} test/${test_name}.cpp) if(TARGET ${test_name}) # catkin_add_gtest đặt target EXCLUDE_FROM_ALL; mở ra để binary có mặt sau `catkin_make` # thường, đúng quy trình verify của repo (chạy thẳng ./devel/lib//). set_target_properties(${test_name} PROPERTIES EXCLUDE_FROM_ALL FALSE) target_compile_options(${test_name} PRIVATE -Wall -Wextra) target_include_directories(${test_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/test SYSTEM PRIVATE ${catkin_INCLUDE_DIRS} ) # catkin_add_gtest đã dùng target_link_libraries dạng plain, nên phần bổ sung cũng phải plain. target_link_libraries(${test_name} move_base2_core ${catkin_LIBRARIES} ${Boost_LIBRARIES} yaml-cpp ${CMAKE_DL_LIBS} ) # Plugin recovery được nạp qua Boost.DLL từ devel/lib, không link thẳng: đúng đường runtime đi. # ctest không mang theo PNKX_NAV_CORE_* của shell nên binary tự trỏ. target_compile_definitions(${test_name} PRIVATE MOVE_BASE2_TEST_CONFIG_DIR="${CMAKE_CURRENT_SOURCE_DIR}/test/config" MOVE_BASE2_TEST_LIBRARY_DIR="${CATKIN_DEVEL_PREFIX}/lib" # Kịch bản là DỮ LIỆU nằm ở nav_test_harness; test không được đoán đường dẫn tới nó. MOVE_BASE2_SCENARIO_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../nav_test_harness/scenarios" ) endif() endforeach() # `NavigationServer` nằm trong thư viện plugin `move_base2`, không phải trong `move_base2_core`. if(TARGET navigation_server_test) target_link_libraries(navigation_server_test move_base2) endif() # Plugin phải có mặt trong devel/lib trước khi test chạy — nó được nạp qua Boost.DLL lúc chạy. if(TARGET planner_runner_test) add_dependencies(planner_runner_test move_base2_test_global_planner) endif() if(TARGET controller_runner_test) add_dependencies(controller_runner_test move_base2_test_local_planner) endif() endif()