Exceptions API
This module provides custom exception classes for error handling in libfrankapy.
Exception Hierarchy
FrankaException
├── ConnectionException
├── ControlException
│ ├── MotionException
│ ├── ForceException
│ └── TrajectoryException
├── SafetyException
│ ├── CollisionException
│ ├── JointLimitException
│ └── WorkspaceLimitException
├── CommunicationException
└── ConfigurationExceptionBase Exception Classes
FrankaException
Base exception class for all libfrankapy errors.
class FrankaException(Exception):
def __init__(self, message: str, error_code: Optional[int] = None)Parameters:
message(str): Error descriptionerror_code(Optional[int]): Numeric error code
Attributes
message(str): Error messageerror_code(Optional[int]): Numeric error codetimestamp(float): Time when error occurredrecoverable(bool): Whether error is recoverable
Methods
get_error_info()
Get detailed error information.
def get_error_info(self) -> dictReturns:
dict: Error information including message, code, timestamp
is_recoverable()
Check if the error is recoverable.
def is_recoverable(self) -> boolReturns:
bool: True if error can be recovered
Connection Exceptions
ConnectionException
Raised when robot connection fails.
class ConnectionException(FrankaException):
def __init__(self, message: str, robot_ip: str)Parameters:
message(str): Error descriptionrobot_ip(str): IP address of the robot
Attributes
robot_ip(str): Robot IP addressconnection_timeout(float): Connection timeout value
Common Causes
- Robot is not reachable on the network
- Robot is already connected to another client
- Network configuration issues
- Robot is in error state
Example
try:
robot = fp.FrankaRobot("192.168.1.100")
robot.connect()
except fp.ConnectionException as e:
print(f"Failed to connect to robot at {e.robot_ip}: {e.message}")
if e.error_code == 1001: # Robot busy
print("Robot is already connected to another client")Control Exceptions
ControlException
Base class for control-related errors.
class ControlException(FrankaException):
def __init__(self, message: str, control_mode: Optional[str] = None)Parameters:
message(str): Error descriptioncontrol_mode(Optional[str]): Active control mode when error occurred
MotionException
Raised when motion commands fail.
class MotionException(ControlException):
def __init__(self, message: str, target_position: Optional[np.ndarray] = None)Parameters:
message(str): Error descriptiontarget_position(Optional[np.ndarray]): Target position that caused the error
Attributes
target_position(Optional[np.ndarray]): Failed target positioncurrent_position(Optional[np.ndarray]): Position when error occurred
Common Causes
- Target position is unreachable
- Motion would violate joint limits
- Motion would cause collision
- Invalid motion parameters
Example
try:
target_joints = [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]
robot.move_to_joint(target_joints)
except fp.MotionException as e:
print(f"Motion failed: {e.message}")
if e.target_position is not None:
print(f"Failed target: {e.target_position}")ForceException
Raised when force control operations fail.
class ForceException(ControlException):
def __init__(self, message: str, applied_force: Optional[np.ndarray] = None)Parameters:
message(str): Error descriptionapplied_force(Optional[np.ndarray]): Force that caused the error
Attributes
applied_force(Optional[np.ndarray]): Force/torque valuesforce_limit(Optional[float]): Force limit that was exceeded
TrajectoryException
Raised when trajectory execution fails.
class TrajectoryException(ControlException):
def __init__(self, message: str, waypoint_index: Optional[int] = None)Parameters:
message(str): Error descriptionwaypoint_index(Optional[int]): Index of problematic waypoint
Attributes
waypoint_index(Optional[int]): Failed waypoint indextrajectory_progress(float): Progress when error occurred (0.0 to 1.0)
Safety Exceptions
SafetyException
Base class for safety-related errors.
class SafetyException(FrankaException):
def __init__(self, message: str, safety_violation: str)Parameters:
message(str): Error descriptionsafety_violation(str): Type of safety violation
CollisionException
Raised when collision is detected.
class CollisionException(SafetyException):
def __init__(self, message: str, collision_force: Optional[float] = None)Parameters:
message(str): Error descriptioncollision_force(Optional[float]): Magnitude of collision force
Attributes
collision_force(Optional[float]): Force magnitude at collisioncollision_joint(Optional[int]): Joint where collision was detectedcollision_direction(Optional[np.ndarray]): Direction of collision force
Example
try:
robot.move_to_pose(target_pose)
except fp.CollisionException as e:
print(f"Collision detected: {e.message}")
print(f"Collision force: {e.collision_force}N")
robot.recover_from_errors()JointLimitException
Raised when joint limits are violated.
class JointLimitException(SafetyException):
def __init__(self, message: str, joint_index: int, limit_type: str)Parameters:
message(str): Error descriptionjoint_index(int): Index of joint that violated limitlimit_type(str): Type of limit (position, velocity, acceleration)
Attributes
joint_index(int): Joint index (0-6)limit_type(str): Type of limit violationcurrent_value(Optional[float]): Current joint valuelimit_value(Optional[float]): Limit that was exceeded
WorkspaceLimitException
Raised when workspace limits are violated.
class WorkspaceLimitException(SafetyException):
def __init__(self, message: str, position: np.ndarray)Parameters:
message(str): Error descriptionposition(np.ndarray): Position that violated workspace
Attributes
position(np.ndarray): End-effector positionworkspace_bounds(Optional[dict]): Workspace boundary definition
Communication Exceptions
CommunicationException
Raised when communication with robot fails.
class CommunicationException(FrankaException):
def __init__(self, message: str, communication_error: str)Parameters:
message(str): Error descriptioncommunication_error(str): Type of communication error
Attributes
communication_error(str): Error typepacket_loss(Optional[float]): Packet loss percentagelatency(Optional[float]): Communication latency
Common Causes
- Network connectivity issues
- High network latency
- Packet loss
- Robot firmware issues
Configuration Exceptions
ConfigurationException
Raised when configuration is invalid.
class ConfigurationException(FrankaException):
def __init__(self, message: str, parameter_name: str)Parameters:
message(str): Error descriptionparameter_name(str): Name of invalid parameter
Attributes
parameter_name(str): Invalid parameter nameparameter_value(Optional[Any]): Invalid parameter valuevalid_range(Optional[tuple]): Valid parameter range
Error Handling Utilities
Error Recovery Functions
recover_from_error()
Attempt to recover from specific error types.
def recover_from_error(robot: FrankaRobot,
exception: FrankaException) -> boolParameters:
robot(FrankaRobot): Robot instanceexception(FrankaException): Exception to recover from
Returns:
bool: True if recovery was successful
get_recovery_strategy()
Get recommended recovery strategy for an error.
def get_recovery_strategy(exception: FrankaException) -> strParameters:
exception(FrankaException): Exception to analyze
Returns:
str: Recommended recovery strategy
Error Logging
log_error()
Log error information for debugging.
def log_error(exception: FrankaException,
context: Optional[dict] = None) -> NoneParameters:
exception(FrankaException): Exception to logcontext(Optional[dict]): Additional context information
Examples
Comprehensive Error Handling
import libfrankapy as fp
import logging
import time
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def robust_robot_operation(robot_ip: str):
robot = fp.FrankaRobot(robot_ip)
max_retries = 3
for attempt in range(max_retries):
try:
# Connection phase
logger.info(f"Attempting to connect (attempt {attempt + 1})")
robot.connect()
robot.start_control()
# Control phase
target_joints = [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]
robot.move_to_joint(target_joints, speed_factor=0.1)
logger.info("Operation completed successfully")
return True
except fp.ConnectionException as e:
logger.error(f"Connection failed: {e.message}")
if e.error_code == 1001: # Robot busy
logger.info("Waiting for robot to become available...")
time.sleep(5.0)
elif not e.is_recoverable():
logger.error("Unrecoverable connection error")
break
except fp.CollisionException as e:
logger.error(f"Collision detected: {e.message}")
logger.info(f"Collision force: {e.collision_force}N")
try:
robot.recover_from_errors()
logger.info("Recovered from collision")
except Exception as recovery_error:
logger.error(f"Recovery failed: {recovery_error}")
break
except fp.MotionException as e:
logger.error(f"Motion failed: {e.message}")
if e.target_position is not None:
logger.info(f"Failed target: {e.target_position}")
# Try with reduced speed
try:
robot.move_to_joint(target_joints, speed_factor=0.05)
logger.info("Motion succeeded with reduced speed")
return True
except Exception:
logger.error("Motion failed even with reduced speed")
except fp.SafetyException as e:
logger.error(f"Safety violation: {e.message}")
logger.error(f"Safety violation type: {e.safety_violation}")
if isinstance(e, fp.JointLimitException):
logger.error(f"Joint {e.joint_index} {e.limit_type} limit exceeded")
elif isinstance(e, fp.WorkspaceLimitException):
logger.error(f"Workspace limit exceeded at position: {e.position}")
# Safety violations usually require manual intervention
break
except fp.CommunicationException as e:
logger.error(f"Communication error: {e.message}")
if e.packet_loss and e.packet_loss > 0.1:
logger.warning(f"High packet loss: {e.packet_loss*100:.1f}%")
# Wait and retry for communication issues
time.sleep(2.0)
except fp.FrankaException as e:
logger.error(f"General robot error: {e.message}")
if e.error_code:
logger.error(f"Error code: {e.error_code}")
# Log error for debugging
fp.log_error(e, {'attempt': attempt + 1, 'robot_ip': robot_ip})
except Exception as e:
logger.error(f"Unexpected error: {e}")
break
finally:
try:
robot.stop_control()
robot.disconnect()
except Exception as e:
logger.error(f"Error during cleanup: {e}")
logger.error(f"Operation failed after {max_retries} attempts")
return False
# Usage
if __name__ == "__main__":
success = robust_robot_operation("192.168.1.100")
if success:
print("Robot operation completed successfully")
else:
print("Robot operation failed")Error-specific Recovery
import libfrankapy as fp
def handle_specific_errors(robot: fp.FrankaRobot):
try:
# Some robot operation
robot.move_to_joint([0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785])
except fp.CollisionException as e:
print(f"Collision detected with force {e.collision_force}N")
# Move away from collision
current_joints = robot.get_joint_positions()
safe_joints = current_joints.copy()
safe_joints[e.collision_joint] -= 0.1 # Move joint away
robot.recover_from_errors()
robot.move_to_joint(safe_joints, speed_factor=0.05)
except fp.JointLimitException as e:
print(f"Joint {e.joint_index} {e.limit_type} limit exceeded")
# Move to safe position
safe_joints = [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]
robot.move_to_joint(safe_joints, speed_factor=0.1)
except fp.WorkspaceLimitException as e:
print(f"Workspace limit exceeded at {e.position}")
# Move to workspace center
center_pose = np.eye(4)
center_pose[0:3, 3] = [0.5, 0.0, 0.4] # Safe position
robot.move_to_pose(center_pose, speed_factor=0.1)
except fp.CommunicationException as e:
print(f"Communication error: {e.communication_error}")
# Reconnect if communication is lost
robot.disconnect()
time.sleep(1.0)
robot.connect()
robot.start_control()Custom Exception Handler
import libfrankapy as fp
from typing import Callable, Dict, Type
class RobotErrorHandler:
def __init__(self):
self.handlers: Dict[Type[fp.FrankaException], Callable] = {
fp.ConnectionException: self._handle_connection_error,
fp.CollisionException: self._handle_collision_error,
fp.MotionException: self._handle_motion_error,
fp.SafetyException: self._handle_safety_error,
}
def handle_error(self, robot: fp.FrankaRobot, error: fp.FrankaException) -> bool:
"""Handle robot error and return True if recovery was successful."""
error_type = type(error)
# Find the most specific handler
for exception_type, handler in self.handlers.items():
if isinstance(error, exception_type):
return handler(robot, error)
# Default handler
return self._handle_generic_error(robot, error)
def _handle_connection_error(self, robot: fp.FrankaRobot,
error: fp.ConnectionException) -> bool:
print(f"Handling connection error: {error.message}")
if error.error_code == 1001: # Robot busy
print("Waiting for robot to become available...")
time.sleep(5.0)
try:
robot.connect()
return True
except Exception:
return False
return False
def _handle_collision_error(self, robot: fp.FrankaRobot,
error: fp.CollisionException) -> bool:
print(f"Handling collision: force = {error.collision_force}N")
try:
robot.recover_from_errors()
# Move to safe position
safe_joints = [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]
robot.move_to_joint(safe_joints, speed_factor=0.05)
return True
except Exception:
return False
def _handle_motion_error(self, robot: fp.FrankaRobot,
error: fp.MotionException) -> bool:
print(f"Handling motion error: {error.message}")
# Try with reduced speed
if error.target_position is not None:
try:
robot.move_to_joint(error.target_position, speed_factor=0.05)
return True
except Exception:
return False
return False
def _handle_safety_error(self, robot: fp.FrankaRobot,
error: fp.SafetyException) -> bool:
print(f"Handling safety error: {error.safety_violation}")
# Safety errors usually require manual intervention
robot.stop()
return False
def _handle_generic_error(self, robot: fp.FrankaRobot,
error: fp.FrankaException) -> bool:
print(f"Handling generic error: {error.message}")
if error.is_recoverable():
try:
robot.recover_from_errors()
return True
except Exception:
return False
return False
# Usage
error_handler = RobotErrorHandler()
robot = fp.FrankaRobot("192.168.1.100")
try:
robot.connect()
robot.start_control()
# Robot operations...
except fp.FrankaException as e:
success = error_handler.handle_error(robot, e)
if success:
print("Error handled successfully")
else:
print("Error handling failed")
finally:
robot.stop_control()
robot.disconnect()