【ROS学习】移动机器人建模仿真(1)
最近实验室的项目中用到了ROS,所以就学了一些。前期先将ROS官网中的基本教程了解了一遍,对于它大体有了一些基本的认识。本文主要是实现一个移动机器人3D URDF建模,其中添加了相机信息和2D雷达信息采集装置,在Gazebo中做仿真实验。
3D URDF建模
移动机器人包括主体,两个*、一个万向轮、相机模块和2D雷达模块。
接下来我们先要建立ROS工作空间mycar_ws,
cd
mkdir mycar_ws
cd mybcar_ws
catkin init
mkdir src
catkin_make
echo "source ~/mycar_ws/devel/setup.bash" >> ~/.bashrc
在工作空间中建立mycar_description功能包,命令如下:
cd src
catkin_create_pkg mycar_description roscpp rospy #加入这两个依赖项便于后期用Python或C++写相应的代码
在所建立的mycar_description功能包中,创建urdf文件夹,并在其中分别创建mycar.xacro、mycar.gazebo、mycar_materials.xacro这三个文本。
- mycar.xacro:是这三者中主要部分,将来负责读取其他两个文本中的内容,并在这个文本中用URDF描述这个移动机器人。
- mycar.gazebo:这个文件运用特定的gazebo标签对移动机器人模型进行包装,使其可以在Gazebo中进行仿真。
- mycar_materials.xacro:这个文件夹负责对移动机器人外观进行修饰。
这三个文件具体内容如下:
mycar.xacro
<?xml version='1.0'?>
<robot name="mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="cameraSize" value="0.05"/>
<xacro:property name="cameraMass" value="0.1"/>
<xacro:include filename="$(find mycar_description)/urdf/mycar.gazebo" />
<xacro:include filename="$(find mycar_description)/urdf/mycar_materials.xacro" />
<link name='chassis'>
<pose>0 0 0.1 0 0 0</pose>
<inertial>
<mass value="10.0"/>
<origin xyz="0.0 0 0.1" rpy=" 0 0 0"/>
<inertia
ixx="0.5" ixy="0" ixz="0"
iyy="1.0" iyz="0"
izz="0.1"
/>
</inertial>
<collision name='collision'>
<geometry>
<box size=".4 .2 .1"/>
</geometry>
</collision>
<visual name='chassis_visual'>
<origin xyz="0 0 0" rpy=" 0 0 0"/>
<geometry>
<box size=".4 .2 .1"/>
</geometry>
</visual>
<collision name='caster_collision'>
<origin xyz="-0.15 0 -0.05" rpy=" 0 0 0"/>
<geometry>
<sphere radius="0.05"/>
</geometry>
<surface>
<friction>
<ode>
<mu>0</mu>
<mu2>0</mu2>
<slip1>1.0</slip1>
<slip2>1.0</slip2>
</ode>
</friction>
</surface>
</collision>
<visual name='caster_visual'>
<origin xyz="-0.15 0 -0.05" rpy=" 0 0 0"/>
<geometry>
<sphere radius="0.05"/>
</geometry>
</visual>
</link>
<link name="left_wheel">
<!--origin xyz="0.1 0.13 0.1" rpy="0 1.5707 1.5707"/-->
<collision name="collision">
<origin xyz="0 0 0" rpy="0 1.5707 1.5707"/>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
</collision>
<visual name="left_wheel_visual">
<origin xyz="0 0 0" rpy="0 1.5707 1.5707"/>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
</visual>
<inertial>
<origin xyz="0 0 0" rpy="0 1.5707 1.5707"/>
<mass value="5"/>
<cylinder_inertia m="5" r="0.1" h="0.05"/>
<inertia
ixx="1.0" ixy="0.0" ixz="0.0"
iyy="1.0" iyz="0.0"
izz="1.0"/>
</inertial>
</link>
<link name="right_wheel">
<!--origin xyz="0.1 -0.13 0.1" rpy="0 1.5707 1.5707"/-->
<collision name="collision">
<origin xyz="0 0 0" rpy="0 1.5707 1.5707"/>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
</collision>
<visual name="right_wheel_visual">
<origin xyz="0 0 0" rpy="0 1.5707 1.5707"/>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
</visual>
<inertial>
<origin xyz="0 0 0" rpy="0 1.5707 1.5707"/>
<mass value="5"/>
<cylinder_inertia m="5" r="0.1" h="0.05"/>
<inertia
ixx="1.0" ixy="0.0" ixz="0.0"
iyy="1.0" iyz="0.0"
izz="1.0"/>
</inertial>
</link>
<joint type="continuous" name="left_wheel_hinge">
<origin xyz="0.1 0.15 0" rpy="0 0 0"/>
<child link="left_wheel"/>
<parent link="chassis"/>
<axis xyz="0 1 0" rpy="0 0 0"/>
<limit effort="100" velocity="100"/>
<joint_properties damping="0.0" friction="0.0"/>
</joint>
<joint type="continuous" name="right_wheel_hinge">
<origin xyz="0.1 -0.15 0" rpy="0 0 0"/>
<child link="right_wheel"/>
<parent link="chassis"/>
<axis xyz="0 1 0" rpy="0 0 0"/>
<limit effort="100" velocity="100"/>
<joint_properties damping="0.0" friction="0.0"/>
</joint>
<link name="camera">
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="${cameraSize} ${cameraSize} ${cameraSize}"/>
</geometry>
</collision>
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="${cameraSize} ${cameraSize} ${cameraSize}"/>
</geometry>
<material name="green"/>
</visual>
<inertial>
<mass value="${cameraMass}" />
<origin xyz="0 0 0" rpy="0 0 0"/>
<box_inertia m="${cameraMass}" x="${cameraSize}" y="${cameraSize}" z="${cameraSize}" />
<inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" />
</inertial>
</link>
<joint name="camera_joint" type="fixed">
<axis xyz="0 1 0" />
<origin xyz=".2 0 0" rpy="0 0 0"/>
<parent link="chassis"/>
<child link="camera"/>
</joint>
<joint name="hokuyo_joint" type="fixed">
<axis xyz="0 1 0" />
<origin xyz=".15 0 .1" rpy="0 0 0"/>
<parent link="chassis"/>
<child link="hokuyo"/>
</joint>
<!-- Hokuyo Laser -->
<link name="hokuyo">
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="0.1 0.1 0.1"/>
</geometry>
</collision>
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<mesh filename="package://mycar_description/meshes/hokuyo.dae"/>
</geometry>
</visual>
<inertial>
<mass value="1e-5" />
<origin xyz="0 0 0" rpy="0 0 0"/>
<inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" />
</inertial>
</link>
</robot>
mycar.gazebo
<?xml version="1.0"?>
<robot>
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<legacyMode>false</legacyMode>
<alwaysOn>true</alwaysOn>
<updateRate>20</updateRate>
<leftJoint>left_wheel_hinge</leftJoint>
<rightJoint>right_wheel_hinge</rightJoint>
<wheelSeparation>0.4</wheelSeparation>
<wheelDiameter>0.1</wheelDiameter>
<torque>20</torque>
<commandTopic>mycar/cmd_vel</commandTopic>
<odometryTopic>odom</odometryTopic>
<odometryFrame>odom</odometryFrame>
<robotBaseFrame>chassis</robotBaseFrame>
</plugin>
</gazebo>
<gazebo reference="chassis">
<material>Gazebo/Orange</material>
</gazebo>
<gazebo reference="left_wheel">
<material>Gazebo/Blue</material>
</gazebo>
<gazebo reference="right_wheel">
<material>Gazebo/Blue</material>
</gazebo>
<gazebo reference="camera">
<material>Gazebo/Green</material>
<sensor type="camera" name="camera1">
<update_rate>30.0</update_rate>
<camera name="head">
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>800</width>
<height>800</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
</camera>
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
<alwaysOn>true</alwaysOn>
<updateRate>0.0</updateRate>
<cameraName>mycar/camera1</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>
</sensor>
</gazebo>
<!-- hokuyo -->
<gazebo reference="hokuyo">
<!-- <sensor type="gpu_ray" name="head_hokuyo_sensor"> -->
<sensor type="ray" name="head_hokuyo_sensor">
<pose>0 0 0 0 0 0</pose>
<visualize>true</visualize>
<update_rate>40</update_rate>
<ray>
<scan>
<horizontal>
<samples>720</samples>
<resolution>1</resolution>
<min_angle>-1.570796</min_angle>
<max_angle>1.570796</max_angle>
</horizontal>
</scan>
<range>
<min>0.1</min>
<max>30.0</max>
<resolution>0.01</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<!-- <plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_gpu_laser.so"> -->
<plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_laser.so">
<topicName>/mycar/laser/scan</topicName>
<frameName>hokuyo</frameName>
</plugin>
</sensor>
</gazebo>
</robot>
mycar_materials.xacro
<?xml version="1.0"?>
<robot>
<material name="black">
<color rgba="0.0 0.0 0.0 1.0"/>
</material>
<material name="blue">
<color rgba="0.0 0.0 0.8 1.0"/>
</material>
<material name="green">
<color rgba="0.0 0.8 0.0 1.0"/>
</material>
<material name="grey">
<color rgba="0.2 0.2 0.2 1.0"/>
</material>
<material name="orange">
<color rgba="${255/255} ${108/255} ${10/255} 1.0"/>
</material>
<material name="brown">
<color rgba="${222/255} ${207/255} ${195/255} 1.0"/>
</material>
<material name="red">
<color rgba="0.8 0.0 0.0 1.0"/>
</material>
<material name="white">
<color rgba="1.0 1.0 1.0 1.0"/>
</material>
</robot>
接着在这个功能包中创建launch文件夹,在其中创建mycar.launch。这个文件是用于启动Gazebo仿真器并将创建好的移动机器人模型载入其中。
mycar.launch
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<arg name="world" default="empty"/>
<arg name="paused" default="false"/>
<arg name="use_sim_time" default="true"/>
<arg name="gui" default="true"/>
<arg name="headless" default="false"/>
<arg name="debug" default="false"/>
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(find mycar_description)/worlds/mycar.world"/>
<arg name="paused" value="$(arg paused)"/>
<arg name="use_sim_time" value="$(arg use_sim_time)"/>
<arg name="gui" value="$(arg gui)"/>
<arg name="headless" value="$(arg headless)"/>
<arg name="debug" value="$(arg debug)"/>
</include>
<param name="robot_description" command="$(find xacro)/xacro.py '$(find mycar_description)/urdf/mycar.xacro'"/>
<node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
args="-urdf -param robot_description -model mybot" />
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
</launch>
<arg name="world_name" value="$(find mycar_description)/worlds/mycar.world"/> 这一句代码的意思是去mycar_description包的worlds文件夹中找mycar.world文件。所以在这里我们需要在mycar_description功能包中创建worlds文件夹,并在其中创建mycar.world文件。
mycar.world
<?xml version="1.0" ?>
<sdf version="1.4">
<!-- We use a custom world for the rrbot so that the camera angle is launched correctly -->
<world name="default">
<include>
<uri>model://ground_plane</uri>
</include>
<include>
<uri>model://sun</uri>
</include>
<gui fullscreen='0'>
<camera name='user_camera'>
<pose>4.927360 -4.376610 3.740080 0.000000 0.275643 2.356190</pose>
<view_controller>orbit</view_controller>
</camera>
</gui>
</world>
</sdf>
建立完这些文件之后,对工作空间进行编译,具体操作如下:
cd ~/mycar_ws
catkin_make
source devel/setup.bash
roslaunch mycar_descripition mycar.launch
未完待续。。。
上一篇: Webots+ROS学习记录(3)——四轮移动机器人
下一篇: Android平台 串口232通讯