草庐IT

【cartographer_ros】七: 主要配置参数说明

CloudFlame 2023-03-28 原文

上一节介绍了路标Landmark数据的订阅和发布,各类数据的发布和订阅基本阐述完毕。

本节会介绍cartographer的主要配置参数,研究这些参数的使用和对算法的影响。

目录

1,map_builder.lua

2,pose_graph.lua

3,trajectory_builder.lua

4,trajectory_builder_2d.lua


首先还是得回到Ros运行demo(第二节)的launch脚本上。 launch脚本中可以看到demo所用的配置文件是【backpack_2d.lua】
而backpack_2d.lua在一开始通过include语句加载了map_builder和trajectory_builder的配置:

    include "map_builder.lua"
    include "trajectory_builder.lua"

所以从这两个配置文件先入手


1,map_builder.lua

从名字可以看出【map_builder.lua】是对于类MapBuilder的参数配置。具体参数如下:

include "pose_graph.lua"

MAP_BUILDER = {
  use_trajectory_builder_2d = false,		--使用2d轨迹
  use_trajectory_builder_3d = false,		--使用3d轨迹
  num_background_threads = 4,				--核心线程数
  pose_graph = POSE_GRAPH,					--位置图赋值
  collate_by_trajectory = false,			--是否根据轨迹构建修正器
}


2,pose_graph.lua

【map_builder.lua 】中引入了【pose_graph.lua】,【pose_graph.lua】是全局位姿优化。具体参数如下:

POSE_GRAPH = {
  optimize_every_n_nodes = 90, 				--每次整体优化间隔nodes数
  constraint_builder = {
    sampling_ratio = 0.3, 					--全局约束采样比率(nodes)
    max_constraint_distance = 15.,			--全局约束最大间距(当前node与当前submap之间的距离)
    min_score = 0.55,						--全局约束当前最小得分(当前node与当前submap的匹配得分)
    global_localization_min_score = 0.6,	--全局约束全局最小得分(当前node与全局submap的匹配得分)
    loop_closure_translation_weight = 1.1e4,--闭环检测平移权重
    loop_closure_rotation_weight = 1e5,		--闭环检测旋转权重
    log_matches = true,						--是否打开直方图约束
    fast_correlative_scan_matcher = {
      linear_search_window = 7.,			--fast_CSM匹配搜索距离
      angular_search_window = math.rad(30.),--fast_CSM匹配搜索角度
      branch_and_bound_depth = 7,			--fast_CSM分支定界深度
    },
    ceres_scan_matcher = {
      occupied_space_weight = 20., 			--ceres_scan匹配占据空间权重
      translation_weight = 10., 			--ceres_scan匹配平移权重
      rotation_weight = 1., 				--ceres_scan匹配旋转权重
      ceres_solver_options = {
        use_nonmonotonic_steps = true,		--是否使用梯度下降策略
        max_num_iterations = 10, 			--最大迭代次数
        num_threads = 1,					--使用线程数
      },
    },
    fast_correlative_scan_matcher_3d = {
      branch_and_bound_depth = 8,
      full_resolution_depth = 3,
      min_rotational_score = 0.77,
      min_low_resolution_score = 0.55,
      linear_xy_search_window = 5.,
      linear_z_search_window = 1.,
      angular_search_window = math.rad(15.),
    },
    ceres_scan_matcher_3d = {
      occupied_space_weight_0 = 5.,
      occupied_space_weight_1 = 30.,
      translation_weight = 10.,
      rotation_weight = 1.,
      only_optimize_yaw = false,
      ceres_solver_options = {
        use_nonmonotonic_steps = false,
        max_num_iterations = 10,
        num_threads = 1,
      },
    },
  },
  matcher_translation_weight = 5e2, 		--匹配平移约束(当前submap与在当前submap内的某个node)
  matcher_rotation_weight = 1.6e3,			--匹配旋转约束(当前submap与在当前submap内的某个node)
  optimization_problem = {
    huber_scale = 1e1, 						--Huber因子(与离群值(错误的数据)对整体的影响正相关)。
    acceleration_weight = 1e3,  			--IMU加速度的权重
    rotation_weight = 3e5, 					--IMU旋转项的权重
    local_slam_pose_translation_weight = 1e5,	--平移约束权重(前后两个node之间的局部观测与全局优化)
    local_slam_pose_rotation_weight = 1e5,	--旋转约束权重(前后两个node之间的局部观测与全局优化)
    odometry_translation_weight = 1e5,		--平移约束权重(前后两个node之阿的局部观测与里程计观测)
    odometry_rotation_weight = 1e5,			--旋转约束权重(前后两个node之阿的局部观测与里程计观测)
    fixed_frame_pose_translation_weight = 1e1, 	
    fixed_frame_pose_rotation_weight = 1e2, 	
    fixed_frame_pose_use_tolerant_loss = false, 
    fixed_frame_pose_tolerant_loss_param_a = 1, 
    fixed_frame_pose_tolerant_loss_param_b = 1, 
    log_solver_summary = false,				--是否记录Ceres全局优化的结果
    use_online_imu_extrinsics_in_3d = true,	--是否在线标定imu的外参
    fix_z_in_3d = false, 
    ceres_solver_options = {
      use_nonmonotonic_steps = false,		--是否使用梯度下降策略
      max_num_iterations = 50,				--最大迭代次数
      num_threads = 7,						--使用线程数
    },
  },
  max_num_final_iterations = 200, 			--建图结束后最终优化迭代次数
  global_sampling_ratio = 0.003, 			--全局地图匹配约束采样比率(nodes)
  log_residual_histograms = true, 			--是否输出残差直方图
  global_constraint_search_after_n_seconds = 10., 	--全局匹配间隔时长
  --  overlapping_submaps_trimmer_2d = {
  --    fresh_submaps_count = 1,
  --    min_covered_area = 2,
  --    min_added_submaps_count = 5,
  --  },
}

