Multiple robots in ROS Gazebo SITL with separate MAVlink/MAVproxy software codes
The problem statement is in simulating ErleCopter and ErleRover simultaneously for a non-commercial research. The statement is in letting quadcopter follow the line-following rover (preferably using GPS) and the documentation has been sparse.
Can somebody consider letting me know the possibilities? I am not sure if this problem is composed of two sub-problems. First problem is in spawning the robots (URDF and Xacro files have been successfully modified to avoid significant performance on system and Copter has been spawned in line-follower environment) and the second one is in controlling both independently (and obtain the state parameters of both vehicles and use that as feedback).
Can you please let me know if two computers are really necessary for this with links to official documentation? (Lenovo-y50-70 is being used with Ubuntu 14.04; Two computers are not easy to obtain immediately though and internet connection has issues)
The following options are being considered:
- Usage of two MavProxy/MavLink channels through the modification of TCP ports.
- Usage of multiple launch files (two in this case with Rover having the 'master' port). (https://github.com/ArduPilot/MAVProxy/issues/215 and http://ardupilot.github.io/MAVProxy/html/getting_started/starting.html)
- Usage of single launch file with 'namespace' grouping.
There is no tutorial or even simplified documentation on this and this 'thread' is being created to help people facing similar problems excepting ClearPath's news-release which employs ROS's "black box" and any insight on that would help too.
So, two attempts were made to launch both. (simvehicle.sh has been modified into two files for software - simcopter.sh and simrover.sh; The $(pwd) in simcopter.sh has been hard-coded to avoid the usage of terminal and that works)
<group ns="copterErle">
<arg name="enable_logging" default="true"/>
<arg name="enable_ground_truth" default="true"/>
<arg name="log_file" default="erlecopter"/>
<arg name="headless" default="false"/>
<arg name="gui" default="true"/>
<arg name="world_name" default="$(find ardupilot_sitl_gazebo_plugin)/worlds/rover_circuit/both_circuit.world"/>
<env name="GAZEBO_MODEL_PATH" value="$(find drcsim_model_resources)/gazebo_models/environments:$(find ardupilot_sitl_gazebo_plugin)/meshes/meshes_sensors:$(find ardupilot_sitl_gazebo_plugin)/meshes/meshes_outdoor:$(find ardupilot_sitl_gazebo_plugin)/meshes/meshes_warehouse"/>
<arg name="name" default="erlecopter"/>
<arg name="model" default="$(find ardupilot_sitl_gazebo_plugin)/urdf/erlecopter_base.xacro"/>
<!--arg name="name" default="rover"/>
<arg name="model" default="$(find ardupilot_sitl_gazebo_plugin)/urdf/rover.urdf"/-->
<arg name="tf_prefix" default="$(optenv ROS_NAMESPACE)"/>
<arg name="debug" default="true"/>
<arg name="verbose" default="true"/>
<!-- Initial pose for the quad-rotor -->
<arg name="x1" default="0.0"/> <!-- [m], positive to the North -->
<arg name="y1" default="0.0"/> <!-- [m], negative to the East -->
<arg name="z1" default="0.08"/> <!-- [m], positive Up -->
<arg name="roll1" default="0"/> <!-- [rad] -->
<arg name="pitch1" default="0"/> <!-- [rad] -->
<arg name="yaw1" default="3.1415"/> <!-- [rad], negative clockwise -->
</group>
The namespace attempt which has been described above is not working properly. The problem is that the MAVproxy terminal terminates as soon as other robot is launched. (Changing INSTANCE to 1 won't roslaunch properly; It is probably port problem as I have not changed it yet; Any input on standard port numbers will be greatly appreciated)
The other attempt was to launch both 'serially' (one after another) and this didn't work either (Including the commented blocks results in argument errors).
<launch>
<arg name="simRate" default="nan"/>
<!-- Enable simulation clock -->
<param name="use_sim_time" type="bool" value="true" />
<include file="$(find mavros)/launch/apm_sitl.launch"></include>
<arg name="enable_logging" default="true"/>
<arg name="enable_ground_truth" default="true"/>
<arg name="log_file" default="erlecopter"/>
<arg name="headless" default="false"/>
<arg name="gui" default="true"/>
<arg name="world_name" default="$(find ardupilot_sitl_gazebo_plugin)/worlds/rover_circuit/both_circuit.world"/>
<env name="GAZEBO_MODEL_PATH" value="$(find drcsim_model_resources)/gazebo_models/environments:$(find ardupilot_sitl_gazebo_plugin)/meshes/meshes_sensors:$(find ardupilot_sitl_gazebo_plugin)/meshes/meshes_outdoor:$(find ardupilot_sitl_gazebo_plugin)/meshes/meshes_warehouse"/>
<arg name="name" default="erlecopter"/>
<arg name="model" default="$(find ardupilot_sitl_gazebo_plugin)/urdf/erlecopter_base.xacro"/>
<!--arg name="name" default="rover"/>
<arg name="model" default="$(find ardupilot_sitl_gazebo_plugin)/urdf/rover.urdf"/-->
<arg name="tf_prefix" default="$(optenv ROS_NAMESPACE)"/>
<arg name="debug" default="true"/>
<arg name="verbose" default="true"/>
<!-- Initial pose for the quad-rotor -->
<arg name="x1" default="0.0"/> <!-- [m], positive to the North -->
<arg name="y1" default="0.0"/> <!-- [m], negative to the East -->
<arg name="z1" default="0.08"/> <!-- [m], positive Up -->
<arg name="roll1" default="0"/> <!-- [rad] -->
<arg name="pitch1" default="0"/> <!-- [rad] -->
<arg name="yaw1" default="3.1415"/> <!-- [rad], negative clockwise -->
<!-- Initial pose for the rover
<arg name="x" default="-18.0"/>
<arg name="y" default="-13.0"/>
<arg name="z" default="0."/>
<arg name="roll" default="0"/>
<arg name="pitch" default="0"/>
<arg name="yaw" default="0"/> -->
<!-- send the robot XML to param server -->
<param name="robot_description" command="
$(find xacro)/xacro.py '$(arg model)'
enable_logging:=$(arg enable_logging)
enable_ground_truth:=$(arg enable_ground_truth)
log_file:=$(arg log_file)"
/>
<param name="tf_prefix" type="string" value="$(arg tf_prefix)" />
<!-- push robot_description to factory and spawn Copter robot in gazebo -->
<node name="spawn_erlecopter" pkg="gazebo_ros" type="spawn_model"
args="-param robot_description
-urdf
-x $(arg x1)
-y $(arg y1)
-z $(arg z1)
-R $(arg roll1)
-P $(arg pitch1)
-Y $(arg yaw1)
-model $(arg name)"
respawn="false" output="screen">
</node>
<!-- push robot_description to factory and spawn Rover robot in gazebo
<node name="spawn_rover" pkg="gazebo_ros" type="spawn_model"
args="-param robot_description
-urdf
-x $(arg x)
-y $(arg y)
-z $(arg z)
-R $(arg roll)
-P $(arg pitch)
-Y $(arg yaw)
-model $(arg name)"
respawn="false" output="screen">
</node> -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="paused" value="true"/> <!-- value unrelevant due to Arducopter plugin steps -->
<arg name="headless" value="$(arg headless)"/>
<arg name="gui" value="$(arg gui)"/>
<arg name="world_name" value="$(arg world_name)"/>
</include>
</launch>
The ".world" file looks like this (which I hope will contain the .so files of both Rover and Copter when arguments are resolved properly).
<?xml version="1.0" ?>
<sdf version="1.5">
<world name="vrc_task_1">
<!-- Light Source -->
<light type="directional" name="sun">
<cast_shadows>false</cast_shadows>
<pose>0 0 100 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.9 0.9 0.9 1</specular>
<attenuation>
<range>1000</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<!--<direction>0.2 0.2 -0.9</direction>-->
<!-- Vertical direction, for easier position debug -->
<direction>0 0 -1</direction>
</light>
<include>
<uri>model://jarama</uri>
<pose>0 0 0 0 0 0</pose>
</include>
<plugin name="ardupilot_sitl_gazebo_plugin" filename="libardupilot_sitl_gazebo_plugin.so">
<UAV_MODEL>erlecopter</UAV_MODEL>
<!-- plugin name="ardupilot_sitl_gazebo_plugin_rover" filename="libardupilot_sitl_gazebo_plugin_rover.so">
<UAV_MODEL>rover</UAV_MODEL -->
</plugin>
</world>
</sdf>
Any help will be gratefully acknowledged; If the robots work as described, that will be great; If there is any official documentation which forbids which I am planning to do, that is fine too.
(Please consider letting me know if this question is not worth the time or something is missing; This question shall be modified accordingly)
Thanks for your valuable time and consideration.
Prasad N R
(A hats-off to great communities like this ROS community for the development of these amazing softwares and big-thanks to Willow Garage, 3DR, Erle Robotics and other communities for such great open-source softwares which I may have forgotten because of their obviousness)
Appended text: Two possibilities have been considered for the same which is as depicted in this image.
(Option 1 uses 6 terminals with independent launch files and MAVproxy initiation terminals)
While trying to search for Option 1, the documentation appeared to be sparse (The idea is to launch the simulation with ErleRover and then spawn ErleCopter on-the-go; I haven't found any official documentation mentioning either the possibility or the impossibility of this option). Can somebody be requested to let me know how option 1 can be achieved or why it is impossible by mentioning corresponding official documentation?
Regarding option 2, additional options have been explored; The problem is apparently with two aspects: param vs rosparam and tf2 vs tf_prefix. Some of the attempts of simulation of multiple turtlebots have used tf_prefix which is deprecated. But, I have been unable to find any example which uses tf2 while simulating multiple (different) robots. But, tf2 works on ROS Hydro (and thus Indigo). Another possible option is the usage of rosparam instead of param (only). But, documentation on that is sparse regarding the usage of same on multi-robot simulation and I have been able to find only one example (for a single robot Husky).
But, one thing is clearer: MAVproxy can support multiple robots through the usage of SYSID and component-ID parameters. (upto 255 robots with 0 being a broadcast ID) Thus, port numbers have to be modified (possibly 14000 and 15000 as each vehicle uses 4 consecutive ports) just like the UCTF simulation. (vehiclebaseport = VEHICLEBASEPORT + mavsysid*4)
To summarise the question, the main concern is to simulate an independent car moving around and an independent quadcopter flying around in the ROS Gazebo SITL (maybe using Python nodes; C++ is fine too). Can somebody be requested to let me know the answers to the following sub-questions?
Is this kind of simulation possible? (Either by the usage of ROS Indigo, Gazebo 7, MAVproxy 1.5.2 on Ubuntu 14.04 or by modifying UCTF project to spawm a car like ErleRover if there is no other option) (You are kindly requested to let me know the examples if possible and official links if this is impossible)
If on-the-go launch is not possible with two launch files, is it possible to launch two different robots with a single launch file?
This is an optional question: How to modify the listener (subscriber) of the node? (Is it to be done in the Python node?)
This simulation is taking relatively long time with system software crashing for about 3 times (NVIDIA instead of Noveau, broken packages etc) and any help will be whole-heartedly, gratefully and greatly appreciated. Thanks for your time and consideration.
Appended text 2: I have tried the spawning of new robot in the existing simulation as mentioned in this question. I have found that roslaunch is problematic (with hacky command options to work with) and rosrun is preferable when multiple terminals are needed for control. Namespace is meant for single type of robots and not different robots and this may not solve the problem. Group is meant to spawn different robots with a single launch file and it has it's own constraints (only three attributes can be set and any suggestion on this is greatly appreciated).
I have tried to roslaunch copter.xacro first followed by rosun of rover.urdf (as Gazebo fails to recognise any other format properly apart from URDF) as mentioned in the example tutorial. But, the problem is with the TCP and UDP addresses that must be while spawning the rover so that the rover is connected to MAVproxy.
MAVproxy calls elf executables through simvehicle.sh as mentioned in the architecture. The problem might be mainly due to MAVproxy which acts as listener waiting for heart beat and thus causes the sequence to be more like simvehicle.sh followed by launch. (Launch followed by simvehicle.sh doesn't work FCU: DeviceError:tcp:connect: connection refused) So, I have created apmsitlcopter.launch and apmsitlrover.launch from apmsitl.launch. The tgtsystem of copter has been changed to 2 so as to avoid conflicts with SYSIDTHISMAV of Rover when spawned. (But, copter when launched alone, works for both SYSIDTHISMAV=1 and SYSIDTHISMAV=2 regardless of tgtsystem in apmsitlcopter.launch launched through coptercircuit.launch)
Copter is being launched with MAVproxy instance 0 and Rover is supposed to be launched using MAVproxy instance 1 and there are plenty of network connection errors like "GCS: DeviceError:udp:bind: Address already in use". I have even tried hard-coding TCP and UDP ports of simvehiclecopter.sh and simvehiclerover.sh and UDP appears to work fine with 14000 port number while TCP is not working for 5763 or 5000 or any other standard port that I know about. Second instance is also causing problems within the instance itself; I have tried to roslaunch without the world file for Rover and I have been unable to find any documentation on that excepting some bug reports or some general forums.
Can somebody be requested to answer the following summarised questions:
How to roslaunch with rover.urdf? (Removing world file? command line options?)
How to rosrun? (with UDP and TCP ports in the command line or apmsitlrover.launch getting called somehow?)
(This is probably the final stage with great hopes with just one command line missing; Number of sensors has been reduced, update rates have been reduced to about 5-10Hz; Anything else? I am thinking of using arp-scan, netstat, telnet or similar software tool to diagnose network errors)
(Any links to official documentation/tutorials will be greatly appreciated if a direct answer cannot be mentioned; If none of these work, the final solution might be to work on movement of joints and controllers; But, that is out of the scope of this question)
Thanks for your time and consideration.
Appended text 3: Second robot has been spawned successfully as mentioned in this video by using the commands mentioned below.
cd path_to_urdf_model_files
rosrun gazebo_ros spawn_model -file rover.urdf -urdf -model rover_object
(Note: ROS Indigo is different; gazeboros must be used instead of gazeboworlds)
The weird behaviour of the robot rotating about itself is probably because of MAVproxy; I have experienced this before.
The entire question probably reduces to "How to link second robot spawned by rosrun to second MAVproxy instance?".
Asked by PrasadNR on 2016-10-20 13:49:40 UTC
Comments
Did you managed to create multiple MAVlinks? I want to do the same for 3 Erle-Copters, I am able to instantiate 3 Quads in Gazebo but I can't control them individually as only 1 MAVlink is created.
Asked by MAS on 2017-05-06 05:57:43 UTC
Hi There! Have you been able to solve this issue?
When I try to launch 2 erlecopters, (I launch different instances of sim_vehicle.sh I and change the addresses accordingly in my launch file), I get the following message GCS: DeviceError:udp:bind: Address already in use any thoughts?
cheers, Hugo
Asked by Hugo Sardinha on 2017-06-20 06:22:30 UTC