Cartographer 1.xy_index

博客讨论了Cartographer中XYRANGFINDER的实现,它是基于输入迭代器的。文章提到了C++17中可能淘汰的iterator_category,并引用了关于迭代器的cppreference资源。此外,还介绍了用于栅格地图建索引的Eigen::Array2i,包括min_xy_index_, max_xy_index_和xy_index_,以及cell的边界和索引管理。" 112633693,10294011,CCD与CMOS图像传感器:一场技术较量,"['图像传感器', 'CCD技术', 'CMOS技术', '工业自动化', '智能硬件']

/*
 * Copyright 2016 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CARTOGRAPHER_MAPPING_2D_XY_INDEX_H_
#define CARTOGRAPHER_MAPPING_2D_XY_INDEX_H_

#include <algorithm>
#include <cmath>
#include <iostream>
#include <iterator>

#include "Eigen/Core"
#include "cartographer/common/math.h"
#include "cartographer/common/port.h"
#include "cartographer/mapping_2d/proto/cell_limits.pb.h"
#include "glog/logging.h"

namespace cartographer {
namespace mapping_2d {

struct CellLimits {
  CellLimits() = default;
  CellLimits(int init_num_x_cells, int init_num_y_cells)
      : num_x_cells(init_num_x_cells), num_y_cells(init_num_y_cells) {}

  explicit CellLimits(const proto::CellLimits& cell_limits)
      : num_x_cells(cell_limits.num_x_cells()),
        num_y_cells(cell_limits.num_y_cells()) {}

  int num_x_cells = 0;
  int num_y_cells = 0;
};//

inline proto::CellLimits ToProto(const CellLimits& cell_limits) {
  proto::CellLimits result;
  result.set_num_x_cells(cell_limits.num_x_cells);
  result.set_num_y_cells(cell_limits.num_y_cells);
  return result;
}

// Iterates in row-major order through a range of xy-indices.
class XYIndexRangeIterator
    : public std::iterator<std::input_iterator_tag, Eigen::Array2i> {
 public:
  // Constructs a new iterator for the specified range.
  XYIndexRangeIterator(const Eigen::Array2i& min_xy_index,
                       const Eigen::Array2i& max_xy_index)
      : min_xy_index_(min_xy_index),
        max_xy_index_(max_xy_index),
        xy_index_(min_xy_index) {}

  // Constructs a new iterator for everything contained in 'cell_limits'.
  explicit XYIndexRangeIterator(const CellLimits& cell_limits)
      : XYIndexRangeIterator(Eigen::Array2i::Zero(),
                             Eigen::Array2i(cell_limits.num_x_cells - 1,
                                            cell_limits.num_y_cells - 1)) {}

  XYIndexRangeIterator& operator++() {
    // This is a necessary evil. Bounds checking is very expensive and needs to
    // be avoided in production. We have unit tests that exercise this check
    // in debug mode.
    DCHECK(*this != end());
    if (xy_index_.x() < max_xy_index_.x()) {
      ++xy_index_.x();
    } else {
      xy_index_.x() = min_xy_index_.x();
      ++xy_index_.y();
    }
    return *this;
  }

  Eigen::Array2i& operator*() { return xy_index_; }

  bool operator==(const XYIndexRangeIterator& other) const {
    return (xy_index_ == other.xy_index_).all();
  }

  bool operator!=(const XYIndexRangeIterator& other) const {
    return !operator==(other);
  }

  XYIndexRangeIterator begin() {
    return XYIndexRangeIterator(min_xy_index_, max_xy_index_);
  }

  XYIndexRangeIterator end() {
    XYIndexRangeIterator it = begin();
    it.xy_index_ = Eigen::Array2i(min_xy_index_.x(), max_xy_index_.y() + 1);
    return it;
  }

 private:
  Eigen::Array2i min_xy_index_;
  Eigen::Array2i max_xy_index_;
  Eigen::Array2i xy_index_;
};

}  // namespace mapping_2d
}  // namespace cartographer

#endif  // CARTOGRAPHER_MAPPING_2D_XY_INDEX_H_

我渐渐发现,代码不用注释,关键是里面一些轮子和原理我是没了解清楚的 那么的话 直接附上轮子原理,再加上总结
应该比较合适


1.


注释也要stateofart ,也没有个document的东西。

这个XYRANGFINDER是继承std::iterator的public

1.

input_iterator_tag

一个类,提供返回类型的iterator_category代表输入迭代器的函数。

结构 input_iterator_tag {};

类别标记类的用法与编译算法选择的相似。 模板函数需要查找其迭代器参数的最特定类别,以便它可以在编译时使用最高效的算法。 类型的每个迭代器Iteratoriterator_traits &lt; Iterator &gt; :: iterator_category必须定义的最具体的类别标记,用于描述迭代器的行为。

类型等同于迭代器&lt; Iter&gt; :: iterator_categoryIter描述一个对象来充当输入迭代器。

其实就是用来选迭代器的


std::iterator<std::input_iterator_tag, Eigen::Array2i>

https://en.cppreference.com/w/cpp/iterator/iterator 这是关于迭代器的类似操作

而且这个好像在c++17要被淘汰了

https://eigen.tuxfamily.org/dox/group__QuickRefPage.html

Eigen::Array2i quick reference 

这个应该是二位的整形数组

这个就是为栅格地图建索引的。

  Eigen::Array2i min_xy_index_;
  Eigen::Array2i max_xy_index_;

  Eigen::Array2i xy_index_;

  int num_x_cells = 0;
  int num_y_cells = 0;

每个cell的bound 和index

-- Copyright 2016 The Cartographer Authors -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. include "map_builder.lua" include "trajectory_builder.lua" options = { map_builder = MAP_BUILDER, trajectory_builder = TRAJECTORY_BUILDER, map_frame = "map", tracking_frame = "imu_link", published_frame = "base_link", odom_frame = "odom", provide_odom_frame = true, publish_frame_projected_to_2d = false, -- use_pose_extrapolator = on, use_odometry = false, use_nav_sat = false, use_landmarks = false, num_laser_scans = 1, num_multi_echo_laser_scans = 0, num_subdivisions_per_laser_scan = 1, num_point_clouds = 0, lookup_transform_timeout_sec = 0.2, submap_publish_period_sec = 0.3, pose_publish_period_sec = 5e-3, trajectory_publish_period_sec = 30e-3, rangefinder_sampling_ratio = 1., odometry_sampling_ratio = 1., fixed_frame_pose_sampling_ratio = 1., imu_sampling_ratio = 1., landmarks_sampling_ratio = 1., } MAP_BUILDER.use_trajectory_builder_2d = true TRAJECTORY_BUILDER_2D.submaps.num_range_data = 35 TRAJECTORY_BUILDER_2D.min_range = 0.3 TRAJECTORY_BUILDER_2D.max_range = 8. TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1. TRAJECTORY_BUILDER_2D.use_imu_data = true TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.1 TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.translation_delta_cost_weight = 10. TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.rotation_delta_cost_weight = 1e-1 TRAJECTORY_BUILDER.collate_landmarks = on POSE_GRAPH.optimization_problem.huber_scale = 1e2 POSE_GRAPH.optimize_every_n_nodes = 35 POSE_GRAPH.constraint_builder.min_score = 0.65 return options 给我改
07-28
<think>我们正在讨论如何修改Cartographer的Lua配置文件。根据引用[1],我们知道这些配置文件通常位于工作空间的`src/cartographer/configuration_files`目录中,包括`map_builder.lua`、`trajectory_builder.lua`等。 用户可能希望调整建图(map_builder)和轨迹构建(trajectory_builder)的参数。以下是一个典型的Lua配置文件示例(如`backpack_2d.lua`)的结构: ```lua include "map_builder.lua" include "trajectory_builder.lua" options = { map_builder = MAP_BUILDER, trajectory_builder = TRAJECTORY_BUILDER, map_frame = "map", tracking_frame = "base_link", published_frame = "base_link", odom_frame = "odom", provide_odom_frame = true, publish_frame_projected_to_2d = false, use_odometry = true, use_nav_sat = false, use_landmarks = false, num_laser_scans = 1, num_multi_echo_laser_scans = 0, num_subdivisions_per_laser_scan = 1, num_point_clouds = 0, lookup_transform_timeout_sec = 0.2, submap_publish_period_sec = 0.3, pose_publish_period_sec = 5e-3, trajectory_publish_period_sec = 30e-3, rangefinder_sampling_ratio = 1., odometry_sampling_ratio = 1., fixed_frame_pose_sampling_ratio = 1., imu_sampling_ratio = 1., landmarks_sampling_ratio = 1., } MAP_BUILDER.use_trajectory_builder_2d = true TRAJECTORY_BUILDER_2D.submaps.num_range_data = 35 TRAJECTORY_BUILDER_2D.min_range = 0.3 TRAJECTORY_BUILDER_2D.max_range = 8. TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1. TRAJECTORY_BUILDER_2D.use_imu_data = false TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.1 TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.translation_delta_cost_weight = 10. TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.rotation_delta_cost_weight = 1e-1 POSE_GRAPH.optimization_problem.huber_scale = 1e2 POSE_GRAPH.optimize_every_n_nodes = 35 POSE_GRAPH.constraint_builder.min_score = 0.65 return options ``` ### 关键参数调整指南 #### 1. **地图构建参数 (MAP_BUILDER)** - `use_trajectory_builder_2d`:设置为`true`表示使用2D轨迹构建器(如果是3D则使用`use_trajectory_builder_3d`)[^1]。 - `num_background_threads`:后台线程数,用于加速计算(默认0,表示使用硬件线程数)[^1]。 #### 2. **轨迹构建参数 (TRAJECTORY_BUILDER_2D)** - `submaps.num_range_data`:每个子图包含的雷达数据帧数(默认90,减少可加快子图生成但降低精度)[^1]。 - `min_range`/`max_range`:有效雷达测距范围(单位:米)[^1]。 - `use_imu_data`:是否使用IMU数据(如果使用则设为`true`)[^1]。 - `motion_filter.max_time_seconds`:运动过滤时间阈值(避免静止时产生过多数据)[^1]。 - `ceres_scan_matcher.translation_weight`:Ceres扫描匹配中平移分量的权重(值越大表示越信任平移)[^1]。 #### 3. **位姿图参数 (POSE_GRAPH)** - `optimize_every_n_nodes`:每累积多少节点进行一次全局优化(默认90,减小可提高精度但增加计算量)[^1]。 - `constraint_builder.min_score`:闭环检测的最小分数阈值(0.55~0.75,值越高闭环越严格)[^1]。 ### 修改示例:提高建图精度 ```lua -- 增加子图分辨率(默认0.05米/像素) TRAJECTORY_BUILDER_2D.submaps.resolution = 0.03 -- 增加Ceres扫描匹配迭代次数(默认25) TRAJECTORY_BUILDER_2D.ceres_scan_matcher.ceres_solver_options.max_num_iterations = 50 -- 放宽闭环检测阈值(更易触发闭环) POSE_GRAPH.constraint_builder.min_score = 0.55 ``` ### 注意事项 1. **参数单位**:距离参数单位为米,角度参数单位为弧度。 2. **参数依赖**:修改一个参数可能影响其他参数(如增加分辨率需同步调整`max_range`)。 3. **性能平衡**:高精度参数(如小分辨率、高频优化)会导致计算量剧增[^3]。 ### 调试建议 - 启动时添加`--logtostderr`参数查看实时日志: ```bash ros2 launch cartographer_ros demo_backpack_2d.launch.py --logtostderr ``` - 检查日志中的`Realtime pose extrapolation is`提示,确保实时性满足要求[^1]。 §§相关问题§§ 1. 如何调整Cartographer参数以适应低性能硬件? 2. Cartographer中如何融合IMU数据? 3. 如何验证修改后的Lua配置是否生效? 4. Cartographer的闭环检测原理是什么?[^4] 5. 如何为Cartographer添加自定义传感器?</think>### Cartographer Lua 配置文件参数修改指南 #### 一、核心配置文件结构 Cartographer 的 Lua 配置文件通常包含以下关键部分(以 `backpack_2d.lua` 为例): ```lua include "map_builder.lua" -- 地图构建参数[^1] include "trajectory_builder.lua" -- 轨迹构建参数[^1] options = { map_builder = MAP_BUILDER, trajectory_builder = TRAJECTORY_BUILDER, map_frame = "map", tracking_frame = "base_link", published_frame = "base_link", odom_frame = "odom", provide_odom_frame = true, use_odometry = true, -- 是否使用里程计数据 num_laser_scans = 1, -- 激光雷达数量 ... } -- 地图构建参数调整 MAP_BUILDER.use_trajectory_builder_2d = true MAP_BUILDER.num_background_threads = 4 -- 后台线程数[^3] -- 2D轨迹构建参数 TRAJECTORY_BUILDER_2D = { min_range = 0.3, -- 最小有效测距(m) max_range = 8.0, -- 最大有效测距(m) missing_data_ray_length = 1.0, use_imu_data = false, ... } -- 位姿图参数 POSE_GRAPH = { optimize_every_n_nodes = 90, -- 每N个节点全局优化一次 constraint_builder = { min_score = 0.55, -- 闭环检测最小分数阈值 ... } } ``` #### 二、关键参数调整说明 ##### 1. **地图构建参数 (`map_builder.lua`)** | 参数 | 默认值 | 作用 | 调整建议 | |------|--------|------|----------| | `use_trajectory_builder_2d` | `true` | 使用2D/3D模式 | 2D建图设为`true`,3D设为`false`[^1] | | `num_background_threads` | `0` | 后台计算线程数 | 设为CPU核心数可加速计算[^3] | | `collate_landmarks` | `false` | 路标点融合 | 使用视觉特征时设为`true` | | `collate_fixed_frame` | `true` | 固定坐标系融合 | 通常保持`true` | ##### 2. **轨迹构建参数 (`trajectory_builder_2d.lua`)** ```lua TRAJECTORY_BUILDER_2D = { submaps = { num_range_data = 90, -- 子图包含的雷达帧数 resolution = 0.05, -- 子图分辨率(m/像素) }, ceres_scan_matcher = { translation_weight = 10, -- 平移权重 rotation_weight = 40, -- 旋转权重 }, motion_filter = { max_time_seconds = 5, -- 运动过滤时间阈值 } } ``` - **精度调整**: - 提高分辨率:`resolution = 0.03`(更精细但增加计算量) - 增加扫描匹配权重:`translation_weight = 15`(提高位姿稳定性) - **性能优化**: - 减少子图数据量:`num_range_data = 60`(降低内存占用) - 放宽运动过滤:`max_time_seconds = 8`(减少关键帧数量) ##### 3. **位姿图优化 (`pose_graph.lua`)** ```lua POSE_GRAPH.optimization_problem = { huber_scale = 1e1, -- Huber损失函数系数 acceleration_weight = 1e3, -- IMU加速度权重 rotation_weight = 3e5, -- 旋转权重 } POSE_GRAPH.constraint_builder = { loop_closure_rotation_weight = 1e5, -- 闭环旋转权重 max_constraint_distance = 15.0, -- 最大闭环搜索距离(m) } ``` - **闭环优化**: - 增加闭环灵敏度:`min_score = 0.5`(更易触发闭环) - 扩大搜索范围:`max_constraint_distance = 20.0` #### 三、参数修改最佳实践 1. **增量调整**:每次只修改1-2个参数,通过ROS2日志观察效果: ```bash ros2 launch cartographer_ros demo_backpack_2d.launch.py ``` 2. **性能监控**:使用`top`命令查看CPU占用,确保不超过硬件负载 3. **验证工具**:通过`cartographer_occupancy_grid_node`生成地图验证精度 4. **自定义参数**:在节点选项中添加自定义参数(参考引用[2]): ```cpp struct NodeOptions { bool use_custom_filter; // 自定义过滤开关 double max_scan_range; // 自定义扫描范围 } ``` #### 四、典型场景配置示例 **高速移动机器人配置:** ```lua TRAJECTORY_BUILDER_2D.motion_filter = { max_distance_meters = 0.2, -- 降低运动触发阈值 max_angle_radians = math.rad(1), max_time_seconds = 0.5 -- 缩短时间阈值 } POSE_GRAPH.optimize_every_n_nodes = 30 -- 增加优化频率 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值