文章目录
机器人仿真环境与物理世界环境已高度相似,在没有真实的机器人和硬件时,这是一个很好的替代工具。另外,我们可以将算法应用到实际机器人之前在仿真环境中进行验证和测试。机器人建模可以使用urdf文件或者xacro文件,复杂的机器人对应的模型文件也比较复杂,实际项目中可以使用solidworks来自动生成。这里,我们使用turtlebot3元包中已经创建好的模型文件来进行仿真。
turtlebot3功能包中包含了TurtleBot3的机器人模型、SLAM和导航功能包、遥控功能包和bringup功能包等,另一个功能包turtlebot3_simulations中包含了更丰富的仿真文件。后面将从这两个包中复制出我们需要的文件来集成,并进行仿真。
turtlebot3包下载地址:https://github.com/ROBOTIS-GIT/turtlebot3
turtlebot3_simulations包下载地址:https://github.com/ROBOTIS-GIT/turtlebot3_simulations
PS:后面步骤是从turtlebot3包中只提取需要的文件来进行集成,如果不想麻烦,也可以直接安装完整的turtlebot3功能包来使用:
使用下面命令来安装:
$ sudo apt install ros-noetic-turtlebot3
使用下面的命令来运行:
$ roscore
$ export TURTLEBOT3_MODEL=waffle_pi
$ roslaunch turtlebot3_gazebo turtlebot3_world.launch
如果运行时出现下面的错误:
libcurl: (51) SSL: no alternative certificate subject name matches target host name 'api.ignitionfuel.org'
修改~/.ignition/fuel/config.yaml文件,将其中的 https://api.ignitionfuel.org 更改为 https://api.ignitionrobotics.org即可。
进入到自己工作空间的src目录下,然后下载源代码,进行编译:
$ cd ~/catkin_ws/src
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3.git
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3_simulations.git
$ cd ~/catkin_ws/
$ catkin_make
turtlebot3有三个版本,burger、waffle和waffle_pi,其中waffle_pi版本中配备的传感器最全面,下面使用的模型文件均为此版本。

这里在项目中创建一个功能包turtlebot3_sim_test,创建时注意添加urdf、xacro、gazebo_ros依赖

PS:关于urdf的介绍,参考:http://wiki.ros.org/urdf
关于xacro的介绍,参考:http://wiki.ros.org/xacro
在turtlebot3_sim_test功能包下创建几个目录:
urdf:用来存储urdf 文件
将下载的包中turtlebot3-master/turtlebot3_description/urdf目录下turtlebot3_waffle_pi.urdf.xacro文件拷贝到robot_test_ws/src/turtlebot3_sim_test/urdf目录下,这是waffle_pi机器人的模型文件

meshes:用来存储机器人模型的渲染文件
将下载的包中turtlebot3-master/turtlebot3_description/meshes目录下的全部文件拷贝到robot_test_ws/src/turtlebot3_sim_test/meshes目录下,这是waffle_pi机器人的模型渲染文件

worlds:用来存储gazebo仿真环境文件
将下载的包中turtlebot3_simulations-master/turtlebot3_gazebo/worlds目录下的turtlebot3_house.world、turtlebot3_world.world文件拷贝到robot_test_ws/src/turtlebot3_sim_test/worlds目录下,这是已经创建好的仿真环境,如果目前电脑的配置不高或者想快速体验的话可以集成turtlebot3_world.world文件,否则建议使用turtlebot3_house.world文件,这个文件与物理环境比较相似,不过在第一次加载时需要几分钟的时间

models:用来存储gazebo仿真环境配置文件
将下载的包中turtlebot3_simulations-master/turtlebot3_gazebo/models目录下的turtlebot3_house、turtlebot3_world两个文件夹拷贝到robot_test_ws/src/turtlebot3_sim_test/models目录下,这是已经创建好的仿真环境配置文件,其中包含了gazebo中的仿真道具

rviz:用来存储rviz环境下机器人配置文件
后面使用到时再进行记录
launch:用来存储启动文件
后面使用到时再进行记录
创建完之后的完整目录如下图所示,后面仿真时会用到这些目录下的文件:

