Quick Reference Guide¶
Essential commands and patterns for the Robot Workspace package.
Table of Contents¶
- Installation
- Core Imports
- Pose Objects
- Workspaces
- Objects
- Spatial Queries
- Serialization
- Common Patterns
- Testing
- Troubleshooting
Installation¶
# Basic installation
pip install -e .
# With Niryo support
pip install -e ".[niryo]"
# Development installation
pip install -e ".[dev]"
# All features
pip install -e ".[all]"
Core Imports¶
# Essential classes
from robot_workspace import (
PoseObjectPNP, # 6-DOF pose
Object, # Detected object
Objects, # Object collection
Location, # Spatial relationships
Workspace, # Abstract workspace
Workspaces, # Workspace collection
NiryoWorkspace, # Niryo implementation
NiryoWorkspaces, # Niryo collection
WidowXWorkspace, # WidowX implementation
WidowXWorkspaces, # WidowX collection
ConfigManager, # Configuration management
)
# For mocking (testing/demos)
from unittest.mock import Mock
Pose Objects¶
Create a Pose¶
# Create 6-DOF pose
pose = PoseObjectPNP(
x=0.2, # meters
y=0.1, # meters
z=0.3, # meters
roll=0.0, # radians
pitch=1.57, # radians (~90°)
yaw=0.0 # radians
)
Pose Operations¶
# Arithmetic
new_pose = pose1 + pose2
difference = pose1 - pose2
# Copy with offsets
offset_pose = pose.copy_with_offsets(
x_offset=0.05,
yaw_offset=0.5
)
# Convert to list
pose_list = pose.to_list() # [x, y, z, roll, pitch, yaw]
# Get transformation matrix
matrix = pose.to_transformation_matrix() # 4x4 numpy array
# Get quaternion
quat = pose.quaternion # [qx, qy, qz, qw]
# Check equality
is_equal = pose1 == pose2
is_close = pose1.approx_eq(pose2, eps_position=0.1, eps_orientation=0.1)
Workspaces¶
Initialize with Mock Environment¶
from unittest.mock import Mock
# Create mock environment
def create_mock_env():
env = Mock()
env.use_simulation.return_value = True
def mock_transform(ws_id, u_rel, v_rel, yaw):
x = 0.4 - u_rel * 0.3
y = 0.15 - v_rel * 0.3
return PoseObjectPNP(x, y, 0.05, 0.0, 1.57, yaw)
env.get_robot_target_pose_from_rel = mock_transform
return env
# Create workspaces
env = create_mock_env()
workspaces = NiryoWorkspaces(env, verbose=False)
Initialize with Configuration¶
from robot_workspace import NiryoWorkspaces, ConfigManager
# Using configuration file
workspaces = NiryoWorkspaces(
environment,
config_path='config/niryo_config.yaml'
)
# Or manually with ConfigManager
config_mgr = ConfigManager()
config_mgr.load_from_yaml('config/niryo_config.yaml')
ws_config = config_mgr.get_workspace_config('niryo_ws')
workspace = NiryoWorkspace.from_config(ws_config, environment)
Access Workspaces¶
# Get home workspace
home = workspaces.get_home_workspace()
# Get by ID
ws = workspaces.get_workspace_by_id("niryo_ws")
# Get by index
ws = workspaces.get_workspace(0)
# Get all IDs
ids = workspaces.get_workspace_ids()
# Get workspace properties
width = workspace.width_m()
height = workspace.height_m()
center = workspace.xy_center_wc()
obs_pose = workspace.observation_pose()
Coordinate Transformation¶
# Transform relative image coords to world coords
world_pose = workspace.transform_camera2world_coords(
workspace_id="niryo_ws",
u_rel=0.5, # [0-1] horizontal
v_rel=0.5, # [0-1] vertical
yaw=0.0 # object orientation
)
Objects¶
Create an Object¶
# Without mask
obj = Object(
label="pencil",
u_min=100, v_min=100, # Bounding box
u_max=200, v_max=200,
mask_8u=None,
workspace=workspace
)
# With segmentation mask
import numpy as np
mask = np.zeros((640, 480), dtype=np.uint8)
mask[100:200, 100:200] = 255
obj_with_mask = Object(
label="cube",
u_min=100, v_min=100,
u_max=200, v_max=200,
mask_8u=mask,
workspace=workspace
)
Access Object Properties¶
# Basic properties
label = obj.label()
position = obj.coordinate() # [x, y]
x, y = obj.x_com(), obj.y_com()
full_pose = obj.pose_com()
# Dimensions
width = obj.width_m()
height = obj.height_m()
area = obj.size_m2()
# Orientation
rotation = obj.gripper_rotation() # radians
Update Object Position¶
# Update XY position
obj.set_position([0.3, 0.05])
# Update full pose (including rotation)
new_pose = obj.pose_com().copy_with_offsets(
x_offset=0.1,
yaw_offset=0.5
)
obj.set_pose_com(new_pose)
Spatial Queries¶
Create Collection¶
Location-Based Queries¶
# Find objects by location
left_objects = objects.get_detected_objects(
location=Location.LEFT_NEXT_TO,
coordinate=[0.25, 0.0]
)
right_objects = objects.get_detected_objects(
location=Location.RIGHT_NEXT_TO,
coordinate=[0.25, 0.0]
)
above_objects = objects.get_detected_objects(
location=Location.ABOVE,
coordinate=[0.25, 0.0]
)
below_objects = objects.get_detected_objects(
location=Location.BELOW,
coordinate=[0.25, 0.0]
)
# Within 2cm radius
nearby = objects.get_detected_objects(
location=Location.CLOSE_TO,
coordinate=[0.25, 0.0]
)
Label-Based Queries¶
# Find by label
pens = objects.get_detected_objects(label="pen")
# Combine location and label
left_pens = objects.get_detected_objects(
location=Location.LEFT_NEXT_TO,
coordinate=[0.25, 0.0],
label="pen"
)
# Get specific object
obj = objects.get_detected_object(
coordinate=[0.2, 0.1],
label="pencil"
)
Distance and Size Queries¶
# Find nearest
nearest, distance = objects.get_nearest_detected_object([0.2, 0.1])
# Find largest/smallest
largest, size = objects.get_largest_detected_object()
smallest, size = objects.get_smallest_detected_object()
# Sort by size
sorted_asc = objects.get_detected_objects_sorted(ascending=True)
sorted_desc = objects.get_detected_objects_sorted(ascending=False)
Serialization¶
Object Serialization¶
# To dictionary
obj_dict = obj.to_dict()
# To JSON string
json_str = obj.to_json()
# From dictionary
reconstructed = Object.from_dict(obj_dict, workspace)
# From JSON string
reconstructed = Object.from_json(json_str, workspace)
Collection Serialization¶
# To list of dicts
dict_list = Objects.objects_to_dict_list(objects)
# From list of dicts
reconstructed = Objects.dict_list_to_objects(dict_list, workspace)
# Get serializable results directly
obj_dict = objects.get_detected_object(
[0.2, 0.1],
serializable=True
)
sorted_dicts = objects.get_detected_objects_sorted(
serializable=True
)
Common Patterns¶
Pick and Place Workflow¶
# 1. Initialize
workspaces = NiryoWorkspaces(environment)
workspace = workspaces.get_home_workspace()
# 2. Detect objects
detected = Objects([obj1, obj2, obj3])
# 3. Find target
target = detected.get_detected_object(
coordinate=[0.2, 0.1],
label="cube"
)
# 4. Get pickup info
pickup_pose = target.pose_com()
rotation = target.gripper_rotation()
# 5. Execute pick (using robot API)
# robot.pick(pickup_pose, rotation)
# 6. Define place location
place_pose = PoseObjectPNP(0.3, -0.1, 0.05, 0.0, 1.57, 0.0)
# 7. Execute place
# robot.place(place_pose)
# 8. Update object in memory
target.set_pose_com(place_pose)
Sorting by Size¶
# Get sorted objects
sorted_objs = objects.get_detected_objects_sorted(ascending=True)
# Place in order
for i, obj in enumerate(sorted_objs):
place_pose = PoseObjectPNP(
x=0.3,
y=-0.1 + i * 0.05, # 5cm spacing
z=0.05,
roll=0.0,
pitch=1.57,
yaw=obj.gripper_rotation()
)
# robot.pick_and_place(obj.pose_com(), place_pose)
obj.set_pose_com(place_pose)
Multi-Workspace Transfer¶
# Get workspaces
left_ws = workspaces.get_workspace_left()
right_ws = workspaces.get_workspace_right()
# Get objects in each
left_objects = Objects([...])
right_objects = Objects([...])
# Transfer object
transfer_obj = left_objects.get_detected_object([0.2, 0.1])
if transfer_obj:
left_objects.remove(transfer_obj)
# New position in right workspace
new_pose = right_ws.transform_camera2world_coords(
right_ws.id(), 0.5, 0.5, 0.0
)
transfer_obj.set_pose_com(new_pose)
right_objects.append(transfer_obj)
LLM Integration¶
# Format for LLM
description = obj.as_string_for_llm()
# Output: "- 'pencil' at world coordinates [0.20, 0.10] with..."
# Format for chat
chat_msg = obj.as_string_for_chat_window()
# Output: "Detected a new object: pencil at..."
# Get all objects as text
for obj in objects:
print(obj.as_string_for_llm())
Testing¶
Run Tests¶
# All tests
pytest
# With coverage
pytest --cov=robot_workspace --cov-report=term
# Specific test file
pytest tests/objects/test_object.py
# Specific test
pytest tests/objects/test_object.py::test_object_initialization
# Verbose output
pytest -v
# Stop on first failure
pytest -x
Run Demo¶
Troubleshooting¶
Common Issues¶
# Import error
# Solution: Install in editable mode
pip install -e .
# Missing workspace image shape
try:
obj = Object(...)
except ValueError as e:
print("Set workspace image shape first")
workspace.set_img_shape((640, 480, 3))
# Object not found
obj = objects.get_detected_object([0.2, 0.1])
if obj is None:
print("No object at that location")
# Workspace not visible
visible_ws = workspaces.get_visible_workspace(camera_pose)
if visible_ws is None:
print("No workspace visible from camera")
Debug Mode¶
# Enable verbose output
workspaces = NiryoWorkspaces(environment, verbose=True)
workspace = NiryoWorkspace("niryo_ws", environment, verbose=True)
obj = Object(..., verbose=True)
objects = Objects([...], verbose=True)
Coordinate Systems Reference¶
Image Coordinates (pixels)
↓ normalize by image dimensions
Relative Coordinates (0-1)
↓ transform_camera2world_coords()
World Coordinates (meters)
Niryo Coordinate System¶
Y (left/right)
↑
│ Workspace
│ ┌─────────┐
│ │ │
│ │ • │ ← Center
│ │ │
│ └─────────┘
└──────────────→ X (forward/back)
Z (up/down) ⊙ (out of page)
Location Filters¶
LEFT_NEXT_TO: y > coordinate[1]RIGHT_NEXT_TO: y < coordinate[1]ABOVE: x > coordinate[0]BELOW: x < coordinate[0]CLOSE_TO: within 2cm radius
Quick Command Reference¶
| Task | Command |
|---|---|
| Install package | pip install -e . |
| Run tests | pytest |
| Run demo | python main.py |
| Format code | black . |
| Lint code | ruff check . |
| Type check | mypy robot_workspace |
| Generate coverage | pytest --cov --cov-report=html |
File Structure¶
robot_workspace/
├── objects/ # Object representation
│ ├── pose_object.py # 6-DOF pose
│ ├── object.py # Single object
│ ├── objects.py # Collection
│ └── object_api.py # API interface
├── workspaces/ # Workspace management
│ ├── workspace.py # Abstract base
│ ├── workspaces.py # Collection
│ ├── niryo_*.py # Niryo implementation
│ └── widowx_*.py # WidowX implementation
├── config.py # Configuration
└── common/ # Utilities
└── logger.py # Logging
Links¶
- Documentation: docs/README.md
- API Reference: docs/api.md
- Examples: docs/examples.md
- Installation: docs/INSTALL.md
- Testing: docs/TESTING.md
- Contributing: CONTRIBUTING.md
Support¶
- Issues: GitHub Issues
- Email: daniel.gaida@th-koeln.de
- Repository: https://github.com/dgaida/robot_workspace
Version: 0.1.6 Author: Daniel Gaida Last Updated: December 2024