jjzjj

ROS中map,odom坐标系的理解以及acml和robot_pose_ekf的对比和小车漂移方法解决

HGGshiwo 2023-05-02 原文

之前一直不知道odom,map到底是什么关系,看了这个博客:https://blog.csdn.net/u012686154/article/details/88174195 才了解了一些。这边记录我自己的看法,看下是否正确:

1 ROS中map,odom坐标系的理解

我想解决的问题是:计算出小车在真实世界(这个坐标系称为map)的位置

我可以得到的数据:

gazebo的传感器(比如 libgazebo_ros_diff_drive.so)会在/odom topic下面发布小车在map坐标系的坐标。但是这个坐标只是根据传感器得到的,gazebo无法保证它是正确的。

于是新增了一个概念:odom坐标系。意思是gazebo本来计算的是小车在map上的坐标,但是这个这个坐标和真实值有偏差,因此把该坐标看成小车在odom坐标系上的坐标,然后odom坐标系相对于map有相对偏差。

坐标变换从base_footprint->map 变化为了:base_footprint->odom->map

2 odom坐标系的总结

  1. 只是一个概念上的坐标系,实际不存在
  2. 如果说完全相信传感器的数据,那么可以认为odom坐标系就是map坐标系
  3. 如何计算odom坐标系相对于map坐标系的位置:首先获得差速计推算出的小车坐标p,然后使用雷达再次估算小车的位置g(此时认为g比较准确,因此认为g就是小车在map上的坐标),那么差速计得到的坐标可以看成是小车在odom的坐标+odom相对于map的偏差,因此odom在map上的坐标就是p-g

3 acml和robot_pose_ekf的区别

先说下他们的共同点:

  • 都是可以估算出robot在map上的位置。
  • 虽然它们都会在某个topic发布小车的坐标,并且发布一个tf变换。tf变换可以看成一个特殊的topic,里面说明了两个坐标系的相对位置。在实际开发中,一般直接使用这个tf变换,而不是使用发布出来的坐标。

区别是:

  • acml估算的方法是输入雷达信号,然后直接算出位置。

  • robot_pose_ekf是通过将imu信号和原来里程计估算出来的坐标整合以后算出一个新的坐标。

  • 真正计算坐标的位置,更多是通过坐标变换进行的

    • acml发布了一个map到odom的变换,
    • robot_pose_ekf发布了一个odom到base_footprint的变换

比较让人困惑的是:acml应该只是知道base_footprint到odom的坐标,它怎么知道map到odom的坐标的?

我的理解是,acml觉得自己准确率非常高,因此把自己计算出的坐标当成了map上的坐标,而通过获得base_footprint到另一个坐标系的坐标,就可以获得该坐标系到map的坐标了。现在这个坐标系被称为了odom而已。

amcl能否和robot_pose_ekf一起使用?

我的理解是可以。理论上来说,因为robot_pose_ekf算出了odom到base_link的变化,而amcl计算出的odom到map的变化其实是通过map到base_link变化得到的,(base_link->map)表示base_link相对于map的坐标,那么有:

(base_link->map) = (base_link->odom) + (odom->map)

而acml计算的odom->map:

(odom->map) = (base_link->map) - (base_link->odom)

把它代入上面,发现算出来的还是acml计算出的base_link对于map的坐标,而base_link到odom的坐标不管是什么都不会产生影响。

但是实际上来说,很多包可能会用到odom坐标系,如果说不太相信里程计的话还是使用一下amcl比较好。

下面是详细解释:

从acml的描述可以看出来:

amcl transforms incoming laser scans to the odometry frame (~odom_frame_id). So there must exist a path through the tf tree from the frame in which the laser scans are published to the odometry frame.

The drawing below shows the difference between localization using odometry and amcl. During operation amcl estimates the transformation of the base frame (~base_frame_id) in respect to the global frame (~global_frame_id) but it only publishes the transform between the global frame and the odometry frame (~odom_frame_id). Essentially, this transform accounts for the drift that occurs using Dead Reckoning. The published transforms are future dated

我的理解是:acml和GPS差不多,根据雷达信息可以直接估算出机器人在map上面的坐标。但是acml提供了一个功能,就是可以指定一个别的坐标系,它帮你把map上的坐标转为该坐标系相对于map的坐标。这个坐标系一般是指定为odom。

4 小车漂移的解决方法

我的现象:小车在运动过程中一会儿飘过来,然后突然飘回去。

一开始我觉得可能是odom不准,后来把里程计坐标直接看成map上的坐标,发现小车不再飘了。于是发现是gmapping发布的map到odom的坐标不准。如果说遇到这种情况,可以按照下面的步骤排除:

  1. 如果说用的是差速计控制的小车,可以去网上找一份键盘控制小车的代码
  2. 让小车原地转圈
  3. 如果说小车原地转圈也会飘一定不是里程计的问题。事实上,如果开的不太远,里程计应该是非常准的

解决方法:

  1. 里程计不准可以使用robot_pose_ekf
  2. gmapping不准可以直接放弃使用gmapping发布坐标,完全相信里程计。就是里程计直接发布map到base_footprint的tf变换
  3. 如果是场景非常空旷,可以在场景中加入一些障碍物,不然雷达不会起效
  4. 可以把gmapping的miniScore改的小一点,甚至是负数。因为雷达在空旷的地区置信度为0,而出现一些小的障碍物就会导致置信度>0,转而使用雷达。而我们希望多使用差速计。

有关ROS中map,odom坐标系的理解以及acml和robot_pose_ekf的对比和小车漂移方法解决的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  8. 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

  9. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

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

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

随机推荐