Skip to content

API Reference

  • The functions you will need are in SG_main.
  • For details on the simulator to work without physical gloves see SG_simulator

SG_API.SG_main

SG_main contains all functions the user needs from the API. See Getting Started docs for a general explanation of how to use it.

Questions? Written by:

  • Amber Elferink

Docs: https://adjuvo.github.io/SenseGlove-R1-API/

Support: https://www.senseglove.com/support/

init

Python
init(
    wait_for_x_gloves: int,
    com_type: Com_type,
    SIMULATION_MODE: Simulation_Mode = FINGERS_OPEN_CLOSE,
) -> List[int]

Initializes the API and connection searching.

If wait_for_x_gloves is not 0, the program will not move on until it finds at least x gloves. Returns list of device_ids connected after init.

If setting Com_type to SIMULATED_GLOVE it will generate a single right hand simulator. The movement can be set with the SIMULATION_MODE parameter (which is not used when the REAL glove mod is on).

Examples:

Python
device_ids = SG_main.init(1, SG_T.Com_type.REAL_GLOVE_USB)  # Block program until 1 glove connects
device_ids = SG_main.init(2, SG_T.Com_type.REAL_GLOVE_USB)  # Block program until 2 gloves connect
device_ids = SG_main.init(1, SG_T.Com_type.SIMULATED_GLOVE)  # Simulate 1 glove (max 1 simulated glove via this init, create more with init_rembrandt_sim())
device_ids = SG_main.init(0, SG_T.Com_type.REAL_GLOVE_USB)  # Doesn't block the program, may return no device_ids. 
If you choose to set it to 0, you can use the add_on_connected_callback() function to capture the device_id on connection, or retrieve the device_ids with get_device_ids(), get_right_hand_deviceid(), get_left_hand_deviceid() after a connection.

init_rembrandt_sim

Python
init_rembrandt_sim(
    handedness: Hand,
    simulation_mode: Simulation_Mode,
    starting_angles=[
        0.0,
        -0.2617993877991494,
        0.7853981633974483,
        -1.5707963267948966,
        2.0943951023931953,
        -1.7453292519943295,
        1.5707963267948966,
        0.7,
    ],
) -> Optional[Glove_Simulator]

Creates a simulated hand to test without physical Rembrandt glove. For more options directly create it via SG_sim.create_glove_sim_device(). Currently does max 2 gloves from this function. A right and a left one.

Examples:

Python
right_sim = SG_main.init_rembrandt_sim(SG_T.Hand.RIGHT, SG_sim.Simulation_Mode.FINGERS_OPEN_CLOSE)
left_sim = SG_main.init_rembrandt_sim(SG_T.Hand.LEFT, SG_sim.Simulation_Mode.STATIC)

get_COM_type

Python
get_COM_type(device_id: int) -> Com_type

Returns the communication type of the specified device. Use:

Python
com_type = SG_main.get_COM_type(device_id)

Examples:

Python
com_type = SG_main.get_COM_type(12345)  # SG_T.Com_type.REAL_GLOVE_USB or SG_T.Com_type.SIMULATED_GLOVE

keep_program_running

Python
keep_program_running()

This is a while true loop with a sleep and exit check. Exits cleanly on Ctrl+C, window close, or stop_program_running()

⚠️ Important Notes

  1. Code after this call will NOT execute until exit
  2. Use this instead of a custom while loop to avoid performance issues with 1000hz glove data (subscr_rembrandt_data_callback)

Usage:

Python
SG_main.subscr_rembrandt_data_callback(on_new_data)
SG_main.keep_program_running()
# code here won't execute until exit

How it's implemented (for reference):

Python
def keep_program_running():
    try:
        while SG_main.SG_cb.running:
            time.sleep(1)  # This loop does not do anything but keep the program alive. Some sleep is important to not eat all CPU capacity.
    except: 
        pass # important errors will still log due to sg_logger. This try/except just ignores the keyboard interrupt error on Ctrl+C.

If you use your own while loop instead (without the sleep), that may steal all CPU capacity, and the data callback will not be called often, which can result in only 70fps glove data update rate in bad cases.

So if you use your own while loop, make sure to add the sleep, and preferably the shutdown check for clean exit.

