Skip to content

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

Manipulator(index, name, state_machine=None, config_source=None)

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

state_machine instance-attribute

state_machine = state_machine

tamper_axis instance-attribute

tamper_axis = 'V'

machine property

machine

Access to machine through state machine for read-only queries.

current_well property

current_well

Access to current well through state machine.

placed_mold_on_scale property

placed_mold_on_scale

Access to mold_on_scale state through state machine.

Functions

_load_config

_load_config(config_source_param)

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: Union[str, Dict[str, Any], None]

RETURNS DESCRIPTION
Optional[Dict[str, Any]]

Configuration dictionary, or None if loading failed

_load_manipulator_config

_load_manipulator_config(config_data)

Load manipulator-specific configuration from config dict (only tamper_axis).

_get_config_dict

_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

home_tamper(machine_connection=None)

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: Optional[Any] DEFAULT: None

Note

Do not home when the mold has a top piston inserted.

tamp

tamp(tamp_depth=40.0, tamp_speed=2000)

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: float DEFAULT: 40.0

tamp_speed

Speed for tamping movement in mm/min (default 2000)

TYPE: int DEFAULT: 2000

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)

vibrate_tamper

vibrate_tamper(machine_connection=None)

get_status

get_status()

Get current manipulator status and configuration.

RETURNS DESCRIPTION
Dict[str, Any]

Dictionary containing manipulator status information

get_current_mold

get_current_mold()

Get the current mold being carried.

RETURNS DESCRIPTION
Optional[Mold]

Mold object if carrying a mold, None otherwise

is_carrying_mold

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_mold(well_id)

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: str

place_mold

place_mold(well_id)

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: str

RETURNS DESCRIPTION
Optional[Mold]

The Mold object that was placed, or None if no mold was being carried

place_top_piston

place_top_piston(piston_dispenser)

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_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_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

class ToolStateError(Exception)

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:

  1. Validates current position (must be at mold slot)
  2. Moves V-axis down to mold height
  3. Moves manipulator under mold
  4. Moves V-axis up with mold
  5. Moves back to mold ready position
  6. 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:

  1. Validates current position
  2. Moves V-axis down
  3. Moves manipulator out from under mold
  4. Moves V-axis up
  5. 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:

  1. Reduce powder volume - Allows the top piston to fit if the powder volume would otherwise prevent insertion
  2. 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_ready position (but can be done at mold_ready positions 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 use
  • v_axis_offset: V-axis offset from machine zero
  • gripper_config: Gripper open/close positions and force
  • mold_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:

# This will raise ToolStateError
manipulator.place_mold("0")  # Error: not holding anything

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