POSIMPlatform for Ocean Simulation · Documentation
Documentation menu
POSIM / Advanced guides

ROS 2 and control

Read observations and send commands using the interfaces configured for the selected vehicle. Gazebo Transport and ROS 2 are separate transports; a bridge or ROS-enabled plugin connects them.

Inspect the graph

Use a second terminal in the same environment as the simulator:

ros2 topic list -t
ros2 service list -t
gz topic -l
ros2 topic info /model/rexrov/odometry --verbose

Check types, frame IDs, rates and QoS before connecting your node. Nodes using simulation timestamps should set use_sim_time:=true and receive the simulation clock.

REXROV thruster commands

The included REXROV configuration bridges eight cmd_thrust topics as std_msgs/msg/Float64. The values are thrust commands in newtons. A neutral command for the first thruster is:

ros2 topic pub --once /model/rexrov/joint/thruster1_joint/cmd_thrust \
  std_msgs/msg/Float64 '{data: 0.0}'

A controller must allocate forces across the thrusters using their positions and axes. One thruster is not a vehicle-level velocity controller. End an experiment by sending neutral values to every commanded thruster.

BlueROV2 and autopilot

BlueROV2 connects to ArduSub through MAVROS. Inspect state and available command interfaces:

ros2 topic echo /mavros/state --once
ros2 service list -t
ros2 topic info /mavros/manual_control/send --verbose

The manual-control adapter maps /joy and /keyboard/joy to MAVROS commands.

Use one command source and check arming/navigation status. See ROVs for keyboard and WebSocket setup.

Subscribe from Python

This minimal example prints REXROV's simulated position. Save it as observe.py and run python3 observe.py in the sourced ROS environment.

import rclpy
from nav_msgs.msg import Odometry
from rclpy.node import Node

class Observer(Node):
    def __init__(self):
        super().__init__('posim_observer')
        self.subscription = self.create_subscription(
            Odometry, '/model/rexrov/odometry', self.on_pose, 10)

    def on_pose(self, message):
        p = message.pose.pose.position
        self.get_logger().info(f'x={p.x:.2f}, y={p.y:.2f}, z={p.z:.2f}')

rclpy.init()
node = Observer()
try:
    rclpy.spin(node)
except KeyboardInterrupt:
    pass
finally:
    node.destroy_node()
    rclpy.shutdown()

Visualization and recording

Choose RViz displays matching the message type.

POSIM-specific messages are defined in posim_interfaces. Install and source these definitions on each separate ROS client.

ros2 bag record /model/rexrov/odometry /model/rexrov/imu

A remote ROS client requires:

Configure remote gateways in the application hosting the simulator.