is_device_active

Python
is_device_active(device_id: int) -> bool

Checks if a device with given device_id is currently active/connected. Use:

Python
is_active = SG_main.is_device_active(device_id)

get_device_ids

Python
get_device_ids() -> List[int]

Returns list with device_ids of all active devices.

Examples:

Python
device_ids = SG_main.get_device_ids()  # [123, 678] - two gloves connected

get_right_hand_deviceid

Python
get_right_hand_deviceid() -> Optional[int]

Returns the first right hand device_id found in active devices. Use:

Text Only
right_id = SG_main.get_right_hand_deviceid() #returns device_id, or None if no right hand

get_left_hand_deviceid

Python
get_left_hand_deviceid() -> Optional[int]

Returns the first left hand device_id found in active devices.

Examples:

Python
left_id = SG_main.get_left_hand_deviceid()  # returns device_id or None if no left hand

is_left_hand

Python
is_left_hand(device_id: int)

Checks if a device is left handed. Returns True for left hand, False for right hand.

Python
is_left = SG_main.is_left_hand(device_id)

get_handedness

Python
get_handedness(device_id: int) -> Hand

Returns the handedness (left or right) of the specified device.

Python
handedness = SG_main.get_handedness(device_id)   # SG_T.Hand.LEFT or SG_T.Hand.RIGHT

nr_of_fingers_tracking

Python
nr_of_fingers_tracking(device_id: int)

Returns the number of fingers supported by the device for tracking. Use:

Python
finger_count = SG_main.nr_of_fingers_tracking(device_id)

nr_of_fingers_force

Python
nr_of_fingers_force(device_id: int)

Returns the number of fingers supported by the device for force feedback. Use:

Python
finger_count = SG_main.nr_of_fingers_force(device_id)

subscr_r1_data_callback

Python
subscr_r1_data_callback(cb: Callable[[int], None])

Expects a callback function that takes device_id as a parameter.

That function will trigger if new data is available for the Rembrandt device. Within your function, call other API functions to retrieve specific data.

⚠️ Important Note

Do not put too heavy computing into this callback, since it will slow down the update rate of data retrieval from the glove, which must remain ~1kHz for optimal haptic performance. Preferably only place data into variables here.

Python
# on_new_data will be called when new data is available for the Rembrandt device
def on_new_data(device_id): 
    angles = SG_main.get_exo_angles_rad(device_id)

SG_main.add_r1_data_callback(on_new_data)  # subscribes on_new_data to be called

subscr_on_connected_callback

Python
subscr_on_connected_callback(
    cb: Callable[[Device_Info], None]
)

Expects a callback function that takes SG_types.Device_Info as a parameter.

That function will trigger if a new device is connected. Within your function, call other API functions to retrieve specific data.

You can add the following code even before the SG_main.init() call to make sure you capture the connection..

Python
def on_new_device(device_info):
    print(f"New device connected: {device_info.device_id}")
SG_main.add_on_connected_callback(on_new_device)

get_exo_angles_rad

Python
get_exo_angles_rad(
    device_id: int,
) -> Sequence[Sequence[float]]

Retrieves exoskeleton joint angles in radians.

Python
exo_angles = SG_main.get_exo_angles_rad(device_id)

Can be indexed like:

  • exo_angle = exo_angles[finger_nr][exo_joint_nr]

Angle definitions:

  • A fully extended straight exoskeleton gives all angles 0
  • Rotating a joint towards hand palm gives angle > 0
  • Rotating joint towards back of hand angle < 0
  • The first angle is the splay angle. Those after are the flexion angles

Examples:

Python
thumb_splay_angle = exo_angles[0][0]  # thumb splay angle in radians
index_flex1_angle = exo_angles[1][1]  # index finger 1st flexion in radians

get_device_info

Python
get_device_info(device_id: int) -> Device_Info

Returns the device info (such as firmware version, nr_fingers, handedness, etc) for the specified device. Use:

Python
device_info = SG_main.get_device_info(device_id)

get_exo_angles_deg

Python
get_exo_angles_deg(
    device_id: int,
) -> Sequence[Sequence[float]]

Retrieves exoskeleton joint angles in degrees (same as get_exo_angles_rad but degrees). Use:

