Skip to content

Odometer to Imagenex 831L Publisher

This example shows how one can use the blueye.sdk to forward the odometer distance from the position messages from the drone to the PipeSonarL software from Imagenex. The PipeSonarL software is used to operate the Imagenex 831L Pipe Profiling sonar.

The PipeSonarL software accepts input from external cable counting systems, which is used to generate a 3D point cloud from a pipe inspection.

On a Blueye X3, we can use the odometer distance from the position messages to generate the cable count for the PipeSonarL software. The odometer distance is the distance the drone has traveled since the last reset.

The script performs the following steps:

  1. UDP Configuration: Sets up the UDP IP and port for sending NMEA messages. If your receiver expects to receive data on a different port, you need to change it here.
  2. Increase publishing frequency: Increases the publishing frequency of the position estimate message to 5 Hz.
  3. Drone Connection: Establishes a connection to the Blueye drone.
  4. Callback Registration: Registers a callback function to handle position estimate telemetry messages.
  5. Main Loop: Keeps the script running to continuously receive and send messages.
"""publish_odometer_to_831l.py

This example program demonstrates how to publish the drone's odometer as a cable counter
to the PipeSonarL software used to operate the Imagenex 831L Pipe Profiling Sonar.
"""

import socket
import time

import blueye.protocol as bp

from blueye.sdk import Drone


def callback_position_estimate(
    msg_type: str, msg: bp.PositionEstimateTel, udp_socket: socket.socket
):
    """Callback for the PositionEstimateTel message."""
    odometer = msg.position_estimate.odometer * 1000  # Convert to mm
    formatted_message = f"{{,#CABLE,{odometer},mm,}}\r\n"

    udp_socket.sendto(formatted_message.encode("ascii"), (UDP_IP, UDP_PORT))
    print(f"Sent: {formatted_message.strip()}")


if __name__ == "__main__":
    # UDP configuration
    # This IP will broadcast to all devices in the 192.168.1 subnet
    UDP_IP = "192.168.1.255"

    # 1261 is the default UDP port used by the PipeSonarL software.
    UDP_PORT = 1261

    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)  # Enable broadcasting

    # Instantiate a drone object and connect to the drone
    try:
        print("Connecting to the drone...")
        my_drone = Drone(connect_as_observer=True)
    except ConnectionError:
        print("Could not connect to the drone.")
        exit(1)
    finally:
        print("Connected to the drone.")

    # Increase publishing frequenzy for the PositionEstimateTel message
    my_drone.telemetry.set_msg_publish_frequency(bp.PositionEstimateTel, 5)

    # Add a callback for the PositionEstimateTel message
    my_drone.telemetry.add_msg_callback(
        [bp.PositionEstimateTel], callback_position_estimate, udp_socket=udp_socket
    )

    # Keep the script running to receive and send messages
    try:
        print("Press Ctrl+C to exit.")
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Exiting...")
    finally:
        # Cleanup
        my_drone.disconnect()
        udp_socket.close()