自主导航系列9-/odom

自主导航系列9-/odom

主要学习有关move_base的launch文件的常用node与launch

1,成员node

gmapping包,我们不赘述了

<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen" >

move_base参数设置

<node pkg="move_base" type="move_base" respawn="false" name="move_base_node" output="screen">
    <param name="footprint_padding" value="0.01" />
    <param name="controller_frequency" value="5.0" />
    <param name="controller_patience" value="3.0" />
    <param name="oscillation_timeout" value="30.0" />
    <param name="oscillation_distance" value="0.5" />
    <param name="planner_patience" value="1" />
    <param name="controller_patience" value="1" /> 
    <!-- move base -->
    <remap from="cmd_vel" to="mobile_base/commands/velocity"/>
    <param name="recovery_behavior_enabled" value="false" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/base_local_planner_params.yaml" command="load" />  
    <param name="global_costmap/global_frame" value="$(arg namespace)/map"/>
    <param name="global_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="global_costmap/laser_scan_sensor/sensor_frame" value="/$(arg namespace)/base_laser_link"/>
    <param name="global_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>    
    <param name="local_costmap/global_frame" value="$(arg namespace)/odom"/>
    <param name="local_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="local_costmap/laser_scan_sensor/sensor_frame" value="$(arg namespace)/base_laser_link"/>
    <param name="local_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
    <param name="local_costmap/obstacle_layer/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
  </node>

大部分的参数都在四个.yaml文件里设置好了,具体的设置见这里

各种参数可以在rosparam dump之中查询,

2,有关/odom

有关坐标系的部分

  • map:地图坐标系,顾名思义,一般设该坐标系为固定坐标系(fixed frame),一般与机器人所在的世界坐标系一致。

  • base_link:机器人本体坐标系,与机器人中心重合,当然有些机器人(PR 2)是base_footprint,其实是一个意思。

  • odom:里程计坐标系,这里要区分开odom topic,这是两个概念,一个是坐标系,一个是根据编码器(或者视觉等)计算的里程计。但是两者也有关系,odom topic 转化得位姿矩阵是odom-->base_link的tf关系。这时可有会有疑问,odom和map坐标系是不是重合的?可以很肯定的告诉你,机器人运动开始是重合的。但是,随着时间的推移是不重合的,而出现的偏差就是里程计的累积误差。那map-->odom的tf怎么得到?就是在一些校正传感器合作校正的package比如amcl会给出一个位置估计(localization),这可以得到map-->base_link的tf,所以估计位置和里程计位置的偏差也就是odom与map的坐标系偏差。所以,如果你的odom计算没有错误,那么map-->odom的tf就是0.

  • base_laser:激光雷达的坐标系,与激光雷达的安装点有关,其与base_link的tf为固定的。

以上是参考的CSDN,说一说我自己的理解

比如说我现在算出来了一个一维的坐标X=10(odom-->base_link),但是这个位置的真实坐标应该是X'=2(map-->base_link),也就是说我计算的坐标和真实坐标出现了偏差。但是ROS在说的时候换了个说法,不说计算出来的坐标在map中漂了8,而是说是odom坐标系相对于map坐标系漂了8。所以此时base_link相对odom坐标是真实坐标x=2(因为odom坐标系短时间是准确的,如果是刚开始时odom和map重合,odom中的该坐标就是真实坐标);odom相对于map坐标是driftX=8(map-->odom);最后计算出来的base_link相对于map的坐标就是X=drixfX+X'=10了。

如果用IMU作积分的话,通过IMU获得的是odom坐标系下的坐标,初始时odom和map重合,都为0。那么短时间内,由于IMU的漂移很小,所以获得的位移deltaX是准确的,最终的在odom坐标系下的坐标是X=dextaX,在map中的坐标X'也是deltaX。但是时间长了之后,IMU积分开始产生漂移driftX了,最终在map下的坐标X=deltaX+driftX。由于我们定义IMU在短时间内产的的位移deltaX是准确的,所以deltaX是就是IMU在odom坐标系下的真实位移,但是此时odom相对于map则漂移了driftX。

所以odom相当于是根据实际计算得到的坐标和真实坐标之间的变换虚拟出来的一个坐标系。(这里我也是参考的CSDN)

我们造在mrobot中仿真探索:

这是机器人本身发布的/tf关系

在运行gmapping包之后

可见,增加了map->odom的tf的变换关系,这是由gmapping发布的

2,imu与gmapping融合

采用robot_pose_ekf的方式,详见

robot_pose_ekf的问题

 

 

参考:move_base参数配置 ros param

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在ROS中,要订阅/odom话题,首先需要在C++或Python程序中导入相关的ROS包和消息类型。然后,通过创建一个ROS节点来订阅/odom话题。 在C++中,首先需要包括头文件,如下所示: ```cpp #include <ros/ros.h> #include <nav_msgs/Odometry.h> ``` 接下来,在main函数中初始化ROS节点,并创建一个订阅者对象来订阅/odom话题。示例代码如下: ```cpp int main(int argc, char** argv) { // 初始化ROS节点 ros::init(argc, argv, "odom_subscriber"); // 创建节点句柄 ros::NodeHandle nh; // 创建订阅者对象 ros::Subscriber sub = nh.subscribe("/odom", 10, odomCallback); // 循环处理回调函数 ros::spin(); return 0; } ``` 在上述代码中,`odomCallback`是一个回调函数,用于接收并处理消息。在该函数中,需要定义消息类型和进行相应的处理。 接下来,在回调函数中定义`odomCallback`,如下所示: ```cpp void odomCallback(const nav_msgs::Odometry::ConstPtr& msg) { // 处理接收到的消息 // 例如,打印消息的内容 ROS_INFO("Received odometry message: [%f, %f]", msg->pose.pose.position.x, msg->pose.pose.position.y); } ``` 在上述代码中,我们通过`msg`指针来访问接收到的消息的字段,如位置信息`pose`、线速度信息`twist`等。 对于Python,操作类似。首先导入需要的包和消息类型,并创建一个订阅者对象。示例代码如下: ```python import rospy from nav_msgs.msg import Odometry # 回调函数 def odom_callback(msg): # 处理接收到的消息 # 例如,打印消息的内容 rospy.loginfo("Received odometry message: [%f, %f]", msg.pose.pose.position.x, msg.pose.pose.position.y) # 初始化ROS节点 rospy.init_node('odom_subscriber') # 创建订阅者对象 rospy.Subscriber("/odom", Odometry, odom_callback) # 循环处理回调函数 rospy.spin() ``` 在上述代码中,`odom_callback`是一个回调函数,用于接收并处理消息。通过`msg`对象来访问接收到的消息的字段,如位置信息`pose`、线速度信息`twist`等。 总之,在ROS中订阅/odom话题,我们需要导入相关的ROS包和消息类型,并创建一个订阅者对象来接收并处理消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值