Python
exo_angles = SG_main.get_exo_angles_deg(device_id)

Examples:

Python
thumb_splay_deg = exo_angles[0][0]  # thumb splay angle in degrees
index_flex1_angle = exo_angles[1][1]  # index finger 1st flexion in degrees

get_exo_linkage_lengths

Python
get_exo_linkage_lengths(
    device_id: int,
) -> Sequence[Sequence[Union[int, float]]]

Returns the linkage lengths of the exoskeleton for the specified device in mm. Use:

Python
linkage_lengths = SG_main.get_exo_linkage_lengths(device_id) # [11.62, 35, 35, 35, 35, 35, 35, 10] # in mm

get_fingertips_pos_rot

Python
get_fingertips_pos_rot(
    device_id: int,
) -> Tuple[Sequence[Vec3_type], Sequence[Quat_type]]

Returns tuple of positions (x,y,z) and rotations (quat) of each fingertip with respect to the finger base origin. See tracking documentation for more info.

Python
fingertips_pos, fingertips_rot = SG_main.get_fingertips_pos_rot(device_id)

Can be indexed like:

  • fingertip_pos_xyz = fingertips_pos[finger_nr][xyz_index]
  • fingertip_rot_quat = fingertips_rot[finger_nr][quat_wxyz_index]

Examples:

Python
thumb_pos_x = fingertips_pos[0][0]  # thumb x position
index_rot_w = fingertips_rot[1][0]  # index finger quaternion w

get_fingertip_thimble_dims

Python
get_fingertip_thimble_dims(
    device_id: int,
) -> List[Thimble_dims]

Returns thimble dimensions info for each fingertip to approximate its drawing with sphere and a cylinder. See SG_types.Thimble_dims for more info.

Python
thimble_dims = SG_main.get_fingertip_thimble_dims(device_id)

Example:

Python
thumb_dims = thimble_dims[0].radius  # thumb thimble radius

get_fingertip_distances

Python
get_fingertip_distances(device_id: int) -> Sequence[float]

returns: fingertip distances between thumb and [index, middle, ring, pinky] (float in mm)

get_exo_joints_poss_rots

Python
get_exo_joints_poss_rots(
    device_id: int,
) -> Tuple[
    Sequence[Sequence[Vec3_type]],
    Sequence[Sequence[Quat_type]],
]

Returns tuple of positions (x,y,z) and rotations (quat) of each exoskeleton joint. Use:

Python
exo_poss, exo_rot = SG_main.get_exo_joints_poss_rots(hand_id)
Can be indexed like: - joint_pos_xyz = exo_poss[finger_nr][exo_joint_nr][xyz_index] - joint_rot_quat = exo_rot[finger_nr][exo_joint_nr][quat_wxyz_index]

Examples:

Python
thumb_flexion_1_z: exo_poss[0][1][2] # thumb 1st flexion joint z
middlefinger_splay_y: exo_poss[2][0][1] # middle finger splay joint y

get_percentage_bents

Python
get_percentage_bents(
    device_id: int,
) -> Tuple[Sequence[int], Sequence[int]]

Returns percentage bent values for flexion and abduction of each finger.

Returns tuple containing:

  • flexion_perc_bents: Array of flexion percentages (0-out_max_perc_bent, 10000 by default)
  • abduction_perc_bents: Array of abduction percentages (0-out_max_perc_bent, 10000 by default)
Python
flex_bents, abd_bents = SG_main.get_percentage_bents(device_id)

Can be indexed like:

  • finger_flex_bent = flex_bents[finger_nr]
  • finger_abd_bent = abd_bents[finger_nr]

Examples:

Python
thumb_flex_bent = flex_bents[0]  # 0 (open) to 10000 (closed)
thumb_abd_bent = abd_bents[0]    # 0 (in plane with palm) to 10000 (maximally radially extended)
index_abd_bent = abd_bents[1]    # 0 abducted to y, 5000 (neutral) to 10000 (abducted to the -y)

