激光SLAM与ROS中,map、odom、laser_link、base_link几个坐标系和坐标转换的理解

由于SLAM过程中需要用到不同的传感器对环境进行感知和观测,而每一个传感器都应一种坐标系,所以在整个SLAM过程中涉及到非常多次的坐标变换,想要搞清楚SLAM的过程,需要对这些坐标变换有充分的理解,本文主要记录一下我对于激光SLAM中坐标变换的理解(ROS下)

在ROS中,常见的坐标系有map,odom,base_link,laser_link,下面分别对这几个坐标系之间的变换进行阐述

base_link\rightarrowlaser_link

两个坐标系的理解:

base_link一般就是指以机器人为原点的坐标系,可以直接理解成机器人本身,laser_link指以激光雷达为中心的坐标系(其余类似于imu这些装在机器人身上的传感器坐标系都类似laser_link),这两个坐标系之间的变换比较简单,一般都是静态的,因为传感器一旦安装在机器人身上就不会再发生移动,所以只需要发布一个静态的TF变换即可完成base_link到laser_link之间的变换。

 如图所示,雷达扫描到前方3m处有一个障碍物,但是对于机器人来说,该障碍物在前方的6m处,造成这个差距的原因就是两者在不同的坐标系下观测同一障碍物,坐标变换的目的就是把这种观测进行统一,要么在雷达坐标系下认为3m处有障碍,要么在机器人坐标系下认为6m处有障碍。

坐标变换何时用到?

当机器人身上的传感器采集到数据时,这些数据都是位于各个传感器坐标系下的,比如雷达通过icp算法得到的行进里程,如果想要在世界坐标下绘制机器人的运动轨迹,就需要用到laser_link到base_link的坐标变换,把里程数据从雷达坐标系转换到机器人坐标系,再逐层向odom和map进行转换。

谁来发布?

一般由我们直接编写静态坐标变换来发布

odom\rightarrowbase_link

两个坐标系的理解:

odom是里程计坐标系,在这个坐标系下已经可以描述机器人的运动了,由机器人里程计发布的信息转换到odom坐标系后,就能够直观的反映机器人的运动里程。odom与base_link之间的坐标变换就由里程计进行发布。机器人运动的时候,是相对于odom这个系在运动,机器人往前运动了10m,是指在odom这个系上运动了10m,但是注意odom和map这两个坐标系不是重合的,要知道机器人在map上运动了多少,还需要做一个odom到map的转换。odom和map不重合的原因就是存在误差,在odom上前进了10m是传感器测出来的,但是真实移动的距离不一定是10m。

坐标变换何时用到?

机器人的里程计,如雷达等,通过icp等算法获得了机器人在两帧数据之间的运动(x,y,theta),把一段时间内的(x,y,theta)进行累加,就获得了这段时间内机器人的运动轨迹和里程,但是(x,y,theta)是传感器得到的,处于laser_link下,所以需要转换到base_link再转换到odom才能够得到相应的轨迹和里程。

谁来发布?

一般由里程计发布

map\rightarrowodom

两个坐标系的理解:

map是世界坐标,一般我们就站在map的角度观测机器人的运动,机器人在SLAM过程中建立的地图也是在map坐标系下的,ROS中机器人的运动可以理解成发布从base_link\rightarrowmap的坐标变换,让base_link在map中动起来,map到base_link的坐标转换是被定位模块计算出来的。但定位模块并不发布map到base_link的转换,相反它先接受从odom到base_link的转换, 再计算并广播map到odom的位置转换关系,是一个间接的过程。

坐标变换何时用到?

map主要在建图时用到,建图的过程实际上就是在map中的正确位置扫描周围信息,建立栅格地图的过程,而正确的位置,就是通过把odom中的位置变换到map中得到的。

谁来发布?

一般由定位模块进行发布

代码中如何体现坐标变换?

