jjzjj

【Gazebo/ROS】阿克曼小车仿真环境设置中的心得体会

全日制学生混 2023-08-17 原文

最近科研需要在gazebo中做一个阿克曼小车的仿真,要求小车运动能够通过话题来控制,小车上要安装激光雷达、imu、相机等传感器用于SLAM定位建图。由于是第一次接触gazebo仿真,所以分享一下学习心得:

一、优秀资源

1\ 这位up做了现成的阿克曼小车模型,并出了视频演示运行效果 【模型代码】 【演示链接】

2\ 这位up出了一个从零搭建阿克曼小车的视频,让我弄懂了1\中代码的框架 【教学视频】

3\ 这位博主分享了自己对于gazebo与ROS联合进行小车仿真步骤的深入理解 【深入博文】

4\ 这里有一个开源的非平坦地面路径规划链路的项目,至此我基本理解完整过程 【开源项目】

二、心得体会

1\ 关于 .world的加载

如果world用到的模型全都是官方model,那么只需要把官方的model库下载下来,存到.gazebo的models下面就行了,但如果有些model是你自己定义的,例如自己定义的地图、障碍物等,那么你必须把对应的model文件放入.gazebo的models下面,当然,你也可以用prefix来设定gazebo对model的搜索路径,具体操作在13\

2\ 启动gazebo

roslaunch gazebo_ros emputy_world.launch 打开一个空白世界(直接输入gazebo也能打开gazebo软件,但是二者有区别的)

3\ 界面技巧

在gazebo中的view中,可以查看碰撞体积、等可视化

4\ 在环境中添加model

下面这句话是使用模型产生器spawn_model在gazebo中添加模型:<node name="spawn_model" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" args="-urdf -x $(arg x) -y $(arg y) -z $(arg z) -model $(arg robot_name) -param robot_description"/>

其中,robot_description为:<param name="robot_description" command="$(find xacro)/xacro '$(arg urdf_robot_file)' roboname:='smart'" />

5\ 用topic简单控制gazebo中的小车动起来

如果想用rostopic控制gazebo里的小车动起来,在基本模型显示的基础上(empty_world + spawn_model + urdf_description),需要作的改动是:(1)在urdf中添加相应joint的transmission,从而定义joint的执行器类型 (2)在urdf中添加gazebo_ros_control插件(plugin),从而建立起外部控制gazebo中执行器的桥梁 (3)写一个config.yaml文件,来说明各joint的控制器和pid控制参数 (4)在roslaunch中,用controller_spawner功能生成一个控制器,并把控制器和urdf中定义的执行其连接在一起(根据config.yaml中的名字链接) ;当然如果想要实现这些功能,还要下载这些库才行:
    1. sudo apt install ros-melodic-gazebo-ros-control
    2. sudo apt install ros-melodic-ros-control
    3. sudo apt install ros-melodic-ros-controllers

6\ 获取car_model的状态

gazebo能够发布各joint的状态信息(主要是tf关系),如果想在5\的基础上,获取gazebo中,小车速度、姿态和位置,那么就需要在5/的基础上作以下操作:(1)在urdf中加joint_state_publisher插件(plugin),从而把joint和publisher关联在一起 (2)在roslaunch中,用robot_state_publisher功能生成一个状态发布器,从而实现对相关joint状态信息的发布 (3)在rostopic list中,找到“gazebo/model_states”话题,话题的组织形式是:列表[model1,model2,...] + pose + velocity,其中pose和velocity中会按照列表中model的顺序,分别给出,因此在接收这个话题消息后,首先要做的就是找到想要知道的model的index,然后根据index,索引到对应model的pose和velocity,然后进行重新发布即可 (4)上述操作的实质就是:gazebo可以发布其中所有model的pose和velocity,然后我们定义一个node节点,接受这个topic然后,定义回调函数来筛选所需信息,并且publish出自己想发布的信息就行了。

7\ 在urdf中添加gazebo中的额外属性

通常情况下,我们还会用<gazebo reference=“xxx”> 给机器人的xxx零件加上额外的属性,如摩擦力、颜色等,这些可以加在urdf中,到时候作为spawn_model的-param description传入模型

8\ 使用mesh模型

当我们想把更加好看的外部mesh模型作为机器人的一部分时,我们常使用<mesh filename="package://package_name/meshes/xxx.dae"/>来代替原来visual中的geometry中的box或者cylinder,注意这里的package://package_name相当于launch中的 $(find package_name)

9\ 根据阿克曼的输入(速度和打角)解算四轮的转速和转角