Notes:

  • Values range from 0 (finger open) to out_max_perc_bent (finger closed)
  • For the thumb:
    • Flexion: 0 = extended, out_max_perc_bent = fully flexed
    • Abduction: 0 = in plane with palm, out_max_perc_bent = maximally radially extended
  • For other fingers:
    • Flexion: 0 = extended, out_max_perc_bent = fully flexed
    • Abduction: 0 = neutral, out_max_perc_bent = maximally abducted

Other notes:

  • 10000 is used by default instead of 100 to avoid floating point inaccuracies
  • It calculates this based on the fingertip orientation with respect to the finger base orientation
  • This method is used because it's independent of user hand sizes, and requires no calibration
  • Use set_perc_bent_vars() to change the max perc bent values to control and how 0 and 10000 are mapped to the raw values (from raw_percentage_bent_angles())

get_raw_percentage_bent_angles

Python
get_raw_percentage_bent_angles(
    device_id: int,
) -> Tuple[Sequence[float], Sequence[float]]

Returns the raw flexion and abduction angles used to calculate percentage bent. Returns: (flex_angles, abd_angles) Each is an array of the fingers, containing the raw angles in radians. See the tracking documentation for more info. Use:

Python
flex_angles, abd_angles = SG_main.get_raw_percentage_bent_angles(device_id)
Can be indexed like: - finger_flex_angle = flex_angles[finger_nr] - finger_abd_angle = abd_angles[finger_nr]

Examples:

Python
thumb_flex = flex_angles[0]  # thumb flexion angle in radians
index_abd = abd_angles[1]   # index abduction angle in radians

set_percentage_bent_vars

Python
set_percentage_bent_vars(
    device_id: int,
    min_thetas_flexion: NDArray[float64] = array(
        [0, 0.524, 0.345, 0.414, 0.4]
    ),
    max_thetas_flexion: NDArray[float64] = array(
        [1.8, 3.265, 3.0, 3.0, 2.75]
    ),
    min_thetas_abduction: NDArray[float64] = array(
        [0.0, -0.3, -0.3, -0.3, -0.3]
    ),
    max_thetas_abduction: NDArray[float64] = array(
        [0.5, 0.3, 0.3, 0.3, 0.3]
    ),
    out_max_perc_bent: int = 10000,
)

Sets the variables used to calculate percentage bent values. With this you can override when a finger is considered bent or open:

Steps:

  1. Monitor your values from get_raw_percentage_bent_angles()
  2. Move your fingers and note down the values per finger of your desired bent and open
  3. Set the min and max values to the values you noted down on startup of your program, just after init()

Example:

Python
device_ids = SG_main.init(1, SG_T.Com_type.REAL_GLOVE_USB)
device_id = device_ids[0]
SG_main.set_percentage_bent_vars(device_id, 
    min_flex = [0.23, -0.27, -0.27, -0.27, 0.1], 
    max_flex = [1.00, 2.75, 2.75, 2.75, 2.75], 
    min_abd = [0.04, -0.18, -0.27, -0.27, 0.1], 
    max_abd = [0.6, 0.18, 0.27, 0.27, 0.1])

# using SG_main.get_percentage_bents(device_id) you can now see the adjusted percentage bent values for each finger.

create_robot_hand_mapper

Python
create_robot_hand_mapper(
    device_id: int, config: Optional[PinchConfig] = None
) -> RobotHandMapper

Create and return a RobotHandMapper instance. If no config is provided, the default pinch mapping config is used.

Parameters:

Name Type Description Default
device_id int

Rembrandt device ID

required
config Optional[PinchConfig]

Optional custom PinchConfig

None

Returns:

Type Description
RobotHandMapper

Configured RobotHandMapper instance

get_robot_hand_mapper

Python
get_robot_hand_mapper(device_id: int) -> RobotHandMapper

Return the RobotHandMapper instance for the specified device. If no config is provided, the default pinch mapping config is used.

Parameters:

Name Type Description Default
device_id int

Rembrandt device ID

required

Returns:

Type Description
RobotHandMapper

Configured RobotHandMapper instance

create_rhm_pinch_gui

Python
create_rhm_pinch_gui(device_id: int)

Create and register a PinchMapperGUI for the given device_id.

get_pinch_debug_info

Python
get_pinch_debug_info(device_id: int)

Retrieve pinch-config debug info from the RobotHandMapper. Returns pinch diagnostics as dictionary.

