从零开始学习cartographer源码 | 02.cartographer_ros—node_main.cc
- cartographer_ros
- 程序的入口 main()函数
- 程序的主函数Run()函数
特别(防杠)声明:《从零开始学习cartographer源码》系列文章仅仅是本人学习cartographer的学习笔记,不是教学文章,如有错误请大家指出,并友好交流,共同提升,如有喜爱抬杠的朋友,那我一定承认你是对的
cartographer_ros
在ros中使用cartographer,离不开2个功能包,一个是cartographer,另一个是cartographer_ros,cartographer_ros是cartographer适配ros的rosnode,cartographer是cartographer_ros的库文件。
程序的入口 main()函数
int main(int argc, char** argv) {google::InitGoogleLogging(argv[0]); //初始化glog;google::ParseCommandLineFlags(&argc, &argv, true); //初始化gflagsCHECK(!FLAGS_configuration_directory.empty()) //使用glog检查参数是否传入<< "-configuration_directory is missing.";CHECK(!FLAGS_configuration_basename.empty())<< "-configuration_basename is missing.";::ros::init(argc, argv, "cartographer_node"); //初始化ros节点//在创建ros_handle之前操作ros网络,需要显式调用::ros::start() 启动ros,如果在创建ros_handle之后则不用::ros::start(); cartographer_ros::ScopedRosLogSink ros_log_sink; //将glog转换成roslogcartographer_ros::Run(); //程序运行的主要逻辑::ros::shutdown(); //程序运行结束后退出ros
}
程序的主函数Run()函数
void Run() {constexpr double kTfBufferCacheTimeInSeconds = 10.;tf2_ros::Buffer tf_buffer{::ros::Duration(kTfBufferCacheTimeInSeconds)};//tf缓冲区保持10秒tf2_ros::TransformListener tf(tf_buffer);//启动tf订阅NodeOptions node_options;TrajectoryOptions trajectory_options;// std::tie将node_options, trajectory_options两个变量分别赋值为LoadOptions()函数返回值// 当函数有多个返回值的时候,可以将其打包为一个元组,再通过std::tie进行解包// LoadOptions()输入参数为lua的目录和文件名,将lua中的参数读取到程序中std::tie(node_options, trajectory_options) =LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);// MapBuilder类是完整的SLAM算法类,函数传入从lua读取建图相关的参数,返回一个unique_ptr智能指针管理map_builder对象// 包含前端(TrajectoryBuilders,scan to submap) 与 后端(用于查找回环的PoseGraph)auto map_builder =cartographer::mapping::CreateMapBuilder(node_options.map_builder_options);// 初始化node对象// node_options:传入lua中读取的参数// 使用std::move将unique_ptr对象作为参数传入实例化构造一个node对象,在node对象被销毁时map_builder指针也自动释放,防止拷贝过程优化性能// 传入tf_buffer的引用,在类内对其进行赋值和操作// FLAGS_collect_metrics:是否将cartographer的配置参数ros化的标志位Node node(node_options, std::move(map_builder), &tf_buffer, FLAGS_collect_metrics);// 判断在launch中是否加载了.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);}// 定频回调,程序阻塞直到ctrl+c退出后执行后面内容::ros::spin();// 结束所有轨迹node.FinishAllTrajectories();//执行最后的全局优化node.RunFinalOptimization();// 如果save_state_filename非空, 就保存pbstream文件if (!FLAGS_save_state_filename.empty()) {node.SerializeState(FLAGS_save_state_filename,true /* include_unfinished_submaps */);}
}