Manipulator API Reference¶
The Manipulator class represents a gripper tool with a vertical axis (V-axis) used for picking and placing molds.
Overview¶
The Manipulator is a custom toolhead that provides:
- Gripper: moves up/down to hold objects
- V-Axis: Vertical movement independent of machine Z-axis
- State Integration: Automatically updates state machine context
Class Reference¶
Manipulator
¶
Bases: Tool
Jubilee toolhead for mold handling and tamping operations. Tracks a Mold object representing the current mold being carried.
State tracking: - current_well: Mold object representing the current mold (None if not carrying one) - The Mold object tracks has_top_piston, valid, weight, and other mold properties
Operations: - Tamping: Only allowed when carrying a mold without a top piston - Top piston placement: Only allowed when carrying a mold without a top piston - Mold handling: Pick up and place Mold objects
Attributes¶
placed_mold_on_scale
property
¶
Access to mold_on_scale state through state machine.
Functions¶
_load_config
¶
Load configuration from either a file path string or a dict.
| PARAMETER | DESCRIPTION |
|---|---|
config_source_param
|
Either a string (path to JSON file) or a dict (already loaded config)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Optional[Dict[str, Any]]
|
Configuration dictionary, or None if loading failed |
_load_manipulator_config
¶
Load manipulator-specific configuration from config dict (only tamper_axis).
_get_config_dict
¶
Helper to package manipulator configuration for state machine calls.
Note: Only returns tamper_axis now. State machine should provide: - tamper_travel_pos (from motion_platform_positions.json z_heights) - safe_z (from motion_platform_positions.json z_heights) - dispenser_safe_z (from motion_platform_positions.json z_heights)
home_tamper
¶
Perform homing for the tamper axis (V-axis).
Can be performed while holding a mold WITHOUT a top piston. The homing process uses the mold itself as a reference: - Start position: v=2 (tamper inserted into mold) - End position: v=-7 (tamper touching bottom of mold)
This allows accurate positioning establishment using the mold as a reference.
Validates and executes through MotionPlatformStateMachine.
| PARAMETER | DESCRIPTION |
|---|---|
machine_connection
|
Deprecated parameter (for backward compatibility)
TYPE:
|
Note
Do not home when the mold has a top piston inserted.
tamp
¶
Perform tamping action to compress powder in the held mold.
Tamping reduces powder volume for two purposes: 1. Allowing the top piston to fit in the mold if it otherwise wouldn't 2. Reducing the amount of powder that becomes airborne when the top piston is inserted
Only allowed if carrying a mold without a top piston. Typically performed at the scale_ready position after filling the mold with powder.
After tamping, the V axis is automatically re-homed to ensure axis accuracy.
| PARAMETER | DESCRIPTION |
|---|---|
tamp_depth
|
Target depth for tamping movement in mm (default 40.0)
TYPE:
|
tamp_speed
|
Speed for tamping movement in mm/min (default 2000)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
|
True if successful |
| RAISES | DESCRIPTION |
|---|---|
RuntimeError
|
If state machine not configured |
ToolStateError
|
If tamping is not allowed in current state or parameters out of bounds |
Note
Valid parameter ranges are defined in system_config.json under manipulator settings: - tamp_depth_min/tamp_depth_max (default: 10-60 mm) - tamp_speed_min/tamp_speed_max (default: 500-5000 mm/min)
get_status
¶
Get current manipulator status and configuration.
| RETURNS | DESCRIPTION |
|---|---|
Dict[str, Any]
|
Dictionary containing manipulator status information |
get_current_mold
¶
Get the current mold being carried.
| RETURNS | DESCRIPTION |
|---|---|
Optional[Mold]
|
Mold object if carrying a mold, None otherwise |
is_carrying_mold
¶
Check if the manipulator is currently carrying a mold.
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if carrying a mold, False otherwise |
pick_mold
¶
Pick up mold from mold slot.
Assumes toolhead is directly above the mold slot at safe_z height with tamper axis in travel position. Validates move through state machine before execution.
| PARAMETER | DESCRIPTION |
|---|---|
well_id
|
Mold slot identifier (numerical string "0" through "17")
TYPE:
|
place_mold
¶
Place down the current mold and return it.
Assumes toolhead is directly above the mold slot at safe_z height with tamper axis in travel position. Validates move through state machine before execution.
| PARAMETER | DESCRIPTION |
|---|---|
well_id
|
Mold slot identifier using numerical indexing (e.g., "0", "1", "2")
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Optional[Mold]
|
The Mold object that was placed, or None if no mold was being carried |
place_top_piston
¶
Place the top piston on the current mold. Only allowed if carrying a mold without a top piston.
Assumes toolhead is at dispenser position. Validates move through state machine before execution.
place_mold_on_scale
¶
Place the current mold on the scale. Only allowed if carrying a mold without a top piston.
Validates move through state machine before execution.
pick_mold_from_scale
¶
Pick up the current mold from the scale. Only allowed if carrying a mold without a top piston.
Validates move through state machine before execution.
Exceptions¶
ToolStateError¶
Exception raised when a tool operation is attempted in an invalid state.
This error is raised when trying to perform operations that require specific tool or payload states that are not currently met.
Common Scenarios: - Attempting to pick a mold when already holding one - Trying to place a mold when not holding one - Operating at wrong position for the requested action
Example:
from src.Manipulator import Manipulator, ToolStateError
try:
manipulator.pick_mold("0")
except ToolStateError as e:
print(f"Operation failed: {e}")
Usage Examples¶
Creating a Manipulator¶
from src.Manipulator import Manipulator
from src.MotionPlatformStateMachine import MotionPlatformStateMachine
# Assume state_machine is already created
manipulator = Manipulator(
index=0, # Tool index on Jubilee
name="manipulator", # Tool name
state_machine=state_machine # Reference to state machine
)
Picking and Placing Molds¶
# Pick up a mold from a well
manipulator.pick_mold(well_id="0")
# Place mold on scale
manipulator.place_mold_on_scale()
# Pick mold from scale
manipulator.pick_mold_from_scale()
# Place mold back in well
manipulator.place_mold(well_id="0")
V-Axis Movement and Homing¶
# Move V-axis to specific position
manipulator.move_v_axis(position=50.0) # 50mm
# Home V-axis
manipulator.home_tamper() # or home_v_axis()
Homing with a Mold:
The V-axis can be homed while holding a mold, as long as the mold does not have a top piston. During homing:
- Start position:
v=2- Tamper is inserted into the mold - End position:
v=-7- Tamper touches the bottom of the mold - This allows the system to establish accurate positioning reference using the mold itself
# Example: Homing after picking up a mold without top piston
manipulator.pick_mold(well_id="0")
manipulator.home_tamper() # Valid - mold has no top piston
# After tamping, V-axis is automatically re-homed
manipulator.tamp() # Automatically homes V-axis after completion
Important: Do not attempt to home the V-axis when: - The mold already has a top piston inserted - Not holding a mold (should home before picking up mold)
Pick and Place Operations¶
Pick Mold¶
The pick_mold() operation:
- Validates current position (must be at mold slot)
- Moves V-axis down to mold height
- Moves manipulator under mold
- Moves V-axis up with mold
- Moves back to mold ready position
- Updates payload state to
"mold"
try:
manipulator.pick_mold(well_id="0")
print("Mold picked successfully")
except ToolStateError as e:
print(f"Pick failed: {e}")
Requirements:
- Must be at the correct mold slot position
- Payload must be "empty"
- V-axis must be homed
Place Mold¶
The place_mold() operation:
- Validates current position
- Moves V-axis down
- Moves manipulator out from under mold
- Moves V-axis up
- Updates payload state to
"empty"
try:
manipulator.place_mold(well_id="0")
print("Mold placed successfully")
except ToolStateError as e:
print(f"Place failed: {e}")
Requirements:
- Must be at the correct mold slot position
- Payload must be "mold" or "mold_with_piston"
Scale Operations¶
Special methods for scale interaction:
# Place on scale
manipulator.place_mold_on_scale()
# Pick from scale
manipulator.pick_mold_from_scale()
These are very similar to regular pick/place for scale interaction.
Tamping Operations¶
Tamp Mold¶
The tamp() method compresses powder in a mold held by the manipulator. This is typically done at the scale_ready position after filling a mold with powder and before inserting the top piston.
Purpose of Tamping:
- Reduce powder volume - Allows the top piston to fit if the powder volume would otherwise prevent insertion
- Minimize airborne powder - Compressing the powder reduces the amount that becomes airborne when the top piston is inserted
# After filling mold with powder
manipulator.pick_mold_from_scale()
# Tamp the powder to compress it
manipulator.tamp(tamp_depth=40.0, tamp_speed=2000)
# Now safe to insert top piston
manager.move_to_dispenser(dispenser_index=0)
manipulator.place_top_piston(piston_dispenser)
Parameters:
tamp_depth(float): Target depth for tamping movement in mm (default: 40.0)- Valid range configured in
system_config.json(default: 10-60 mm) tamp_speed(int): Speed for tamping movement in mm/min (default: 2000)- Valid range configured in
system_config.json(default: 500-5000 mm/min)
Requirements:
- Must be carrying a mold (not empty)
- Mold must NOT have a top piston yet
- Typically performed at
scale_readyposition (but can be done atmold_readypositions too)
How It Works:
After tamping completes, the V axis is automatically re-homed to ensure axis accuracy. The homing process uses the mold itself as a reference:
- Homing starts at
v=2(tamper inserted into mold) - Homing ends at
v=-7(tamper touching bottom of mold) - This establishes an accurate position reference for subsequent operations
Since the mold does not have a top piston during tamping, the V-axis homing is safe and provides precise positioning.
Example with Error Handling:
try:
# Pick mold after filling
manipulator.pick_mold_from_scale()
# Tamp the powder
manipulator.tamp(tamp_depth=40.0, tamp_speed=2000)
print("Tamping successful")
except ToolStateError as e:
print(f"Tamping failed: {e}")
# Handle error - maybe skip tamping and try inserting piston anyway
Common Errors:
# Error: Trying to tamp when not holding a mold
manipulator.tamp() # ToolStateError: Must be carrying a mold
# Error: Trying to tamp after piston is already inserted
manipulator.place_top_piston(piston_dispenser)
manipulator.tamp() # ToolStateError: Cannot tamp mold that has a top piston
# Error: Tamp depth out of bounds (bounds from system_config.json)
manipulator.tamp(tamp_depth=5.0) # ToolStateError: Tamp depth out of bounds
manipulator.tamp(tamp_depth=70.0) # ToolStateError: Tamp depth out of bounds
# Error: Tamp speed out of bounds (bounds from system_config.json)
manipulator.tamp(tamp_speed=100) # ToolStateError: Tamp speed out of bounds
manipulator.tamp(tamp_speed=10000) # ToolStateError: Tamp speed out of bounds
Configuring Bounds:
Tamping parameter bounds can be customized in system_config.json:
{
"manipulator": {
"tamper_axis": "V",
"tamp_depth_min": 10.0,
"tamp_depth_max": 60.0,
"tamp_speed_min": 500,
"tamp_speed_max": 5000
}
}
State Management¶
Automatic State Updates¶
The Manipulator automatically updates the state machine's payload state:
# Initially empty
print(manipulator.state_machine.context.payload_state) # "empty"
# Pick mold
manipulator.pick_mold("0")
print(manipulator.state_machine.context.payload_state) # "mold"
# Place mold
manipulator.place_mold("0")
print(manipulator.state_machine.context.payload_state) # "empty"
Payload States¶
| State | Description | Set By |
|---|---|---|
empty |
Nothing held | place_mold(), place_mold_on_scale() |
mold |
Holding empty mold | pick_mold(), pick_mold_from_scale() |
mold_with_piston |
Holding mold with piston | Manual update after piston insertion |
Configuration¶
Loading Configuration¶
The Manipulator loads its configuration from system_config.json:
{
"tools": {
"manipulator": {
"index": 0,
"park_position": {"x": 0, "y": 0, "z": 100},
"v_axis_offset": 50.0,
"gripper_config": {
"open_position": 5.0,
"close_position": 0.0,
"grip_force": 10.0
},
"mold_heights": {
"pickup_height": 15.0,
"clearance_height": 50.0
}
}
}
}
Configuration Parameters¶
index: Tool index on Jubilee (usually 0)park_position: Where tool parks when not in usev_axis_offset: V-axis offset from machine zerogripper_config: Gripper open/close positions and forcemold_heights: Heights for mold pickup and clearance
Accessing Configuration¶
# Get current configuration as dict
config = manipulator._get_config_dict()
print(config)
# Configuration is loaded automatically from ConfigLoader
Error Handling¶
Common Error Scenarios¶
Picking when not empty:
# This will raise ToolStateError
manipulator.pick_mold("0")
manipulator.pick_mold("1") # Error: already holding mold
Placing when empty:
Wrong position:
# Move to wrong position
state_machine.validated_move_to_scale()
# This will raise ToolStateError
manipulator.pick_mold("0") # Error: not at mold slot
Advanced Usage¶
Integration with State Machine¶
The Manipulator is tightly integrated with the state machine:
# Create manipulator with state machine reference
manipulator = Manipulator(
index=0,
name="manipulator",
state_machine=state_machine
)
# Manipulator automatically updates state machine context
manipulator.pick_mold("0")
# State machine knows about the payload
result = state_machine.validated_move_to_scale()
if not result.valid:
print(f"Move failed: {result.reason}")
# Might fail if payload not allowed at scale
Best Practices¶
Use Try-Except Blocks¶
Always handle ToolStateError:
try:
manipulator.pick_mold("0")
manipulator.place_mold_on_scale()
except ToolStateError as e:
print(f"Operation failed: {e}")
# Handle error appropriately
# Maybe release gripper, move to safe position, etc.
Coordinate with State Machine¶
Don't bypass state machine validation:
# GOOD: Use state machine for movements
result = state_machine.validated_move_to_mold_slot("0")
if result.valid:
manipulator.pick_mold("0")
# BAD: Direct machine control bypasses validation
machine.move_to(x=100, y=100, z=50) # Not validated!
manipulator.pick_mold("0") # May fail or cause collision
See Also¶
- JubileeManager - High-level interface using Manipulator
- MotionPlatformStateMachine - State tracking and validation
- PistonDispenser - Related component
- Quick Start Guide - Basic usage examples