Skip to Content

Python SDK

Overview

BonicBot Bridge is a Python SDK designed for educational robotics programming. It provides a high-level, intuitive API that abstracts the complexity of ROS2 robotics into simple commands suitable for STEM education and beginners.

Key Features

  • Educational Focus: Simple, easy-to-understand API designed for learning
  • Remote Control: Control robots from any computer on the same network
  • Autonomous Navigation: Path planning and goal-based navigation
  • SLAM Mapping: Create maps of environments for navigation
  • Vision Processing: Camera streaming with real-time image capture
  • Servo Manipulation: Control robot arms, grippers, and neck movements
  • Real-time Feedback: Live updates on position, battery, and navigation status
  • Safety Built-in: Automatic connection management and error handling

System Requirements

  • Python Version: 3.8 or higher
  • Robot Hardware: BonicBot A2 with ROS2 Humble
  • Network: Robot and control computer on same network
  • Dependencies: roslibpy (auto-installed with pip)

Supported Platforms

  • Raspberry Pi 4 (for onboard execution)
  • Ubuntu 20.04/22.04
  • Windows 10/11 (remote control)
  • macOS (remote control)

Installing and Setting Up the Python SDK

Install the BonicBot Bridge SDK using pip:

pip install bonicbot-bridge

Requirements

  • Python 3.8 or higher
  • BonicBot robot running ROS2
  • rosbridge_server running on port 9090
  • Robot and computer on the same network (for remote access)

Understanding the SDK Structure and Basic API Usage

The BonicBot class is the main interface for connecting to and controlling the robot using the Python SDK.

Constructor

BonicBot(host='localhost', port=9090, timeout=10)

Parameters

  • host (str): Robot IP address or hostname
    • Use ‘localhost’ when running code on the robot
    • Use the robot’s IP or hostname for remote access
  • port (int): Port on which rosbridge_server is running (Default: 9090)
  • timeout (int): Maximum connection wait time in seconds

Connection Examples

Local Connection (On Robot)

from bonicbot_bridge import BonicBot bot = BonicBot()

Remote Connection (Using IP)

from bonicbot_bridge import BonicBot bot = BonicBot(host='192.168.1.100')

Remote Connection (Using Hostname)

from bonicbot_bridge import BonicBot bot = BonicBot(host='bonic.local')
from bonicbot_bridge import BonicBot with BonicBot(host='192.168.1.100') as bot: bot.move_forward(0.3, 2)

This ensures the connection is automatically closed after execution.

Checking Robot Connection

To test whether the robot is connected, you can use the is_connected() method.

Purpose: Checks whether the robot is currently connected to the Python SDK. This method should be used before sending any commands to ensure that communication with the robot is active.

Returns:

  • True – if the robot is connected
  • False – if the robot is not connected

Example Usage:

if bot.is_connected(): print("Robot connection OK") else: print("Robot not connected")

Controlling Robot Movement

The movement API allows you to control the robot using either low-level velocity commands or high-level convenience functions.

Low-Level Movement (Velocity Control)

move(linear_x=0, linear_y=0, angular_z=0)

Description: Directly controls robot velocities. This is a low-level command where you specify forward/backward, sideways (if supported), and rotation speeds.

  • linear_x → forward/backward speed in m/s
  • linear_y → sideways speed in m/s (for omnidirectional robots)
  • angular_z → rotation speed in degrees/s

Note: Must be continuously published to keep the robot moving.

Example:

bot.motion.move(linear_x=0.3, angular_z=30) # Move forward while turning bot.motion.move(0, 0, 0)

High-Level Movement (Convenience Functions)

These functions are convenience methods that handle timing and velocity publishing automatically.

move_forward(speed, duration=None)

Description: Moves the robot forward at the given speed. If duration is provided, the robot stops automatically after that time.

Example:

bot.move_forward(0.5, duration=2) # Move forward 2 seconds

move_backward(speed, duration=None)

Description: Moves the robot backward at the given speed. Automatically stops after duration if provided.

Example:

bot.move_backward(0.2, duration=1.5) # Move backward for 1.5 seconds

turn_left(speed, duration=None)

Description: Rotates the robot counter-clockwise at the given speed. Stops after duration if provided.

Example:

bot.turn_left(0.5, duration=1) # Turn left for 1 second

turn_right(speed, duration=None)

Description: Rotates the robot clockwise at the given speed. Stops after duration if provided.

Example:

bot.turn_right(0.5, duration=1) # Turn right for 1 second

stop()

Description: Immediately stops all robot movement. Equivalent to sending zero velocities.

Example:

bot.stop() # Stop immediately

