cartographer通过main()函数调用void Run()来启动程序,Run()也承接了cartographer的业务逻辑。
void Run()
{
constexpr double kTfBufferCacheTimeInSeconds = 10.;
//tf2_ros::Buffer是tf2 library的主要工具。Its main public API is defined by tf2_ros::BufferInterface.
tf2_ros::Buffer tf_buffer
{
::ros::Duration(kTfBufferCacheTimeInSeconds)
};
tf2_ros::TransformListener tf(tf_buffer);//定义监听器
NodeOptions node_options;
TrajectoryOptions trajectory_options;
std::tie(node_options, trajectory_options) =LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
auto map_builder = absl::make_unique<cartographer::mapping::MapBuilder>(node_options.map_builder_options);
Node node(node_options, std::move(map_builder), &tf_buffer,FLAGS_collect_metrics);
if (!FLAGS_load_state_filename.empty())
{
node.LoadState(FLAGS_load_state_filename, FLAGS_load_frozen_state);//加载数据包数据
}
if (FLAGS_start_trajectory_with_default_topics) {
node.StartTrajectoryWithDefaultTopics(trajectory_options);
}
::ros::spin();//将会进入循环, 一直调用回调函数chatterCallback(),
node.FinishAllTrajectories();
node.RunFinalOptimization();
if (!FLAGS_save_state_filename.empty())
{//如果保存的状态文件不为空
node.SerializeState(FLAGS_save_state_filename, true /* include_unfinished_submaps */);
}
}
解析:
constexpr double kTfBufferCacheTimeInSeconds = 10.;
tf2_ros::Buffer tf_buffer
{
::ros::Duration(kTfBufferCacheTimeInSeconds)
};
tf2_ros::TransformListener tf(tf_buffer);//定义监听器
//这里定义了一个10s的tf缓存器。然后定义了监听器tf,用于监听cartographer系统发布的所有的坐标系变换的关系,并将缓存到tf_buffer中,而kTfBufferCacheTimeInSeconds表示缓存10s
NodeOptions node_options;
TrajectoryOptions trajectory_options;
std::tie(node_options, trajectory_options) =LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
NodeOptions在/cartographer_ros/cartographer_ros/cartographer/node_options.h中定义;用于加载配置文件。
该struct中包含了对一些基本参数的设置,比如接收tf的timeout时间设置、子图发布周期设置等
tie将LoadOptions获取到的参数值分别赋给node_options和trajectory_options. LoadOptions函数在node_options.h中定义。
if (!FLAGS_load_state_filename.empty())
{
node.LoadState(FLAGS_load_state_filename, FLAGS_load_frozen_state);//加载数据包数据
}
if (FLAGS_start_trajectory_with_default_topics) {
node.StartTrajectoryWithDefaultTopics(trajectory_options);
}
LoadState(),大概意思就是说通过命令参数的形式,加载已有的系统状态文件,那么系统可以接着这个状态接着运行。
StartTrajectoryWithDefaultTopics(),根据默认的topic,开始启动新的轨迹,接着进入node.cc调用
AddTrajectory(options, DefaultSensorTopics());函数,开始接收各个topic数据,启动cartographer底层算法。
::ros::spin();//将会进入循环, 一直调用回调函数chatterCallback(),
完成系列初始化和必要的变量定义之后,就可以开启逻辑循环了,node对象将通过消息回调多线程等机制完成整个定位建图过程。
node.FinishAllTrajectories();
node.RunFinalOptimization();
如果在ROS的逻辑循环过程中,触发退出机制,Run函数就会执行以上语句,完成最终的轨迹和地图的优化。
if (!FLAGS_save_state_filename.empty())
{
node.SerializeState(FLAGS_save_state_filename, true /* include_unfinished_submaps */);
}
最后如果运行参数保存的系统状态文件不为空,则将当前的系统状态存到参数save_state_filename所指定的文件中。