在代码中,一般通过tf这个库来进行坐标变换的处理,通过建立一个变换矩阵T来存储两个坐标系之间的坐标变换,在进行坐标变换时,遵循以下步骤:

  1. 把数据转换为TF所需要的格式,从TF中创建一个容器V存储这个数据
  2. 通过乘以变换矩阵T的方式进行坐标变换,V(base_link) = V(laser_link) * T(laser_link to base_link)
  3. 得到V(base_link)后再把数据从TF格式转换为原始格式,供进一步处理

举例:

  tf2::Transform corr_ch;
 
    if (output_.valid)
    {
        // 将雷达数据转换为TF格式数据corr_ch_1
        tf2::Transform corr_ch_l;
        CreateTfFromXYTheta(output_.x[0], output_.x[1], output_.x[2], corr_ch_l);
 
        // 将雷达坐标系下的数据 转换成 base_link坐标系下
        corr_ch = base_to_laser_ * corr_ch_l * laser_to_base_;
 
        // 将base_link坐标系下的数据,转换到odom坐标系下
        base_in_odom_ = base_in_odom_keyframe_ * corr_ch;
   
    }

<launch> <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping" output="screen"> <!-- Frame names --> <param name="pub_map_odom_transform" value="true"/> <param name="map_frame" value="map" /> <param name="base_frame" value="base_link" /> <param name="odom_frame" value="base_link" /> <!-- Tf use --> <param name="use_tf_scan_transformation" value="true"/> <param name="use_tf_pose_start_estimate" value="false"/> <!-- Map size / start point --> <param name="map_resolution" value="0.05"/> <param name="map_size" value="512"/> <param name="map_start_x" value="0.5"/> <param name="map_start_y" value="0.5" /> <param name="laser_z_min_value" value = "-1.0" /> <param name="laser_z_max_value" value = "1.0" /> <param name="map_multi_res_levels" value="2" /> <param name="map_pub_period" value="2" /> <param name="laser_min_dist" value="0.4" /> <param name="laser_max_dist" value="5.5" /> <param name="output_timing" value="false" /> <param name="pub_map_scanmatch_transform" value="true" /> <!--<param name="tf_map_scanmatch_transform_frame_name" value="scanmatcher_frame" />--> <!-- Map update parameters --> <param name="update_factor_free" value="0.4"/> <param name="update_factor_occupied" value="0.7" /> <param name="map_update_distance_thresh" value="0.2"/> <param name="map_update_angle_thresh" value="0.06" /> <!-- Advertising config --> <param name="advertise_map_service" value="true"/> <param name="scan_subscriber_queue_size" value="5"/> <param name="scan_topic" value="scan"/> </node> <node pkg="tf" type="static_transform_publisher" name="base_to_laser_broadcaster" args="0 0 0 0 0 0 /base_link /laser 100"/> <node pkg="rviz" type="rviz" name="rviz" args="-d $(find hector_slam_launch)/rviz_cfg/mapping_demo.rviz"/> </launch>解析一下这上面的代码
最新发布
03-27
<think>好的,我现在需要解析ROS中hector_mapping相关的launch文件配置及参数含义。首先,我应该回顾一下用户提供的引用内容,看看里面有没有相关的信息。引用[1]提到在launch文件里给Hector_Mapping设置参数,并提到可以通过ROS index查找参数。引用[4]给出了一个launch文件的示例,里面包含了hector_mapping节点的配置一些参数引用的路径,比如why_slam.launchhector.rviz。引用[2][3]主要涉及启动Hector_Mapping建图功能的步骤,但可能参数设置的详细内容在引用[1][4]中更相关。 接下来,我需要整理Hector_Mapping的常见参数节点配置。根据ROS官方文档,Hector_Mapping的参数可能包括地图分辨率、更新频率、扫描匹配参数等。例如,map_size、map_resolution、update_factor_freeupdate_factor_occupied这些参数会影响地图的生成更新。此外,base_frameodom_frame的设置也很重要,它们定义了传感器里程计的坐标系。 在launch文件中,通常使用<node>标签来启动hector_mapping节点,并指定参数。引用[4]中的例子展示了如何包含其他launch文件,以及如何配置节点参数。可能需要使用<param>标签或在参数服务器中加载参数文件。比如,<param name="map_resolution" value="0.05"/>这样的设置。 用户可能还想知道如何调整建图性能,比如处理计算负载或优化地图更新策略。例如,pub_map_odom_transform参数控制是否发布地图到里程计的变换,这对导航可能有影响。scan_topic参数指定激光雷达的话题名称,需要实际发布的话题一致。 此外,引用[1]提到通过ROS index查找参数,所以建议用户参考ROS官方文档或Hector_Mapping的wiki页面获取完整参数列表详细说明。在回答中需要将这些参数分类,比如基础配置、地图参数、扫描匹配参数等,并举例说明典型的配置值及其影响。同时,要确保LaTeX格式的正确应用,例如数学表达式用$...$包裹,独立公式用$$...$$。 最后,生成的相关问题需要围绕参数调整、性能优化、坐标系设置、其他SLAM算法的比较等方面展开。例如,如何优化Hector_Mapping的实时性,或者gmapping的区别适用场景。 需要确保回答结构清晰,分点说明参数配置,并正确引用提供的资料,比如引用[1][4]中的launch文件示例。同时,检查是否有遗漏的重要参数或配置步骤,确保信息的准确性实用性。</think>### ROS hector_mapping launch文件配置及参数详解 #### 一、节点基础配置 在launch文件中,`hector_mapping`节点的标准配置如下: ```xml <node name="hector_mapping" pkg="hector_mapping" type="hector_mapping" output="screen"> <param name="base_frame" value="base_link"/> <!-- 机器人坐标系 --> <param name="odom_frame" value="odom"/> <!-- 里程计坐标系 --> <param name="map_frame" value="map"/> <!-- 地图坐标系 --> <param name="scan_topic" value="scan"/> <!-- 激光雷达话题名称 --> </node> ``` 通过`<param>`标签可覆盖默认参数,例如坐标系名称需实际硬件配置一致[^4]。 #### 二、关键参数分类说明 1. **地图参数** - `map_size`:地图尺寸(单位:米),默认值$2048$(对应$2048 \times 2048$像素) - `map_resolution`:地图分辨率(米/像素),典型值$0.05$,计算公式: $$地图实际宽度 = map\_size \times map\_resolution$$ - `map_start_x`/`map_start_y`:地图初始中心点偏移量 2. **扫描匹配参数** - `update_factor_free`:空闲区域置信度更新系数,默认$0.4$ - `update_factor_occupied`:占用区域置信度更新系数,默认$0.9$ - `map_update_distance_thresh`:地图更新的最小位移阈值,默认$0.4$米 - `map_update_angle_thresh`:地图更新的最小旋转阈值,默认$0.9$弧度 3. **输出可视化** - `pub_map_odom_transform`:是否发布`map`到`odom`的坐标变换,默认$true$ - `pub_drawings`:是否发布可视化边界框,默认$true$ - `pub_map_scanmatch_transform`:是否发布扫描匹配后的位姿,默认$true$[^1] #### 三、高级参数示例 ```xml <param name="map_resolution" value="0.025"/> <!-- 提高地图精度 --> <param name="update_factor_free" value="0.3"/> <!-- 降低空闲区域更新速度 --> <param name="laser_min_dist" value="0.4"/> <!-- 忽略0.4米内的激光数据 --> <param name="laser_max_dist" value="30.0"/> <!-- 忽略30米外的激光数据 --> ``` #### 四、其他组件的联动 通过`<include>`标签可整合其他功能包: ```xml <include file="$(find why_simulation)/launch/why_slam.launch"/> <!-- 加载传感器配置 --> <node name="rviz" pkg="rviz" type="rviz" args="-d $(find why_simulation)/rviz/hector.rviz"/> <!-- 可视化界面 --> ``` 此配置实现了传感器数据接入实时建图可视化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值