cartographer_ros定位功能位姿获取与重定位设置

本人小白,项目中使用cartographer进行机器人的定位。cartographer_ros中没有发布机器人在地图坐标系中的位姿topic,只发布各frame间的tf变换。若通过tf变换获取位姿坐标,测试发现不管激光频率多高(20~100hz),获取的位姿频率只有5h左右。因此对源码进行简单修改,获取高频率的位姿topic并在rviz中根据机器人当前位置进行重定位。

准备工作

源码安装

首先对cartographer进行源码安装,相关链接如下:

demo运行

cartographer_rosd的demo运行demo,主要参考.launch运行文件和.lua配置文件。需要注意的是需要开启pure localization功能。

位姿获取

tf坐标变换-不修改源码

通过tf变换获取位姿坐标,获取的位姿频率只有5hz左右,但不用修改源码。

建立tf变换节点,发布2D位姿topic。

ros::NodeHandle nh;
ros::Publisher _pose_pub;
_pose_pub = nh.advertise<geometry_msgs::Pose2D>("pose_nav", 10);

tf::StampedTransform transform;
    tf::TransformListener listener;
    try
    {
        listener.waitForTransform("/map", "/base_link", ros::Time(0), ros::Duration(3.0));
        listener.lookupTransform("/map", "/base_link", ros::Time(0), transform);
    }
    catch (tf::TransformException &ex)
    {
        ROS_ERROR("%s", ex.what());
    }
    //输出位置信息
    pos_now.x = static_cast<double>(transform.getOrigin().x());
    pos_now.y = static_cast<double>(transform.getOrigin().y());
    pos_now.theta = tf::getYaw(transform.getRotation());
    _pose_pub.publish(pos_now);

修改源码

在cartographer_ros/cartographer_ros/cartographer_ros/node.h添加::ros::Publisher _pose_pub。对node.cc进行修改:

_pose_pub = node_handle_.advertise<geometry_msgs::Pose2D>("pose_nav", 10);//100hz  
geometry_msgs::Pose2D pos_now;

if (trajectory_data.published_to_tracking != nullptr) {
      if (trajectory_data.trajectory_options.provide_odom_frame) {
        std::vector<geometry_msgs::TransformStamped> stamped_transforms;

        stamped_transform.header.frame_id = node_options_.map_frame;
        stamped_transform.child_frame_id =
            trajectory_data.trajectory_options.odom_frame;
        stamped_transform.transform =
            ToGeometryMsgTransform(trajectory_data.local_to_map);
        stamped_transforms.push_back(stamped_transform);

        stamped_transform.header.frame_id =
            trajectory_data.trajectory_options.odom_frame;
        stamped_transform.child_frame_id =
            trajectory_data.trajectory_options.published_frame;
        stamped_transform.transform = ToGeometryMsgTransform(
            tracking_to_local * (*trajectory_data.published_to_tracking));
        stamped_transforms.push_back(stamped_transform);

        tf_broadcaster_.sendTransform(stamped_transforms);

        geometry_msgs::Transform transform = ToGeometryMsgTransform(
            tracking_to_map * (*trajectory_data.published_to_tracking));
        //********修改部分:添加位姿发布**********/
        pos_now.x = static_cast<double>(transform.translation.x);
        pos_now.y = static_cast<double>(transform.translation.y);
        pos_now.theta = tf::getYaw(transform.rotation);
        _pose_pub.publish(pos_now);
      } 

rviz重定位设置

订阅/initialpose话题

rviz中的“2D Pose Estimate”可发布/initialpose话题,通过点击地图位置可以发布相应位置的topic,包括x,y和theta。

_pose_init_sub = nh.subscribe("/initialpose", 1000, &NavNode::init_pose_callback, this);

重定位设置

重定位功能通过调用API设置,参考API

void NavNode::init_pose_callback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &msg)
{
    double x = msg->pose.pose.position.x;
    double y = msg->pose.pose.position.y;
    double theta = tf2::getYaw(msg->pose.pose.orientation);
    ros::NodeHandle nh;

    ros::ServiceClient client_traj_finish = nh.serviceClient<cartographer_ros_msgs::FinishTrajectory>("finish_trajectory");
    cartographer_ros_msgs::FinishTrajectory srv_traj_finish;
    srv_traj_finish.request.trajectory_id = traj_id;
    if (client_traj_finish.call(srv_traj_finish))
    {
        ROS_INFO("Call finish_trajectory %d success!", traj_id);
    }
    else
    {
        ROS_INFO("Failed to call finish_trajectory service!");
    }

    ros::ServiceClient client_traj_start = nh.serviceClient<cartographer_ros_msgs::StartTrajectory>("start_trajectory");
    cartographer_ros_msgs::StartTrajectory srv_traj_start;
    srv_traj_start.request.configuration_directory = "xxx";//.lua文件所在路径
    srv_traj_start.request.configuration_basename = "xxx.lua";//lua文件
    srv_traj_start.request.use_initial_pose = 1;
    srv_traj_start.request.initial_pose = msg->pose.pose;
    srv_traj_start.request.relative_to_trajectory_id = 0;
    if (client_traj_start.call(srv_traj_start))
    {
        // ROS_INFO("Status ", srv_traj_finish.response.status)
        ROS_INFO("Call start_trajectory %d success!", traj_id);
        traj_id++;
    }
    else
    {
        ROS_INFO("Failed to call start_trajectory service!");
    }
}

