Skip to main content
Version: v26.06

Emio API

Emio API is a Python package created to control the Emio robot.

Emio API uses tkinter for the GUI. On certains OS, you may need to install additional packages to use tkinter.

On Ubuntu, you can install it using the following command:

sudo apt-get install tk

To install it from PyPI, run the following command:

pip install emioapi

To install the latest version from the Github repository, run:

pip install git+https://github.com/SofaComplianceRobotics/Emio.API.git@main

EmioAPI Class

class EmioAPI()

Class to control emio motors. It is essentially divided into two objects:

The EmioAPI class is the main class that combines both classes and provides a simple interface to control the emio device. It also provides static utility methods to list the emio devices connected to the computer.

Motors:

The motors are controlled in position mode. The class is thread-safe and can be used in a multi-threaded environment. All the data sent to the motors are list of 4 values for the 4 motors of the emio device. The order in the list corresponds to the motor ID's in the emio device. Motor 0 is the first motor in the list, motor 1 is the second motor, etc. You can open a connection directly to the motors using the open method of the motors object.

warning

Emio motors are clamped between 0 and PI radians (0 and 180 degrees). If you input a value outside this range, the motor will not move. Important: the security temperature for the motors is 53°C. Above this temperature, the motors turn the torque off. Close the connection and turn off Emio, let it cool for a few minutes then Emio back on.

Camera:

The camera is used to track objects and compute the point cloud. The camera parameters are stored in a config file. If the config file is not found, default values are used. The camera can be configured to show the frames, track objects, and compute the point cloud. You can open a connection directly to the camera using the open method of the camera object.

warning

By default, EmioAPI launches the camera in the same process by creating an EmioCamera object. You can launch the camera in another process using a MultiProcessEmioCamera by setting the multiprocess_camera=True when creating an EmioAPI object.

Example:

from emioapi import EmioAPI

# Create an EmioAPI instance
emio = EmioAPI(multiprocess_camera=False)

# Connect to the first available Emio device
if emio.connectToEmioDevice():
print("Connected to Emio device.")

# Print device status
emio.printStatus()

# Example: Move all motors to 90 degrees (PI/2 radians)
target_angles = [math.pi/2] * 4
emio.motors.angles = target_angles

# Disconnect when done
emio.disconnect()
else:
print("Failed to connect to Emio device.")

motors

The emio motors object: EmioMotors

camera

The emio camera object: EmioCamera | MultiprocessEmioCamera

device_name

@property
def device_name() -> str | None

Get the port name to which the EmioAPI object is connected if connected, else None

camera_serial

@property
def camera_serial() -> str | None

Get the camera serial number to which the EmioAPI object is connected if connected, else None

listEmioDevices

@staticmethod
def listEmioDevices() -> list

List all the emio devices connected to the computer.

Returns:

A list of device names (the ports).

listUnusedEmioDevices

@staticmethod
def listUnusedEmioDevices() -> list

List all the emio devices that are not currently used by any instance of EmioAPI in this process.

Returns:

A list of device names (the ports).

listUsedEmioDevices

@staticmethod
def listUsedEmioDevices() -> list

List all the emio devices that are currently used by an instance of EmioAPI in this process.

Returns:

A list of device names (the ports).

connectToEmioDevice

def connectToEmioDevice(device_name: str = None,
multi_turn: bool = False) -> bool

Connect to the emio device with the given name.

Arguments:

  • device_name - str: The name of the device to connect to. If None, the first device found that is not used will be used.
  • multi_turn - bool: Whether to enable the multi-turn mode of the motors. In multi-turn mode on, the angles interval is [-2562π, 2562π]

Returns:

True if the connection is successful, False otherwise.

disconnect

def disconnect()

Close the connection to motors and camera.

printStatus

def printStatus()

Print the status of the Emio device.

EmioCamera Class

class EmioCamera()

A class to interface with the Realsense camera on Emio. This class opens the camera in the same process as the code is running from.

It is recommendend to use this class if you want to use the camera in a SOFA scene.

warning

If you want to open the camera in another process, you can use the MultiprocessEmioCamera class.

Example:

from emioapi import EmioCamera

# Create an instance of EmioCamera
camera = EmioCamera(show=True, track_markers=True, compute_point_cloud=True, configuration="extended")

# Open the camera
if camera.open():
try:
while camera.is_running:
# Update camera frames and tracking
camera.update()

# Access tracker positions
positions = camera.trackers_pos
print("Tracker positions:", positions)

