Several vehicles and several simulations
One name per instance
Every instance of a vehicle goes by one name, which is at once its Gazebo
model name and its topic namespace (/<name>/... for every sensor and
thruster topic, on both the Gazebo and the ROS side). A name is letters,
digits and underscores, starting with a letter, because it also has to be a
valid ROS name; the generator refuses anything else.
The launch argument is the name. sim.launch.xml always passes name:=,
blueboat or bluerov2 by default, to configure_vehicle.py --name, which
applies it to the config before generating the artifacts (the config
actually used is written next to them as vehicle.yaml), so the model
name, the plugin topics and the bridge cannot disagree. A topic_namespace
in a custom config is therefore overridden by the launch; it only names the
instance when the generator runs without --name. x, y, z, roll,
pitch and yaw place the instance:
ros2 launch blueboat_gazebo sim.launch.xml name:=boat_b x:=4 yaw:=1.57
Joint states are bridged as /<name>/joint_states, and every TF frame and
sensor frame_id carries <name>/ in front, so two instances have separate
TF trees. The node names of this repository’s own launch
(robot_state_publisher, ros_gz_bridge) carry no instance name, since
that launch runs one vehicle; gz-maritime’s spawn launch, below, runs each
instance’s nodes in its namespace.
Topic overrides under the name
Per part, topic, gz_topic and ros_topic in the config still override
the base name, and the override goes under the instance name too, so two
instances of one config never share a topic: topic: sonar on the Ping of
boat_b gives /boat_b/sonar/range. An override that starts with a slash
is used as given, and is then shared by every instance.
Note
Before this rule, a relative override replaced the namespace: topic: sonar
gave /sonar/range. A config written that way, or one that spelled the
namespace out (gz_topic: blueboat/ping_raw), now gets the namespace in
front of it. To keep an absolute topic, start it with a slash.
extra_bridge_topics are appended to the bridge config verbatim, so they
are shared by every instance too.
A second instance in the same world
sim.launch.xml starts a Gazebo server of its own, so running it twice gives
two simulations, not two boats. Several instances share one world through
gz-maritime, whose simulation launch names no vehicle and whose spawn launch
adds any vehicle by name and pose, running this generator for it. In one
terminal, the ocean:
ros2 launch kai_bringup simulation.launch.xml
In another terminal, one command per boat:
boat="$(ros2 pkg prefix blueboat_gazebo)/lib/blueboat_gazebo/configure_vehicle.py --config $(ros2 pkg prefix --share blueboat_description)/config/blueboat.yaml"
ros2 launch kai_bringup spawn_vehicle.launch.xml name:=boat_a y:=4 generator:="$boat"
ros2 launch kai_bringup spawn_vehicle.launch.xml name:=boat_b y:=-4 yaw:=1.57 generator:="$boat"
Each boat gets its topics under its name, its own bridge and
robot_state_publisher in its namespace, and its own TF prefix; the clock
is bridged once by the simulation launch, which drops the /clock entry
this bridge config carries. A controller binds to one boat through those
topics: the teleop stack takes
name:=boat_b and runs under /boat_b, so a second stack on a second
gamepad drives boat_a alongside it. The boats float there under any name because
their displacement collisions are marked (Buoyancy).
In this repository’s own worlds, buoyancy is enabled by model name
(<enable>blueboat::hull_displacement</enable>), so a renamed instance
needs its own <enable> line in a copy of the world.
Several simulations
To run several simulations side by side instead, give each Gazebo
instance its own GZ_PARTITION and each ROS graph its own ROS_DOMAIN_ID.