cartographer_ros是cartographer算法库针对ROS开发的接口库。
cartographer_ros是基于ros的通信机制获取传感器的数据并将他们转换成cartographer中定义的格式传递给cartographer处理,与此同时也将cartographer的处理发布用于显示或保存。是基于cartographer的上层应用。所以,cartographer_ros相当于是对cartographer进行了一层ROS接口的封装
换句话说,cartographer_ros中没有任何的算法!
通过ros的订阅机制接收传感器数据, 并将传感器数据做坐标变换以及数据类型的转换, 转换完成之后送到cartographer算法库中进行具体的SLAM的计算
根据前端与后端计算的结果, 发布轨迹, tf, 栅格地图, 约束信息, 以及landmark
提供了外部控制的接口, 如开始结束轨迹, 保存数据, 获取数据等
编写CMakeLists.txt
最常用的功能就是调用其他的.h头文件和.so/.a库文件,将.cpp/.c/.cc文件编译成可执行文件或者新的库文件
Ros工程中除了CMakeLists.txt,还包含一个package.xml
一般的工程只有CMakeLists.txt,作用是生成相应的库文件
Cartographer_ros的CMakeLists.txt生成了一个相应的库以及Cartographer_node一个可执行文件
Cartographer的CMakeLists.txt生成了一个相应的库
路径:src/cartographer_ros/cartographer_ros/package.xml
作用:简要说明了cartographer_ros相关信息以及一些所需的依赖项
<package format="2">
<name>cartographer_rosname>
<version>1.0.0version>
<description>
Cartographer is a system that provides real-time simultaneous localization
and mapping (SLAM) in 2D and 3D across multiple platforms and sensor
configurations. This package provides Cartographer's ROS integration.
description>
<maintainer email="[email protected]">
The Cartographer Authors
maintainer>
<license>Apache 2.0license>
<url>https://github.com/cartographer-project/cartographer_rosurl>
<author email="[email protected]">
The Cartographer Authors
author>
<buildtool_depend>catkinbuildtool_depend>
<build_depend>gitbuild_depend>
<build_depend>google-mockbuild_depend>
<build_depend>protobuf-devbuild_depend>
<build_depend>python3-sphinxbuild_depend>
<depend version_gte="1.0.0">cartographerdepend>
<depend version_gte="1.0.0">cartographer_ros_msgsdepend>
<depend>geometry_msgsdepend>
<depend>libgflags-devdepend>
<depend>libgoogle-glog-devdepend>
<depend>libpcl-all-devdepend>
<depend>message_runtimedepend>
<depend>nav_msgsdepend>
<depend>pcl_conversionsdepend>
<depend>robot_state_publisherdepend>
<depend>rosbagdepend>
<depend>roscppdepend>
<depend>roslaunchdepend>
<depend>roslibdepend>
<depend>sensor_msgsdepend>
<depend>std_msgsdepend>
<depend>tf2depend>
<depend>tf2_eigendepend>
<depend>tf2_rosdepend>
<depend>urdfdepend>
<depend>visualization_msgsdepend>
<test_depend>rosunittest_depend>
<export>
<rviz plugin="${prefix}/rviz_plugin_description.xml" />
export>
package>
路径:src/cartographer_ros/cartographer_ros/CMakeLists.txt
(下面的txt附有注释)
# Copyright 2016 The Cartographer Authors
#
# 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.
cmake_minimum_required(VERSION 2.8.12) # Ships with Ubuntu 14.04 (Trusty)
project(cartographer_ros)
# 将cartographer_ros_msgs一直到最后visualization_msgs的库一起放到定义的变量PACKAGE_DEPENDENCIES中
set(PACKAGE_DEPENDENCIES
cartographer_ros_msgs
geometry_msgs
message_runtime
nav_msgs
pcl_conversions
rosbag
roscpp
roslib
sensor_msgs
std_msgs
tf2
tf2_eigen
tf2_ros
urdf
visualization_msgs
)
if(WIN32)
set(Boost_USE_STATIC_LIBS FALSE)
endif()
# For yet unknown reason, if Boost is find_packaged() after find_package(cartographer),
# some Boost libraries including Thread are set to static, despite Boost_USE_STATIC_LIBS,
# which causes linking problems on windows due to shared/static Thread clashing.
# PCL also finds Boost. Work around by moving before find_package(cartographer).
# 如果找不到Boost和PCL库,就会报错!
find_package(Boost REQUIRED COMPONENTS system iostreams)
find_package(PCL REQUIRED COMPONENTS common io)
find_package(cartographer REQUIRED)
#functions.cmake作用是生成可执行文件
include("${CARTOGRAPHER_CMAKE_DIR}/functions.cmake")
#将BUILD_GRPC设置成false,即不构建Cartographer gRPC 的远程功能
option(BUILD_GRPC "build features that require Cartographer gRPC support" false)
google_initialize_cartographer_project()
google_enable_testing()
set(CARTOGRAPHER_GMOCK_LIBRARIES ${GMOCK_LIBRARIES})
#找到之前放到PACKAGE_DEPENDENCIES的所有库,否则报错!
find_package(catkin REQUIRED COMPONENTS ${PACKAGE_DEPENDENCIES})
include(FindPkgConfig)
#找到absl、LuaGoogle、Eigen3、urdfdom_headers的库
find_package(absl REQUIRED)
find_package(LuaGoogle REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(urdfdom_headers REQUIRED)
if(DEFINED urdfdom_headers_VERSION)
if(${urdfdom_headers_VERSION} GREATER 0.4.1)
add_definitions(-DURDFDOM_HEADERS_HAS_SHARED_PTR_DEFS)
endif()
endif()
#将urdfdom_headers的头文件放到本文件中
include_directories(
${urdfdom_headers_INCLUDE_DIRS}
)
# Override Catkin's GTest configuration to use GMock.
set(GTEST_FOUND TRUE)
set(GTEST_INCLUDE_DIRS ${GMOCK_INCLUDE_DIRS})
set(GTEST_LIBRARIES ${CARTOGRAPHER_GMOCK_LIBRARIES})
catkin_package(
CATKIN_DEPENDS
${PACKAGE_DEPENDENCIES} #ros的依赖
DEPENDS
# TODO(damonkohler): This should be here but causes Catkin to abort because
# protobuf specifies a library '-lpthread' instead of just 'pthread'.
# CARTOGRAPHER
PCL #非ros的依赖
EIGEN3
Boost
urdfdom_headers
INCLUDE_DIRS "."
LIBRARIES ${PROJECT_NAME}
)
#GLOB_RECURSE表示循环找,迭代的意思!
#file的功能是将"cartographer_ros/*.cc" "cartographer_ros/*.h"都放进变量ALL_SRCS中,其他句子同理
file(GLOB_RECURSE ALL_SRCS "cartographer_ros/*.cc" "cartographer_ros/*.h")
file(GLOB_RECURSE ALL_TESTS "cartographer_ros/*_test.cc")
file(GLOB_RECURSE ALL_EXECUTABLES "cartographer_ros/*_main.cc")
file(GLOB_RECURSE ALL_GRPC_FILES "cartographer_ros/cartographer_grpc/*")
#将ALL_SRCS中结尾是ALL_TESTS的删掉,因为*.cc是包含了*_test.cc
list(REMOVE_ITEM ALL_SRCS ${ALL_TESTS})
#将ALL_SRCS中结尾是ALL_EXECUTABLES的删掉,因为*.cc是包含了*_main.cc
list(REMOVE_ITEM ALL_SRCS ${ALL_EXECUTABLES})
#如果不构建Cartographer gRPC 的远程功能,则进入该if
if (NOT ${BUILD_GRPC})
list(REMOVE_ITEM ALL_SRCS ${ALL_GRPC_FILES})
list(REMOVE_ITEM ALL_TESTS ${ALL_GRPC_FILES})
list(REMOVE_ITEM ALL_EXECUTABLES ${ALL_GRPC_FILES})
endif()
# 生成library(将"cartographer_ros/*.cc" "cartographer_ros/*.h"中除去相关文件生成库文件)
add_library(${PROJECT_NAME} STATIC ${ALL_SRCS})
# 添加子目录,生成可执行文件(生成一个新的CMakeLists.txt,路径是`scr/cartographer_ros/cartographer_ros/cartographer_ros/CMakeLists.txt`)
add_subdirectory("cartographer_ros")
# 链接到cartographer
target_link_libraries(${PROJECT_NAME} PUBLIC cartographer)
# 链接到Lua
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${LUA_INCLUDE_DIR})
# 链接到PCL
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${PCL_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${PCL_LIBRARIES})
set(BLACKLISTED_PCL_DEFINITIONS " -march=native -msse4.2 -mfpmath=sse ")
foreach(DEFINITION ${PCL_DEFINITIONS})
list (FIND BLACKLISTED_PCL_DEFINITIONS "${DEFINITION}" DEFINITIONS_INDEX)
if (${DEFINITIONS_INDEX} GREATER -1)
continue()
endif()
set(TARGET_COMPILE_FLAGS "${TARGET_COMPILE_FLAGS} ${DEFINITION}")
endforeach()
# 链接到Eigen
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${EIGEN3_INCLUDE_DIR}")
# 链接到Boost
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${Boost_INCLUDE_DIRS}")
target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES})
# 链接到Catkin
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${catkin_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${catkin_LIBRARIES})
#先编译完catkin相关的包,才能编译cartographer_ros相关的包
add_dependencies(${PROJECT_NAME} ${catkin_EXPORTED_TARGETS})
# Add the binary directory first, so that port.h is included after it has
# been generated.
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
set(TARGET_COMPILE_FLAGS "${TARGET_COMPILE_FLAGS} ${GOOG_CXX_FLAGS}")
set_target_properties(${PROJECT_NAME} PROPERTIES
COMPILE_FLAGS ${TARGET_COMPILE_FLAGS})
if (CATKIN_ENABLE_TESTING)
foreach(TEST_SOURCE_FILENAME ${ALL_TESTS})
get_filename_component(TEST_NAME ${TEST_SOURCE_FILENAME} NAME_WE)
catkin_add_gtest(${TEST_NAME} ${TEST_SOURCE_FILENAME})
# catkin_add_gtest uses a plain (i.e. no PUBLIC/PRIVATE/INTERFACE) call to
# target_link_libraries. That forces us to do the same.
target_link_libraries(${TEST_NAME} ${GMOCK_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
target_include_directories(${TEST_NAME} SYSTEM PUBLIC ${LUA_INCLUDE_DIR})
target_link_libraries(${TEST_NAME} ${LUA_LIBRARIES})
target_include_directories(${TEST_NAME} SYSTEM PUBLIC ${catkin_INCLUDE_DIRS})
target_link_libraries(${TEST_NAME} ${catkin_LIBRARIES})
add_dependencies(${TEST_NAME} ${catkin_EXPORTED_TARGETS})
target_link_libraries(${TEST_NAME} cartographer)
target_link_libraries(${TEST_NAME} ${PROJECT_NAME})
set_target_properties(${TEST_NAME} PROPERTIES COMPILE_FLAGS ${TARGET_COMPILE_FLAGS})
# Needed for dynamically linked GTest on Windows.
if (WIN32)
target_compile_definitions(${TEST_NAME} PUBLIC -DGTEST_LINKED_AS_SHARED_LIBRARY)
endif()
endforeach()
endif()
#安装launch、urdf、configuration_files文件夹到CATKIN_PACKAGE_SHARE_DESTINATION
install(DIRECTORY launch urdf configuration_files
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
install(PROGRAMS scripts/tf_remove_frames.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
)
# Install source headers.
file(GLOB_RECURSE HDRS "cartographer_ros/*.h")
foreach(HDR ${HDRS})
file(RELATIVE_PATH REL_FIL ${PROJECT_SOURCE_DIR} ${HDR})
get_filename_component(INSTALL_DIR ${REL_FIL} DIRECTORY)
install(
FILES
${HDR}
DESTINATION
include/${INSTALL_DIR}
)
endforeach()
路径:scr/cartographer/cartographer/CMakeLists.txt
和Cartographer_ros的CMakeList.txt语法大同小异!类比推理!
# Copyright 2016 The Cartographer Authors
#
# 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.
cmake_minimum_required(VERSION 3.2)
project(cartographer)
set(CARTOGRAPHER_MAJOR_VERSION 1)
set(CARTOGRAPHER_MINOR_VERSION 0)
set(CARTOGRAPHER_PATCH_VERSION 0)
set(CARTOGRAPHER_VERSION ${CARTOGRAPHER_MAJOR_VERSION}.${CARTOGRAPHER_MINOR_VERSION}.${CARTOGRAPHER_PATCH_VERSION})
set(CARTOGRAPHER_SOVERSION ${CARTOGRAPHER_MAJOR_VERSION}.${CARTOGRAPHER_MINOR_VERSION})
option(BUILD_GRPC "build Cartographer gRPC support" false)
set(CARTOGRAPHER_HAS_GRPC ${BUILD_GRPC})
option(BUILD_PROMETHEUS "build Prometheus monitoring support" false)
include("${PROJECT_SOURCE_DIR}/cmake/functions.cmake")
google_initialize_cartographer_project()
# google_enable_testing()
find_package(absl REQUIRED)
set(BOOST_COMPONENTS iostreams)
if(WIN32)
list(APPEND BOOST_COMPONENTS zlib)
set(Boost_USE_STATIC_LIBS FALSE)
endif()
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(Ceres REQUIRED COMPONENTS SuiteSparse)
find_package(Eigen3 REQUIRED)
find_package(LuaGoogle REQUIRED)
if(WIN32)
# On Windows, Protobuf is incorrectly found by the bundled CMake module, so prefer native CMake config.
set(protobuf_MODULE_COMPATIBLE TRUE CACHE INTERNAL "")
find_package(Protobuf 3.0.0 CONFIG)
else()
find_package(Protobuf 3.0.0 REQUIRED)
endif()
if (${BUILD_GRPC})
find_package(async_grpc REQUIRED)
endif()
if(${BUILD_PROMETHEUS})
find_package( ZLIB REQUIRED )
endif()
include(FindPkgConfig)
if (NOT WIN32)
PKG_SEARCH_MODULE(CAIRO REQUIRED cairo>=1.12.16)
else()
find_library(CAIRO_LIBRARIES cairo)
endif()
# Only build the documentation if we can find Sphinx.
find_package(Sphinx)
if(SPHINX_FOUND)
add_subdirectory("docs")
endif()
# Install catkin package.xml
install(FILES package.xml DESTINATION share/cartographer)
set(CARTOGRAPHER_CONFIGURATION_FILES_DIRECTORY ${CMAKE_INSTALL_PREFIX}/share/cartographer/configuration_files
CACHE PATH ".lua configuration files directory")
install(DIRECTORY configuration_files DESTINATION share/cartographer/)
install(DIRECTORY cmake DESTINATION share/cartographer/)
file(GLOB_RECURSE ALL_LIBRARY_HDRS "cartographer/*.h")
file(GLOB_RECURSE ALL_LIBRARY_SRCS "cartographer/*.cc")
file(GLOB_RECURSE TEST_LIBRARY_HDRS "cartographer/fake_*.h" "cartographer/*test_helpers*.h" "cartographer/mock_*.h")
file(GLOB_RECURSE TEST_LIBRARY_SRCS "cartographer/fake_*.cc" "cartographer/*test_helpers*.cc" "cartographer/mock_*.cc")
file(GLOB_RECURSE ALL_TESTS "cartographer/*_test.cc")
file(GLOB_RECURSE ALL_EXECUTABLES "cartographer/*_main.cc")
# Remove dotfiles/-folders that could potentially pollute the build.
# 移除所有以.开头的文件
file(GLOB_RECURSE ALL_DOTFILES ".*/*")
if (ALL_DOTFILES)
list(REMOVE_ITEM ALL_LIBRARY_HDRS ${ALL_DOTFILES})
list(REMOVE_ITEM ALL_LIBRARY_SRCS ${ALL_DOTFILES})
list(REMOVE_ITEM TEST_LIBRARY_HDRS ${ALL_DOTFILES})
list(REMOVE_ITEM TEST_LIBRARY_SRCS ${ALL_DOTFILES})
list(REMOVE_ITEM ALL_TESTS ${ALL_DOTFILES})
list(REMOVE_ITEM ALL_EXECUTABLES ${ALL_DOTFILES})
endif()
list(REMOVE_ITEM ALL_LIBRARY_SRCS ${ALL_EXECUTABLES})
list(REMOVE_ITEM ALL_LIBRARY_SRCS ${ALL_TESTS})
list(REMOVE_ITEM ALL_LIBRARY_HDRS ${TEST_LIBRARY_HDRS})
list(REMOVE_ITEM ALL_LIBRARY_SRCS ${TEST_LIBRARY_SRCS})
file(GLOB_RECURSE ALL_GRPC_FILES "cartographer/cloud/*")
file(GLOB_RECURSE ALL_PROMETHEUS_FILES "cartographer/cloud/metrics/prometheus/*")
list(REMOVE_ITEM ALL_GRPC_FILES ${ALL_PROMETHEUS_FILES})
if (NOT ${BUILD_GRPC})
list(REMOVE_ITEM ALL_LIBRARY_HDRS ${ALL_GRPC_FILES})
list(REMOVE_ITEM ALL_LIBRARY_SRCS ${ALL_GRPC_FILES})
list(REMOVE_ITEM TEST_LIBRARY_HDRS ${ALL_GRPC_FILES})
list(REMOVE_ITEM TEST_LIBRARY_SRCS ${ALL_GRPC_FILES})
list(REMOVE_ITEM ALL_TESTS ${ALL_GRPC_FILES})
list(REMOVE_ITEM ALL_EXECUTABLES ${ALL_GRPC_FILES})
endif()
if (NOT ${BUILD_PROMETHEUS})
list(REMOVE_ITEM ALL_LIBRARY_HDRS ${ALL_PROMETHEUS_FILES})
list(REMOVE_ITEM ALL_LIBRARY_SRCS ${ALL_PROMETHEUS_FILES})
list(REMOVE_ITEM TEST_LIBRARY_HDRS ${ALL_PROMETHEUS_FILES})
list(REMOVE_ITEM TEST_LIBRARY_SRCS ${ALL_PROMETHEUS_FILES})
list(REMOVE_ITEM ALL_TESTS ${ALL_PROMETHEUS_FILES})
list(REMOVE_ITEM ALL_EXECUTABLES ${ALL_PROMETHEUS_FILES})
endif()
set(INSTALL_SOURCE_HDRS ${ALL_LIBRARY_HDRS} ${TEST_LIBRARY_HDRS})
# 移除internal文件夹内的头文件,不进行安装
file(GLOB_RECURSE INTERNAL_HDRS "cartographer/*/internal/*.h")
list(REMOVE_ITEM INSTALL_SOURCE_HDRS ${INTERNAL_HDRS})
file(GLOB_RECURSE ALL_PROTOS "cartographer/*.proto")
file(GLOB_RECURSE ALL_GRPC_SERVICES "cartographer/*_service.proto")
list(REMOVE_ITEM ALL_PROTOS ALL_GRPC_SERVICES)
if (NOT ${BUILD_GRPC})
list(REMOVE_ITEM ALL_PROTOS ${ALL_GRPC_FILES})
endif()
# TODO(cschuet): Move proto compilation to separate function.
set(ALL_PROTO_SRCS)
set(ALL_PROTO_HDRS)
foreach(ABS_FIL ${ALL_PROTOS})
file(RELATIVE_PATH REL_FIL ${PROJECT_SOURCE_DIR} ${ABS_FIL})
get_filename_component(DIR ${REL_FIL} DIRECTORY)
get_filename_component(FIL_WE ${REL_FIL} NAME_WE)
list(APPEND ALL_PROTO_SRCS "${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.cc")
list(APPEND ALL_PROTO_HDRS "${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.h")
add_custom_command(
OUTPUT "${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.cc"
"${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --cpp_out ${PROJECT_BINARY_DIR} -I
${PROJECT_SOURCE_DIR} ${ABS_FIL}
DEPENDS ${ABS_FIL}
COMMENT "Running C++ protocol buffer compiler on ${ABS_FIL}"
VERBATIM
)
endforeach()
set_source_files_properties(${ALL_PROTO_SRCS} ${ALL_PROTO_HDRS} PROPERTIES GENERATED TRUE)
# 添加.pb.h与.pb.cc到头文件源文件列表
list(APPEND ALL_LIBRARY_HDRS ${ALL_PROTO_HDRS})
list(APPEND ALL_LIBRARY_SRCS ${ALL_PROTO_SRCS})
if(${BUILD_GRPC})
set(ALL_GRPC_SERVICE_SRCS)
set(ALL_GRPC_SERVICE_HDRS)
foreach(ABS_FIL ${ALL_GRPC_SERVICES})
file(RELATIVE_PATH REL_FIL ${PROJECT_SOURCE_DIR} ${ABS_FIL})
get_filename_component(DIR ${REL_FIL} DIRECTORY)
get_filename_component(FIL_WE ${REL_FIL} NAME_WE)
list(APPEND ALL_GRPC_SERVICE_SRCS "${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.cc")
list(APPEND ALL_GRPC_SERVICE_HDRS "${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.h")
add_custom_command(
OUTPUT "${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.cc"
"${PROJECT_BINARY_DIR}/${DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --cpp_out ${PROJECT_BINARY_DIR}
-I ${PROJECT_SOURCE_DIR}
${ABS_FIL}
DEPENDS ${ABS_FIL}
COMMENT "Running C++ protocol buffer compiler on ${ABS_FIL}"
VERBATIM
)
endforeach()
set_source_files_properties(${ALL_GRPC_SERVICE_SRCS} ${ALL_GRPC_SERVICE_HDRS} PROPERTIES GENERATED TRUE)
list(APPEND ALL_LIBRARY_HDRS ${ALL_GRPC_SERVICE_HDRS})
list(APPEND ALL_LIBRARY_SRCS ${ALL_GRPC_SERVICE_SRCS})
endif()
set(INSTALL_GENERATED_HDRS ${ALL_PROTO_HDRS} ${ALL_GRPC_SERVICE_HDRS})
# 生成cartographer库文件
add_library(${PROJECT_NAME} STATIC ${ALL_LIBRARY_HDRS} ${ALL_LIBRARY_SRCS})
configure_file(
${PROJECT_SOURCE_DIR}/cartographer/common/config.h.cmake
${PROJECT_BINARY_DIR}/cartographer/common/config.h)
google_binary(cartographer_autogenerate_ground_truth
SRCS
cartographer/ground_truth/autogenerate_ground_truth_main.cc
)
google_binary(cartographer_compute_relations_metrics
SRCS
cartographer/ground_truth/compute_relations_metrics_main.cc
)
google_binary(cartographer_pbstream
SRCS
cartographer/io/pbstream_main.cc
)
google_binary(cartographer_print_configuration
SRCS
cartographer/common/print_configuration_main.cc
)
if(${BUILD_GRPC})
google_binary(cartographer_grpc_server
SRCS
cartographer/cloud/map_builder_server_main.cc
)
target_link_libraries(cartographer_grpc_server PUBLIC grpc++)
target_link_libraries(cartographer_grpc_server PUBLIC async_grpc)
if(${BUILD_PROMETHEUS})
target_link_libraries(cartographer_grpc_server PUBLIC ${ZLIB_LIBRARIES})
target_link_libraries(cartographer_grpc_server PUBLIC prometheus-cpp-core)
target_link_libraries(cartographer_grpc_server PUBLIC prometheus-cpp-pull)
endif()
endif()
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${EIGEN3_INCLUDE_DIR}")
target_link_libraries(${PROJECT_NAME} PUBLIC ${EIGEN3_LIBRARIES})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${CERES_INCLUDE_DIRS}")
target_link_libraries(${PROJECT_NAME} PUBLIC ${CERES_LIBRARIES})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${LUA_INCLUDE_DIR}")
target_link_libraries(${PROJECT_NAME} PUBLIC ${LUA_LIBRARIES})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${Boost_INCLUDE_DIRS}")
target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES})
if (WIN32)
find_package(glog REQUIRED)
set(GLOG_LIBRARY glog::glog)
else()
set(GLOG_LIBRARY glog)
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC ${GLOG_LIBRARY})
target_link_libraries(${PROJECT_NAME} PUBLIC gflags)
if(WIN32)
# Needed to fix conflict with MSVC's error macro.
target_compile_definitions(${PROJECT_NAME} PUBLIC -DGLOG_NO_ABBREVIATED_SEVERITIES)
endif()
if(MSVC)
# Needed for VS 2017 5.8
target_compile_definitions(${PROJECT_NAME} PUBLIC -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_USE_MATH_DEFINES)
endif()
if("${CAIRO_INCLUDE_DIRS}")
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${CAIRO_INCLUDE_DIRS}")
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC ${CAIRO_LIBRARIES})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
${PROTOBUF_INCLUDE_DIR})
# TODO(hrapp): This should not explicitly list pthread and use
# PROTOBUF_LIBRARIES, but that failed on first try.
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROTOBUF_LIBRARY}
absl::algorithm
absl::base
absl::debugging
absl::flat_hash_map
absl::memory
absl::meta
absl::numeric
absl::str_format
absl::strings
absl::synchronization
absl::time
absl::utility
)
if (NOT WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC pthread)
endif()
if(${BUILD_GRPC})
target_link_libraries(${PROJECT_NAME} PUBLIC grpc++)
target_link_libraries(${PROJECT_NAME} PUBLIC async_grpc)
endif()
if(${BUILD_PROMETHEUS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${ZLIB_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PUBLIC prometheus-cpp-core)
target_link_libraries(${PROJECT_NAME} PUBLIC prometheus-cpp-pull)
target_compile_definitions(${PROJECT_NAME} PUBLIC USE_PROMETHEUS=1)
endif()
set(TARGET_COMPILE_FLAGS "${TARGET_COMPILE_FLAGS} ${GOOG_CXX_FLAGS}")
set_target_properties(${PROJECT_NAME} PROPERTIES
COMPILE_FLAGS ${TARGET_COMPILE_FLAGS})
# 不编译test_library
# set(TEST_LIB
# cartographer_test_library
# )
# add_library(${TEST_LIB} ${TEST_LIBRARY_HDRS} ${TEST_LIBRARY_SRCS})
# target_include_directories(${TEST_LIB} SYSTEM PRIVATE
# "${GMOCK_INCLUDE_DIRS}")
# # Needed for dynamically linked GTest on Windows.
# if (WIN32)
# target_compile_definitions(${TEST_LIB} PUBLIC -DGTEST_LINKED_AS_SHARED_LIBRARY)
# endif()
# target_link_libraries(${TEST_LIB} PUBLIC ${GMOCK_LIBRARY})
# target_link_libraries(${TEST_LIB} PUBLIC ${PROJECT_NAME})
# set_target_properties(${TEST_LIB} PROPERTIES
# COMPILE_FLAGS ${TARGET_COMPILE_FLAGS})
# 不编译_test.cc文件
# foreach(ABS_FIL ${ALL_TESTS})
# file(RELATIVE_PATH REL_FIL ${PROJECT_SOURCE_DIR} ${ABS_FIL})
# get_filename_component(DIR ${REL_FIL} DIRECTORY)
# get_filename_component(FIL_WE ${REL_FIL} NAME_WE)
# # Replace slashes as required for CMP0037.
# string(REPLACE "/" "." TEST_TARGET_NAME "${DIR}/${FIL_WE}")
# google_test("${TEST_TARGET_NAME}" ${ABS_FIL})
# if(${BUILD_GRPC})
# target_link_libraries("${TEST_TARGET_NAME}" PUBLIC grpc++)
# target_link_libraries("${TEST_TARGET_NAME}" PUBLIC async_grpc)
# endif()
# if(${BUILD_PROMETHEUS})
# target_link_libraries("${TEST_TARGET_NAME}" PUBLIC ${ZLIB_LIBRARIES})
# target_link_libraries("${TEST_TARGET_NAME}" PUBLIC prometheus-cpp-core)
# target_link_libraries("${TEST_TARGET_NAME}" PUBLIC prometheus-cpp-pull)
# endif()
# target_link_libraries("${TEST_TARGET_NAME}" PUBLIC ${TEST_LIB})
# endforeach()
# Add the binary directory first, so that port.h is included after it has
# been generated.
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
# 安装cartographer库
install(
TARGETS ${PROJECT_NAME}
EXPORT CartographerExport
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
# 安装头文件
foreach(HDR ${INSTALL_SOURCE_HDRS})
file(RELATIVE_PATH REL_FIL ${PROJECT_SOURCE_DIR} ${HDR})
get_filename_component(DIR ${REL_FIL} DIRECTORY)
install(
FILES ${HDR}
DESTINATION include/${DIR}
)
endforeach()
foreach(HDR ${INSTALL_GENERATED_HDRS})
file(RELATIVE_PATH REL_FIL ${PROJECT_BINARY_DIR} ${HDR})
get_filename_component(DIR ${REL_FIL} DIRECTORY)
install(
FILES ${HDR}
DESTINATION include/${DIR}
)
endforeach()
set(CARTOGRAPHER_CMAKE_DIR share/cartographer/cmake)
include(CMakePackageConfigHelpers)
configure_package_config_file(
cartographer-config.cmake.in
${PROJECT_BINARY_DIR}/cmake/cartographer/cartographer-config.cmake
PATH_VARS CARTOGRAPHER_CMAKE_DIR
INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/share/cartographer
)
install(
EXPORT CartographerExport
DESTINATION share/cartographer/cmake/
FILE CartographerTargets.cmake
)
install(
FILES ${PROJECT_BINARY_DIR}/cmake/cartographer/cartographer-config.cmake
DESTINATION share/cartographer/
)
gflags是google开源的命令行标记处理库
命令行标记,顾名思义就是当运行一个可执行文件时, 由用户为其指定的标记, 形如:
fgrep -l -f ./test ccc jjj
-l 与 -f 是命令行标记, 而 ccc 与 jjj 是命令行参数, 因为这两者不是以 - 开头的.
一般的一个可执行文件, 允许用户为其传入命令行标记以及参数.
如上述例子, -l 是一个不带参数的标记, -f 是一个带了参数 ./test 的标记, 而gflags可以解析这些标记以及参数并将其存储在某些数据结构中.
gflags主要支持的参数类型包括bool, int32, int64, uint64, double, string等
定义参数通过DEFINE_type宏实现, 该宏的三个参数含义分别为命令行参数名, 参数默认值, 以及参数的帮助信息
当参数被定义后, 通过FLAGS_name就可访问到对应的参数
详细使用请见:gflags使用详解 - 知乎 (zhihu.com)
/**
* note: gflags是一套命令行参数解析工具
* DEFINE_bool在gflags.h中定义
* gflags主要支持的参数类型包括bool, int32, int64, uint64, double, string等
* 定义参数通过DEFINE_type宏实现, 该宏的三个参数含义分别为命令行参数名, 参数默认值, 以及参数的帮助信息
* 当参数被定义后, 通过FLAGS_name就可访问到对应的参数
*/
// collect_metrics :激活运行时度量的集合.如果激活, 可以通过ROS服务访问度量
DEFINE_bool(collect_metrics, false,
"Activates the collection of runtime metrics. If activated, the "
"metrics can be accessed via a ROS service.");
/*
通过launch文件传入到对应的变量configuration_directory,configuration_basename,load_state_filename中,使用的时候在前面加上FLAGS
*/
DEFINE_string(configuration_directory, "",
"First directory in which configuration files are searched, "
"second is always the Cartographer installation to allow "
"including files from there.");
DEFINE_string(configuration_basename, "",
"Basename, i.e. not containing any directory prefix, of the "
"configuration file.");
DEFINE_string(load_state_filename, "",
"If non-empty, filename of a .pbstream file to load, containing "
"a saved SLAM state.");
DEFINE_bool(load_frozen_state, true,
"Load the saved state as frozen (non-optimized) trajectories.");
DEFINE_bool(
start_trajectory_with_default_topics, true,
"Enable to immediately start the first trajectory with default topics.");
DEFINE_string(
save_state_filename, "",
"If non-empty, serialize state and write it to disk before shutting down.");
它提供基于C++风格的流和各种辅助宏的日志API.支持以下功能:
参数设置, 以命令行参数的方式设置标志参数来控制日志记录行为
严重性分级, 根据日志严重性分级记录日志 - INFO WARNING ERROR FATAL
可有条件地记录日志信息 - LOG_IF LOG_EVERY_N LOG_IF_EVERY_N LOG_FIRST_N
条件中止程序。丰富的条件判定宏, 可预设程序终止条件 - CHECK宏
异常信号处理。程序异常情况, 可自定义异常处理过程
支持debug功能
自定义日志信息
线程安全日志记录方式
系统级日志记录
google perror风格日志信息
精简日志字符串信息
最终的结果不仅会在屏幕终端显示出来, 同时会将log日志写入到/tmp/…log…这个文件中
//CHECK_OP(_EQ, ==, val1, val2) 表示当va1等于val2返回true,否则返回false;后面同理
#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
路径:src/cartographer/CMakeLists.txt
if (WIN32)
find_package(glog REQUIRED)
set(GLOG_LIBRARY glog::glog)
else()
set(GLOG_LIBRARY glog)
endif()
//将glog库链接到cartographer里面
target_link_libraries(${PROJECT_NAME} PUBLIC ${GLOG_LIBRARY})
target_link_libraries(${PROJECT_NAME} PUBLIC gflags)
在文件ros_log_sink.h/cc
中通过类ScopedRosLogSink
继承::google::LogSink
进行自定义的输出日志方式
//进行了ros_log的注册,以至于只要使用glog都会使用ros_log_sink的send函数
// 使用ROS_INFO进行glog消息的输出
cartographer_ros::ScopedRosLogSink ros_log_sink;
::google::LogSink
并重载了send函数,这样就可以使用ROS_INFO进行glog消息的输出WaitTillSent()
,该函数会在每次send后调用, 用于一些异步写的场景#ifndef CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_ROS_LOG_SINK_H
#define CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_ROS_LOG_SINK_H
#include
#include "glog/logging.h"
namespace cartographer_ros {
// Makes Google logging use ROS logging for output while an instance of this
// class exists.
/**
* @brief 自定义的输出日志的方式: 使用ROS_INFO进行glog消息的输出
*/
class ScopedRosLogSink : public ::google::LogSink {
public:
ScopedRosLogSink();
~ScopedRosLogSink() override;
void send(::google::LogSeverity severity, const char* filename,
const char* base_filename, int line, const struct std::tm* tm_time,
const char* message, size_t message_len) override;
void WaitTillSent() override;
private:
bool will_die_;
};
} // namespace cartographer_ros
总结:通过对
::google::LogSink
的继承,与send函数的重载,使得只要声明了ros_log_sink这个变量,就默认使用ROS_INFO进行glog消息的输出
位置:scr/cartographer_ros/cartographer_ros/cartographer_ros/node_main.cc
cartographer::Run()
函数#include "absl/memory/memory.h"
#include "cartographer/mapping/map_builder.h"
#include "cartographer_ros/node.h"
#include "cartographer_ros/node_options.h"
#include "cartographer_ros/ros_log_sink.h"
#include "gflags/gflags.h"
#include "tf2_ros/transform_listener.h"
/**
* note: gflags是一套命令行参数解析工具
* DEFINE_bool在gflags.h中定义
* gflags主要支持的参数类型包括bool, int32, int64, uint64, double, string等
* 定义参数通过DEFINE_type宏实现, 该宏的三个参数含义分别为命令行参数名, 参数默认值, 以及参数的帮助信息
* 当参数被定义后, 通过FLAGS_name就可访问到对应的参数
*/
// collect_metrics :激活运行时度量的集合.如果激活, 可以通过ROS服务访问度量
DEFINE_bool(collect_metrics, false,
"Activates the collection of runtime metrics. If activated, the "
"metrics can be accessed via a ROS service.");
DEFINE_string(configuration_directory, "",
"First directory in which configuration files are searched, "
"second is always the Cartographer installation to allow "
"including files from there.");
DEFINE_string(configuration_basename, "",
"Basename, i.e. not containing any directory prefix, of the "
"configuration file.");
DEFINE_string(load_state_filename, "",
"If non-empty, filename of a .pbstream file to load, containing "
"a saved SLAM state.");
DEFINE_bool(load_frozen_state, true,
"Load the saved state as frozen (non-optimized) trajectories.");
DEFINE_bool(
start_trajectory_with_default_topics, true,
"Enable to immediately start the first trajectory with default topics.");
DEFINE_string(
save_state_filename, "",
"If non-empty, serialize state and write it to disk before shutting down.");
namespace cartographer_ros {
namespace {
void Run() {
//见下面
} // namespace cartographer_ros
int main(int argc, char** argv) {
// note: 初始化glog库
google::InitGoogleLogging(argv[0]);
// 使用gflags进行参数的初始化,例如前面的configuration_directory、configuration_basename等.
// 其中第三个参数为remove_flag,如果为true, gflags会移除parse过的参数, 否则gflags就会保留这些参数, 但可能会对参数顺序进行调整.
google::ParseCommandLineFlags(&argc, &argv, true);
/**
* @brief glog里提供的CHECK系列的宏, 检测某个表达式是否为真
* 检测expression如果不为真, 则打印后面的description和栈上的信息
* 然后退出程序, 出错后的处理过程和FATAL比较像.
*/
//FLAGS_name:gflag的使用规则,使用时在变量前面加上FLAGS
CHECK(!FLAGS_configuration_directory.empty())
<< "-configuration_directory is missing.";
CHECK(!FLAGS_configuration_basename.empty())
<< "-configuration_basename is missing.";
// ros节点的初始化
::ros::init(argc, argv, "cartographer_node");
// 一般不需要在自己的代码中显式调用
// 但是若想在创建任何NodeHandle实例之前启动ROS相关的线程, 网络等, 可以显式调用该函数.
::ros::start();
// 使用ROS_INFO进行glog消息的输出
cartographer_ros::ScopedRosLogSink ros_log_sink;
// 开始运行cartographer_ros
cartographer_ros::Run();
// 结束ROS相关的线程, 网络等
::ros::shutdown();
}
node_options
和trajectory_options
变量中namespace cartographer_ros {
namespace {
void Run() {
//tf缓冲区缓存时间(秒)
constexpr double kTfBufferCacheTimeInSeconds = 10.;
//创建tf_buffer
tf2_ros::Buffer tf_buffer{::ros::Duration(kTfBufferCacheTimeInSeconds)};
// 开启监听tf的独立线程
tf2_ros::TransformListener tf(tf_buffer);
NodeOptions node_options;
TrajectoryOptions trajectory_options;
// c++11: std::tie()函数可以将变量连接到一个给定的tuple上,生成一个元素类型全是引用的tuple
// 根据Lua配置文件中的内容, 为node_options, trajectory_options 赋值
std::tie(node_options, trajectory_options) =
LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
// MapBuilder类是完整的SLAM算法类
// 包含前端(TrajectoryBuilders,scan to submap) 与 后端(用于查找回环的PoseGraph)
auto map_builder =
cartographer::mapping::CreateMapBuilder(node_options.map_builder_options);
// c++11: std::move 是将对象的状态或者所有权从一个对象转移到另一个对象,
// 只是转移, 没有内存的搬迁或者内存拷贝所以可以提高利用效率,改善性能..
// 右值引用是用来支持转移语义的.转移语义可以将资源 ( 堆, 系统对象等 ) 从一个对象转移到另一个对象,
// 这样能够减少不必要的临时对象的创建、拷贝以及销毁, 能够大幅度提高 C++ 应用程序的性能.
// 临时对象的维护 ( 创建和销毁 ) 对性能有严重影响.
// Node类的初始化, 将ROS的topic传入SLAM, 也就是MapBuilder
Node node(node_options, std::move(map_builder), &tf_buffer,
FLAGS_collect_metrics);
// 如果加载了pbstream文件, 就执行这个函数
if (!FLAGS_load_state_filename.empty()) {
node.LoadState(FLAGS_load_state_filename, FLAGS_load_frozen_state);
}
// 使用默认topic 开始轨迹
if (FLAGS_start_trajectory_with_default_topics) {
node.StartTrajectoryWithDefaultTopics(trajectory_options);
}
::ros::spin();
//按ctrl+c才能结束!
// 结束所有处于活动状态的轨迹
node.FinishAllTrajectories();
// 当所有的轨迹结束时, 再执行一次全局优化
node.RunFinalOptimization();
// 如果save_state_filename非空, 就保存pbstream文件
if (!FLAGS_save_state_filename.empty()) {
node.SerializeState(FLAGS_save_state_filename,
true /* include_unfinished_submaps */);
}
}
} // namespace
} // namespace cartographer_ros
在cartographer_ros::Run()
的代码中包含以下三句:
NodeOptions node_options;
TrajectoryOptions trajectory_options;
// c++11: std::tie()函数可以将变量连接到一个给定的tuple上,生成一个元素类型全是引用的tuple
// 根据Lua配置文件中的内容, 为node_options, trajectory_options 赋值
std::tie(node_options, trajectory_options) =
LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
NodeOptions
的结构体CreateNodeOptions
,作用是读取lua文件内容, 将lua文件的内容赋值给NodeOptionsLoadOptions
,作用是加载lua配置文件中的参数#ifndef CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_NODE_OPTIONS_H
#define CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_NODE_OPTIONS_H
#include
#include
#include "cartographer/common/lua_parameter_dictionary.h"
#include "cartographer/common/port.h"
#include "cartographer/mapping/proto/map_builder_options.pb.h"
#include "cartographer_ros/trajectory_options.h"
namespace cartographer_ros {
// Top-level options of Cartographer's ROS integration.
struct NodeOptions {
::cartographer::mapping::proto::MapBuilderOptions map_builder_options;
std::string map_frame;
double lookup_transform_timeout_sec;
double submap_publish_period_sec;
double pose_publish_period_sec;
double trajectory_publish_period_sec;
bool publish_to_tf = true;
bool publish_tracked_pose = false;
bool use_pose_extrapolator = true;
};
NodeOptions CreateNodeOptions(
::cartographer::common::LuaParameterDictionary* lua_parameter_dictionary);
std::tuple<NodeOptions, TrajectoryOptions> LoadOptions(
const std::string& configuration_directory,
const std::string& configuration_basename);
} // namespace cartographer_ros
#endif // CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_NODE_OPTIONS_H
TrajectoryOptions
的结构体CreateTrajectoryOptions
,作用是读取lua文件内容, 将lua文件的内容赋值给TrajectoryOptions#ifndef CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_TRAJECTORY_OPTIONS_H
#define CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_TRAJECTORY_OPTIONS_H
#include
#include "cartographer/common/lua_parameter_dictionary.h"
#include "cartographer/common/port.h"
#include "cartographer/mapping/proto/trajectory_builder_options.pb.h"
namespace cartographer_ros {
// 一条轨迹的基础参数配置
struct TrajectoryOptions {
::cartographer::mapping::proto::TrajectoryBuilderOptions
trajectory_builder_options;
std::string tracking_frame;
std::string published_frame;
std::string odom_frame;
bool provide_odom_frame;
bool use_odometry;
bool use_nav_sat;
bool use_landmarks;
bool publish_frame_projected_to_2d;
int num_laser_scans;
int num_multi_echo_laser_scans;
int num_subdivisions_per_laser_scan;
int num_point_clouds;
double rangefinder_sampling_ratio;
double odometry_sampling_ratio;
double fixed_frame_pose_sampling_ratio;
double imu_sampling_ratio;
double landmarks_sampling_ratio;
};
TrajectoryOptions CreateTrajectoryOptions(
::cartographer::common::LuaParameterDictionary* lua_parameter_dictionary);
} // namespace cartographer_ros
#endif // CARTOGRAPHER_ROS_CARTOGRAPHER_ROS_TRAJECTORY_OPTIONS_H
如果需要从lua文件中添加和删除文件,则需要从这两个文件中做相应的处理!
LoadOptions
中,有以下几句: // 获取配置文件所在的目录
auto file_resolver =
absl::make_unique<cartographer::common::ConfigurationFileResolver>(
std::vector<std::string>{configuration_directory});
// 读取配置文件内容到code中
const std::string code =
file_resolver->GetFileContentOrDie(configuration_basename);
// 根据给定的字符串, 生成一个lua字典
cartographer::common::LuaParameterDictionary lua_parameter_dictionary(
code, std::move(file_resolver));
其中cartographer::common::ConfigurationFileResolver
这个类定义在configuration_file_resolver.h
中,ConfigurationFileResolver类继承于FileResolver类,而FileResolver类以及后面的定义LuaParameterDictionary类 都在lua_parameter_dictionary.h中
只粘贴了FileResolver类的定义,该头文件中还包含LuaParameterDictionary类,但定义过长,所以没有粘贴!LuaParameterDictionary类的作用就是从lua文件中加载参数!
GetFullPathOrDie
和GetFileContentOrDie
两个接口函数class FileResolver {
public:
virtual ~FileResolver() {}
virtual std::string GetFullPathOrDie(const std::string& basename) = 0;
virtual std::string GetFileContentOrDie(const std::string& basename) = 0;
};
kConfigurationFilesDirectory
,而这个变量会用在src\cartographer\cartographer\common\config.h.cmake
中,对应的lua文件配置参数会创建在install_isolated/share/cartographer/configuration_files
中,换句话说,cartographer在运行中是在install_isolated文件夹中查看lua配置文件,这也解释了为什么在src目录下修改了lua文件的参数,需要重新编译才能生效!GetFullPathOrDie
,作用是在所有的配置文件目录中 根据给定配置文件的名字 搜索 配置文件GetFileContentOrDie
,作用是读取配置文件内容class ConfigurationFileResolver : public FileResolver {
public:
// c++11: explicit关键字 的作用就是防止类构造函数的隐式自动转换
explicit ConfigurationFileResolver(
const std::vector<std::string>& configuration_files_directories);
std::string GetFullPathOrDie(const std::string& basename) override;
std::string GetFileContentOrDie(const std::string& basename) override;
private:
std::vector<std::string> configuration_files_directories_;
};
} // namespace common
} // namespace cartographer
#endif // CARTOGRAPHER_COMMON_CONFIGURATION_FILE_RESOLVER_H_
这俩头文件的主要作用就是获取到lua文件中参数的配置,然后传给NodeOptions和TrajectoryOptions这两个类