下面在turtlebot3_sim_test包中添加turtlebot3_sim_rviz.launch文件来在rviz中显示机器人模型
<launch>
<arg name="model" default="waffle_pi" />
<!-- 在参数服务器载入xacro文件 -->
<param name="robot_description" command="$(find xacro)/xacro $(find turtlebot3_sim_test)/urdf/turtlebot3_$(arg model).urdf.xacro" />
<!-- 启动rviz -->
<node name="rviz" pkg="rviz" type="rviz" />
<!-- 启动机器人状态和关节状态发布节点 -->
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
</launch>
这里加载的机器人模型文件为turtlebot3_waffle_pi.urdf.xacro,在这个xacro文件中多处引用下载的turtlebot3功能包中的turtlebot3_description目录下的文件,这里要修改成我们自己的文件路径(turtlebot3_sim_test),否则会找不到依赖文件。如果感觉麻烦的话,也可以直接将下载的turtlebot3包下的turtlebot3_description包整个复制到我们的项目中

启动launch文件
$ roslaunch turtlebot3_sim_test turtlebot3_sim_rviz.launch
启动之后rviz并没有显示机器人模型

将左上角的map更改为base_link,点击左下角的Add按钮,添加RobotModel选项后即会显示机器人模型,还可以添加TF坐标关系等

可以将已设置好的配置保存为文件,下次启动launch文件时即可自动加载配置信息,在turtlebot3_sim_test包中添加rviz文件夹,点击左上角的File->Save Config As,然后选择保存的目录,输入文件名称后,点右上角的Save按钮即可保存配置文件。上面下载的功能包turtlebot3-master/turtlebot3_description/rviz目录下有一个model.rviz的配置文件,也可以直接复制到我们的robot_test_ws/src/turtlebot3_sim_test/rviz目录下来使用

