在使用cartographer的纯定位工作模式下,默认机器人的起点位姿位map坐标系原点位姿。
如果当机器人启动定位launch时不在初始位置附近,cartograpeher默认从map坐标系原点位姿附近开始搜索,当地图较大时重定位会花费较多时间,甚至失败。
因此,本文通过修改cartograpeher源码的方式,修改定位模式的初始位姿,从而达到快速重定位的目的。
主要借鉴了博文: https://blog.csdn.net/weixin_43259286/article/details/106643625
的方法,但其中有些小错误,对此稍作修改。
把大象装进冰箱,总共需要三步:
在cartographer_ros/cartographer_ros/cartographer_ros文件夹下找到node_main.cc,在其头部添加头文件和rosparam参数获取函数:
#include "cartographer_ros/msg_conversion.h"
template<typename T>
T getParam_Func(ros::NodeHandle& pnh,
const std::string& param_name, const T & default_val)
{
T param_val;
pnh.param<T>(param_name, param_val, default_val);
return param_val;
}
这一部分主要是获取launch文件中的参数。
然后,在void Run()函数中,在 Node node(node_options, std::move(map_builder), &tf_buffer,FLAGS_collect_metrics);
这一行下面添加如下代码:
// 获取轨迹配置项指针
auto trajectory_options_handle = &(trajectory_options); //原博文这里少了个auto
ros::NodeHandle pnh("~");
// 获取配置参数
bool localization = getParam_Func<bool>(pnh, "/localization", 0); //是否为纯定位模式
double pos_x = getParam_Func<double>(pnh, "/set_inital_pose_x", 0.0);
double pos_y = getParam_Func<double>(pnh, "/set_inital_pose_y", 0.0);
double pos_z = getParam_Func<double>(pnh, "/set_inital_pose_z", 0.0);
double pos_ox = getParam_Func<double>(pnh, "/set_inital_pose_ox", 0.0);
double pos_oy = getParam_Func<double>(pnh, "/set_inital_pose_oy", 0.0);
double pos_oz = getParam_Func<double>(pnh, "/set_inital_pose_oz", 0.0);
double pos_ow = getParam_Func<double>(pnh, "/set_inital_pose_ow", 1.0);
geometry_msgs::Pose init_pose;
init_pose.position.x = pos_x;
init_pose.position.y = pos_y;
init_pose.position.z = pos_z;
init_pose.orientation.x = pos_ox;
init_pose.orientation.y = pos_oy;
init_pose.orientation.z = pos_oz;
init_pose.orientation.w = pos_ow;
if(localization == true)
{
//更改轨迹配置项中的初始位姿值
*trajectory_options_handle->trajectory_builder_options.mutable_initial_trajectory_pose()->mutable_relative_pose()
= cartographer::transform::ToProto(cartographer_ros::ToRigid3d(init_pose));
}
这一部分为更改初始位姿,pos_x … pos_ow分别对应初始位姿的x,y,z和四元数。bool localization 判断是否为纯定位模式,原博文中没有此项,但若不添加这一判断会导致建图时报错。
在launch文件头部添加:
<param name="/localization" type="bool" value = "1"/>
<param name="/set_inital_pose_x" type="double" value = "0"/>
<param name="/set_inital_pose_y" type="double" value = "0"/>
<param name="/set_inital_pose_z" type="double" value = "0.0"/>
<param name="/set_inital_pose_ox" type="double" value = "0.0"/>
<param name="/set_inital_pose_oy" type="double" value = "0.0"/>
<param name="/set_inital_pose_oz" type="double" value = "0"/>
<param name="/set_inital_pose_ow" type="double" value = "1"/>
其中把x,y,z,ox,oy,oz,ow改成你想设定的初值即可。这里由于是纯定位模式的launch文件,故设置localization为1,在建图的launch文件中添加
<param name="/localization" type="bool" value = "0"/>
即可。
cd到cartographer的文件夹下,catkin_make_isolated --install --use-ninja.
亲测如果给定一个与真实位置相差不大的初值,重定位会比不修改快很多。如果地图很大的话或许会更明显。
参考:https://blog.csdn.net/weixin_43259286/article/details/106643625