Example: High-Level Robot Movement

This example demonstrates the use of high-level movement methods in the BonicBot SDK. It shows how to move the robot forward, backward, turn left, turn right, and stop, with automatic duration control and built-in command management for easy educational use.

from bonicbot_bridge import BonicBot import time # Connect to the robot with BonicBot() as bot: print("Starting high-level movement demo...") # Move forward for 2 seconds print("Moving forward...") bot.move_forward(0.5, duration=2) time.sleep(0.5) # Turn left for 1 second print("Turning left...") bot.turn_left(0.5, duration=1) time.sleep(0.5) # Move backward for 1.5 seconds print("Moving backward...") bot.move_backward(0.3, duration=1.5) time.sleep(0.5) # Turn right for 1 second print("Turning right...") bot.turn_right(0.5, duration=1) time.sleep(0.5) # Stop the robot print("Stopping robot...") bot.stop() print("High-level movement demo complete!")

Reading Sensor Data

Sensor methods provide access to the robot’s real-time state information such as position, orientation, and battery level.

get_position()

Returns the robot’s current position and orientation.

Returns: A dictionary containing:

  • x – X position in meters
  • y – Y position in meters
  • theta – Orientation in degrees
  • Returns None if position data is not available

Example:

pos = bot.get_position() if pos: print(f"X: {pos['x']:.2f}, Y: {pos['y']:.2f}, Heading: {pos['theta']:.2f}°")

get_x(), get_y(), get_heading()

Return individual components of the robot’s position.

  • get_x() – Current X position (meters)
  • get_y() – Current Y position (meters)
  • get_heading() – Current heading in degrees

Example:

x = bot.get_x() y = bot.get_y() heading = bot.get_heading() print(f"X: {x}, Y: {y}, Heading: {heading}°")

get_heading_degrees()

Return the robot’s heading in degrees. This method is functionally equivalent to get_heading().

Example:

heading_deg = bot.get_heading_degrees() print(f"Heading: {heading_deg}°")

get_battery()

Returns the robot’s battery level as a percentage.

Note: Not implemented yet

Returns: Integer value between 0 and 100

Example:

battery = bot.get_battery() print(f"Battery Level: {battery}%")

Example: Reading Sensor Data in a Loop

This example demonstrates how to read the robot’s current position, orientation, and battery level at regular intervals using the sensor API.

from bonicbot_bridge import BonicBot import time with BonicBot() as bot: for i in range(5): pos = bot.get_position() battery = bot.get_battery() if pos: print(f"X={pos['x']:.2f}, Y={pos['y']:.2f}, Heading={pos['theta']:.2f}°") print(f"Battery: {battery}%") time.sleep(1)

System Control Methods

Control the robot’s mapping and localization systems using these methods.

start_mapping()

Start SLAM (Simultaneous Localization and Mapping) mode to create a map of the environment.

Example:

bot.start_mapping() # Drive the robot around to explore bot.save_map() # Save the map after mapping

stop_mapping()

Stop the SLAM mapping process.

Example:

bot.stop_mapping()

save_map()

Save the map created during mapping for future navigation.

Example:

bot.save_map()

Example: Mapping the Environment

This example demonstrates starting SLAM mapping, exploring the environment, stopping mapping, and saving the map for future use.

from bonicbot_bridge import BonicBot import time with BonicBot() as bot: print("Starting SLAM mapping...") # Start mapping bot.start_mapping() # Move the robot around manually or programmatically bot.move_forward(0.3, duration=2) bot.turn_left(0.5, duration=1) bot.move_forward(0.3, duration=2) bot.turn_right(0.5, duration=1) # Stop mapping bot.stop_mapping() # Save the created map bot.save_map() print("Mapping complete and map saved!")

Control the robot’s autonomous navigation system using these methods. To use navigation, mapping should be done or a saved map should be available. If mapping is currently running, you can start navigation and set goals directly. However, if you are using a saved map (mapping is not running), you must first set the initial position before starting navigation, and then you can set goals for the robot.

start_navigation()

Start the robot’s navigation system. Must be called before sending navigation commands.

Example:

bot.start_navigation()

stop_navigation()

Stop the navigation system.

Example:

bot.stop_navigation()

go_to(x, y, theta=0)

Sending a navigation to a goal. Navigate the robot autonomously to the specified coordinates.

Parameters:

  • x (float): Target X coordinate in meters
  • y (float): Target Y coordinate in meters
  • theta (float, optional): Target orientation in degrees

Example:

bot.go_to(2.0, 1.5) # Go to (2.0, 1.5) bot.go_to(0.0, 0.0, 90) # Go to origin facing 90°

