ROV Thrusters not Running

Issue Description

I am currently working with ROS 2 and Mavros on a Blue ROV 2 platform. My goal is to control the thrusters using RC override through the /mavros/rc/override topic. I have set up a publisher for this topic, and when running the executable, I encounter no errors. However, none of the thrusters respond to the RC commands.

Steps to Reproduce

Build the ROS 2 package and source it.
Run the Python script that subscribes and publishes to /mavros/rc/override.
Observe that despite running without errors, the thrusters do not respond to the RC commands sent through the script.

Expected Behavior

I expect that when publishing RC override commands to /mavros/rc/override, the commands should be successfully transmitted and result in controlling the thrusters on the Blue ROV 2.

Actual Behavior

Upon running the script, there are no errors reported. However, none of the thrusters on the Blue ROV 2 respond to the RC commands sent through /mavros/rc/override.

Here is my code:

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
from mavros_msgs.srv import CommandBool
from mavros_msgs.msg import OverrideRCIn
from sensor_msgs.msg import Imu
from rclpy.qos import QoSProfile, QoSHistoryPolicy, QoSReliabilityPolicy, QoSDurabilityPolicy

class BlueROV2Controls(Node):
    def __init__(self):
        super().__init__('bluerov2_controls')

        qos_profile = QoSProfile(
            history=QoSHistoryPolicy.KEEP_LAST,
            depth=3,
            reliability=QoSReliabilityPolicy.BEST_EFFORT,
            durability=QoSDurabilityPolicy.VOLATILE
        )
        
        self.publisher = self.create_publisher(
            OverrideRCIn,
            "/mavros/rc/override",
            qos_profile
        )

        # Subscription to the IMU topic
        self.imu_subscriber = self.create_subscription(
            Imu,
            '/mavros/imu/data',
            self.imu_callback,
            qos_profile
        )

        self.cli = self.create_client(CommandBool, '/mavros/cmd/arming')
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('Waiting for arming service...')
        self.get_logger().info('Arming service is ready.')

        self.publisher_timer = self.create_timer(1.0, self.run_sequence)

    def run_sequence(self):
        rc_msg = OverrideRCIn()

        # Step 1: Go down
        rc_msg.channels = [1500, 1500, 1600, 1500, 1500, 1500, 1500, 1500]
        self.publisher.publish(rc_msg)
        self.get_logger().info(f"Step 1: Descend - {rc_msg.channels}")

        # Wait for a moment
        rclpy.spin_once(self, timeout_sec=3)

        # Step 2: Move forward
        rc_msg.channels = [1600, 1500, 1500, 1500, 1500, 1500, 1500, 1500]
        self.publisher.publish(rc_msg)
        self.get_logger().info(f"Step 2: Move forward - {rc_msg.channels}")

        # Wait for a moment
        rclpy.spin_once(self, timeout_sec=3)

        # Step 3: Rotate 180 degrees
        rc_msg.channels = [1500, 1500, 1500, 1900, 1500, 1500, 1500, 1500]
        self.publisher.publish(rc_msg)
        self.get_logger().info(f"Step 3: Rotate 180 - {rc_msg.channels}")

        # Wait for a moment
        rclpy.spin_once(self, timeout_sec=3)

        # Step 4: Move forward (same distance)
        rc_msg.channels = [1600, 1500, 1500, 1500, 1500, 1500, 1500, 1500]
        self.publisher.publish(rc_msg)
        self.get_logger().info(f"Step 4: Move forward - {rc_msg.channels}")

        # Wait for a moment
        rclpy.spin_once(self, timeout_sec=3)

        # Step 5: Ascend
        rc_msg.channels = [1500, 1500, 1400, 1500, 1500, 1500, 1500, 1500]
        self.publisher.publish(rc_msg)
        self.get_logger().info(f"Step 5: Ascend - {rc_msg.channels}")

        # Wait for a moment and then stop the sequence
        rclpy.spin_once(self, timeout_sec=3)
        self.destroy_node()

    def send_request(self, arm: bool):
        req = CommandBool.Request()
        req.value = arm
        future = self.cli.call_async(req)
        rclpy.spin_until_future_complete(self, future)
        if future.result() is not None:
            self.get_logger().info(f"Request successful: {future.result().success}")
        else:
            self.get_logger().error(f"Request failed: {future.exception()}")

    def imu_callback(self, msg: Imu):
        """
        Callback function for IMU messages. Logs IMU data (orientation, angular velocity, linear acceleration).

        Parameters:
        msg (Imu)
        """
        self.imu = msg
        # self.get_logger().info(f"IMU (Orientation, Angular Velocity, Linear Acceleration): {msg.orientation}    {msg.angular_velocity}   {msg.linear_acceleration}")
        # self.get_logger().info(f"IMU Orientation: {msg.orientation}")
        # self.get_logger().info(f"IMU Angular Velocity: {msg.angular_velocity}")
        self.get_logger().info(f"IMU Linear Acceleration: {msg.linear_acceleration}")

def main(args=None):
    rclpy.init(args=args)
    node = BlueROV2Controls()
    node.send_request(True)  # Arm the robot

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('KeyboardInterrupt received, shutting down...')
    finally:
        node.send_request(False)  # Disarm the robot
        node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()

Additional Information

  • No errors are reported during script execution.
  • The issue persists across multiple attempts and checks of setup and configuration files.
  • No thrusters respond to the RC override commands despite proper setup of publisher for /mavros/rc/override.

Hi @liujpatrick, welcome to the forum :slight_smile:

I don’t have experience with using ROS, but from a search of our forums these seem like the most relevant posts/comments:

Feel free to follow up if those aren’t helpful / if something in particular isn’t clear or isn’t working as expected.