目录

1. proto文件

2. .lua配置文件

3. 代码

1)读取lua文件

2)赋值给proto options

   获取proto参数值有两种方式:1)lua文件 2)通过service,例如如下代码中 InitialTrajectoryPose 的赋值

3)  如何使用 proto options

纯定位模式入口

我们需要掌握的是什么?要知道在哪里改变参数,从而更深入的理解算法。

TODO:

1. sensor topic 在哪里设置?

2. 自定义的一堆service 如何使用,效果如何?


系统的配置文件框架主要有三部分构成:

1. proto文件

   - 根据自己的需要,自定义proto文件。比如:我们希望 参数 A 通过配置文件来设定具体数值,则 参数A 在proto文件中被定义。

   - 一系列的proto文件 位于 cartographer/mapping/proto

   - 如何自定义proto文件呢?例如:

//如下代码取自 cartographer/mapping/proto/trajectory_builder_options.proto 

import "cartographer/mapping/proto/2d/local_trajectory_builder_options_2d.proto";
import "cartographer/mapping/proto/3d/local_trajectory_builder_options_3d.proto";

// 一组参数的集合称为options,用 message name{} 的形式定义
// options内部可以包含对个其他的options,必须import其所在的proto 如上面两行
// 也可以在内部定义新的 options 如 PureLocalizationTrimmerOptions
message TrajectoryBuilderOptions {
  LocalTrajectoryBuilderOptions2D trajectory_builder_2d_options = 1;
  LocalTrajectoryBuilderOptions3D trajectory_builder_3d_options = 2;
  InitialTrajectoryPose initial_trajectory_pose = 4;

  reserved 5;

  bool pure_localization = 3 [deprecated = true];
  message PureLocalizationTrimmerOptions {
    int32 max_submaps_to_keep = 1;
  }
  PureLocalizationTrimmerOptions pure_localization_trimmer = 6;

  bool collate_fixed_frame = 7;
  bool collate_landmarks = 8;
}

2. .lua配置文件

对应的lua配置文件:

// 代码取自 cartographer2019-05-25/configuration_files/trajectory_builder.lua

// 对应的,也要 include options 相应的lua文件
include "trajectory_builder_2d.lua"
include "trajectory_builder_3d.lua"

// 这些options的名字必须是大写,但是不必和proto中保持一致
// 但是成员变量的名字必须和proto中保持一致

TRAJECTORY_BUILDER = {
  trajectory_builder_2d = TRAJECTORY_BUILDER_2D,
  trajectory_builder_3d = TRAJECTORY_BUILDER_3D,
--  pure_localization_trimmer = {   -- 这个是定位模式
--    max_submaps_to_keep = 3,
--  },
  collate_fixed_frame = true,
  collate_landmarks = false,
}

3. 代码

主要分为如下三个步骤:

1)读取lua文件

     - 这部分不细看了

2)赋值给proto options

     其赋值主要有两种方式:
    - 1. options.set_变量名(参数值)
    - 2. options.mutable_变量名 = 参数值

   获取proto参数值有两种方式:1)lua文件 2)通过service,例如如下代码中 InitialTrajectoryPose 的赋值

// 如下代码位于: cartographer_ros/node.cc
// cartographer_ros_msgs::StartTrajectory 是自定义的service,位于cartographer_ros_msgs/srv/StartTrajectory.srv

bool Node::HandleStartTrajectory(
    ::cartographer_ros_msgs::StartTrajectory::Request& request, 
    ::cartographer_ros_msgs::StartTrajectory::Response& response) {

// 这个是在cartographer_ros/trajectory_options.h 中 自定义的类,与proto中的不同。
// 该类型包含了
// cartographer::mapping::proto::TrajectoryBuilderOptions 变量 
// 和 一些其他的topic,频率等变量(这些变量会根据数据集的不同可能会变化,因此在最外层)。
// 对应 cartographer_ros/configuration_files/backpack_2d.lua 等文件
// 这些lua文件全部       include "map_builder.lua"
//                     include "trajectory_builder.lua"
// 所以,核心的lua还是 map_builder.lua; trajectory_builder.lua
// 而 map_builder.lua; trajectory_builder.lua 又分别包含其他的很多lua 就这样一层一层的。

  TrajectoryOptions trajectory_options;

  // 将lua转换为 proto options
  // tie 可以将tuple解包,赋值给相应的参数。std::ignore 表示忽略第一个参数
  std::tie(std::ignore, trajectory_options) = LoadOptions(
      request.configuration_directory, request.configuration_basename);


  // 省略中间部分
  
  // 可以注意到:cartographer/configuration_files/trajectory_builder.lua中,
  // 并没有给InitialTrajectoryPose 这个变量赋值,虽然 proto中包含这个变量
  // 而是留到service中进行赋值

  if (request.use_initial_pose) {

  // InitialTrajectoryPose 是在 cartographer/mapping/proto/trajectory_builder_options.proto 
// 中定义的一个 options , 其赋值主要有两种方式:
// 1. options.set_变量名(参数值)
// 2. options.mutable_变量名 = 参数值
// 注意:options 也是一个成员变量,其赋值也是使用上述两种方式之一

      ::cartographer::mapping::proto::InitialTrajectoryPose
        initial_trajectory_pose;
    initial_trajectory_pose.set_to_trajectory_id(
        request.relative_to_trajectory_id);
    *initial_trajectory_pose.mutable_relative_pose() =
        cartographer::transform::ToProto(pose);
    initial_trajectory_pose.set_timestamp(cartographer::common::ToUniversal(
        ::cartographer_ros::FromRos(ros::Time(0))));
    *trajectory_options.trajectory_builder_options
         .mutable_initial_trajectory_pose() = initial_trajectory_pose;

}

}

         