完毕,若有问题,欢迎沟通,大家共同学习。

<think>好的,我现在需要回答用户关于CartographerROS 2中如何进行重定位的问题。首先,我得确认自己对CartographerROS 2的基本了解。Cartographer是一个开源的实SLAM库,支持2D和3D,而ROS 2是其机器人操作系统的新版本。重定位通常指在已有地中重新定位机器人,尤其是在丢失置跟踪后。 接下来,用户的问题是如何在ROS 2中实现Cartographer重定位。我需要回忆Cartographer功能是否原生支持重定位。记得Cartographer主要专注于定位的实处理,但可能没有直接的重定位接口。可能需要利用其提供的服务或者话题来触发重定位过程。 然后,我应该考虑CartographerROS 2中的具体实现。ROS 2的节点和服务ROS 1有所不同,所以需要确认CartographerROS 2包是否支持相关服务。例如,是否有用于加载现有地设置初始姿态的服务。同重定位可能需要调整某些参数,比如关闭增量式,启用纯定位模式。 接着,步骤可能包括:首先加载已有地,然后切换到纯定位模式,通过传感器数据匹配当前姿。用户可能需要调用特定的服务来初始化姿,比如通过RViz中的手动设置初始姿态,或者使用传感器数据自动匹配。 另外,需要提醒用户可能遇到的问题,比如初始置估计不准确导致重定位失败,或者需要调整配置参数以提高匹配精度。可能还需要参考Cartographer的官方文档和ROS 2的相关教程,确保步骤正确。 最后,要组织回答的结构,分步骤说明如何在ROS 2中配置Cartographer进行重定位,包括必要的服务调用、参数设置和工具使用,同指出注意事项和常见问题解决方法。需要确保语言清晰,步骤详细,帮助用户逐步操作。</think>在ROS 2中使用Cartographer进行重定位的实现步骤如下: ### 一、核心原理 Cartographer重定位依赖于预先构好的子地(submap)和实传感器数据匹配。其本质是通过关闭SLAM模式,切换为纯定位模式(`POSE_TRACKING`),利用已有地进行姿推算。 ### 二、配置步骤 1. **加载已有地** ```bash ros2 service call /load_state cartographer_ros_msgs/srv/LoadState "{filename: 'map.pbstream'}" ``` 需提前将构好的地保存为`.pbstream`格式 2. **启动纯定位模式** 修改`backpack_2d.lua`配置文件: ```lua POSE_GRAPH.optimize_every_n_nodes = 0 # 关闭持续优化 TRAJECTORY_BUILDER.pure_localization = true # 启用纯定位 TRAJECTORY_BUILDER.trajectory_builder_2d.submaps.num_range_data = 35 # 调整子地匹配范围 ``` 3. **设置初始姿** ```bash ros2 topic pub /initialpose geometry_msgs/msg/PoseWithCovarianceStamped " header: frame_id: 'map' pose: pose: position: {x: 1.0, y: 2.0, z: 0.0} orientation: {z: 0.7071, w: 0.7071} " ``` 可通过RViz的`2D Pose Estimate`工具手动设置 ### 三、关键ROS 2接口 | 服务/话题 | 类型 | 功能 | |---------|------|-----| | `/finish_trajectory` | cartographer_ros_msgs/srv/FinishTrajectory | 结束在轨迹 | | `/write_state` | cartographer_ros_msgs/srv/WriteState | 地保存 | | `/get_trajectory_states` | cartographer_ros_msgs/srv/GetTrajectoryStates | 查询轨迹状态 | ### 四、调试技巧 1. 可视化验证: ```bash ros2 launch cartographer_ros occupancy_grid_node_launch.py ``` 2. 检查匹配质量: ```bash ros2 topic echo /scan_matched_points2 ``` 3. 调整关键参数: - `TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight` - `POSE_GRAPH.constraint_builder.min_score` ### 五、常见问题处理 1. **定位漂移**: - 检查IMU数据同步性 - 增大`TRAJECTORY_BUILDER_2D.submaps.num_range_data` 2. **初始化失败**: - 确保初始姿误差小于子地尺寸的1/2 - 调整`POSE_GRAPH.constraint_builder.fast_correlative_scan_matcher`参数 议结合Cartographer的离线工具分析定位质量: ```bash cartographer_pbstream -pbstream_filename=map.pbstream ``` 注意:ROS 2 Humble版本对Cartographer的参数接口有更新,需确认使用的版本配置文件兼容。
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值