在5\的基础上,实现实现对车辆的话题控制(可以使用C++,也可以使用python,这里使用pyhton):(1)总的思路是生成一个发布话题的节点,接收我们发布的小车速度和转角的话题命令,并将之分解为小车四轮的转速和转角 (2)根据阿克曼模型,对模型的输入量为:小车后轮速度 和 小车中轴线处的虚拟车轮的打角;(3)处理输入量1:给打角加限制。根据轴距和车轮间距,可由实际车轮的最大打角半径,算出输入量中的最大打角 (4)处理输入量2:将车速转换为后轮角速度。后轮的线速度就是车速,要换算成后轮的角速度,才能后发送给后轮的执行器 (5)判断输入打角是否为0:如果为0,那就很简单,直接给前轮发送0角度,给后轮发送输入处理量2——后轮角速度 (6)判断输入打角是否为0:如果不为0,首先根据输入处理量2——后轮角速度由半径比例拓展到两个后轮的角速度(内圈慢,外圈快);然后根据前轮的actan值,得到两个前轮的打角;另,如果前轮也有驱动力,也可以根据前轮转弯半径和车速计算出两个前轮的驱动角速度 (7)将各轮的控制量按照对应的msgs格式发送到对应的话题就行了。

10\ 阿克曼模型的核心

在其他量已知的情况下,打角和转弯半径是相互决定的,知道其中一个,即可求另一个

11\ 在rviz中看到小车

想要在rviz中看到gazebo中的汽车模型和相关信息,最重要的是要关注tf坐标变换:(1)打开空白rviz,加入robotmodel,在参数服务器中填入事先写好的param(已在launch中定义好了,放在参数服务器中,叫做robot_description:<param name="robot_description" command="$(find xacro)/xacro '$(arg urdf_robot_file)' roboname:='smart'" />)  (2)使用rosrun rqt_tf_tree rqt_tf_tree查看当前tf树,发现没有/world坐标系,因此需要创建一个tf.TransformBroadcaster来广播world和base_link的关系,这个位置关系是随时间发生变化的,因此还要读取小车的位置和姿态(这个位置和姿态是6\中,最初由joint_state_publisher发布全体model,后续经过自定义节点发布的car_model的PoseStamped,我们只需要把这个消息接受起来,然后使用回调函数,把这个位姿信息当成world和baselink的关系广播出来即可) (3)在rviz中,将Fixed Frame设置为/world,即可在rviz中显示小车在world坐标系下的运动(如果想要显示小车的Pose,那么记得把5\中发布的car_model信息的frame_id 设置为 '/world'

12\ 踩坑

在重构代码时遇到各种各样样的问题,主要是以下几点

(1)urdf和xaro文件中,不能有中文注释,如果要写了,那就要加utf-8:<?xml version="1.0" encoding="utf-8"?>(2)对于那些fixed的joint,直接在launch中写一个robot_state_publisher就行了,但是如果还有其他运动型joint,就需要在xacro中插入joint_state_publisher的plugin,并把想要输出的tf的jointname写上去逗号\回车隔开,且其中最需要注意的是namespace要对应上,对于fixed,publisher默认输出的位置是/joint_states,而对于运动型,是在urdf中的plugin中决定的,robotNamespace+/joint_states,一定要把两者对应起来,否则会变成两颗tf树,无法在rviz中完整显示(具体可看这篇博文https://blog.csdn.net/blue_skyLZW/article/details/112394119) (3)在controller的config.ymal文件中,旋转joint不配置pid参数是可以的,只会报红然后生成一个理想控制器,但摆动joint如果不定义pid参数,会直接无法生成控制器,最好都把pid参数放进去,当然二者的存放方式要根据 (4)出现小车在地面慢慢滑动的问题:在车轮joint上加入摩擦力标签来让小车在零输入时稳定下来 <dynamics damping="0.0" friction="1.0"/> (5)小车打角、轮子转动出现较大波动,考虑两个问题:激光雷达等传感器点束过于密集,导致卡顿;控制器的pid参数需要调整(在config.yaml中调整) (6)出现[TF_REPEATED_DATA ignoring data with redundant timestamp for frame base_footprint at time...]的warning信息:??? (7)出现车轮跟不上车体运动的情况:??? 【目前6和7可以通过直接world->baselink解决,但是到basefootprint我不知道要怎么弄了】(8)激光雷达采样点过于密集引起卡顿:这个暂时还没有好的办法,只能减少采样点数和缩短最大投射距离

13\ 将模型放在本地

在工作空间存放模型(考虑到模型的可移植性),步骤是:(1)在功能包package中建立一个models文件夹,然后把model文件都存在这个文件夹中 (2)在功能包的配置文件package.xml中的<export>标签中,加入<gazebo_ros gazebo_model_path="${prefix}/models"/> (解释一下,环境变量${prefix}表示指的是package.xml所在位置的路径信息)(3)此外,如果这个package.xml是自动生成的,还需要加上<depend>gazebo_ros</depend>和<exec_depend>gazebo</exec_depend> (4)改完package.xml要catkin_make以下才能生效 (5)当然,也可以使用另外的方式加载模型,但本方法是最推荐的。其他方法的参考链接放在这里【https://blog.csdn.net/benchuspx/article/details/116404058】

有关【Gazebo/ROS】阿克曼小车仿真环境设置中的心得体会的更多相关文章

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

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

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  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-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  8. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  9. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  10. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

随机推荐