3)  如何使用 proto options

   - 1. 如果想使用 options 成员变量,则先通过 has_name()来判断lua中是否给这个变量赋值了

   - 2. 直接 name()即可获得该变量的值

// 位于 map_builder.cc
int MapBuilder::AddTrajectoryBuilder(
    const std::set<SensorId>& expected_sensor_ids,
    const proto::TrajectoryBuilderOptions& trajectory_options,
    LocalSlamResultCallback local_slam_result_callback)
{
    std::unique_ptr<LocalTrajectoryBuilder2D> local_trajectory_builder;
    // 1. 如果想使用 options 成员变量,则先通过 has_name()来判断lua中是否给这个变量赋值了
    if (trajectory_options.has_trajectory_builder_2d_options()) {
      local_trajectory_builder = absl::make_unique<LocalTrajectoryBuilder2D>(
          2. 直接 name()即可获得该变量的值
          trajectory_options.trajectory_builder_2d_options(),
          SelectRangeSensorIds(expected_sensor_ids));
    }
    

    // 下面这部分同理
  if (trajectory_options.has_initial_trajectory_pose()) {
    const auto& initial_trajectory_pose =
        trajectory_options.initial_trajectory_pose();
    pose_graph_->SetInitialTrajectoryPose(
        trajectory_id, initial_trajectory_pose.to_trajectory_id(),
        transform::ToRigid3(initial_trajectory_pose.relative_pose()),
        common::FromUniversal(initial_trajectory_pose.timestamp()));
  }
 }

纯定位模式入口

// 位于文件 map_builder.cc 
void MaybeAddPureLocalizationTrimmer(
    const int trajectory_id,
    const proto::TrajectoryBuilderOptions& trajectory_options,
    PoseGraph* pose_graph) {
  if (trajectory_options.pure_localization()) {
    // 已经被弃用了,现在是改为使用pure_localization_trimmer
    LOG(WARNING)
        << "'TrajectoryBuilderOptions::pure_localization' field is deprecated. "
           "Use 'TrajectoryBuilderOptions::pure_localization_trimmer' instead.";
    pose_graph->AddTrimmer(absl::make_unique<PureLocalizationTrimmer>(
        trajectory_id, 3 /* max_submaps_to_keep */));
    return;
  }
  if (trajectory_options.has_pure_localization_trimmer()) {
    pose_graph->AddTrimmer(absl::make_unique<PureLocalizationTrimmer>(
        trajectory_id,
        trajectory_options.pure_localization_trimmer().max_submaps_to_keep()));
  }
}

// 对应的 proto : cartographer/mapping/proto/trajectory_builder_options.proto 
message TrajectoryBuilderOptions {
  LocalTrajectoryBuilderOptions2D trajectory_builder_2d_options = 1;
  LocalTrajectoryBuilderOptions3D trajectory_builder_3d_options = 2;
  InitialTrajectoryPose initial_trajectory_pose = 4;

  reserved 5;

  bool pure_localization = 3 [deprecated = true];// deprecated 被弃用
  message PureLocalizationTrimmerOptions {
    int32 max_submaps_to_keep = 1;
  }
  PureLocalizationTrimmerOptions pure_localization_trimmer = 6;

  bool collate_fixed_frame = 7;
  bool collate_landmarks = 8;
}

我们需要掌握的是什么?要知道在哪里改变参数,从而更深入的理解算法。

1. proto文件全部位于:cartographer/mapping/proto

2. lua文件:

     1)外层文件全部位于:cartographer_ros/configuration_files。 例如 backpack_2d.lua。

     2)算法相关的文件全部位于:cartographer/configuration_files

TODO:

1. sensor topic 在哪里设置?

2. 自定义的一堆service 如何使用,效果如何?