二、cartographer的Node初始化(node_main.cc代码笔记)

1、创建tf监听线程:在ROS(Robot Operating System)中,tf2_ros库用于处理坐标变换(Transforms),这是因为在多传感器和多机器人系统中,不同传感器数据可能以不同的坐标系表示。tf_buffer和tf2_ros::TransformListener是实现这一功能的关键组件。
    (1)tf2_ros::Buffer tf_buffer: tf_buffer 是一个缓冲区对象,它存储了所有在给定时间窗口内的TF(Transform)消息。这里初始化时传入了一个ros::Duration(kTfBufferCacheTimeInSeconds)参数,这意味着tf_buffer将缓存最近10秒内的所有坐标变换信息。这样,当需要查询某个时间点的坐标转换关系时,可以从缓冲区内快速查找而不必等待新的TF消息到达。
    (2)tf2_ros::TransformListener (tf): tf2_ros::TransformListener 是一个类,它监听ROS主题上的TF消息,并自动将这些消息添加到关联的tf_buffer中。创建这个对象时,会启动一个独立线程来监听 /tf 主题或其他指定的主题,以便实时更新坐标变换信息。
    (3)通过这种方式,tf_buffer与tf2_ros::TransformListener协同工作,确保程序可以随时获取最新的或历史的坐标变换数据,这对于正确地融合来自多个传感器的数据、计算机器人的全局定位以及进行路径规划等任务至关重要。例如,在Cartographer这样的SLAM系统中,需要不断地获取并应用IMU、激光雷达等传感器相对于机器人基坐标系的变换,从而完成对环境地图的构建和自身位置的估计。
2、读取lua文件的配置信息到 NodeOptions node_options、TrajectoryOptions trajectory_options;
3、使用node_options的参数初始化MapBuilder map_builder
4、使用1-3的数据初始化Node node并声明一下数据传递操作
    (1)发布话题:
        1)submap_list_publisher_:发布SubmapList,发布消息类型为SubmapList,话题为"submap_list",消息队列的缓冲区大小为1(当有多个订阅者(subscriber)连接到同一个主题时,并且它们接收消息的速度不一致,这个参数决定了ROS系统会为该主题维护的最大未发送消息数量。如果缓冲区大小设置为1,则意味着当发布者发布的消息速度超过订阅者的处理速度时,最多可以累积1条未被订阅者接收到的消息。一旦消息数量达到1条,如果发布者继续发布新的消息,那么最早进入队列但尚未被处理的消息将会被丢弃。如果将缓冲区大小设为0,则表示无限制的缓冲,但这可能导致内存使用量持续增长,特别是在发布频率远高于订阅者处理速度的情况下。因此,在实际应用中,合理设置缓冲区大小对于确保消息系统的稳定性和资源有效利用十分重要。根据具体的实时性要求和系统性能来调整这一参数。)
        2)trajectory_node_list_publisher_:发布轨迹,发布消息类型为MarkerArray,话题为"trajectory_node_list",消息队列的缓冲区大小为1
        3)landmark_poses_list_publisher_:发布landmark_pose,发布消息类型为MarkerArray,话题为"landmark_poses_list",消息队列的缓冲区大小为1
        4)constraint_list_publisher_:发布约束,发布消息类型为MarkerArray,话题为"constraint_list",消息队列的缓冲区大小为1
    (2)声明服务,并依次将服务的发布器放入到service_servers_:
        1)服务名称为"submap_query",处理函数为&Node::HandleSubmapQuery(这里的服务声明都有一个this参数,作用为将当前对象实例的指针传递给 advertiseService 函数。这样,当服务被调用时,ROS 系统就知道应该使用哪个具体的 Node 对象来执行 HandleSubmapQuery 成员函数。)
        2)服务名称为"trajectory_query",处理函数为&Node::HandleTrajectoryQuery
        3)服务名称为"start_trajectory",处理函数为&Node::HandleStartTrajectory
        4)服务名称为"finish_trajectory",处理函数为&Node::HandleFinishTrajectory
        5)服务名称为"write_state",处理函数为&Node::HandleWriteState
        6)服务名称为"get_trajectory_states",处理函数为&Node::HandleGetTrajectoryStates
        7)服务名称为"read_metrics",处理函数为&Node::HandleReadMetrics
    (3)发布话题
        1)scan_matched_point_cloud_publisher_:发布处理之后的点云,发布消息类型为PointCloud2,话题为"scan_matched_points2",消息队列的缓冲区大小为1
    (4)定时器使用函数定时发布数据,并将所有定时器放入wall_timers_:
        1)每0.3s walltime执行一次&Node::PublishSubmapList(这里传递回调函数被调用时,就能访问到该Node对象的所有成员变量和方法)
        2)publish_local_trajectory_data_timer_(这个不放入wall_timers_):每0.005s ROS_time调用&Node::PublishLocalTrajectoryData
        3)每0.3s walltime执行一次 &Node::PublishTrajectoryNodeList
        4)每0.3s walltime执行一次&Node::PublishLandmarkPosesList
        5)每0.5s walltime执行一次&Node::PublishConstraintList