# Access point cloud data
pc = camera.point_cloud
print("Point cloud shape:", pc.shape)

# Access HSV and mask frames
hsv = camera.hsv_frame
mask = camera.mask_frame

# ... (process frames as needed)

# For demonstration, break after one iteration
break
finally:
# Close the camera when done
camera.close()

__init__

def __init__(camera_serial: str = None,
parameter: dict = None,
show: bool = False,
track_markers: bool = False,
compute_point_cloud: bool = False,
configuration: str = "extended")

Initialize the camera.

Arguments:

  • camera_serial - str: The serial number of the camera to connect to. If None, the first camera found will be used.
  • parameter - dict: The camera parameters. If None, the lastest save paramters are used from a file, but if no file is found, default values will be used.
  • show - bool: Whether to show the camera HSV and Mask frames or not.
  • track_markers - bool: Whether to track objects or not.
  • compute_point_cloud - bool: Whether to compute the point cloud or not.
  • configuration - str: Configuration of Emio, either "extended" (default) or "compact"

depth_frame

@property
def depth_frame()

Get the latest depth frame

Returns:

  • numpy.ndarray - the latest depth frame

frame

@property
def frame()

Get the latest color frame

Returns:

  • numpy.ndarray - the latest color frame

is_running

@property
def is_running() -> bool

Get the running status of the camera.

Returns:

  • bool - The running status of the camera.

track_markers

@property
def track_markers() -> bool

Get whether the camera is tracking objects or not.

Returns:

  • bool - True if the camera is tracking the markers, else False.

track_markers

@track_markers.setter
def track_markers(value: bool)

Set the tracking status of the camera.

Arguments:

  • value - bool: The new tracking status.

compute_point_cloud

@property
def compute_point_cloud() -> bool

Get whether the camera is computing the point cloud or not.

Returns:

  • bool - True if the camera is computing the point cloud, else False.

compute_point_cloud

@compute_point_cloud.setter
def compute_point_cloud(value: bool)

Set the point cloud computation status of the camera.

Arguments:

  • value - bool: The new point cloud computation status.

show_frames

@property
def show_frames() -> bool

Get whether the camera HSV and mask frames are shown in windows.

Returns:

  • bool - The show status of the camera.

show_frames

@show_frames.setter
def show_frames(value: bool)

Set the show status of the camera.

Arguments:

  • value - bool: The new show status.

parameters

@property
def parameters() -> dict

Get the camera parameters in a dict object:

  • hue_h: int: The upper hue value.
  • hue_l: int: The lower hue value.
  • sat_h: int: The upper saturation value.
  • sat_l: int: The lower saturation value.
  • value_h: int: The upper value value.
  • value_l: int: The lower value value.
  • erosion_size: int: The size of the erosion kernel.
  • area: int: The minimum area of the detected objects.

Returns:

  • dict - The camera parameters.

parameters

@parameters.setter
def parameters(value: dict)

Set the camera tracking parameters from the dict object:

  • hue_h: int: The upper hue value.
  • hue_l: int: The lower hue value.
  • sat_h: int: The upper saturation value.
  • sat_l: int: The lower saturation value.
  • value_h: int: The upper value value.
  • value_l: int: The lower value value.
  • erosion_size: int: The size of the erosion kernel.
  • area: int: The minimum area of the detected objects.
warning
  • The camera parameters are not saved to a file. You need to save them manually.
  • The paramters are set when opening the camera. To change the parameters programatically, you need to close the camera and open it again with the wanted parameters.

Arguments:

  • value - dict: The new camera parameters.

trackers_pos

@property
def trackers_pos() -> list

Get the positions of the trackers.

Returns:

  • list - The positions of the trackers as a list of lists.

trackers_pos_image

@property
def trackers_pos_image() -> list

Get the positions of the trackers in the image frame.

Returns:

  • list - The positions of the trackers in the image frame as a list of lists.

point_cloud

@property
def point_cloud() -> np.ndarray

Get the point cloud data.

Returns:

The point cloud data as a numpy array.

hsv_frame

@property
def hsv_frame() -> np.ndarray

Get the HSV frame.

Returns:

The HSV frame as a numpy array.

mask_frame

@property
def mask_frame() -> np.ndarray

Get the mask frame.

Returns:

The mask frame as a numpy array.

calibration_status

@property
def calibration_status() -> int

Get the calibration status of the camera.

Returns:

  • int - The calibration status of the camera. -1 if camera is None

