1.创建一个多机器人的工作区
1.命令行创建工作区:
catkin_create_pkg multiple_robots
2.创建launch文件夹
3.创建一个main.launch于launch文件夹中
2.main.launch
2.1 加载自定义的世界
<!-- start world -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(find a309_room)/worlds/c.world"/>
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="recording" value="false"/>
<arg name="debug" value="false"/>
</include>
其中:<arg name="world_name" value="$(find a309_room)/worlds/c.world"/>
是加载自己创造的世界c.world
注:以先加载一个empty世界再导入我们自己创造的世界的方式,才可以正确加载世界,不然会有各种错误。
2.2 导入多机器人
<!-- include our robots -->
<include file="$(find multiple_robots)/launch/robots.launch"/>
导入多机器人的launch文件
3.robots.launch
3.1导入机器人的描述文件(为rviz)
<param name="robot_description"
command="$(find xacro)/xacro $(find wpr1_bringup)/urdf/wpr1.urdf" />
这里主要是为rviz提供启明机器人的模型文件(.urdf格式),用于在rviz加载,与在gazebo中加载的启明机器人文件(.model格式)是两个!
3.2 导入一个机器人
导入一个机器人后,其它的类似写即可。
3.2.1 导入机器人的描述文件(为gazebo)
<!-- BEGIN ROBOT 1-->
<group ns="/robot1">
<param name="tf_prefix" value="robot1_tf" />
<include file="$(find multiple_robots)/launch/one_robot.launch" >
<arg name="init_pose" value="-x 8.950 -y -15.4501 -z 0" />
<arg name="robot_name" value="robot1" />
<!-- 这里的名字无大碍 -->
</include>
1.<group ns="/robot1">
代表在/robot1的命名空间中加载一个机器人,加入group后,属于次空间中(robot1)的主题!主题!主题!便会在头部添加一个/robot1的标签。
此图中的主题在加了ns后,前面都会增添一个/robot1,我演示的删除之后的主题。
2. <param name="tf_prefix" value="robot1_tf" />
代表在这个工作空间下,此参数改变tf的描述,改为robot1_tf,即在原来的rviz的主题名的前面,添加了/robot1_tf这个前缀。
3.<include file="$(find multiple_robots)/launch/one_robot.launch" >
加载单个机器人的launch文件(gazebo),之后的init_pose,是为robot1添加的初始位置。
3.2.2 加载机器人的控制
<!-- load the controllers of WPR1 -->
<include file="$(find wpr_simulation)/launch/wpr1_controllers.launch">
<arg name="robot_name" value="robot1" />
</include>
加载机器人的控制部分wpr1_controllers.launch
4.one_robot.launch
<launch>
<arg name="robot_name"/>
<arg name="init_pose"/>
<node name="spawn_qiming_model" pkg="gazebo_ros" type="spawn_model"
args="-file $(find wpr_simulation)/models/wpr1.model $(arg init_pose) -urdf -model $(arg robot_name)"
respawn="false" output="screen" />
</launch>
其中最核心的就是调用gazebo_ros包中的spaen_model,这个文件可以给gazebo环境添加一个机器人,-file $(find wpr_simulation)/models/wpr1.model
这里可以是.model类型的机器人,当然我也见过加载.urdf类型的机器人,不过要改一下前面的-file。init_pose放了初始位置,robot_name代表gazebo环境中机器人的名字。
5.wpr1_controllers.launch
<launch>
<arg name="robot_name"/>
<!-- Load joint controller configurations from YAML file to parameter server -->
<rosparam file="$(find wpr_simulation)/config/wpr1_control.yaml" command="load" ns = "/$(arg robot_name)"/>
<!-- load the controllers -->
<node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen" ns="/$(arg robot_name)" args=
"
--namespace=/$(arg robot_name)
joint_state_controller
base_to_torso_position_controller
torso_to_upperarm_position_controller
upperarm_to_forearm_position_controller
forearm_to_palm_position_controller
palm_left_finger_position_controller
left_finger_tip_position_controller
palm_right_finger_position_controller
right_finger_tip_position_controller"/>
<!-- convert joint states to TF transforms for rviz, etc -->
<param name="/$(arg robot_name)/wpr1_description" textfile="$(find wpr_simulation)/models/wpr1.model" />
<node name="gazebo_wpr1_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="false" output="screen" ns="/$(arg robot_name)" >
<remap from="robot_description" to="/$(arg robot_name)/wpr1_description" />
<remap from="/joint_states" to="/$(arg robot_name)/joint_states" />
</node>
<node name="wpr1_sim" pkg="wpr_simulation" type="wpr1_sim" output="screen"/>
</launch>
5.1 加载启明机器人控制的描述文件(yaml)
<rosparam file="$(find wpr_simulation)/config/wpr1_control.yaml" command="load" ns = "/$(arg robot_name)"/>
注意!此处需要对机器人的描述文件修改,打开!
wpr1:
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 30
# Position Controllers ---------------------------------------
base_to_torso_position_controller:
type: position_controllers/JointPositionController
joint: base_to_torso
pid: {p: 1000.0, i: 150.0, d: 50.0, i_clamp_max: 500.0, i_clamp_min: -500.0}
torso_to_upperarm_position_controller:
type: position_controllers/JointPositionController
joint: torso_to_upperarm
pid: {p: 100.0, i: 0.01, d: 10.0}
upperarm_to_forearm_position_controller:
type: position_controllers/JointPositionController
joint: upperarm_to_forearm
pid: {p: 100.0, i: 0.01, d: 10.0}
forearm_to_palm_position_controller:
type: position_controllers/JointPositionController
joint: forearm_to_palm
pid: {p: 100.0, i: 0.01, d: 10.0}
palm_left_finger_position_controller:
type: position_controllers/JointPositionController
joint: palm_left_finger
pid: {p: 100.0, i: 0.01, d: 10.0}
left_finger_tip_position_controller:
type: position_controllers/JointPositionController
joint: left_finger_tip
pid: {p: 10.0, i: 0.01, d: 1.0}
palm_right_finger_position_controller:
type: position_controllers/JointPositionController
joint: palm_right_finger
pid: {p: 100.0, i: 0.01, d: 10.0}
right_finger_tip_position_controller:
type: position_controllers/JointPositionController
joint: right_finger_tip
pid: {p: 10.0, i: 0.01, d: 1.0}
#PID Gains ---------------------------------------
gazebo_ros_control:
pid_gains:
base_to_torso:
p: 1000.0
i: 150.0
d: 50.0
i_clamp_max: 500.0
i_clamp_min: -500.0
torso_to_upperarm:
p: 100.0
i: 0.01
d: 10.0
upperarm_to_forearm:
p: 100.0
i: 0.01
d: 10.0
forearm_to_palm:
p: 100.0
i: 0.01
d: 10.0
palm_left_finger:
p: 100.0
i: 0.01
d: 7.0
left_finger_tip:
p: 10.0
i: 0.01
d: 0.5
palm_right_finger:
p: 100.0
i: 0.01
d: 7.0
right_finger_tip:
p: 10.0
i: 0.01
d: 0.5
这里的第一行有一个wpr1: 这个东西会限制描述文件的命名空间,因为加载多个机器人,故将其删除就好,只删除这一行就可。
5.2 启动控制器
<!-- load the controllers -->
<node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen" ns="/$(arg robot_name)" args=
"
--namespace=/$(arg robot_name)
joint_state_controller
base_to_torso_position_controller
torso_to_upperarm_position_controller
upperarm_to_forearm_position_controller
forearm_to_palm_position_controller
palm_left_finger_position_controller
left_finger_tip_position_controller
palm_right_finger_position_controller
right_finger_tip_position_controller"/>
关于控制器的具体描述可以参考:
http://wiki.ros.org/cn/controller_manager
注意,添加命名空间,在哪个命名空间加载控制器,这个要设置好,不然怎么知道是加载的谁的控制呢?如果不设置–namespace和ns,可能会导致rviz中的机器人无法正常加载。
5.3 转化连接器部分的位置到tf,以便给rviz
<!-- convert joint states to TF transforms for rviz, etc -->
<param name="/$(arg robot_name)/wpr1_description" textfile="$(find wpr_simulation)/models/wpr1.model" />
<node name="gazebo_wpr1_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="false" output="screen" ns="/$(arg robot_name)" >
<remap from="robot_description" to="/$(arg robot_name)/wpr1_description" />
<remap from="/joint_states" to="/$(arg robot_name)/joint_states" />
</node>
1.加载启明机器人的model文件,注意要在名字前面添加命名空间 param name="/$(arg robot_name)/wpr1_description"
2.启动robot_state_publisher节点,注意要加命名空间,相当于把gazebo中的机器人的连接器(组成机器人的各个部件)的位置相对关系进行发布。
3.<remap from="robot_description" to="/$(arg robot_name)/wpr1_description" />
机器人1的命名空间,在该空间内加载了机器人模型。
4.<remap from="/joint_states" to="/$(arg robot_name)/joint_states" />
发布部件的位置信息,再次强调不要忘记添加命名空间!
5.4 机器人成功加载的检测文件
<node name="wpr1_sim" pkg="wpr_simulation" type="wpr1_sim" output="screen"/>
检测机器人是否成功加载了。
按照robot1的加载文件,添加robot2和robot3即可了
6. 检测
成功加载三个机器人。
全部代码:
这里将tf_prefix修改为和机器人命名空间同样的名称了,方便调试
1.main.launch
<launch>
<!-- start world -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(find a309_room)/worlds/c.world"/>
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="recording" value="false"/>
<arg name="debug" value="false"/>
</include>
<!-- include our robots -->
<include file="$(find multiple_robots)/launch/robots.launch"/>
</launch>
2.robots.launch
<launch>
<!-- No namespace here as we will share this description.
Access with slash at the beginning -->
<param name="robot_description"
command="$(find xacro)/xacro $(find wpr1_bringup)/urdf/wpr1.urdf" />
<!-- BEGIN ROBOT 1-->
<group ns="/robot_1">
<param name="tf_prefix" value="robot_1" />
<include file="$(find multiple_robots)/launch/one_robot.launch" >
<arg name="init_pose" value="-x 8.950 -y -15.4501 -z 0" />
<arg name="robot_name" value="robot1" />
<!-- 这里的名字无大碍 -->
</include>
<!-- load the controllers of WPR1 -->
<include file="$(find wpr_simulation)/launch/wpr1_controllers.launch">
<arg name="robot_name" value="robot_1" />
</include>
</group>
<!-- BEGIN ROBOT 2-->
<group ns="/robot_2">
<param name="tf_prefix" value="robot_2" />
<include file="$(find multiple_robots)/launch/one_robot.launch" >
<arg name="init_pose" value="-x 25.8001 -y -5.5 -z 0" />
<arg name="robot_name" value="robot2" />
<!-- 这里的名字无大碍 -->
</include>
<!-- load the controllers of WPR1 -->
<include file="$(find wpr_simulation)/launch/wpr1_controllers.launch">
<arg name="robot_name" value="robot_2" />
</include>
</group>
<!-- BEGIN ROBOT3-->
<group ns="/robot_3">
<param name="tf_prefix" value="robot_3" />
<include file="$(find multiple_robots)/launch/one_robot.launch" >
<arg name="init_pose" value="-x 4.7 -y -26.9 -z 0" />
<arg name="robot_name" value="robot3" />
<!-- 这里的名字无大碍 -->
</include>
<!-- load the controllers of WPR1 -->
<include file="$(find wpr_simulation)/launch/wpr1_controllers.launch">
<arg name="robot_name" value="robot_3" />
</include>
</group>
</launch>
3.one_robot.launch
<launch>
<arg name="robot_name"/>
<arg name="init_pose"/>
<node name="spawn_qiming_model" pkg="gazebo_ros" type="spawn_model"
args="-file $(find wpr_simulation)/models/wpr1.model $(arg init_pose) -urdf -model $(arg robot_name)"
respawn="false" output="screen" />
</launch>
4.wpr1_controllers.launch
<launch>
<arg name="robot_name"/>
<!-- Load joint controller configurations from YAML file to parameter server -->
<rosparam file="$(find wpr_simulation)/config/wpr1_control.yaml" command="load" ns = "/$(arg robot_name)"/>
<!-- load the controllers -->
<node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen" args=
"
joint_state_controller
base_to_torso_position_controller
torso_to_upperarm_position_controller
upperarm_to_forearm_position_controller
forearm_to_palm_position_controller
palm_left_finger_position_controller
left_finger_tip_position_controller
palm_right_finger_position_controller
right_finger_tip_position_controller"/>
<!-- convert joint states to TF transforms for rviz, etc -->
<param name="/$(arg robot_name)/wpr1_description" textfile="$(find wpr_simulation)/models/wpr1.model" />
<node name="gazebo_wpr1_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="false" output="screen" ns="/$(arg robot_name)" >
<remap from="robot_description" to="/$(arg robot_name)/wpr1_description" />
<remap from="/joint_states" to="/$(arg robot_name)/joint_states" />
</node>
<node name="wpr1_sim" pkg="wpr_simulation" type="wpr1_sim" output="screen"/>
</launch>
7.报错
7.1 gazebo加载机器人问题
偶尔gazebo会抽风,spawn一个机器人时出现错误,在gazebo体现的就是无法加载机器人,导致controller有问题,此时
尝试:
killall gzserver
killzll gzclient