wait_for_goal(timeout=30)

Monitoring Navigation Status. Waits until the navigation goal is completed or fails.

Returns: ‘goal_reached’, ‘goal_failed’, ‘cancelled’, or ‘timeout’

Example:

result = bot.wait_for_goal() if result == 'goal_reached': print("Successfully reached destination!")

cancel_goal()

Cancel the current navigation goal immediately.

Example:

bot.cancel_goal()

set_initial_pose(x, y, theta=0)

Set the robot’s initial position and orientation on a map. Useful when using saved maps for navigation.

Example:

bot.set_initial_pose(0.0, 0.0, 0.0) # At origin bot.set_initial_pose(2.0, 1.5, 90) # At specific location and orientation

Example: Navigation with Active and Saved Maps

Demonstrates how to navigate a BonicBot both during active SLAM mapping and using a saved map. The example shows setting goals, waiting for completion, and handling initial poses when using a saved map.

from bonicbot_bridge import BonicBot with BonicBot() as bot: # ------------------------------- # Scenario 1: Navigation while mapping is running # ------------------------------- print("Starting navigation with active mapping...") bot.start_mapping() # Start SLAM mapping bot.start_navigation() # Start navigation system # Set a navigation goal while mapping bot.go_to(2.0, 1.5) result = bot.wait_for_goal(timeout=30) if result == 'goal_reached': print("Reached goal during active mapping!") else: print(f"Navigation result: {result}") # Stop navigation and mapping bot.stop_navigation() bot.stop_mapping() # ------------------------------- # Scenario 2: Navigation using a saved map # ------------------------------- print("\nStarting navigation using a saved map...") bot.set_initial_pose(0.0, 0.0, 0.0) # Set initial position for localization bot.start_navigation() # Start navigation system # Set a goal on the saved map bot.go_to(3.0, 2.0) result = bot.wait_for_goal(timeout=30) if result == 'goal_reached': print("Reached goal on saved map!") else: print(f"Navigation result: {result}") # Stop navigation bot.stop_navigation() print("\nNavigation demo complete!")

Status Methods

Status methods allow you to monitor the robot’s connection, navigation state, and progress toward goals in real time.

is_connected()

Purpose: Checks whether the robot is currently connected to the Python SDK. This is useful before sending any commands to ensure communication with the robot is active.

Returns:

  • True if the robot is connected
  • False if not connected

Example Usage:

if bot.is_connected(): print("Robot connection OK") else: print("Robot not connected")

get_nav_status()

Purpose: Retrieves the current navigation status of the robot. This helps you know whether the robot is idle, moving toward a goal, or if there was a problem during navigation.

Returns: A string indicating the robot’s navigation state:

  • 'idle' – No navigation goal is active
  • 'navigating' – Robot is currently moving toward a goal
  • 'goal_reached' – Robot successfully reached its goal
  • 'goal_failed' – Robot failed to reach the goal
  • 'cancelled' – Navigation was cancelled

Example Usage:

status = bot.get_nav_status() print(f"Navigation Status: {status}")

get_distance_to_goal()

Purpose: Returns the remaining distance from the robot’s current position to the active navigation goal. Useful for monitoring progress during autonomous navigation.

Returns:

  • A float representing distance in meters
  • Returns None if there’s no active navigation goal

Example Usage:

distance = bot.get_distance_to_goal() if distance is not None: print(f"Distance to Goal: {distance:.1f} meters") else: print("No active goal")

Example: Real-Time Robot Status Monitoring

Demonstrates how to monitor a BonicBot’s connection, navigation status, and distance to its goal in real time, providing feedback during autonomous movement.

from bonicbot_bridge import BonicBot import time with BonicBot() as bot: # Check connection if not bot.is_connected(): print("Robot not connected!") else: print("Robot connection OK") # Start navigation (assuming a map is ready) bot.start_navigation() bot.go_to(2.0, 1.5) # Set a goal # Monitor status until goal is reached or failed while True: status = bot.get_nav_status() distance = bot.get_distance_to_goal() print(f"Navigation Status: {status}") if distance is not None: print(f"Distance to Goal: {distance:.1f} meters") if status in ['goal_reached', 'goal_failed', 'cancelled']: break time.sleep(1) print("Navigation finished!")

BonicBot Camera Methods

start_camera(callback=None)

Start camera streaming. Optionally, provide a callback function to process each frame in real-time.

Parameters:

  • callback (function, optional): Function called for each frame: callback(image)

Examples:

# Simple streaming bot.start_camera() # Streaming with callback for processing def process_frame(image): print(f"Frame shape: {image.shape}") bot.start_camera(callback=process_frame)

stop_camera()

Stop camera streaming.

Example:

bot.stop_camera()

get_image()

Get the latest camera image as a NumPy array (BGR format). Returns None if no image is available.

Returns: numpy.ndarray or None

Example:

image = bot.get_image() if image is not None: print(f"Image shape: {image.shape}")

save_image(filepath)

Saves the current camera image to a file or in rpi or dev system.

Parameters:

  • filepath (str): Path and filename to save the image

Example:

bot.save_image("robot_view.jpg")

Example: Using Camera Methods

This example demonstrates how to use the BonicBot camera via the BonicBot Bridge Python SDK. It shows how to start and stop camera streaming, process frames in real-time with a callback, retrieve the latest image as a NumPy array, and save images to a file.

# Import the BonicBot Bridge SDK from bonicbot_bridge import BonicBot import time # Initialize the robot bot = BonicBot() # ------------------------------ # Start camera streaming without a callback # ------------------------------ bot.start_camera() print("Streaming started without callback...") time.sleep(3) # Stream for 3 seconds # Stop streaming bot.stop_camera() print("Streaming stopped.") # ------------------------------ # Start camera streaming with a callback for processing frames # ------------------------------ def process_frame(image): print(f"Processing frame with shape: {image.shape}") bot.start_camera(callback=process_frame) print("Streaming started with callback...") time.sleep(5) # Stream for 5 seconds bot.stop_camera() print("Streaming stopped.") # ------------------------------ # Get the latest image # ------------------------------ image = bot.get_image() if image is not None: print(f"Latest image shape: {image.shape}") # ------------------------------ # Save the latest image to file # ------------------------------ bot.save_image("robot_view.jpg") print("Image saved as robot_view.jpg")

BonicBot Servo Control Methods

Control the robot’s servos for arms, grippers, and neck movements. You can set individual or multiple servo angles, move arms, operate grippers, rotate the neck, or reset all servos to their neutral positions.

set_servos(angles)

Set multiple servo angles at once.

Parameters:

  • angles (dict): Dictionary mapping joint names to angles in degrees

Example:

bot.set_servos({ 'left_shoulder_pitch_joint': 45.0, 'neck_yaw_joint': -30.0 })

move_left_arm(shoulder, elbow) / move_right_arm(shoulder, elbow)

Move robot arms to specified shoulder and elbow angles.

Parameters:

  • shoulder (float): Shoulder pitch angle (-45° to 180°)
  • elbow (float): Elbow angle (0° to 50°)

Example:

bot.move_left_arm(90, 30) # Left arm up bot.move_right_arm(45, 20) # Right arm halfway

set_grippers(left, right) / open_grippers() / close_grippers()

Control the robot’s gripper fingers.

Examples:

bot.open_grippers() # Open both grippers bot.close_grippers() # Close both grippers bot.set_grippers(30, 30) # Partially open

set_neck(yaw) / look_left() / look_right() / look_center()

Control neck rotation.

Parameters:

  • yaw (float): Neck yaw angle (-90° to 90°)

Examples:

bot.set_neck(-45) # Look right 45° bot.look_left() # Turn fully left bot.look_center() # Center position

reset_servos()

Reset all servos to neutral (0°) position.

Example:

bot.reset_servos()

Example: Full Servo Control

This example demonstrates the full range of BonicBot servo controls using the BonicBot Bridge Python SDK. It shows how to move arms, set multiple servo angles, operate grippers, rotate the neck, and reset all servos to neutral positions, providing a complete overview of basic robot motion and gestures.

from bonicbot_bridge import BonicBot # Initialize the robot bot = BonicBot() # ------------------------------ # Move arms to specific positions # ------------------------------ bot.move_left_arm(90, 30) # Left arm up bot.move_right_arm(45, 20) # Right arm halfway # ------------------------------ # Set multiple servos at once # ------------------------------ bot.set_servos({ 'left_shoulder_pitch_joint': 60, 'right_shoulder_pitch_joint': 60, 'neck_yaw_joint': 0 }) # ------------------------------ # Control grippers # ------------------------------ bot.open_grippers() # Open both grippers bot.set_grippers(30, 30) # Partially open grippers bot.close_grippers() # Close both grippers # ------------------------------ # Control neck rotation # ------------------------------ bot.set_neck(-45) # Turn neck right bot.look_left() # Turn fully left bot.look_right() # Turn fully right bot.look_center() # Reset neck to center # ------------------------------ # Reset all servos # ------------------------------ bot.reset_servos()
Last updated on