fps

@property
def fps() -> int

Get the current stream framerate of the camera in frames per second. Default is 30 fps.

You have to set the fps before calling the open method.

Returns:

  • int - The framerate in fps

fps

@fps.setter
def fps(value: int)

Set the camera framerate. Available framerates are 30, 60 and 90 fps. Default is 30 fps.

depth_max

@property
def depth_max() -> int

Get the maximum depth value of the camera in millimiters. Default is 430 mm.

Returns:

  • int - The maximum depth value in millimiters.

depth_max

@depth_max.setter
def depth_max(value: int)

Set the maximum depth value of the camera in millimiters. Must be positive. Default is 430 mm.

Arguments:

  • value - int: The new maximum depth value in millimmiters.

depth_min

@property
def depth_min() -> int

Get the minimum depth value of the camera in millimiters. Default is 2 mm.

Returns:

  • int - The minimum depth value in millimiters.

depth_min

@depth_min.setter
def depth_min(value: int)

Set the minimum depth value of the camera in millimiters. Must be positive. Default is 2 mm.

Arguments:

  • value - int: The new minimum depth value in millimmiters.

listCameras

@staticmethod
def listCameras() -> list

Static method to list all the Realsense cameras connected to the computer

Returns:

  • list - A list of the serial numbers as string.

open

def open(camera_serial: str = None) -> bool

Initialize and open the camera in another process. This function creates a new handle to the camera and starts it.

Arguments:

  • camera_serial - str: the serial number of the camera to open. If None, the first found Realsense camera will be opened. If the camera_serial was set as a parameter or before, the given camera will be opened.

Returns:

  • bool - True if a camera was opened, else False

calibrate

def calibrate()

Calibrate the camera. You need to set up Emio in the calibration configuration before calling this method. See the Emio documentation.

image_to_simulation

def image_to_simulation(x: int, y: int, depth: float = None) -> list[float]

Get the 3D point in the simulation reference frame from the pixels and depth

Arguments:

x, y: int: the horizontal and vertical position in the image/frame

Returns:

a list of float of the corresponding 3D point in the simulation reference frame

update

def update()

Update the camera frames and tracking elements (markers and point cloud)

close

def close()

Close the camera and terminate the process. Sets the running status to False.

EmioMotors Class

class EmioMotors(DynamixelMotors)

Class to control Emio motors. The class is designed to be used with the Emio device. The motors are controlled in position mode. The class is thread-safe and can be used in a multi-threaded environment.

Important: the security temperature for the motors is 53°C. Above this temperature, the motors turn the torque off. Close the connection and turn off Emio, let it cool for a few minutes then Emio back on.

It is a wrapper around the DynamixelMotors class from the dynamixelmotorsapi package, with some specific configurations for the Emio device. You can find the documentation of the DynamixelMotors class in the dynamixelmotorsapi package.

Example:

from emioapi import EmioMotors

# Create an instance of EmioMotors
motors = EmioMotors()

# Open connection to the motors (optionally specify device name)
if motors.open():
# Print current angles in radians
print("Current angles (rad):", motors.angles)

# Set new goal angles (example values)
motors.angles = [0.5, 1.0, -0.5, 1.0]

# Print status
motors.printStatus()

# Close connection when done
motors.close()
else:
print("Failed to connect to motors.")

MultiprocessEmioCamera Class

class MultiprocessEmioCamera()

A class to interface with the realsense camera on Emio. This class creates a process using mulltiprocessing to handle the camera.

warning

This class does not work in a SOFA scene. The multiprocessing clashes with SOFA. If you want to use the camera in a SOFA scene, use the not-paralelized version of the class: EmioCamera

Example:

from emioapi import MultiprocessEmioCamera

# Initialize the camera with default parameters
camera = MultiprocessEmioCamera(show=True, tracking=True, compute_point_cloud=True)

# Open the camera (starts the camera process)
if camera.open():
print("Camera started successfully.")

# Access tracker positions and point cloud in a loop
for _ in range(10):
print("Trackers positions:", camera.trackers_pos)
print("Point cloud shape:", camera.point_cloud.shape if camera.point_cloud is not None else None)
time.sleep(1)

# Close the camera process
camera.close()
print("Camera closed.")
else:
print("Failed to start camera.")

__init__

def __init__(camera_serial=None,
parameter=None,
show=False,
tracking=True,
compute_point_cloud=False)

Initialize the camera.

