【移动机器人技术】cartographer定位模式下的功能开发(一):设置起始位姿

google开发的cartographer开源包,既可以用来做SLAM建图,又可以用来做纯定位。
在纯定位工作模式下,默认机器人的起点位姿位map坐标系原点位姿,如果机器人实际放置在一个固定的起始点,且此点不在map系原点,该如何操作呢?
在实时定位工作过程中,若从外部信息获取到了机器人的准确位姿,如何像move_base中的amcl模块一样,通过订阅/initialpose话题达到修正定位结果的目的呢?
本文记录了整个操作流程。

1 初始位姿的设置

本方法较笨拙,但可以实现功能。

1.1 在launch文件中设置初始位姿参数

  <param name="/set_inital_pose_x" type="double" value = "0.991371298387"/>
  <param name="/set_inital_pose_y" type="double" value = "0.011122568834"/>
  <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.0123087794108"/>
  <param name="/set_inital_pose_ow" type="double" value = "-0.999924244105"/>

注:参数名称前的“/”符号,表示该参数为全局变量,本launch文件启动的所有node都已使用。

1.2 在node文件中使用配置参数

在文件node_main.cc头部编写rosparam参数获取函数:

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;
}

在文件node_main.cc的void Run()函数中添加如下代码:

// 获取轨迹配置项指针
trajectory_options_handle = &(trajectory_options);

// 获取配置参数
ros::NodeHandle pnh("~");
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;
    
//更改轨迹配置项中的初始位姿值
*trajectory_options_handle->trajectory_builder_options.mutable_initial_trajectory_pose()->mutable_relative_pose()
    = cartographer::transform::ToProto(cartographer_ros::ToRigid3d(init_pose));

以下是源码中加载配置参数并启动新轨迹的代码:

// 开启Trajectory
if (FLAGS_start_trajectory_with_default_topics) {
  node.StartTrajectoryWithDefaultTopics(trajectory_options);
}

经过以下操作可以完成初始位姿的配置。

1.3 错误初始位姿配置案例

有些博文介绍了以下这个错误的配置方式:

  • 在launch文件中启动cartographer_node节点的参数arg选项中增加一条:
-set_inital_pose {to_trajectory_id=0,relative_pose={translation={0.0,0.0,0.},rotation={0.,0.,2.75,timestamp=0}}}
  • 在node_options.h,node_options.cc中增加函数实现带初始位姿配置

std::tuple<NodeOptions, TrajectoryOptions> LoadOptions_with_initpose(
    const std::string& configuration_directory,
    const std::string& configuration_basename,
    const std::string& init_pose_filename) {

    auto file_resolver = cartographer::common::make_unique<
    cartographer::common::ConfigurationFileResolver>(
    std::vector<std::string>{configuration_directory});
    const std::string code =
    file_resolver->GetFileContentOrDie(configuration_basename);

//   std::string initial_pose =
//     file_resolver->GetFileContentOrDie(init_pose_filename);
    std::string initial_pose = init_pose_filename;
    
    auto lua_parameter_dictionary =
    cartographer::common::LuaParameterDictionary::NonReferenceCounted(
          code, std::move(file_resolver));

    auto initial_trajectory_pose_file_resolver =
        cartographer::common::make_unique<
            cartographer::common::ConfigurationFileResolver>(
            std::vector<std::string>{configuration_directory});
    auto initial_trajectory_pose =
        cartographer::common::LuaParameterDictionary::NonReferenceCounted(
            "return " + initial_pose,
            std::move(initial_trajectory_pose_file_resolver));

  return std::make_tuple(CreateNodeOptions(lua_parameter_dictionary.get()),
                              CreateTrajectoryOptions(lua_parameter_dictionary.get(),
                                   initial_trajectory_pose.get()));
}
  • 在node_main.cc中调用此配置函数
    (1) 在文件头部分加入参数定义
    DEFINE_string(
    set_inital_pose, “”,
    “set a initial pose of new trajectory.”);
    (2) 在文件Run()函数中调用
if (!FLAGS_set_inital_pose.empty()) {
    std::tie(node_options, trajectory_options) =
   	 LoadOptions_with_initpose(FLAGS_configuration_directory, FLAGS_configuration_basename, FLAGS_set_inital_pose);
}
else
{
	std::tie(node_options, trajectory_options) =
   	 LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
}

通过以下操作,设置的是trajectory 0与trajectory 1的相对位姿关系,即纯定位的新建轨迹起点位姿与已经建图完毕的冻结状态的轨迹位姿关系。这个位姿关系的设定,会影响下面介绍的第二项功能的实现。

Cartographer 是一款 Google 开源的用于实时构建 2D 和 3D 室内地图的工具,主要用于在机器人等移动设备上进行定位和建图任务。本文将对 Cartographer 的源代码进行分析解读,以帮助读者更好地理解该工具的实现原理。 1. 源码结构 Cartographer 的源码分为多个部分,包括: - cartographer:主要代码库,包含地图构建、局部地图匹配、位姿估计等核心功能。 - cartographer_ros:ROS wrapper,将 cartographer 代码库与 ROS 框架进行了整合,提供了 ROS 接口。 - cartographer_rviz:RViz 插件,用于可视化展示地图、轨迹等信息。 - cartographer_android:Android 版本,用于在 Android 系统上运行 Cartographer。 2. 核心算法 Cartographer 采用了多种算法来实现室内地图的构建和定位,其中比较重要的算法包括: - 位姿图优化(Pose Graph Optimization):通过对传感器数据进行多次优化,得到机器人在运动过程中的位置和方向信息。 - 实时建图(Real-Time Mapping):使用激光雷达等传感器,实时获取机器人周围环境的信息,构建室内地图。 - 局部地图匹配(Local Submap Matching):将当前传感器数据与已构建的局部地图进行匹配,从而得到更准确的位置信息。 - 点云滤波(Point Cloud Filtering):将激光雷达获取的点云数据进行滤波处理,去除噪声和无效数据。 3. 关键函数解析 以下是 Cartographer 中比较重要的几个函数的解析: - cartographer/mapping/internal/pose_graph_2d.cc: PoseGraph2D::AddNode():向位姿图中添加新的节点,包括节点 ID、位姿信息等。 - cartographer/mapping/internal/pose_graph_2d.cc: PoseGraph2D::AddConstraint():向位姿图中添加新的约束,包括约束类型、起始和终止节点 ID、约束值等。 - cartographer/mapping/internal/scan_matching/ceres_scan_matcher.cc: CeresScanMatcher::Match():使用 Ceres 库实现激光雷达数据与局部地图的匹配过程。 - cartographer/mapping/internal/3d/optimization/optimization_problem_3d.cc: OptimizationProblem3D::Solve():使用 Ceres 库实现位姿图优化过程,得到机器人在运动过程中的位置和方向信息。 - cartographer/mapping/internal/3d/scan_matching/real_time_correlative_scan_matcher_3d.cc: RealTimeCorrelativeScanMatcher3D::Match():实时建图过程中使用的一种激光雷达数据与局部地图的匹配算法。 4. 开发环境 Cartographer开发环境需要使用 Google 推荐的 Bazel 构建系统,以及 C++11 编译器和 ROS 框架。具体的开发环境搭建和编译过程可以参考 Cartographer 的官方文档。 5. 总结 Cartographer 是一款非常优秀的室内地图构建和定位工具,在机器人、自动驾驶等领域有着广泛的应用。本文对 Cartographer 的源代码进行了分析解读,希望能够帮助读者更好地理解该工具的实现原理。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值