Hey, here is the launchfile that we are using to launch a drone running PX4 and communicating with ROS2.
You will notice that we were forced to use hard-coded paths, that you will need to update and prevent your package from being used like a regular, generic, ROS2 package. We had to do this because PX4 is not (yet) compiled as a ROS2 package and thus none of the executable, model files or Gazebo plugins are copied to the install space upon colcon build. Fixing that will allow fixing this launchfile.
Another point of improvement would be to replace the 5s sleep with a proper ROS2 Lifecycle management is ready, both in PX4 and in Gazebo-ROS.
Please credit us if you plan on integrating this launchfile (modified) into your own work or into the PX4 codebase.
"""Launch a Gazebo simulation spawning a PX4 drone communicating over ROS2."""
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.substitutions import LaunchConfiguration
from launch.actions import IncludeLaunchDescription, DeclareLaunchArgument, ExecuteProcess, SetEnvironmentVariable
from launch.launch_description_sources import PythonLaunchDescriptionSource
def generate_launch_description():
"""Launch Gazebo with a drone running PX4 communicating over ROS 2."""
HOME = os.environ.get('HOME')
PX4_RUN_DIR = HOME + '/tmp/px4_run_dir'
gazebo_launch_dir = os.path.join(get_package_share_directory('gazebo_ros'), 'launch')
blackdrones_description_dir = get_package_share_directory('blackdrones_description')
world = os.path.join(blackdrones_description_dir, 'worlds', 'blackdrone.world')
model = os.path.join(blackdrones_description_dir, 'models', 'blackdrone', 'blackdrone.urdf')
custom_gazebo_models = os.path.join(blackdrones_description_dir, 'models')
px4_init = os.path.join(blackdrones_description_dir, 'PX4-init')
os.makedirs(PX4_RUN_DIR, exist_ok=True)
return LaunchDescription([
SetEnvironmentVariable('GAZEBO_PLUGIN_PATH',
HOME + '/blackdrones_ws/PX4-Autopilot/build/px4_sitl_rtps/build_gazebo'),
SetEnvironmentVariable('GAZEBO_MODEL_PATH', HOME + '/blackdrones_ws/PX4-Autopilot/Tools/sitl_gazebo/models'
+ ':' + custom_gazebo_models),
SetEnvironmentVariable('PX4_SIM_MODEL', 'blackdrone_gimbal'),
DeclareLaunchArgument('world', default_value=world),
DeclareLaunchArgument('model', default_value=model),
DeclareLaunchArgument('x', default_value='1.01'),
DeclareLaunchArgument('y', default_value='0.98'),
DeclareLaunchArgument('z', default_value='0.83'),
DeclareLaunchArgument('R', default_value='0.0'),
DeclareLaunchArgument('P', default_value='0.0'),
DeclareLaunchArgument('Y', default_value='0.0'),
IncludeLaunchDescription(
PythonLaunchDescriptionSource([gazebo_launch_dir, '/gzserver.launch.py']),
launch_arguments={'world': LaunchConfiguration('world'),
'verbose': 'true'}.items(),
),
IncludeLaunchDescription(
PythonLaunchDescriptionSource([gazebo_launch_dir, '/gzclient.launch.py'])
),
ExecuteProcess(
cmd=[
'gz', 'model',
'--spawn-file', LaunchConfiguration('model'),
'--model-name', 'drone',
'-x', LaunchConfiguration('x'),
'-y', LaunchConfiguration('y'),
'-z', LaunchConfiguration('z'),
'-R', LaunchConfiguration('R'),
'-P', LaunchConfiguration('P'),
'-Y', LaunchConfiguration('Y')
],
prefix="bash -c 'sleep 5s; $0 $@'",
output='screen'),
ExecuteProcess(
cmd=[
'xterm',
'-e',
HOME + '/blackdrones_ws/PX4-Autopilot/build/px4_sitl_rtps/bin/px4',
px4_init,
'-s', px4_init + '/init.d-posix/rcS'
],
cwd=PX4_RUN_DIR,
output='screen'),
ExecuteProcess(
cmd=['micrortps_agent', '-t', 'UDP'],
output='screen'),
ExecuteProcess(
cmd=['QGroundControl'],
output='screen'),
])