Parameters:

Name Type Description Default
device_id int

Rembrandt device ID

required

get_rhm_percentage_bents

Python
get_rhm_percentage_bents(
    device_id: int,
) -> Tuple[
    Sequence[Union[int, float]], Sequence[Union[int, float]]
]

Retrieve robot-mapped percentage flexion and abduction values (pinch mapping).

Parameters:

Name Type Description Default
device_id int

Rembrandt device ID

required

Returns:

Name Type Description
tuple Tuple[Sequence[Union[int, float]], Sequence[Union[int, float]]]

(robot_flex, robot_abd)

update_robot_hand_mapper_gui

Python
update_robot_hand_mapper_gui(device_id: int)

Update the RHM GUI

Parameters:

Name Type Description Default
device_id int

Rembrandt device ID

required

get_forces_sensed

Python
get_forces_sensed(
    device_id: int,
) -> Sequence[Union[int, float]]

Returns the currently sensed forces for each finger. Use:

Python
forces = SG_main.get_forces_sensed(device_id)
Can be indexed like: - finger_force = forces[finger_nr]

Examples:

Python
thumb_force = forces[0]  # thumb sensed force
index_force = forces[1]  # index finger sensed force

set_force_goals

Python
set_force_goals(
    device_id: int, force_goals: Sequence[Union[int, float]]
)

Sets force goals for each finger (thumb to ringfinger) in milliNewtons. Note: pinky has no force module

⚠️ Development Status

The resulting force on the wire might differ from the force goal requested to allow stable control. Scale up the forces if necessary. The milliNewtons is the tension in the wire pulling the finger back.

⚠️ Warning for motor jitter

Do not use if contact -> set force_goal to full force logic, since that is not stable around the contact point. Instead, use: force_goal = K * distance_to_contact or another gradual function, tuning K to stability.

Use:

Python
force_goals = [3000, 3000, 3000, 3000]  # forces in mN per finger thumb to ring. 
SG_main.set_force_goals(device_id, force_goals)

Parameters: - force_goals: List of force goals per finger

Troubleshooting jittering: - If you notice jittering, plot your input data (easy with Teleplot extension VScode). - Check sudden force goal changes you command, improve data FPS, reduce K or in another way transition force goals more gradually. - Note that filtering/averaging your data too much can cause delays, which can cause instable feedback loops as result!

set_raw_vibro_data

Python
set_raw_vibro_data(
    device_id: int, vibro_data: Sequence[Sequence[int]]
)

Sets vibration data for the specified device.

Parameters: - device_id: ID of the device - vibro_data: List of vibration data per actuator.

Still in development. See examples/vibration_example.py for an example of the current format.

exit

Python
exit()

Closes all connections and cleans up resources. This is AUTOMATICALLY CALLED by the atexit module. (no need to manually call this)

Python
SG_main.exit()

SG_API.SG_simulator

SenseGlove Rembrandt Simulator Module

This module provides glove simulation functionality for testing and development when no physical device is connected. It simulates finger tracking data with various animation modes.

The simulator can generate realistic finger movements for: - Static poses (STEADY_MODE) - Sine wave animations (SINE_MODE) - Finger open/close cycles (FINGERS_OPEN_CLOSE)

Basic Usage:

Python
import SG_API.SG_simulator as SG_sim

# Create a simulated left hand with finger animation
device_info = SG_T.Device_Info(device_id=123, handedness=SG_T.Hand.LEFT)
sim = SG_sim.create_glove_sim_device(device_info, SG_sim.Simulation_Mode.FINGERS_OPEN_CLOSE)

# Update simulation in your main loop
while True:
    SG_sim.update_all_glove_sims()
    time.sleep(0.001)


# You can then read data from SG_main like usual, but the output will be coming from the simulated glove.

Questions? Written by: - Amber Elferink Docs: https://adjuvo.github.io/SenseGlove-R1-API/ Support: https://www.senseglove.com/support/

Simulation_Mode

Bases: Enum

Enumeration of available simulation modes for the glove simulator.

Modes: - STEADY_MODE: Static finger pose, no animation - SINE_MODE: Sine wave oscillations across all finger joints - FINGERS_OPEN_CLOSE: Smooth finger opening and closing cycles

