---
title: "Migration Guide sdk v2.2.0 to v3.0.0"
slug: "migrationguide"
updated: 2026-02-13T21:55:12Z
published: 2026-02-13T21:55:12Z
---

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vention.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Guide sdk v2.2.0 to v3.0.0

This guide helps you migrate your Python applications from MachineLogic 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 |