Arguments:

  • camera_name - str: The name of the camera to connect to. If None, the first camera found will be used.
  • parameter - dict: The camera parameters. If None, the lastest save paramters are used from a file, but if no file is found, default values will be used.
  • show - bool: Whether to show the camera HSV and Mask frames or not.
  • tracking - bool: Whether to track objects or not.
  • compute_point_cloud - bool: Whether to compute the point cloud or not.

camera_serial

@property
def camera_serial() -> str

Get the current camera serial number

is_running

@property
def is_running() -> bool

Get the running status of the camera.

Returns:

  • bool - The running status of the camera.

track_markers

@property
def track_markers() -> bool

Get whether the camera is tracking objects or not.

Returns:

  • bool - True if the camera is tracking the markers, else False.

track_markers

@track_markers.setter
def track_markers(value: bool)

Set the tracking status of the camera.

Arguments:

  • value - bool: The new tracking status.

compute_point_cloud

@property
def compute_point_cloud() -> bool

Get whether the camera is computing the point cloud or not.

Returns:

  • bool - True if the camera is computing the point cloud, else False.

compute_point_cloud

@compute_point_cloud.setter
def compute_point_cloud(value: bool)

Set the point cloud computation status of the camera.

Arguments:

  • value - bool: The new point cloud computation status.

show_frames

@property
def show_frames() -> bool

Get the show status of the camera.

Returns:

  • bool - The show status of the camera.

show_frames

@show_frames.setter
def show_frames(value: bool)

Set the show status of the camera.

Arguments:

  • value - bool: The new show status.

parameters

@property
def parameters() -> dict

Get the camera parameters in a dict:

  • hue_h: int: The upper hue value.
  • hue_l: int: The lower hue value.
  • sat_h: int: The upper saturation value.
  • sat_l: int: The lower saturation value.
  • value_h: int: The upper value value.
  • value_l: int: The lower value value.
  • erosion_size: int: The size of the erosion kernel.
  • area: int: The minimum area of the detected objects.

Returns:

  • dict - The camera parameters.

parameters

@parameters.setter
def parameters(value: dict)

Set the camera tracking parameters from the dict:

  • hue_h: int: The upper hue value.
  • hue_l: int: The lower hue value.
  • sat_h: int: The upper saturation value.
  • sat_l: int: The lower saturation value.
  • value_h: int: The upper value value.
  • value_l: int: The lower value value.
  • erosion_size: int: The size of the erosion kernel.
  • area: int: The minimum area of the detected objects.
warning
  • The camera parameters are not saved to a file. You need to save them manually.
  • The paramters are set when opening the camera. To change the parameters programatically, you need to close the camera and open it again with the wanted parameters.

Arguments:

  • value - dict: The new camera parameters.

trackers_pos

@property
def trackers_pos() -> list

Get the positions of the trackers.

Returns:

  • list - The positions of the trackers as a list of lists.

point_cloud

@property
def point_cloud() -> np.ndarray

Get the point cloud data.

Returns:

The point cloud data as a numpy array.

hsv_frame

@property
def hsv_frame() -> np.ndarray | None

Get the HSV frame.

Returns:

The HSV frame as a numpy array.

mask_frame

@property
def mask_frame() -> np.ndarray | None

Get the mask frame.

Returns:

The mask frame as a numpy array.

listCameras

@staticmethod
def listCameras()

Static method to list all the Realsense cameras connected to the computer

Returns:

  • list - A list of the serial numbers as string.

__getstate__

def __getstate__()

Get the state of the object for pickling. This method is used to remove the _manager attribute from the object state based on https://laszukdawid.com/blog/2017/12/13/multiprocessing-in-python-all-about-pickling/

open

def open(camera_serial: str = None) -> bool

Initialize and open the camera in another process. This function creates a new process to handle the camera and starts it.

close

def close()

Close the camera and terminate the process. Sets the running status to False.

UDPBridgeConfig Class

@dataclass
class UDPBridgeConfig()

fps

the required FPS of transfer

nb_markers

number of markers to track

side

"plane", "top" or "front"

sort

"y" or "z", only for front camera

remote_ip

IP address of the remote host

remote_port

UDP port Remote host listens on (Python -> Remote host)

local_port

UDP port Python listens on (Remote host -> Python)

bind_port

Local port used for sending

recv_timeout

Socket timeout in seconds while waiting for a reply

camera_only

Only send camera data, the motors command will be sent as 0 and no command will be applied to the motors

motors_only