再来修改下launch文件,将启动rviz的代码修改为下面的代码,修改完之后,再次启动launch文件即可自动加载配置信息
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find turtlebot3_sim_test)/rviz/model.rviz" />
注意:在执行后面的操作之前先来修改下package.xml文件,否则会出现:waitForService: Service [/gazebo_gui/set_physics_properties] has not been advertised, waiting... Error Code 12 Msg: Unable to find uri[model://turtlebot3_house]错误
在package.xml文件中添加下面这行代码,添加的原因:打开turtlebot3_house.world文件后可以看到,其中加载仿真环境配置文件的地址默认为gazebo下的地址(/usr/share/gazebo-11/models),而并非我们项目中存放仿真环境配置文件的models目录,所以会找不到文件,报上面的错误。另外一种解决办法是,将turtlebot3_sim_test包中models下的turtlebot3_house文件夹复制到/usr/share/gazebo-11/models下
<gazebo_ros gazebo_model_path="${prefix}/models"/>

下面在turtlebot3_sim_test包中添加turtlebot3_sim_gazebo.launch文件来在gazebo中显示机器人模型
<launch>
<arg name="model" default="waffle_pi"/>
<arg name="x_pos" default="-2.0"/>
<arg name="y_pos" default="-0.5"/>
<arg name="z_pos" default="0.0"/>
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(find turtlebot3_sim_test)/worlds/turtlebot3_house.world"/>
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="headless" value="false"/>
<arg name="debug" value="false"/>
</include>
<param name="robot_description" command="$(find xacro)/xacro $(find turtlebot3_sim_test)/urdf/turtlebot3_$(arg model).urdf.xacro" />
<node pkg="gazebo_ros" type="spawn_model" name="spawn_urdf" args="-urdf -model turtlebot3_$(arg model) -x $(arg x_pos) -y $(arg y_pos) -z $(arg z_pos) -param robot_description" />
</launch>
启动launch文件
$ roslaunch turtlebot3_sim_test turtlebot3_sim_gazebo.launch
这里使用的gazebo仿真文件为turtlebot3_house.world,在第一次加载时非常慢,需要几分钟的时间,此时并不是gazebo软件卡死了,后面再加载时就可以秒开了,打开后如下图所示,这里模拟的是室内环境,其中有门、桌子等仿真物


使用roslaunch命令启动turtlebot3_sim_gazebo.launch文件之后,使用rostopic list命令来看下当前发布的话题,可以看到有一个/cmd_vel的话题,这个话题已经比较熟悉了,之前再小乌龟的示例中用到过

再来使用rostopic info /cmd_vel命令来看下话题的详细信息,可以看到gazebo订阅了这个话题,下面我们在这个话题上发布速度指令即可操作机器人模型运动

这里使用ROS提供的通用键盘控制包来操作机器人模型,如果之前没有下载的话使用下面的命令先下载安装
$ sudo apt-get install ros-noetic-teleop-twist-keyboard
参考:http://wiki.ros.org/teleop_twist_keyboard
安装完成后,使用下面的命令启动键盘控制节点,然后按照按键说明就可以控制机器人模型运动了,这个节点会在/cmd_vel话题上发布速度指令
$ roslaunch turtlebot3_sim_test turtlebot3_sim_gazebo.launch
$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py
还可以通过修改配置参数来调整运动速度或停止方式,详细内容参考:https://github.com/ros-teleop/teleop_twist_keyboard
这里通过简单的修改《ROS之手柄控制》中手柄控制小乌龟运动的示例代码,来实现手柄控制机器人模型在gazebo中运动
这里手柄控制机器人模型运动和之前手柄控制小乌龟运动只有一个简单的区别,这里发布的话题名称为/cmd_vel,小乌龟示例中发布的话题为/turtle1/cmd_vel,把小乌龟示例中发布的话题名称改为/cmd_vel,其它代码无需修改,再来分别启动下turtlebot3_sim_gazebo.launch文件和teleop_turtle.launch文件即可使用手柄控制机器人模型运动了

$ roslaunch turtlebot3_sim_test turtlebot3_sim_gazebo.launch
$ roslaunch teleop teleop_turtle.launch
Rviz是ROS的三维可视化工具,它的主要目的是以三维方式显示ROS消息,可以将数据进行可视化表达。例如,可以无需编程就能表达激光测距仪(LRF)传感器中的传感器到障碍物的距离,RealSense、Kinect或Xtion等三维距离传感器的点云数据(PCD,Point Cloud Data),从相机获取的图像值等。
Gazebo是一个仿真系统,可以模拟真实的物理环境,快速测试机器人设计、执行回归测试以及训练AI系统等相关算法的可用性。Gazebo提供了在复杂的室内和室外环境中,准确地模拟多个数量机器人的功能。Gazebo支持 ODE、Bullet、Simbody等强大的物理引擎,具备高质量的图形以及便捷的图形编程界面。
总结来说,Rviz主要用来显示数据,Gazebo用来仿真,使用实际机器人的话,Gazebo就可以不使用了,但还是需要Rviz来进行调试。
先启动下gazebo仿真环境
$ roslaunch turtlebot3_sim_test turtlebot3_sim_gazebo.launch
接着启动下rviz
$ roslaunch turtlebot3_sim_test turtlebot3_sim_rviz.launch
rviz启动后,依次加入RobotModel(机器人模型)、Odometry(里程计)、LaserScan(激光雷达)、Image(摄像头),并选择对应的话题,可以通过更改子选项来调整显示效果,这里Odometry中的Covariance选项不要勾选,否则画面会很模糊

再来运行下键盘控制节点,此时,使用键盘控制机器人模型运动即可看到里程计、雷达、摄像头数据的变化
$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py _key_timeout:=0.2

依次启动gazebo和rviz,再来启动上面记录的键盘或手柄节点即可操作机器人模型在gazebo和rviz环境下的运动

再来进一步分析下,gazebo和rviz下的运动是不同的,单独启动rviz然后运行键盘控制节点,是无法控制机器人模型运动的。gazebo仿真环境下,机器人有驱动器,其依赖/cmd_vel上的速度信息。rviz环境下,机器人运动实际上是坐标变换,依赖的是/joint_states。单独启动gazebo和rviz来看下两者发布的话题

再来看下计算图,会更清晰,单独启动gazebo

单独启动rviz

rviz中机器人模型的运动依赖turtlebot3_sim_rviz.launch文件中的一行代码,robot_state_publisher节点将机器人的状态发布到tf2
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
参考:http://wiki.ros.org/robot_state_publisher、http://wiki.ros.org/joint_state_publisher?distro=noetic
分别启动gazebo和rviz

☝ ★★★ — 返回 《ROS机器人开发笔记汇总》总目录 — ★★★ ☝
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub