Overview
The RoboticServices class is the main orchestrator for the robotic arm controller. It coordinates all hardware modules, manages service execution, and handles communication with the Raspberry Pi host.
Location : arm_controller/src/main.py:294
Class Definition
class RoboticServices :
def __init__ ( self ):
# Initialize modules
self .sensor_module = SensorModule()
self .perception_module = PerceptionModule( self .sensor_module)
self .mapping_module = MappingModule()
self .control_module = ControlModule()
self .safety_module = SafetyModule( self .sensor_module, self .control_module)
self .communication = CommunicationManager()
Motor Control
Motor Configuration
The ControlModule manages four motors for arm manipulation:
class ControlModule :
def __init__ ( self ):
self .base_motor = Motor(Ports. PORT1 , True )
self .shoulder_motor = Motor(Ports. PORT2 , True )
self .elbow_motor = Motor(Ports. PORT3 , True )
self .gripper_motor = Motor(Ports. PORT4 , True )
Base Motor
Purpose : 360° rotation for environmental scanning
# Rotate base for scanning
self .control_module.rotate_motor_forward( self .control_module.base_motor, 20 )
Base motor rotation speed is set to 20 RPM during scanning to ensure accurate object detection and mapping.
Shoulder Motor
Purpose : Vertical arm positioning and height adjustment
# Raise shoulder
self .control_module.rotate_motor_forward( self .control_module.shoulder_motor, 60 )
# Lower shoulder on bumper collision
self .control_module.rotate_motor_reverse( self .control_module.shoulder_motor, 10 )
Safety Integration : Bumper sensor monitors for collisions and triggers automatic reversal.
Elbow Motor
Purpose : Arm extension and retraction
# Controlled via ControlModule
self .control_module.elbow_motor.spin( FORWARD , speed, RPM )
Gripper Motor
Purpose : Object grasping with current-based grip detection
# Activate gripper
self .control_module.rotate_motor_forward( self .control_module.gripper_motor, 20 )
# Check grip force via current draw
gripper_current = self .control_module.get_current_motor( self .control_module.gripper_motor)
if gripper_current > 0.3 : # Object gripped
self .control_module.general_stop()
Gripper current threshold is set at 0.3A. Exceeding this value indicates successful object grip or motor stall.
Sensor Integration
Distance Sensors
Base Distance Sensor (PORT11)
Purpose : Object detection during 360° scan
# Get base distance measurement
base_distance = self .sensor_module.get_base_distance() # Returns distance in MM
# Detection zone: 50-300mm
if 50 <= base_distance <= 300 :
object_size = self .sensor_module.get_base_object_size()
self .sensor_module.set_color(LEDColors. OBJECT_DETECTED )
Detection Parameters :
Range : 50-300mm
Purpose : Primary object detection
Returns : Distance in millimeters and raw object size
Gripper Distance Sensor (PORT7)
Purpose : Close-range object detection for grasping
gripper_distance = self .sensor_module.get_gripper_distance() # Returns distance in MM
Bumper Sensor (PORT12)
Purpose : Collision detection for shoulder safety
if self .sensor_module.is_bumper_pressed():
self .control_module.general_stop()
self .sensor_module.set_color(LEDColors. ERROR )
# Reverse shoulder motor
self .control_module.rotate_motor_reverse( self .control_module.shoulder_motor, 10 )
Inertial Sensor
Purpose : Track rotation angle during scanning
# Calibrate on startup
self .sensor_module.calibrate_intertial_sensor()
# Get current heading (0-360°)
current_angle = self .sensor_module.get_angle()
# Calculate rotation delta
delta = current_angle - self .last_angle
if delta > 180 : delta -= 360
elif delta < - 180 : delta += 360
self .accumulated_rotation += abs (delta)
TouchLED Sensor (PORT10)
Purpose : Visual status indicator
# Set LED color
self .sensor_module.set_color(LEDColors. READY ) # Green
self .sensor_module.set_color(LEDColors. ERROR ) # Red
self .sensor_module.set_color(LEDColors. RUNNING ) # Blue
Service Operations
Check Service
Purpose : Validate all hardware components before operation
def check_service ( self ) -> bool :
if self .safety_module.check_sensors() and self .safety_module.check_motors():
self .sensor_module.set_color(LEDColors. READY )
return True
else :
self .sensor_module.set_color(LEDColors. ERROR )
return False
Validation Checks :
All four motors installed and responsive
All three distance sensors operational
Bumper sensor functional
Response Message :
{
"type" : "check_service" ,
"data" : {
"state" : "approved"
}
}
Or on error:
{
"type" : "check_service" ,
"data" : {
"error" : "Sensors or motors not installed"
}
}
Safety State Service
Purpose : Sequential safety validation for shoulder and gripper mechanisms
def safety_state_service ( self ) -> bool :
while self .safety_service_loop == True :
if not self .safety_shoulder:
safety_shoulder = self .safety_module.check_shoulder_safety()
if safety_shoulder:
self .safety_shoulder = True
else :
if not self .safety_gripper:
safety_gripper = self .safety_module.check_gripper_safety()
if safety_gripper:
self .safety_gripper = True
self .safety_service_loop = False
self .safety_mode_active = True
self .sensor_module.set_color(LEDColors. READY )
return True
return False
Shoulder Safety Check
Raises shoulder until bumper sensor is pressed, then reverses to safe position
Gripper Safety Check
Closes gripper until current threshold is reached, confirming grip strength
Service Completion
Returns approval message and sets system to READY state
Reset Method :
def reset_safety_sequence ( self ):
self .safety_mode_active = False
self .safety_shoulder = False
self .safety_gripper = False
self .safety_service_loop = True
Scan Service
Purpose : Execute 360° rotation while detecting and mapping objects
def scan_service ( self ):
while not self .scan_complete:
if self .scan_start:
scan_init = self .start_scan_service()
if scan_init:
self .scan_start = False
self .scan_update = True
elif self .scan_update:
scan_finish = self .update_scan_service()
if scan_finish:
self .scan_update = False
self .scan_mode_active = False
self .scan_complete = True
return True
return self .scan_complete
Start Scan
def start_scan_service ( self ):
self .scan_mode_active = True
self .scan_start_time = time.time()
self .last_angle = self .sensor_module.get_angle()
self .control_module.rotate_motor_forward( self .control_module.base_motor, 20 )
self .sensor_module.set_color(LEDColors. RUNNING )
return True
Update Scan
def update_scan_service ( self ):
current_angle = self .sensor_module.get_angle()
# Calculate rotation
delta = current_angle - self .last_angle
if delta > 180 : delta -= 360
elif delta < - 180 : delta += 360
self .accumulated_rotation += abs (delta)
self .last_angle = current_angle
# Process sensor data
sensor_data = self .perception_module.process_sensor_data()
self .mapping_module.process_object_detection(current_angle, sensor_data[ 'size' ], sensor_data[ 'distance' ])
# Check if scan is complete
if self .accumulated_rotation >= 360 or time.time() - self .scan_start_time > self .scan_timeout:
self .control_module.general_stop()
return True
return False
Completion Conditions :
Accumulated rotation reaches 360°
Timeout exceeded (30 seconds)
Response Message :
{
"type" : "scan_service" ,
"data" : {
"state" : "complete" ,
"objects" : [
{
"center_angle" : 45.5 ,
"width" : 12.3 ,
"distance" : 150 ,
"max_size" : 85
}
]
}
}
Real Code Examples
Complete Service Workflow
def run ( self ):
self .communication.initialize()
while True :
try :
# Process incoming messages
message = self .communication.read_message()
if message:
self .sensor_module.print_screen( "rx: {} " .format(message), 1 , 15 )
self .process_raspberry_message(message)
# Execute check service
if self .check_mode_active:
check_service = self .check_service()
if check_service:
data = { 'state' : 'approved' }
self .communication.send_message( 'check_service' , data)
self .check_mode_active = False
else :
data = { 'error' : 'Sensors or motors not installed' }
self .communication.send_message( 'check_service' , data)
self .check_mode_active = False
# Execute safety service
if self .safety_mode_active:
safety_state = self .safety_state_service()
if safety_state:
data = { 'state' : 'approved' }
self .communication.send_message( 'safety_service' , data)
self .safety_mode_active = False
# Execute scan service
if self .scan_mode_active:
scan_complete = self .scan_service()
if scan_complete:
objects_map = self .mapping_module.get_objects_map()
data = { 'state' : 'complete' , 'objects' : objects_map}
self .communication.send_message( 'scan_service' , data)
self .scan_mode_active = False
except Exception as e:
self .sensor_module.print_screen( "Error: {} " .format( str (e)[: 20 ]), 1 , 95 )
self .control_module.general_stop()
Message Processing
def process_raspberry_message ( self , message : dict ):
if not message or 'type' not in message:
return
msg_type = message[ 'type' ].lower()
msg_data = message.get( 'data' , {})
if msg_type == 'check_service' :
self .check_mode_active = True
elif msg_type == 'safety_service' :
self .reset_safety_sequence()
self .safety_mode_active = True
elif msg_type == 'scan_service' :
self .reset_scan_sequence()
self .scan_mode_active = True
Error Handling
try :
# Service operations
except Exception as e:
self .sensor_module.print_screen( "Error: {} " .format( str (e)[: 20 ]), 1 , 95 )
self .control_module.general_stop()
All exceptions trigger emergency stop via general_stop() to prevent hardware damage.
Best Practices
Service Sequencing Always run check_service before safety_service, and safety_service before scan_service
Emergency Stop Use general_stop() to halt all motors immediately in error conditions
State Reset Call reset methods before restarting services to clear previous state
LED Feedback Monitor TouchLED color for real-time system status during operations
Serial Communication Message protocol and connection setup
Safety System Detailed safety check procedures
Overview System architecture and components