Only send motor data, the markers position will be sent as 0 and the camera will not be read

CommStatus Class

class CommStatus(Enum)

Status returned by :meth:UDPBridge.send_and_receive.

Attributes:

  • OK - Reply received, sequence numbers match (one-tick delay).
  • OK_NO_DELAY - Reply received with no delay (seq matches exactly).
  • DESYNC - Sequence mismatch detected; bridge is flushing the buffer.
  • TIMEOUT - No reply received within recv_timeout.
  • RECONNECTED - Bridge lost sync and successfully re-handshaked.

UDPBridge Class

class UDPBridge()

UDP bridge between Python and a Remote host (e.g. Simulink) for real-time control.

The bridge consists in two processes running in parallel: one for the camera and one for the motors:

  • The camera process reads the camera frames, tracks the markers and updates a shared variable with the markers position.
  • The motors process waits for the camera process to update the markers position, then it reads the motors position, sends both the motors position and the markers position to the remote host and applies the received command to the motors.

The UDPBridge is the clock master: it sends a vector of send_size doubles at each tick (prepended with a sequence number) and blocks until Remote host replies with a vector of recv_size doubles (also prepended with a sequence number).

Wire format (both directions)::

[ seq (float64) | data[0] | data[1] | ... ] total bytes = (1 + send_size) * 8 (Python -> Remote host) total bytes = (1 + recv_size) * 8 (Remote host -> Python)

Not thread-safe: send_and_receive must be called from a single thread.

Typical usage::

with UDPBridge(send_size=3, recv_size=2) as bridge: bridge.handshake() while True: reply, status = bridge.send_and_receive(my_data)

Arguments:

  • send_size - Number of data doubles sent to UDP each tick.
  • recv_size - Number of data doubles expected from UDP each tick.
  • remote_ip - IP address of the UDP host.
  • remote_port - UDP port Remote host listens on (Python -> Remote host).
  • local_port - UDP port Python listens on (Remote host -> Python).
  • bind_port - Local port used for sending.
  • recv_timeout - Socket timeout in seconds while waiting for a reply.

handshake

def handshake(handshake_timeout: float = 0.05) -> None

Block until Remote host acknowledges the connection.

Sends seq=-1 with a zero payload of send_size doubles so the wire size is identical to the main loop. Resets the sequence counter on success.

Arguments:

  • handshake_timeout - Per-attempt socket timeout in seconds.

send_and_receive

def send_and_receive(data: np.ndarray) -> tuple[np.ndarray, CommStatus]

Send a data vector and return the reply from Remote host.

data is silently padded with zeros or truncated to match send_size if needed (a warning is emitted).

On consecutive timeouts (>= MAX_RECONNECT_ATTEMPTS) or persistent desyncs (>= _MAX_DESYNC_COUNT), a new handshake is triggered automatically.

Arguments:

  • data - Vector of doubles, ideally shape (send_size,) or (send_size, 1).

Returns:

A tuple (reply, status) where reply has shape (recv_size, 1) and status is one of: :class:CommStatus.

Raises:

  • RuntimeError - If the packet received from Remote host has an unexpected size (mismatch between recv_size and the Remote host UDP Send block configuration).

close

def close() -> None

Release UDP sockets.

seq

@property
def seq() -> int

Current sequence counter.

process_motors

def process_motors(shared_markers_pos: SynchronizedArray, event_frame: Event,
event_measure: Event, config: UDPBridgeConfig) -> None

Motor control loop bridging the remote controller and the physical motors.

Waits for frame and measure events, reads motor positions and marker data, then exchanges them with the remote host to get the next command. Runs until interrupted by a KeyboardInterrupt (Ctrl-C).

Arguments:

  • shared_markers_pos - Shared memory array holding marker positions.
  • event_frame - Event set by the camera process at each new frame.
  • event_measure - Event set when marker measurement is ready.

setup_motors

def setup_motors() -> EmioMotors

Open and return an EmioMotors instance, retrying until successful.

Returns:

An open EmioMotors instance.

send_motors_command

def send_motors_command(motors: EmioMotors, command: np.ndarray) -> None

Send a command vector to the motors.

Arguments:

  • motors - An open EmioMotors instance.
  • command - Command vector, any shape — will be flattened.

get_motors_position

def get_motors_position(motors: EmioMotors) -> np.ndarray

Read current motor angles.

Arguments:

  • motors - An open EmioMotors instance.

Returns:

Motor positions as a column vector, shape (n_motors, 1).