Examples:

Python
# Set different animation modes
SG_sim.set_mode(device_id, SG_sim.Simulation_Mode.STEADY_MODE)
SG_sim.set_mode(device_id, SG_sim.Simulation_Mode.FINGERS_OPEN_CLOSE)

Glove_Simulator

Python
Glove_Simulator(device_info: Device_Info, mode)

Simulates a SenseGlove Rembrandt device for testing and development.

Provides realistic finger tracking data without requiring physical hardware. Supports multiple animation modes and allows manual control of finger positions.

Attributes: device_id (int): Unique identifier for this simulated device mode (Simulation_Mode): Current animation mode running (bool): Whether simulation is active

Examples:

Python
# Create simulator with finger animation
sim = Glove_Simulator(device_id=123, mode=Simulation_Mode.FINGERS_OPEN_CLOSE)

# Update simulation in loop
while sim.running:
    sim.update()
    time.sleep(0.001)

Initialize a new glove simulator instance.

Args: device_id (int): Unique device identifier for this simulator mode (Simulation_Mode): Animation mode to use

Examples:

Python
sim = Glove_Simulator(123, Simulation_Mode.SINE_MODE)

restart
Python
restart()

Restart the simulator with current settings.

Resets all animation timers and returns to initial finger positions.

Examples:

Python
sim.restart()  # Reset animation to beginning

stop
Python
stop()

Stop the simulator from updating.

Sets running flag to False, preventing further animation updates.

Examples:

Python
sim.stop()  # Stop animation

update_exo_hand_angles_rad
Python
update_exo_hand_angles_rad(
    exo_angles_rad: Sequence[Sequence[Union[int, float]]]
)

Update the exoskeleton joint angles in radians without changing the starting angles (which are used for base of open/close etc). So this is for calls from the update, and set_exo_rad_hand is for the user.

Args: exo_angles_rad (SG_T.Sequence[Sequence[Union[int, float]]]): Joint angles in radians

update
Python
update()

Update the simulation for one frame. This is called automatically by update_all_glove_sims (called by SG_main.update)

Calculates new finger positions based on the current simulation mode: - SINE_MODE: Applies sine wave oscillations to all joints - FINGERS_OPEN_CLOSE: Smooth finger opening/closing cycles - STEADY_MODE: Maintains static finger positions

set_simulation_mode
Python
set_simulation_mode(mode: Simulation_Mode)

Change the simulation animation mode.

Args: mode (Simulation_Mode): New animation mode to use

Examples:

Python
sim.set_simulation_mode(Simulation_Mode.SINE_MODE)     # Switch to sine waves
sim.set_simulation_mode(Simulation_Mode.STEADY_MODE)   # Switch to static pose

set_exo_rad_hand
Python
set_exo_rad_hand(
    exo_rad_hand_angles: Sequence[
        Sequence[Union[int, float]]
    ]
)

Set exoskeleton joint angles in radians. Also saves it to the simulation starting angles, so all simulation functions (such as open close) will be done around these initial angles.

Args: exo_rad_hand_angles (SG_T.Sequence[Sequence[Union[int, float]]]): Joint angles in radians

Updates both current and starting angles for the simulation.

Examples:

Python
# Set custom finger pose
import numpy as np

zero_angles = np.zeros((5, 8))  # 5 fingers, 8 joints each, this would be setting all exo linkages in a straight long line (not a natural pose)


angles_rad_single_finger = np.radians(_angles_deg_single_finger) # convert to radians
angles = np.tile(angles_rad_single_finger, (5, 1))               # create array using the the single finger angles for all fingers

angles[1][2] = 0.5        # Bend index finger second joint
sim.set_exo_rad_hand(angles)

set_exo_deg_hand
Python
set_exo_deg_hand(
    exo_deg_hand_angles: Sequence[
        Sequence[Union[int, float]]
    ]
)

Set exoskeleton joint angles in degrees.

Args: exo_deg_hand_angles (SG_T.Sequence[Sequence[Union[int, float]]]): Joint angles in degrees

Convenience method that converts degrees to radians internally.

Examples:

