技巧 §
- 多屏显示时启动Gazebo:Gazebo将出现在鼠标指针所在的那块屏幕上
- 重置模拟状态
rosservice call /gazebo/reset_simulation "{}"
Launch file §
- 使用ROS launch
- 参数
- 默认启动后即开始仿真,可以通过参数使得其启动后暂停
<arg name="paused" value="false"/>
- 是否显示界面
<arg name="gui" value="true"/>
*.world file §
<?xml version="1.0" ?>
<sdf version="1.5">
<world name="default">
<include>
<uri>model://ground_plane</uri>
</include>
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://obstacle</uri>
<name>obstacle_1</name>
<pose>0 0 0 0 0 0</pose>
</include>
<include>
<uri>model://obstacle</uri>
<name>obstacle_2</name>
<pose>0 0 1 0 0 0</pose>
</include>
<include>
<uri>model://robot</uri>
<name>robot</name>
<pose>-2.0 1.0 0 0 0 0</pose>
</include>
</world>
</sdf>
- SDF与URDF的关系:
- URDF描述机器人,SDF描述机器人以外的外部世界
- 若在
.world
文件中对模型配置了<pose>
属性,它将覆盖模型的sdf中的<pose>
属性
传感器 §
添加相机 §
- 参考教程
- 在world文件中添加相机:
<?xml version='1.0' encoding='utf-8'?>
<sdf version="1.5">
<model name='camera1'>
<static>true</static>
<pose>1 0 0.3 0 0 3.1415926</pose>
<link name='link'>
<visual name='visual'>
<geometry>
<box>
<size>0.1 0.1 0.1</size>
</box>
</geometry>
</visual>
<sensor name='camera1' type='camera'>
<camera>
<save enabled="false">
<path>/tmp/camera_save</path>
</save>
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>1920</width>
<height>1080</height>
</image>
<clip>
<near>0.1</near>
<far>100</far>
</clip>
</camera>
<always_on>1</always_on>
<update_rate>30</update_rate>
<!--insert the plugin to convert image data to rostopic here-->
</sensor>
</link>
</model>
</sdf>
- 将相机捕获数据转发至rostopic:
在
<sensor>
中插入
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
<alwaysOn>true</alwaysOn>
<updateRate>0.0</updateRate>
<cameraName>/test_camera/camera</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>
<frameName>camera</frameName>
<hackBaseline>0.07</hackBaseline>
<distortionK1>0.0</distortionK1>
<distortionK2>0.0</distortionK2>
<distortionK3>0.0</distortionK3>
<distortionT1>0.0</distortionT1>
<distortionT2>0.0</distortionT2>
</plugin>
需使用plugin进行转发
- 在rViz中查看:
Add
->By topic
->/test_camera/camera
(topic名)->image_raw
->选择Image
,raw
开发 §
使用自定义mesh(未测试) §
- 需要在
package.xml
中定义gazebo model/mesh path路径(<export>
标签中的部分)
...
<build_depend>gazebo_dev</build_depend>
<exec_depend>gazebo_ros</exec_depend>
<exec_depend>xacro</exec_depend>
<depend>pluginlib</depend>
<depend>urdf</depend>
<export>
<!--Export gazebo models and worlds-->
<gazebo_ros gazebo_model_path="${prefix}/models"/>
<gazebo_ros gazebo_resource _path="${prefix}/worlds"/>
</export>
</package>
Gazebo直接向ROS提供的数据 §
获取运行时模型/link姿态 §
通过rostopic查看 §
- ,可以通过
/gazebo/model_states
访问模型状态,通过/gazebo/link_states
访问link状态
- 模型/link姿态数据:
gazebo_msgs.msg
中ModelStates
的格式发布于/gazebo/model_states
gazebo_msgs.msg
中LinkStates
的格式发布于/gazebo/link_states
- 分为三个部分,name,pose,twist
- 示例(修改自gazebo_link_pose.py):
#!/usr/bin/env python
import rospy
from gazebo_msgs.msg import LinkStates
from geometry_msgs.msg import Pose
class GazeboLinkPose:
link_name = ''
link_pose = Pose()
def __init__(self):
self.states_sub = rospy.Subscriber("/gazebo/link_states", LinkStates, self.callback)
def callback(self, data):
try:
...
# data.name provides the list of names
# find the index of your link by the name
# data.pose provides the list of poses (use the index here for the corresponding pose)
# data.twist provides the list of twists
except ValueError:
pass
if __name__ == '__main__':
try:
rospy.init_node('gazebo_link_pose', anonymous=True)
gp = GazeboLinkPose()
rate = rospy.Rate(10)
while not rospy.is_shutdown():
rate.sleep()
except rospy.ROSInterruptException:
pass
通过rosservice查看 §
- 参考命令为(以获取link的状态为例)
rosservice call /gazebo/get_link_state "link_name:'link_1'
reference_frame:'world'"
- 参考代码(以获取link的状态为例):
from gazebo_msgs.srv import GetLinkState
rospy.wait_for_service('/gazebo/get_link_state')
try:
read_state = rospy.ServiceProxy('/gazebo/get_link_state', GetLinkState)
state = read_state(link_name='link_1')
注:如果需要获取model的信息,需要将代码中的五处”link”替换为”model”。
实例化rospy.ServiceProxy和read_state之间不能使用try/except。
修改运行时模型/link姿态 §
- 参考:官方教程
- 修改数据使用rostopic (Gazebo Subscribed Topics)
如果只pub一次数据,不一定会被Gazebo响应。在官方教程中采用了
-r 20
这个参数(Rate=20hz,默认为10hz)。
不清楚响应的机理,实测在rostopic pub -r 20 /gazebo/set_model_state gazebo_msgs/ModelState 'YOURMESSAGE CONTENT'
之后若干秒Gazebo才有响应。
- 模型:
/gazebo/set_model_state
,数据类型gazebo_msgs/ModelState
(注意没有s)
- link:
/gazebo/set_link_state
,数据类型gazebo_msgs/LinkState
- 修改数据使用或rosservice
rospy.wait_for_service('/gazebo/set_model_state')
try:
set_state = rospy.ServiceProxy('/gazebo/set_model_state', SetModelState)
state = ModelState()
state.model_name = 'link_1'
state.pose = SOMEPOSE
print(state)
resp = set_state(state)
except rospy.ServiceException as e:
pass
参考 §