process_camera

def process_camera(shared_markers_pos: SynchronizedArray, event_frame: Event,
event_measure: Event, config: UDPBridgeConfig) -> None

Main camera loop: grab frames, track markers, and update shared state.

Sets event_frame at each new frame and event_measure once the marker positions are written to shared_markers_pos. Stops when the user presses q.

Arguments:

  • shared_markers_pos - Shared memory array written with marker positions.
  • event_frame - Event set at each new camera frame.
  • event_measure - Event set once marker data is ready.

setup_camera

def setup_camera(config: UDPBridgeConfig) -> EmioCamera

Initialise and open the depth camera from params.

Returns:

A configured, open DepthCamera instance.

process_frame

def process_frame(camera: EmioCamera, last_pos: np.ndarray,
config: UDPBridgeConfig) -> np.ndarray

Extract marker positions from the current frame.

Returns last_pos unchanged if the expected number of markers is not detected.

Arguments:

  • camera - An open, tracking-enabled DepthCamera instance.
  • last_pos - Position array returned on detection failure.

Returns:

Marker positions as a column vector, shape (ny, 1).

pixel_to_mm

def pixel_to_mm(points: np.ndarray, depth: float,
config: UDPBridgeConfig) -> np.ndarray

Project pixel coordinates to millimetres using pinhole intrinsics.

Arguments:

  • points - Tracker positions in pixels, shape (n, 3).
  • depth - Fixed depth in mm used for the projection.

Returns:

Projected points in mm, shape (n, 3).

camera_to_sofa_order

def camera_to_sofa_order(points: np.ndarray,
config: UDPBridgeConfig) -> np.ndarray

Reorder markers by ascending y-coordinate (SOFA convention).

Arguments:

  • points - Marker positions, shape (nb_markers, 3).

Returns:

Reordered positions as a flat array.

startUDPbridge

def startUDPbridge(config: UDPBridgeConfig)

Start a UDP bridge configured with the parameters found in args Start a UDP bridge configured with the parameters found in args or will default to emioapi/udpbridge/udpbridge_params.py.

The bridge consists in two processes running in parallel: one for the camera and one for the motors:

  • The camera process reads the camera frames, tracks the markers and updates a shared variable with the markers position.
  • The motors process waits for the camera process to update the markers position, then it reads the motors position, sends both the motors position and the markers position to the remote host and applies the received command to the motors.

A handshake is done at the beginning to ensure that the remote host is ready to receive data. It shold follow the same protocol describded below with dummy data.

The protocol is as follows:

  • The bridge sends a packet made of a sequence number, the four motors positions and followed by the marker(s) position(s)
  • The remote host should reply with a packet containing the four motors positions to send to the Emio robot.

side

"top", "front", "plane"

sort

"y" or "z", only for front camera

ny

number of measurements

nu

number of actuators

depth

for front camera,

Emio API Tools

This module provides command-line tools for working with Emio devices, including camera calibration and starting a UDP bridge for real-time communication between the Emio robot and a remote host (e.g., Simulink).

To use these tools, run the following command in your terminal:

python -m emioapi <command> [options]

Available Commands

  • calibrate: Calibrate the Emio camera. This command will open the camera feed and allow you to perform the calibration process. The camera will be automatically closed after calibration.
  • startUDP: Start a UDP bridge for motor/camera data. This command will launch a UDP bridge that sends the camera's markers and motors positions and receives motor commands from a remote host. The bridge can be configured with various options such as FPS, number of markers, remote IP/port, etc.

You can run each command with the --help flag to see the specific options available for that command. For example:

python -m emioapi --help
python -m emioapi calibrate --help
python -m emioapi startUDP --help

calibrate

def calibrate()

Calibrate the camera of the first Emio camera found. For more informations about the calibration process, please refer to the EmioCamera.calibrate() method documentation.

startUDP

def startUDP(args)

Start a UDP bridge configured with the parameters found in args or will default to emioapi/udpbridge/udpbridge_params.py.

A handshake is done at the beginning to ensure that the remote host is ready to receive data. It should follow the same protocol describded below with dummy data.

The sequence number is a simple counter that is incremented at each frame. It is used by the process_motors process to make sure that the remote is synchronized.

The protocol is as follows:

  • The bridge sends a packet made of a sequence number, the four motors positions and followed by the marker(s) position(s) (x, y, z)
  • The remote host should reply with a packet containing the four motors positions to send to the Emio robot.