Python
# Set finger pose in degrees (easier to visualize)
import numpy as np
angles = np.zeros((5, 8))  # 5 fingers, 8 joints each, this would be setting all exo linkages in a straight long line (not a natural pose)

angles_deg_single_finger = np.array([0, -15, 45, -90, 120, -100, 90, -50]) # this is a more natural starting pose for a single finger
angles = np.tile(angles_deg_single_finger, (5, 1))               # create array using the the single finger angles for all fingers
angles[1][2] = 30         # Bend index exo joint 2 30 degrees

sim.set_exo_deg_hand(angles)

smoothstep

Python
smoothstep(t)

Smooth interpolation function for easing animations.

Args: t (float): Input value between 0 and 1

Returns: float: Smoothed output value between 0 and 1

Uses the smoothstep formula: t² × (3 - 2t) for smooth acceleration/deceleration.

set_angles_rad

Python
set_angles_rad(
    device_info: Device_Info,
    exo_angles_rad_hand: Sequence[
        Sequence[Union[int, float]]
    ],
)

Set finger joint angles for a simulated device (radians).

Args: device_id (int): Device ID of the simulator exo_angles_rad_hand (SG_T.Sequence[Sequence[Union[int, float]]]): Joint angles in radians

Examples:

Python
zero_angles = np.zeros((5, 8))  # 5 fingers, 8 joints each, this would be setting all exo linkages in a straight long line (not a natural pose)


angles_rad_single_finger = np.radians(_angles_deg_single_finger) # convert to radians
angles = np.tile(angles_rad_single_finger, (5, 1))               # create array using the the single finger angles for all fingers

angles[1][2] = 0.5        # Bend index finger second joint

SG_sim.set_angles_rad(123, angles)

set_angles_deg

Python
set_angles_deg(
    device_info: Device_Info,
    exo_angles_deg_hand: Sequence[
        Sequence[Union[int, float]]
    ],
)

Set finger joint angles for a simulated device (degrees).

Args: device_info: DeviceInfo of the simulator exo_angles_deg_hand (SG_T.Sequence[Sequence[Union[int, float]]]): Joint angles in degrees

Examples:

Python
# Set finger pose in degrees (easier to visualize)
import numpy as np
angles = np.zeros((5, 8))  # 5 fingers, 8 joints each, this would be setting all exo linkages in a straight long line (not a natural pose)

angles_deg_single_finger = np.array([0, -15, 45, -90, 120, -100, 90, -50]) # this is a more natural starting pose for a single finger
angles = [angles_deg_single_finger.copy() for _ in range(5)]  # Create list of arrays, one per finger
angles[1][2] = 30         # Bend index exo joint 2 30 degrees

SG_main.SG_sim.set_angles_deg(SG_main.get_device_info(hand_id), angles)
SG_sim.set_angles_deg(device_info, angles)

create_glove_sim_device

Python
create_glove_sim_device(
    device_info: Device_Info, mode: Simulation_Mode
) -> Glove_Simulator

Create a glove simulator that integrates with the main API system.

Args: device_info (SG_T.Device_Info): Device information (device_id, handedness, etc.) mode (Simulation_Mode): Animation mode to use

Returns: Optional[Glove_Simulator]: The created simulator instance, or None if validation fails

This function creates a simulator and properly registers it with the callback system so it appears as a connected device to the main API.

Examples:

Python
# Create left hand simulator that integrates with SG_main functions
device_info = SG_T.Device_Info(device_id=123, handedness=SG_T.Hand.LEFT)
sim = SG_sim.create_glove_sim_device(device_info, SG_sim.Simulation_Mode.SINE_MODE)

# Now you can use normal API functions
angles = SG_main.get_exo_angles_rad(123)

stop_all_glove_sims

Python
stop_all_glove_sims()

Stop all active glove simulators.

Calls stop() on every simulator, preventing further updates. Useful for clean shutdown of all simulations.

Examples:

Python
# Stop all simulators when exiting application
SG_sim.stop_all_glove_sims()

get_sim

Python
get_sim(device_id: int)

Get the simulator instance for a specific device ID.

Args: device_id (int): Device ID of the simulator to retrieve

Returns: Glove_Simulator: The simulator instance

Examples:

Python
sim = SG_sim.get_sim(123)
sim.set_simulation_mode(SG_sim.Simulation_Mode.STEADY_MODE)

