--- title: "Migration guide machine-logic-sdk v2.2.0 to v3.0.0" slug: "migrationguide" updated: 2026-08-21T19:26:18Z published: 2026-08-21T19:26:18Z canonical: "docs.vention.com/migrationguide" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.vention.com/llms.txt > Use this file to discover all available pages before exploring further. # Migration guide machine-logic-sdk v2.2.0 to v3.0.0 This guide helps you migrate your Python applications from machine-logic-sdk v2.2.0 to v3.0.0. The v3.0.0 release introduces significant changes to our robot programming SDK. --- ## Table of Contents 1. [Breaking Changes Overview](/docs/migrationguide#breaking-changes-overview) 2. [Robot API Changes](/docs/migrationguide#robot-api-changes) - [Operational State Enum Changes](/docs/migrationguide#operational-state-enum-changes) - [Safety State Enum Changes](/docs/migrationguide#safety-state-enum-changes) - [Removed Methods](/docs/migrationguide#removed-methods) - [Changed Method Signatures](/docs/migrationguide#changed-method-signatures) - [New Methods](/docs/migrationguide#new-methods) 3. [RobotState Changes](/docs/migrationguide#robotstate-changes) 4. [Sequence Builder Changes](/docs/migrationguide#sequence-builder-changes) 5. [Callback Management Changes](/docs/migrationguide#callback-management-changes) 6. [Migration Examples](/docs/migrationguide#migration-examples) 7. [Quick Reference Table](/docs/migrationguide#quick-reference-table) --- ## Breaking Changes Overview | Category | Change Type | v2.2.0 | v3.0.0 | | --- | --- | --- | --- | | Robot States | **Breaking** | Previous enums | New enums (different values) | | Teach Mode | **Removed** | `robot.teach_mode()` context manager | Use `set_to_freedrive()` + `set_to_normal()` | | Set Payload | **Breaking** | `set_payload(weight) → bool` | `set_payload(weight, center_of_mass, inertia?) → None` | | Timestamp | **Breaking** | Custom `Timestamp` type | Standard Python `datetime` | | Sequence Return | **Breaking** | `execute_sequence() → bool` | `execute_sequence() → None` | | Wait for Motion | **Breaking** | `wait_for_motion_completion(timeout?) → bool` | `wait_for_motion_completion() → None` | | Digital I/O | **Removed** | `robot.set_tool_digital_output()` | Removed | | Velocity Limits | **Deprecated** | Returns actual limits | Returns default values (250.0 mm/s, 120.0 deg/s) | --- ## Robot API Changes ### Operational State Enum Changes The `RobotOperationalState` enum has been completely redesigned. **Both the names and values have changed.** #### v2.2.0 ```python from machinelogic.ivention.irobot import RobotOperationalState        # Old enum values        RobotOperationalState.OFFLINE # = 0        RobotOperationalState.NON_OPERATIONAL # = 1        RobotOperationalState.FREEDRIVE # = 2        RobotOperationalState.NORMAL # = 3        RobotOperationalState.UNKNOWN # = 4        RobotOperationalState.NEED_MANUAL_INTERVENTION # = 5 ``` #### v3.0.0 ```python from machinelogic.types import RobotOperationalState        # New enum values        RobotOperationalState.UNKNOWN # = 0 (value changed from 4)        RobotOperationalState.IDLE # = 1 ✨ NEW        RobotOperationalState.RUNNING # = 2 ✨ NEW        RobotOperationalState.JOGGING # = 3 ✨ NEW        RobotOperationalState.FREEDRIVE # = 4 (value changed from 2)        RobotOperationalState.STOPPING # = 5 ✨ NEW        RobotOperationalState.NON_OPERATIONAL # = 6 (value changed from 1) ``` #### Migration Notes | Old State (v2.2.0) | New State (v3.0.0) | Action Required | | --- | --- | --- | | `OFFLINE = 0` | ❌ Removed | Check for `NON_OPERATIONAL` instead | | `NON_OPERATIONAL = 1` | `NON_OPERATIONAL = 6` | Update value comparisons | | `FREEDRIVE = 2` | `FREEDRIVE = 4` | Update value comparisons | | `NORMAL = 3` | ❌ Removed | Use `IDLE` or `RUNNING` instead | | `UNKNOWN = 4` | `UNKNOWN = 0` | Update value comparisons | | `NEED_MANUAL_INTERVENTION = 5` | ❌ Removed | Handle via safety states | | - | `IDLE = 1` ✨ | Robot ready but not moving | | - | `RUNNING = 2` ✨ | Robot executing trajectory | | - | `JOGGING = 3` ✨ | Robot in jog mode | | - | `STOPPING = 5` ✨ | Robot stopping motion | **Before (v2.2.0):** ```python if robot.state.operational_state == RobotOperationalState.NORMAL:        print("Robot ready") ``` **After (v3.0.0):** ```python if robot.state.operational_state == RobotOperationalState.IDLE:        print("Robot ready")        # Or check for running state        if robot.state.operational_state == RobotOperationalState.RUNNING:        print("Robot is executing a trajectory") ``` --- ### Safety State Enum Changes The `RobotSafetyState` enum has also been updated. #### v2.2.0 ```python RobotSafetyState.NORMAL # = 0        RobotSafetyState.EMERGENCY_STOP # = 2        RobotSafetyState.REDUCED_SPEED # = 3        RobotSafetyState.SAFEGUARD_STOP # = 4        RobotSafetyState.UNKNOWN # = 5 ``` #### v3.0.0 ```python RobotSafetyState.UNKNOWN # = 0 (value changed from 5)        RobotSafetyState.NORMAL # = 1 (value changed from 0)        RobotSafetyState.EMERGENCY_STOP # = 2 (unchanged)        RobotSafetyState.REDUCED_SPEED # = 3 (unchanged)        RobotSafetyState.RECOVERABLE_FAULT # = 4 ✨ NEW (replaces SAFEGUARD_STOP) ``` #### Migration Notes | Old State (v2.2.0) | New State (v3.0.0) | Action Required | | --- | --- | --- | | `NORMAL = 0` | `NORMAL = 1` | Update value comparisons | | `SAFEGUARD_STOP = 4` | ❌ Removed | Use `RECOVERABLE_FAULT` instead | | `UNKNOWN = 5` | `UNKNOWN = 0` | Update value comparisons | | - | `RECOVERABLE_FAULT = 4` ✨ | Handle recoverable faults | --- ### Removed Methods The following methods have been **removed** in v3.0.0: #### `robot.teach_mode()` - Context Manager for Freedrive **v2.2.0:** ```python with my_robot.teach_mode():        print("Robot is in teach mode for 5 seconds")        time.sleep(5)        # Robot automatically returns to normal mode ``` **v3.0.0:** ```python my_robot.set_to_freedrive()        print("Robot is in freedrive mode for 5 seconds")        time.sleep(5)        my_robot.set_to_normal() ``` #### `robot.set_tool_digital_output(pin, value)` This method has been **removed**. Tool digital outputs are no longer managed through the Robot class. **v2.2.0:** ```python my_robot.set_tool_digital_output(pin=1, value=1) ``` **v3.0.0:** This functionality is no longer available through the SDK. #### `robot.state.get_digital_input_value(pin)` **v2.2.0:** ```python value = my_robot.state.get_digital_input_value(pin=1) ``` **v3.0.0:** This method has been removed. #### `robot.state.cartesian_position` and `robot.state.joint_angles` These deprecated properties have been **removed**. Use `cartesian_position_data` and `joint_angles_data` instead. **v2.2.0:** ```python # These were already deprecated in v1.14.0        position = my_robot.state.cartesian_position        angles = my_robot.state.joint_angles ``` **v3.0.0:** ```python position, timestamp = my_robot.state.cartesian_position_data        angles, timestamp = my_robot.state.joint_angles_data ``` --- ### Changed Method Signatures #### `robot.set_payload()` **v2.2.0:** ```python def set_payload(self, payload: Kilograms) -> bool:        ...        # Usage        success = my_robot.set_payload(2.76)        if success:        print("Payload set") ``` **v3.0.0:** ```python def set_payload(        self,        payload: Kilograms,        center_of_mass: Vector, # Required: [x, y, z] in mm        inertia: Inertia | None = None # Optional: [ixx, ixy, ixz, iyy, iyz, izz] in kg·mm²        ) -> None:        ...        # Usage        my_robot.set_payload(2.76, center_of_mass=[10, 10, 10])        print("Payload set")        # With inertia (optional)        my_robot.set_payload(        2.76,        center_of_mass=[10, 10, 10],        inertia=[100, 0, 0, 100, 0, 100]        ) ``` #### `robot.execute_sequence()` and `robot.execute_sequence_async()` **v2.2.0:** ```python def execute_sequence(self, sequence: ISequenceBuilder) -> bool:        ...        # Usage        success = my_robot.execute_sequence(seq)        if not success:        print("Sequence execution failed") ``` **v3.0.0:** ```python def execute_sequence(self, sequence: IRobotMoveSequence) -> None:        ...        # Usage - raises exception on failure        my_robot.execute_sequence(seq) ``` #### `robot.wait_for_motion_completion()` **v2.2.0:** ```python def wait_for_motion_completion(self, timeout: float | None = None) -> bool:        ...        # Usage        success = my_robot.wait_for_motion_completion(timeout=30.0) ``` **v3.0.0:** ```python def wait_for_motion_completion(self) -> None:        ...        # Usage - timeout parameter removed        my_robot.wait_for_motion_completion() ``` #### `robot.reset()` → `robot.set_to_normal()` (Deprecated) **v2.2.0:** ```python success = my_robot.reset() ``` **v3.0.0:** ```python # reset() is deprecated, use set_to_normal() instead        my_robot.set_to_normal()        # reset() still works but is deprecated        success = my_robot.reset() # Deprecated ``` --- ### New Methods #### `robot.set_to_normal()` Sets the robot to normal operational state. This is the preferred replacement for `reset()`. ```python my_robot.set_to_normal() ``` #### `robot.set_to_freedrive()` Puts the robot into freedrive mode. Use with `set_to_normal()` to replace the removed `teach_mode()` context manager. ```python my_robot.set_to_freedrive()        # Robot can be manually moved        time.sleep(5)        my_robot.set_to_normal() ``` #### `robot.remove_log_alarm_callback(callback_id)` Remove a previously registered log alarm callback. ```python callback_id = my_robot.on_log_alarm(my_callback)        # Later...        my_robot.remove_log_alarm_callback(callback_id) ``` #### `robot.remove_system_state_change_callback(callback_id)` Remove a previously registered system state change callback. ```python callback_id = my_robot.on_system_state_change(my_callback)        # Later...        my_robot.remove_system_state_change_callback(callback_id) ``` --- ## RobotState Changes ### Timestamp Type Change The timestamp returned by `cartesian_position_data` and `joint_angles_data` has changed from a custom `Timestamp` namedtuple to a standard Python `datetime` object. **v2.2.0:** ```python joint_angles, timestamp = my_robot.state.joint_angles_data        # timestamp was a custom Timestamp namedtuple with seconds and nanoseconds        print(f"Timestamp: {timestamp}") # Timestamp(seconds=..., nanoseconds=...) ``` **v3.0.0:** ```python joint_angles, timestamp = my_robot.state.joint_angles_data        # timestamp is now a standard datetime object        print(f"Timestamp: {timestamp.isoformat()}") # 2026-02-12T10:30:00.123456 ``` --- ## Sequence Builder Changes ### Blend Parameter Change The blend parameter in `append_movel` and `append_movej` has changed from a `blend_factor` (0.0-1.0 scale factor) to a `blend_radius` (millimeters). **v2.2.0:** ```python seq = my_robot.create_sequence()        seq.append_movel(target, velocity, acceleration, blend_factor=0.5) # Scale factor        seq.append_movej(target, velocity, acceleration, blend_factor=0.5) ``` **v3.0.0:** ```python seq = my_robot.create_sequence()        seq.append_movel(target, velocity, acceleration, blend_radius=5.0) # Millimeters        seq.append_movej(target, velocity, acceleration, blend_radius=5.0) ``` ### Context Manager Support v3.0.0 adds context manager support for sequences with automatic execution: ```python # Synchronous execution with context manager        with my_robot.create_sequence() as seq:        seq.append_movej(joint_target, velocity=10.0, acceleration=10.0)        seq.append_movel(cartesian_target, velocity=100.0, acceleration=100.0)        # Sequence executes automatically on exit        # Async execution with context manager        with my_robot.create_sequence().execute_async_on_exit() as seq:        seq.append_movej(joint_target, velocity=10.0, acceleration=10.0)        # Sequence starts executing asynchronously on exit ``` --- ## Callback Management Changes ### `on_system_state_change()` Now Returns a Callback ID **v2.2.0:** ```python my_robot.on_system_state_change(handle_state_change)        # No way to remove the callback ``` **v3.0.0:** ```python callback_id = my_robot.on_system_state_change(handle_state_change)        # Later, you can remove it:        my_robot.remove_system_state_change_callback(callback_id) ``` ### Import Path for Types **v2.2.0:** ```python from machinelogic.ivention.irobot import RobotOperationalState, RobotSafetyState ``` **v3.0.0:** ```python from machinelogic.types import RobotOperationalState, RobotSafetyState ``` --- ## Migration Examples ### Example 1: Basic Robot State Monitoring **v2.2.0:** ```python from machinelogic import Machine        from machinelogic.ivention.irobot import RobotOperationalState, RobotSafetyState        machine = Machine()        robot = machine.get_robot("Robot")        def handle_state(op_state: RobotOperationalState, safety_state: RobotSafetyState):        if op_state == RobotOperationalState.NORMAL:        print("Robot is in normal mode")        elif op_state == RobotOperationalState.FREEDRIVE:        print("Robot is in freedrive")        robot.on_system_state_change(handle_state) ``` **v3.0.0:** ```python from machinelogic import Machine        from machinelogic.types import RobotOperationalState, RobotSafetyState        machine = Machine()        robot = machine.get_robot("Robot")        def handle_state(op_state: RobotOperationalState, safety_state: RobotSafetyState):        if op_state == RobotOperationalState.IDLE:        print("Robot is ready (idle)")        elif op_state == RobotOperationalState.RUNNING:        print("Robot is executing a trajectory")        elif op_state == RobotOperationalState.FREEDRIVE:        print("Robot is in freedrive")        callback_id = robot.on_system_state_change(handle_state)        # Store callback_id if you need to remove the callback later ``` ### Example 2: Teach Mode / Freedrive **v2.2.0:** ```python import time        from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        # Using context manager        with robot.teach_mode():        print("Teach mode active")        time.sleep(10)        # Automatically exits teach mode ``` **v3.0.0:** ```python import time        from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        # Manual freedrive control        robot.set_to_freedrive()        print("Freedrive active")        time.sleep(10)        robot.set_to_normal()        print("Back to normal") ``` ### Example 3: Setting Payload **v2.2.0:** ```python from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        success = robot.set_payload(2.5)        if success:        print("Payload configured")        else:        print("Failed to set payload") ``` **v3.0.0:** ```python from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        # center_of_mass is now required [x, y, z] in mm        robot.set_payload(        payload=2.5,        center_of_mass=[0, 0, 50], # 50mm above the flange        inertia=None # Optional        )        print("Payload configured") ``` ### Example 4: Execute Sequence **v2.2.0:** ```python from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        joint_target = [10, 20, 30, 40, 50, 60]        seq = robot.create_sequence()        seq.append_movej(joint_target, 10.0, 10.0, 0.5) # blend_factor        success = robot.execute_sequence(seq)        if not success:        print("Sequence failed")        success = robot.wait_for_motion_completion(timeout=30.0) ``` **v3.0.0:** ```python from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        joint_target = [10, 20, 30, 40, 50, 60]        # Option 1: Manual execution        seq = robot.create_sequence()        seq.append_movej(joint_target, 10.0, 10.0, 5.0) # blend_radius in mm        robot.execute_sequence(seq) # Raises on failure, no return value        # Option 2: Context manager (cleaner)        with robot.create_sequence() as seq:        seq.append_movej(joint_target, velocity=10.0, acceleration=10.0, blend_radius=5.0)        # Automatically executes and waits ``` ### Example 5: Reading Position Data **v2.2.0:** ```python from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        angles, timestamp = robot.state.joint_angles_data        print(f"Joint angles: {angles}")        print(f"Timestamp seconds: {timestamp.seconds}, ns: {timestamp.nanoseconds}") ``` **v3.0.0:** ```python from machinelogic import Machine        machine = Machine()        robot = machine.get_robot("Robot")        angles, timestamp = robot.state.joint_angles_data        print(f"Joint angles: {angles}")        print(f"Timestamp: {timestamp.isoformat()}") # Standard datetime ``` --- ## Quick Reference Table | Feature | v2.2.0 | v3.0.0 | | --- | --- | --- | | **Import enums** | `from machinelogic.ivention.irobot import ...` | `from machinelogic.types import ...` | | **Check robot ready** | `state == NORMAL` | `state == IDLE` | | **Check robot moving** | `state.move_in_progress` | `state == RUNNING` or `state.move_in_progress` | | **Freedrive mode** | `with robot.teach_mode():` | `robot.set_to_freedrive()` / `robot.set_to_normal()` | | **Reset robot** | `robot.reset()` | `robot.set_to_normal()` | | **Set payload** | `robot.set_payload(kg)` | `robot.set_payload(kg, [x,y,z])` | | **Execute sequence** | `success = robot.execute_sequence(seq)` | `robot.execute_sequence(seq)` | | **Wait for motion** | `robot.wait_for_motion_completion(timeout=30)` | `robot.wait_for_motion_completion()` | | **Blend parameter** | `blend_factor` (0-1) | `blend_radius` (mm) | | **Timestamp type** | `Timestamp(seconds, nanoseconds)` | `datetime` | | **Remove callbacks** | Not supported | `robot.remove_system_state_change_callback(id)` | --- ## Deprecated Features The following features are deprecated in v3.0.0 and will be removed in a future version: | Feature | Status | Replacement | | --- | --- | --- | | `robot.reset()` | Deprecated | `robot.set_to_normal()` | | `robot.set_tcp_offset()` | Deprecated (since v2.2.0) | `robot.set_active_tcp()` | | `robot.configuration.cartesian_velocity_limit` | Deprecated | Returns default 250.0 mm/s | | `robot.configuration.joint_velocity_limit` | Deprecated | Returns default 120.0 deg/s |