5、StartTrajectoryWithDefaultTopics->Node::AddTrajectory(步骤2读取的trajectory_options作为传入参数options)
    (1)ComputeExpectedSensorIds:根据配置文件,读取传感器类型expected_sensor_ids,官方demo是Range:echo和IMU:imu
    (2)使用(1)的expected_sensor_ids和trajectory_options和回调函数OnLocalSlamResult,调用MapBuilder::AddTrajectoryBuilder:
        1)获取轨迹id trajectory_id,此时trajectory_builders_还未添加东西,大小为0
            (1)使用Range数据初始化前端LocalTrajectoryBuilder2D(就是获取数据并且预处理):这里只是配置参数
            (2)创建GlobalTrajectoryBuilder,trajectory_id_为轨迹id 0,pose_graph_为后端优化,local_trajectory_builder_为2)初始化的前端,local_slam_result_callback_为(2)传入的回调函数OnLocalSlamResult,pose_graph_odometry_motion_filter_为里程计滤波器
            (3)创建CollatedTrajectoryBuilder放到trajectory_builders_,sensor_collator_为空,trajectory_id_为0,wrapped_trajectory_builder_为3)创建的GlobalTrajectoryBuilder,last_logging_time_为当前时间,调用sensor_collator_::AddTrajectory,传入HandleCollatedSensorData回调函数
                  1)queue的key由轨迹id和传感器(echoes)构成
                  2)queue_keys_按轨迹id(这里是0)放入queue_的key
                  3)queue_按(1)的key来放入回调函数HandleCollatedSensorData
            (4)这里不是纯定位模式,故MaybeAddPureLocalizationTrimmer无用
            (5)无初始位姿,pose_graph_->SetInitialTrajectoryPose跳过
            (6)将轨迹的配置文件保存到all_trajectory_builder_options_
            (7)返回轨迹id 0
        2)创建SensorBridge,按轨迹id保存到sensor_bridges_:
            (1)num_subdivisions_per_laser_scan_为10
            (2)tf_bridge_:"base_link"、lookup_transform_timeout_sec为0.2、tf_buffer
            (3)trajectory_builder_为5-(2)-1)-(3)对应轨迹的trajectory_builders_
        3)将轨迹id和创建这个id时使用的参数保存到trajectory_options_
        4)返回轨迹id
    (3)运行Node::AddExtrapolator,新增一个位姿估计器:
        1)获取配置文件里定义的重力常数gravity_time_constant为10
        2)以轨迹id 0 为key在extrapolators_放入PoseExtrapolator(pose_queue_duration_为1ms,gravity_time_constant_为10,cached_extrapolated_pose_时间为最小值,位姿为幺元)
    (4)运行Node::AddSensorSamplers,新生成一个传感器数据采样器:
        1)以轨迹id 0 为key在sensor_samplers_放入TrajectorySensorSamplers,使用FixedRatioSampler初始化各个采样器rangefinder_sampler(1),odometry_sampler(1),fixed_frame_pose_sampler(1),imu_sampler(1),landmark_sampler(1)
    (5)运行LaunchSubscribers,订阅话题与注册回调函数并放入到subscribers_[轨迹id]
        1)订阅多回波激光雷达扫描数据并处理消息,消息类型MultiEchoLaserScan,话题为“echoes",回调函数&Node::HandleMultiEchoLaserScanMessage,缓冲大小为0(这里的参数0代表的是消息队列的缓冲区大小。在ROS中,当发布者发布消息到某个话题时,如果订阅者没有及时处理这些消息,那么未处理的消息会暂时存储在一个缓冲区中。缓冲区大小就是指这个临时存储消息的最大数量。当设置为0时,表示使用默认值,通常默认值会被系统设置为一个合理的数值。)
        2)订阅IMU数据,消息类型Imu,话题为"imu",回调函数为&Node::HandleImuMessage,缓冲大小为0
        3)注:这里订阅的信息来源与playbag主线程
    (6)创建一个3s wall time后触发一次&Node::MaybeWarnAboutTopicMismatch的定时器,并放入wall_timers_
    (7)将话题(echoes、imu)放入subscribed_topics_
5、运行::ros::spin(),在 ROS 节点的主执行线程中调用此函数后,它会进入一个无限循环,等待并处理与该节点相关的各种消息和事件。只有运行了这个函数,发布和订阅信息、定时器才会开始运行,等待plagbag的数据到来。

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FAILED: CMakeFiles/cartographer.transform.timestamped_transform_test.dir/cartographer/transform/timestamped_transform_test.cc.o /usr/bin/c++ -DBOOST_ALL_NO_LIB -DBOOST_IOSTREAMS_DYN_LINK -DGFLAGS_IS_A_DLL=0 -I../cartographer -I. -I../ -isystem /usr/include/eigen3 -isystem /usr/include/lua5.2 -O3 -DNDEBUG -pthread -fPIC -Wall -Wpedantic -Werror=format-security -Werror=missing-braces -Werror=reorder -Werror=return-type -Werror=switch -Werror=uninitialized -O3 -DNDEBUG -pthread -fPIC -Wall -Wpedantic -Werror=format-security -Werror=missing-braces -Werror=reorder -Werror=return-type -Werror=switch -Werror=uninitialized -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/cartographer.transform.timestamped_transform_test.dir/cartographer/transform/timestamped_transform_test.cc.o -MF CMakeFiles/cartographer.transform.timestamped_transform_test.dir/cartographer/transform/timestamped_transform_test.cc.o.d -o CMakeFiles/cartographer.transform.timestamped_transform_test.dir/cartographer/transform/timestamped_transform_test.cc.o -c ../cartographer/transform/timestamped_transform_test.cc In file included from ../cartographer/transform/timestamped_transform_test.cc:17: ../cartographer/transform/timestamped_transform.h:21:10: fatal error: cartographer/transform/proto/timestamped_transform.pb.h: No such file or directory 21 | #include "cartographer/transform/proto/timestamped_transform.pb.h" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. [44/380] Building CXX object CMakeFiles/cartographer.sensor.internal.voxel_filter_test.dir/cartographer/sensor/internal/voxel_filter_test.cc.o
最新发布
07-23

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值