update_all_glove_sims

Python
update_all_glove_sims()

Update all active glove simulators for one frame.

Call this continuously in your main loop to keep all simulations running. Should be called at ~1kHz for smooth animation.

Examples:

Python
# Main simulation loop
while True:
    SG_sim.update_all_glove_sims()
    time.sleep(0.001)  # ~1kHz

set_mode

Python
set_mode(device_id: int, mode: Simulation_Mode)

Change the animation mode for a specific simulator.

Args: device_id (int): Device ID of the simulator mode (Simulation_Mode): New animation mode to use

Examples:

Python
# Switch to different animation modes
SG_sim.set_mode(123, SG_sim.Simulation_Mode.SINE_MODE)
SG_sim.set_mode(123, SG_sim.Simulation_Mode.FINGERS_OPEN_CLOSE)

is_exo_angles_type

Python
is_exo_angles_type(obj) -> bool

Check if an object is of type Sequence[Sequence[Union[int, float]]] AKA Union[List[List[float]], List[List[int]], List[np_array_type]]

set_simulation_fn

Python
set_simulation_fn(
    device_id: int,
    update_fn: Callable[
        [float], Sequence[Sequence[Union[int, float]]]
    ],
)

Set the custom update function for angles for a specific simulator, when CUSTOM_FUNCTION mode is enabled.

Args: device_id (int): Device ID of the simulator update_fn (Simulation_Mode): Function to call. Should have signature myFunction(t: float) and must return Sequence[Sequence[Union[int, float]]] containing 8 angles per finger.

Examples:

Python
_angles_deg_single_finger = np.array([0, -15, 45, -90, 120, -100, 90, 90]) 
_angles_rad_single_finger = np.radians(_angles_deg_single_finger)
_starting_angles_rad_hand = np.tile(_angles_rad_single_finger, (5, 1))

def test_custom_fn(t : float) -> SG_T.Sequence[Sequence[Union[int, float]]]:
    realT = t * 50
    MIN_ANGLE_RAD = math.radians(75)  # Set your minimum angle (e.g., 10°)
    MAX_ANGLE_RAD = math.radians(90)  # Set your maximum angle (e.g., 60°)
    t_normalized = 0.5 * (1 - math.cos(2 * math.pi * realT))  
    angle = MIN_ANGLE_RAD + SG_simulator.smoothstep(t_normalized) * (MAX_ANGLE_RAD - MIN_ANGLE_RAD)
    return _starting_angles_rad_hand + np.cos(angle)

SG_main.SG_sim.set_simulation_fn(hand_id, test_custom_fn)

SG_API.SG_types

Contains all types used throughout the whole API.

Questions? Written by: - Amber Elferink Docs: https://adjuvo.github.io/SenseGlove-R1-API/ Support: https://www.senseglove.com/support/

Vec3_type module-attribute

Python
Vec3_type = Sequence[Union[int, float]]

List, tuple, or np array of 3 numbers: x, y, z

Quat_type module-attribute

Python
Quat_type = Sequence[Union[int, float]]

List, tuple, or np array of 4 numbers: w, x, y, z

Control_Mode

Bases: IntEnum

FORCE_GOAL_DEFAULT class-attribute instance-attribute
Python
FORCE_GOAL_DEFAULT = 0

This is the default mode. The motors will try to reach the force goal set. Set the force goal to 0 to move freely.

OFF class-attribute instance-attribute
Python
OFF = 9999

Motors will fully turn off, so also not move with your finger

CALIBRATE_TRACKING_NEVER_EVER_USE class-attribute instance-attribute
Python
CALIBRATE_TRACKING_NEVER_EVER_USE = 42666

DON'T EVER SEND THIS TO THE GLOVE, it will reset tracking offset angles. It will ruin it the glove for good and requires customer support to fix it.

Thimble_dims dataclass

Python
Thimble_dims(
    sphere_center_pos: Vec3_type,
    rot: Quat_type,
    radius: float,
    cylinder_center_pos: Vec3_type,
    cylinder_length: float,
)

To draw the users fingertip thimble, we use a sphere and a cilinder. These are the dimensions of the sphere and cilinder.