3,trajectory_builder.lua

从名字可以看出【trajectory_builder.lua】是对于类TrajectoryBuilder的参数配置。具体参数如下:

include "trajectory_builder_2d.lua"
include "trajectory_builder_3d.lua"

TRAJECTORY_BUILDER = {
  trajectory_builder_2d = TRAJECTORY_BUILDER_2D,		--2d轨迹赋值
  trajectory_builder_3d = TRAJECTORY_BUILDER_3D,		--3d轨迹赋值
--  pure_localization_trimmer = {
--    max_submaps_to_keep = 3,
--  },
  collate_fixed_frame = true,							--是否通过固定帧修正
  collate_landmarks = false,							--是否通过反光板修正
}


4,trajectory_builder_2d.lua

【trajectory_builder_2d.lua 】中引入了【trajectory_builder_2d.lua】【trajectory_builder_3d.lua】,两个配置内容是大致类似的,但各自有些特有参数。这里主要说明2D轨迹的参数【trajectory_builder_2d.lua】。具体参数如下:

TRAJECTORY_BUILDER_2D = {
  use_imu_data = true, 				--是否使用imu数据
  min_range = 0., 					--激光的最近距离
  max_range = 30.,					--激光的最远距离
  min_z = -0.8, 					--激光的最小高度
  max_z = 2., 						--激光的最大高度
  missing_data_ray_length = 5., 	--激光的默认数值
  num_accumulated_range_data = 1, 	--单个Node节点累积激光帧数
  voxel_filter_size = 0.025, 		--激光的网格滤波大小
  
  adaptive_voxel_filter = { 		--自适应滤波	
    max_length = 0.5, 				--网格滤波的大小
    min_num_points = 200, 			--最小点云数据
    max_range = 50., 				--最远点云距离
  },

  loop_closure_adaptive_voxel_filter = { --闭环检测自适应滤波
    max_length = 0.9, 
    min_num_points = 100, 
    max_range = 50.,
  },

  use_online_correlative_scan_matching = false, 	--是否使用CSM激光匹配
  real_time_correlative_scan_matcher = { 			--快速CSN激光匹配
    linear_search_window = 0.1, 					--平移搜索范围
    angular_search_window = math.rad(20.), 			--角度搜索范围
    translation_delta_cost_weight = 1e-1, 			--平移代价权重
    rotation_delta_cost_weight = 1e-1, 				--旋转代价权重
  },

  ceres_scan_matcher = { 							--ceres优化激光匹配
    occupied_space_weight = 1., 					--占据空间权重
    translation_weight = 10., 						--平移权重
    rotation_weight = 40., 							--旋转权重
    ceres_solver_options = { 						
      use_nonmonotonic_steps = false, 				--是否使用梯度下降策略
      max_num_iterations = 20, 						--最大迭代次数
      num_threads = 1, 								--使用线程数
    },
  },

  motion_filter = { 					--移动滤波
    max_time_seconds = 5., 				--2帧激光最小间隔
    max_distance_meters = 0.2, 			--2帧激光最小距离
    max_angle_radians = math.rad(1.), 	--2帧激光最小角度
  },

  -- TODO(schwoere,wohe): Remove this constant. This is only kept for ROS.
  imu_gravity_time_constant = 10., 		--imu的重力常数
  pose_extrapolator = { 				
    use_imu_based = false, 				--是否使用3d初始化位姿预估器
    constant_velocity = {
      imu_gravity_time_constant = 10., 	--imu的重力常数
      pose_queue_duration = 0.001,		--位姿时间间隔
    },
    imu_based = { 
      pose_queue_duration = 5., 		--位姿时间间隔
      gravity_constant = 9.806, 		--重力常数
      pose_translation_weight = 1.,		--位姿偏移权重
      pose_rotation_weight = 1., 		--位姿旋转权重
      imu_acceleration_weight = 1., 	--IMU加速度权重
      imu_rotation_weight = 1., 		--IMU旋转权重
      odometry_translation_weight = 1., --里程计平移权重
      odometry_rotation_weight = 1., 	--里程计旋转权重
      solver_options = { 
        use_nonmonotonic_steps = false;
        max_num_iterations = 10;
        num_threads = 1;
      },
    },
  },

  submaps = { 
    num_range_data = 90, 				--子图中Node的数量
    grid_options_2d = {
      grid_type = "PROBABILITY_GRID", 	--概率栅格地图
      resolution = 0.05, 				--分辨率
    },
    range_data_inserter = { 
      range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D",
      probability_grid_range_data_inserter = {
        insert_free_space = true,		--是否改变改变占用网格中的概率。
        hit_probability = 0.55, 		--hit(占用) 时的概率
        miss_probability = 0.49,		--miss(空闲) 时的概率
      },
      tsdf_range_data_inserter = {
        truncation_distance = 0.3,
        maximum_weight = 10.,
        update_free_space = false,
        normal_estimation_options = {
          num_normal_samples = 4,
          sample_radius = 0.5,
        },
        project_sdf_distance_to_scan_normal = true,
        update_weight_range_exponent = 0,
        update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.5,
        update_weight_distance_cell_to_hit_kernel_bandwidth = 0.5,
      },
    },
  },
}

以上就是cartographer中的主要配置参数,这里只是简单的介绍说明,要更加深入的了解还需要到实际案例中使用或者查看其在代码中的功能作用。

【完】


下一节就结合demo案例一起说明,在Ros中使用这些参数时实际的配置及效果。

有关【cartographer_ros】七: 主要配置参数说明的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  4. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  5. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  6. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  7. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  8. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  9. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  10. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

随机推荐