easy_robot_control package

Subpackages

Submodules

easy_robot_control.EliaNode module

I this adds functionalities to the default ros2 Node object. And slowly became a mess I have to cleanup …

Author:

Elian NEPPEL

Lab:

SRL, Moonshot team

easy_robot_control.EliaNode.tf2np(tf)[source]

converts a TF into a np array and quaternion

Parameters:

tf (Transform) – TF to convert

Returns:

xyz coordinates quat: quaternion for the rotation

Return type:

xyz

Return type:

Tuple[NDArray[Shape[3], floating], quaternion]

easy_robot_control.EliaNode.np2tf(coord=None, quat=None, sendNone=False)[source]

converts an NDArray and quaternion into a Transform.

Parameters:
  • coord (None | NDArray[Shape[3], floating] | Sequence[float]) – xyz coordinates

  • quat (quaternion | None) – quaternion for the rotation

  • sendNone (bool)

Returns:

resulting TF

Return type:

tf

Return type:

Transform

easy_robot_control.EliaNode.np2tfReq(coord=None, quat=None)[source]

converts an NDArray and quaternion into a Transform request for a service.

Parameters:
  • xyz – xyz coordinates

  • quat (quaternion | None) – quaternion for the rotation

  • coord (ndarray | None)

Returns:

Resulting Request for a service call

Return type:

TFService_Request

easy_robot_control.EliaNode.np2TargetSet(arr=None)[source]

Converts a target set message to np array

Return type:

TargetSet

Parameters:

arr (NDArray[Shape[3], floating] | None)

easy_robot_control.EliaNode.targetSet2np(ts)[source]

Converts a np array to target set message

Return type:

NDArray[Shape[3], floating]

Parameters:

ts (TargetSet)

easy_robot_control.EliaNode.error_catcher(func)[source]

This is a wrapper to catch and display exceptions.

Note

This only needs to be used on functions executed in callbacks. It is not necessary everywhere.

Example

@error_catcher
def foo(..):
    ...
Parameters:

func (Callable) – Function executed by a callback

Returns:

warpped function

easy_robot_control.EliaNode.rosTime2Float(time)[source]

Converts ros2 time objects to seconds as float

Parameters:

time (Time | Duration) – ros time obj

Returns:

corresponding seconds as float value

Return type:

float

easy_robot_control.EliaNode.list_cyanize(l, default_color=None)[source]

Makes each element of a list cyan.

Parameters:
  • l (Iterable) – Iterable

  • default_color (str | None) – color to go back to outise of the cyan

Return type:

str

Returns:

Return type:

str

Parameters:
  • l (Iterable)

  • default_color (str | None)

easy_robot_control.EliaNode.replace_incompatible_char_ros2(string_to_correct)[source]

Sanitizes strings for use by ros2.

replace character that cannot be used for Ros2 Topics by _ inserts “WARN” in front if topic starts with incompatible char

Return type:

str

Parameters:

string_to_correct (str)

class easy_robot_control.EliaNode.TCOL[source]

Bases: object

Colors for the terminal

HEADER = '\x1b[95m'

Type:    str

OKBLUE = '\x1b[94m'

Type:    str

OKCYAN = '\x1b[96m'

Type:    str

OKGREEN = '\x1b[92m'

Type:    str

WARNING = '\x1b[33;20m'

Type:    str

FAIL = '\x1b[91m'

Type:    str

ENDC = '\x1b[0m'

Type:    str

BOLD = '\x1b[1m'

Type:    str

UNDERLINE = '\x1b[4m'

Type:    str

easy_robot_control.EliaNode.get_src_folder(package_name)[source]

Absolute path to workspace/src/package_name.

Note

Meant for debugging. Avoid using this, you should build properly.

Parameters:

package_name (str) – workspace/src/package_name

Return type:

str

Returns: Absolute path as str

Return type:

str

Parameters:

package_name (str)

easy_robot_control.EliaNode.transform_joint_to_transform_Rx(transform, jointET)[source]

Takes a transform and a joint (TRANSFORM * +-Rxyz), and returns the (rotational) transform so that RESULT * Rx = TRANSFORM * +-Rxyz. So the transform now places the x base vector onto the axis.

Parameters:
  • transform (ET)

  • jointET (ET)

Returns:

RESULT * Rx = TRANSFORM * +-Rxyz

Return type:

ET

easy_robot_control.EliaNode.loadAndSet_URDF(urdf_path, end_effector_name=None, start_effector_name=None)[source]

I am so sorry. This works to parse the urdf I don’t have time to explain

Note

will change, I hate this

Parameters:
  • urdf_path (str)

  • end_effector_name (str | int | None)

  • start_effector_name (str | None)

Return type:

Tuple[Robot, ETS, List[str], List[Joint], Link | None]

Returns:

Return type:

Tuple[Robot, ETS, List[str], List[Joint], Optional[Link]]

Parameters:
  • urdf_path (str)

  • end_effector_name (str | int | None)

  • start_effector_name (str | None)

easy_robot_control.EliaNode.future_list_complete(future_list)[source]

Returns True is all futures in the input list are done.

Parameters:

future_list (List[Future] | Future) – a list of futures

Returns:

True if all futures are done

Return type:

bool

class easy_robot_control.EliaNode.EZRate(parent, frequency, clock=None)[source]

Bases: object

Parameters:
  • parent (Node)

  • frequency (float)

  • clock (Clock | None)

sleep()[source]

sleeps (blocking) until next tick

Return type:

None

destroy()[source]

Destroys the object

Return type:

None

is_ready()[source]
Return type:

bool

class easy_robot_control.EliaNode.EliaNode(name)[source]

Bases: Node

Parameters:

name (str)

wait_for_lower_level(more_services={}, all_requiered=False)[source]

Blocks until all or any service is available.

Note

  • List of waited services is given by services_to_wait ros2 param

  • Overload this to wait for an additional service

Parameters:
  • more_services (Iterable[str]) – add more services

  • all_requiered (bool) – if True, all listed services must be available

getNow()[source]

quick: self.get_clock().now()

Return type:

Time

sleep(seconds)[source]

sleeps using the node’s clock.

Note

Special case for good old foxy

Parameters:

seconds (float) – time to sleep

Return type:

None

wait_on_futures(future_list, wait_Hz=10)[source]

Waits for the completion of a list of futures, checking completion at the provided rate.

Parameters:
  • future_list (List[Future] | Future) – List of Future to wait for

  • wait_Hz (float) – rate at which to wait

perror(object, force=False)[source]

Prints/Logs error if Yapping==True (default) or force==True.

Parameters:
  • object (Any) – Thing to print

  • bool (force -) – if True the message will print whatever if self.Yapping is.

  • force (bool)

pwarn(object, force=False)[source]

Prints/Logs warning if Yapping==True (default) or force==True.

Parameters:
  • object – Thing to print

  • bool (force -) – if True the message will print whatever if self.Yapping is.

  • force (bool)

pinfo(object, force=False)[source]

Prints/Logs info if Yapping==True (default) or force==True.

Parameters:
  • object – Thing to print

  • force (bool) – if True the message will print whatever if self.Yapping is.

resolve_service_name(service, *, only_expand=False)[source]

Return a service name expanded and remapped.

Note

Overloaded to handle missing foxy

Parameters:
  • service (str) – service name to be expanded and remapped.

  • only_expand (bool) – if True, remapping rules won’t be applied.

Return type:

str

Returns:

a fully qualified service name, result of applying expansion and remapping to the given service.

setAndBlockForNecessaryNodes(necessary_node_names, silent_trial=3, intervalSec=0.5)[source]

Blocks for nodes to be alive

Parameters:
  • necessary_node_names (List[str] | str)

  • silent_trial (int | None)

  • intervalSec (float | None)

get_and_wait_Client(service_name, service_type, cbk_grp=None)[source]

Return the client to the corresponding service, wait for it ot be available.

Parameters:
  • str (service_name -)

  • service_type (service_type - Ros2)

  • cbk_grp (CallbackGroup | None) – Not important I think but it’s there

  • service_name (str)

Return type:

Client

Returns:

Return type:

Client

Parameters:
  • service_name (str)

  • cbk_grp (CallbackGroup | None)

create_EZrate(frequency, clock=None)[source]

Creates a better rate where rate.destroy actually destroys the rate

Parameters:
  • frequency (float) – frequency of the rate

  • clock (Clock | None) – clock to use

Returns:

EZRate manipulating a Rate object

Return type:

EZRate

execute_in_cbk_group(fun, callback_group=None)[source]

Executes the given function by adding it as a callback to a callback_group.

Note

Pretty sure that’s not how it should be done.

Parameters:
  • fun (Callable) – function to execute

  • callback_group (CallbackGroup | None) – callback group in which to execute the function

Returns:

holds the future results quardian: the guard condition object in the callback_group

Return type:

future

Return type:

Tuple[Future, GuardCondition]

easy_robot_control.EliaNode.myMain(nodeClass, multiThreaded=False, args=None)[source]

Main function used through the motion stack.

Parameters:
  • nodeClass – Node to spin

  • multiThreaded (bool) – using multithreaded executor or not

  • () (args)

easy_robot_control.gait_key_dev module

This node is responsible for controlling movement of Moonbot HERO. For now keyboard and controller (PS4).

Authors: Elian NEPPEL, Shamistan KARIMOV Lab: SRL, Moonshot team

easy_robot_control.gait_key_dev.float_formatter()

S.format(*args, **kwargs) -> str

Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces (‘{’ and ‘}’).

class easy_robot_control.gait_key_dev.Leg(number, parent)[source]

Bases: Leg

Parameters:
recover()[source]
Return type:

Future

halt()[source]
Return type:

Future

class easy_robot_control.gait_key_dev.Wheel(number, parent)[source]

Bases: Leg

Parameters:
add_joints(all_joints)[source]
Return type:

List[JointMini]

Parameters:

all_joints (List[str])

connect_movement_clients()[source]
forward()[source]
backward()[source]
stop()[source]
class easy_robot_control.gait_key_dev.KeyGaitNode(name='keygait_node')[source]

Bases: EliaNode

Parameters:

name (str)

makeTBclient()[source]
leg_scanTMRCBK()[source]

Looks for new legs and joints

wheel_scanTMRCBK()[source]

Looks for new legs and joints

refresh_joint_mapping()[source]

joint mapping based on leg number (realguy or MoonbotH)

switch_to_grip_ur16()[source]

joint mapping based on leg number (realguy or MoonbotH)

key_upSUBCBK(msg)[source]

Executes when keyboard released

Parameters:

msg (Key)

stop_all_joints()[source]

stops all joint by sending the current angle as target. if speed was set, sends a speed of 0 instead

all_wheel_speed(speed)[source]

Need a re-work

minimal_wheel_speed(speed)[source]

Need a re-work

tricycle_wheel_speed(speed)[source]

Need a re-work

dragon_wheel_speed(speed)[source]

Need a re-work

wheels_speed(wheels, speed)[source]

Need a re-work

key_downSUBCBK(msg)[source]

Executes when keyboard pressed

Parameters:

msg (Key)

default_3legs()[source]
align_with(leg_number)[source]
Parameters:

leg_number (int)

default_vehicle()[source]
default_dragon()[source]
dragon_align()[source]
dragon_front_left()[source]
dragon_front_right()[source]
dragon_base_lookup()[source]
dragon_base_lookdown()[source]
dragon_back_left()[source]
dragon_back_right()[source]
zero_without_grippers()[source]
goToTargetBody(ts: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyXYZ: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyQuat: quaternion.quaternion | None = None, blocking: Literal[True] = True) rclpy.task.Future[source]
goToTargetBody(ts: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyXYZ: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyQuat: quaternion.quaternion | None = None, blocking: Literal[False] = False) motion_stack_msgs.srv._send_target_body.SendTargetBody_Response
goToTargetBody(ts=None, bodyXYZ=None, bodyQuat=None, blocking=True)
Return type:

Union[Future, SendTargetBody_Response]

Parameters:
  • ts (ndarray[Any, dtype[_ScalarType_co]] | None)

  • bodyXYZ (ndarray[Any, dtype[_ScalarType_co]] | None)

  • bodyQuat (quaternion | None)

  • blocking (bool)

euler_to_quaternion(roll, pitch, yaw)[source]

Convert Euler angles to a quaternion.

Parameters:
  • roll (float) – Rotation around the X-axis in radians.

  • pitch (float) – Rotation around the Y-axis in radians.

  • yaw (float) – Rotation around the Z-axis in radians.

Returns:

The resulting quaternion.

Return type:

Quaternion

Return type:

Optional[quaternion]

msg_to_JoyBits(msg)[source]

Converts a joy msg to a JoyState

Return type:

JoyState

Parameters:

msg (Joy)

display_JoyBits(joy_state)[source]
Parameters:

joy_state (JoyState)

any_pressed(bits, button_names)[source]

Checks if any button in the list is pressed.

Parameters:
  • bits (int) – set of joybits to check against

  • button_names (List[Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR']] | ~typing.Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR']) – list of button names to check if True

Returns:

True if any bit corresponding to a button is True.

Return type:

bool

bits2name(bits)[source]

Converts a bit field to a list of button names

Return type:

List[Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR']]

Parameters:

bits (int)

one_bit2name(bits)[source]

Converts a bit field with 1 bit to 1, to a single button name

Return type:

Optional[Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR']]

Parameters:

bits (int)

joy_pressed(button_name)[source]

Executes for each button that is pressed. Like a callback.

Parameters:
  • bits – Should only have one single bit set to 1, for 1 single button

  • button_name (Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'])

joy_released(button_name)[source]

Executes for each button that is released. Like a callback.

Parameters:
  • bits – Should only have one single bit set to 1, for 1 single button

  • button_name (Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'])

get_joint_index(selected_joint)[source]
Return type:

Optional[int]

Parameters:

selected_joint (int)

joySUBCBK(msg)[source]

Processes incomming joy messages. Converts and stores the received state in self.joy_state . executes self.joy_pressed and self.joy_released for each button that changed state

Parameters:

msg (Joy) – Ros2 Joy message type

joint_control_joy()[source]
joint_timer_start()[source]
static collapseT_KeyCodeModifier(variable)[source]

Collapses the variable onto a KeyCodeModifier type, or None

Returns:

None if variable is not a KCM The variable as a KCM type-hint if it is a KCM

Return type:

Optional[Tuple[int, Union[int, Literal['ANY']]]]

Parameters:

variable (Any)

static collapseT_JoyCodeModifier(variable)[source]

Collapses the variable onto a JoyCodeModifier type, or None

Returns:

None if variable is not a JCM The variable as a JCM type-hint if it is a JCM

Return type:

Optional[Tuple[Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'], Union[int, Literal['ANY']]]]

Parameters:

variable (Any)

static remap_onto_any(mapping, input)[source]

runs the input through the INPUTMap as if the key_modifier was any if it is already, it does not run it.

Parameters:
  • mapping (Dict[Tuple[int, int | Literal['ANY']] | ~typing.Tuple[~typing.Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'], int | ~typing.Literal['ANY']] | ~typing.Literal['ALWAYS'], ~typing.List[~typing.Callable[[], ~typing.Any]]])

  • input (Tuple[int, int | Literal['ANY']] | ~typing.Tuple[~typing.Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'], int | ~typing.Literal['ANY']] | ~typing.Literal['ALWAYS'])

static connect_mapping(mapping, input)[source]

Given the user input, executes the corresponding function mapping

Parameters:
  • mapping (Dict[Tuple[int, int | Literal['ANY']] | ~typing.Tuple[~typing.Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'], int | ~typing.Literal['ANY']] | ~typing.Literal['ALWAYS'], ~typing.List[~typing.Callable[[], ~typing.Any]]]) – Dict of function to execute

  • input (Tuple[int, int | Literal['ANY']] | ~typing.Tuple[~typing.Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'], int | ~typing.Literal['ANY']] | ~typing.Literal['ALWAYS']) – key to the entry to execute

select_leg(leg_ind)[source]

Selects the leg(s) for operation. If None select all.

Parameters:

leg_ind (List[int] | None) – List of leg keys (leg numbers) to use

cycle_leg_selection(increment)[source]

Cycles the leg selection by increment if None, selects all known legs

Parameters:

increment (int | None)

get_active_leg(leg_key=None)[source]

Return the keys to get the current active legs from the self.legs dict

Parameters:
  • leg_number – you can specify a leg key if you need instead of using active legs

  • leg_key (List[int] | int | None)

Returns:

list of active leg keys

Return type:

List[Leg]

get_active_leg_keys(leg_key=None)[source]

Return the keys to get the current active legs from the self.legs dict

Parameters:
  • leg_number – you can specify a leg key if you need instead of using active legs

  • leg_key (List[int] | int | None)

Returns:

list of active leg keys

Return type:

List[int]

halt_all()[source]
halt_detected()[source]
recover_all(leg_keys=None)[source]
Parameters:

leg_keys (List[int] | int | None)

recover_legs(leg_keys=None)[source]
Parameters:

leg_keys (List[int] | int | None)

set_joint_speed(speed, joint=None, leg_number=None)[source]

Sets joint speed or given joints and legs. If Nones, picks the selected or active things

Parameters:
  • speed (float)

  • joint (str | int | None)

  • leg_number (int | None)

start_ik2_timer()[source]

properly checks and start the timer loop for ik of lvl2

ik2TMRCBK()[source]

Timer callback responsable for fast ik movement of lvl2

send_ik2_offset(xyz=None, quat=None, ee_relative=False)[source]
Parameters:
  • xyz (ndarray[Any, dtype[_ScalarType_co]] | None)

  • quat (quaternion | None)

  • ee_relative (bool)

send_ik2_movement(xyz=None, quat=None, ee_relative=False)[source]

debug

Parameters:
  • xyz (ndarray[Any, dtype[_ScalarType_co]] | None)

  • quat (quaternion | None)

  • ee_relative (bool)

select_joint(joint_index)[source]

can be better

angle_zero(leg_number=None)[source]

Sets all joint angles to 0 (dangerous)

Parameters:

leg_number (List[int] | int | None) – The leg on which to set. If none, applies on the active leg

enter_vehicle_mode()[source]

Creates the sub input map for vehicle

Returns:

InputMap for joint control

Return type:

None

enter_dragon_mode()[source]

Creates the sub input map for dragon

Returns:

InputMap for joint control

Return type:

None

enter_tricycle_mode()[source]

Creates the sub input map for tricycle

Returns:

InputMap for joint control

Return type:

None

enter_leg_mode()[source]

Creates the sub input map for leg selection

Returns:

InputMap for leg selection

Return type:

None

ik2_switch_rel_mode(val=None)[source]
Parameters:

val (bool | None)

inch()[source]
inch_to_wheel()[source]
joy_raw()[source]
joy_null()[source]
enter_ik2()[source]

Creates the sub input map for ik control lvl2 by elian

Returns:

InputMap for ik2 control

Return type:

None

enter_joint_mode()[source]

Creates the sub input map for joint control

Returns:

InputMap for joint control

Return type:

None

no_no_leg()[source]

Makes sure no legs are not selected

enter_select_mode()[source]

Mode to select other modes. Should always be accessible when pressing ESC key

easy_mode()[source]
create_main_map()[source]

Creates the main input map, mapping user input to functions, This is supposed to be constant + always active, unlike the sub_map

Return type:

Dict[Union[Tuple[int, Union[int, Literal['ANY']]], Tuple[Literal['NONE', 'x', 'o', 't', 's', 'L1', 'R1', 'L2', 'R2', 'share', 'option', 'PS', 'stickLpush', 'stickRpush', 'down', 'right', 'up', 'left', 'stickL', 'stickR'], Union[int, Literal['ANY']]], Literal['ALWAYS']], List[Callable[[], Any]]]

easy_robot_control.gait_key_dev.main(args=None)[source]

easy_robot_control.gait_node module

This node is responsible for chosing targets and positions.

Author: Elian NEPPEL Lab: SRL, Moonshot team

easy_robot_control.gait_node.float_formatter()

S.format(*args, **kwargs) -> str

Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces (‘{’ and ‘}’).

class easy_robot_control.gait_node.JointMini(joint_name, prefix, parent_leg)[source]

Bases: object

Parameters:
  • joint_name (str)

  • prefix (str)

  • parent_leg (Leg)

is_active()[source]
self_report()[source]
property effort

Optional[float]

Type:

rtype

property speed

Optional[float]

Type:

rtype

property angle

Optional[float]

Type:

rtype

apply_speed_target(speed)[source]

Moves the joint at a given speed using position command. It sends everincreasing angle target (this is for safety, so it stops when nothing happens).

The next angle target sent cannot be more than MAX_DELTA radian away from the current sensor angle (safe, because you can only do small movements with this method) If it is too far away, the speed value will decrease to match the max speed of the joint (not exactly, it will be a little higher).

Parameters:

speed (float | None) – approx speed value (max speed if for 1) or None

Return type:

None

speedTMRCBK()[source]

Updates angle based on stored speed. Stops if speed is None

apply_angle_target(angle)[source]

Sets angle target for the joint, and cancels speed command

Parameters:

angle (float) – angle target

Return type:

None

class easy_robot_control.gait_node.Leg(number, parent)[source]

Bases: object

Helps you use lvl 1-2-3 of a leg

Parameters:
number

leg number

parent

parent node spinning

joint_name_list

list of joints belonging to the leg

static do_i_exist(number, parent, timeout=0.1)[source]

Slow do not use to spam scan. Returns True if the leg is alive

Parameters:
  • number (int)

  • parent (EliaNode)

  • timeout (float)

self_report()[source]
Return type:

str

send_joint_cmd(states)[source]
Parameters:

states (List[JState])

look_for_joints()[source]

scans and updates the list of joints of this leg

go2zero()[source]

sends angle target of 0 on all joints

get_joint_obj(joint)[source]
Return type:

Optional[JointMini]

Parameters:

joint (int | str)

get_angle(joint)[source]

Gets an angle from a joint

Parameters:

joint (int | str) – joint name or number (alphabetically ordered)

Returns:

last recieved angle as float

Return type:

Optional[float]

set_angle(angle, joint)[source]

Sends a angle to a joint

Parameters:
  • angle (float) – rad

  • joint (int | str) – joint name or number (alphabetically ordered)

Returns:

True if message sent

Return type:

bool

ik(xyz=None, quat=None)[source]

Publishes an ik target for the leg () relative to baselink. Motion stack lvl2

Parameters:
  • xyz (None | ndarray[Any, dtype[_ScalarType_co]] | Sequence[float])

  • quat (quaternion | None)

Return type:

None

move(xyz: None | numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | Sequence[float] = None, quat: quaternion.quaternion | None = None, mvt_type: Literal['shift', 'transl', 'rot', 'hop'] = 'shift', blocking: Literal[True] = True) rclpy.task.Future[source]
move(xyz: None | numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | Sequence[float] = None, quat: quaternion.quaternion | None = None, mvt_type: Literal['shift', 'transl', 'rot', 'hop'] = 'shift', blocking: Literal[False] = False) motion_stack_msgs.srv._tf_service.TFService_Response
move(xyz=None, quat=None, mvt_type='shift', blocking=True)

Calls the leg’s movement service. Motion stack lvl3

Parameters:
  • xyz (None | ndarray[Any, dtype[_ScalarType_co]] | Sequence[float]) – vector part of the tf

  • quat (quaternion | None) – quat of the tf

  • mvt_type (Literal['shift', 'transl', 'rot', 'hop']) – type of movement to call

  • blocking (bool) – if false returns a Future. Else returns the response

Return type:

Future | TFService_Response

Returns:

Return type:

Union[Future, TFService_Response]

Parameters:
  • xyz (None | ndarray[Any, dtype[_ScalarType_co]] | Sequence[float])

  • quat (quaternion | None)

  • mvt_type (Literal['shift', 'transl', 'rot', 'hop'])

  • blocking (bool)

class easy_robot_control.gait_node.GaitNode[source]

Bases: EliaNode

firstSpinCBK()[source]
hero_vehicle()[source]
hero_dragon()[source]
hero_arm()[source]
gustavo()[source]
ashutosh(res=None)[source]
Return type:

None

shiftCrawlDebbug(res=None)[source]
crawl1Wheel()[source]

for moonbot hero one arm+wheel only

mZeroBasicSetAndWalk()[source]

for moonbot 0

randomPosLoop()[source]

for multi legged robots

getTargetSet()[source]
Return type:

Future

getTargetSetBlocking()[source]
Return type:

ndarray[Any, dtype[+_ScalarType_co]]

goToTargetBody(ts: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyXYZ: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyQuat: quaternion.quaternion | None = None, blocking: Literal[False] = False) motion_stack_msgs.srv._send_target_body.SendTargetBody_Response[source]
goToTargetBody(ts: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyXYZ: numpy.ndarray[Any, numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None = None, bodyQuat: quaternion.quaternion | None = None, blocking: Literal[True] = True) rclpy.task.Future
goToTargetBody(ts=None, bodyXYZ=None, bodyQuat=None, blocking=True)
Return type:

Union[Future, SendTargetBody_Response]

Parameters:
  • ts (ndarray[Any, dtype[_ScalarType_co]] | None)

  • bodyXYZ (ndarray[Any, dtype[_ScalarType_co]] | None)

  • bodyQuat (quaternion | None)

  • blocking (bool)

crawlToTargetSet(NDArray)[source]
Return type:

None

goToDefault()[source]
stand()[source]
easy_robot_control.gait_node.main(args=None)[source]

easy_robot_control.ik_heavy_node module

This node is responsible for recieving targets in the body reference frame, and send the corresponding angles to the motors.

Author: Elian NEPPEL Lab: SRL, Moonshot team

easy_robot_control.ik_heavy_node.float_formatter()

S.format(*args, **kwargs) -> str

Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces (‘{’ and ‘}’).

class easy_robot_control.ik_heavy_node.WheelMiniNode(joint_name, wheel_size_mm, parent_node)[source]

Bases: object

Parameters:
  • joint_name (str)

  • wheel_size_mm (float)

  • parent_node (EliaNode)

publish_speed_below(speed)[source]

Sends speed to nodes below

Parameters:
  • float (angle)

  • speed (float)

Return type:

None

roll(speed)[source]

Increases the angular speed correspongin to the linear speed

Parameters:
  • float (distance) – distance to roll

  • speed (float)

Return type:

None

class easy_robot_control.ik_heavy_node.IKNode[source]

Bases: EliaNode

firstSpinCBK()[source]
all_limits(et_chain, jobjL)[source]
Parameters:
  • et_chain (ETS)

  • jobjL (List[Joint])

roll_CBK(msg)[source]
Return type:

None

Parameters:

msg (Float64 | float)

compute_raw_ik(xyz, quat, start, compute_budget=None, mvt_duration=None)[source]
Return type:

Tuple[Optional[ndarray[Any, dtype[+_ScalarType_co]]], bool]

Parameters:
  • xyz (ndarray[Any, dtype[_ScalarType_co]])

  • quat (quaternion)

  • start (ndarray[Any, dtype[_ScalarType_co]])

  • compute_budget (Duration | None)

  • mvt_duration (Duration | None)

find_next_ik(xyz, quat, compute_budget=None, mvt_duration=None)[source]
Return type:

ndarray[Any, dtype[+_ScalarType_co]]

Parameters:
  • xyz (ndarray[Any, dtype[_ScalarType_co]])

  • quat (quaternion)

  • compute_budget (Duration | EZRate | None)

  • mvt_duration (Duration | None)

set_ik_CBK(msg)[source]

recieves target from leg, converts to numpy, computes IK, sends angle results to joints

Parameters:

msg (Transform) – target as Ros2 Vector3

Return type:

None

replace_none_target(xyz, quat)[source]
Return type:

Tuple[ndarray[Any, dtype[+_ScalarType_co]], quaternion]

Parameters:
  • xyz (ndarray[Any, dtype[_ScalarType_co]])

  • quat (quaternion)

joint_readSUBCBK(js)[source]
Parameters:

js (JointState)

send_command(angles)[source]
Parameters:

angles (ndarray[Any, dtype[_ScalarType_co]])

current_fk()[source]
Return type:

Tuple[ndarray[Any, dtype[+_ScalarType_co]], quaternion]

publish_tip_pos()[source]

Computes foward kinematics given angles stored in array, publishes tip position result. This is executed x ms after an angle reading is received

Return type:

None

easy_robot_control.ik_heavy_node.main()[source]

easy_robot_control.joint_state_interface module

class easy_robot_control.joint_state_interface.JointHandler(name, parent_node, joint_object, IGNORE_LIM=False, MARGIN=0.0)[source]

Bases: object

This handles a single joint. The main purpose is to update stateSensor and stateCommand. As well as getting the newest values for those (in order to not continuously publish unchanging data).

Parameters:
  • name (str)

  • parent_node (JointNode)

  • joint_object (Joint)

  • IGNORE_LIM (bool)

  • MARGIN (float)

load_limit(ignore, jobj=None)[source]

Loads the limit from the (urdf) joint object

Parameters:
  • ignore (bool) – if limits should be ignored

  • jobj (Joint | None)

property limit_rejected

if the limit was rejected when loading (often when not defined in urdf)

Return type:

bool

Type:

Returns

speakup_when_angle()[source]

start a verbose check every seconds for new angles

checkAngle(angle)[source]

True is angle is valid or None

Return type:

bool

Parameters:

angle (float | None)

applyAngleLimit(angle)[source]

Clamps the angle between the joints limits

Return type:

Tuple[float, bool]

Parameters:

angle (float)

resetAnglesAtZero()[source]
update_js_command(js)[source]

Updates the stateCommand to a new js.

Parameters:

js (JState)

is_new_jssensor(js)[source]

True if js is different enough from the last received. Also true if stateSensor is more the TOL_NO_CHANGE.time old relative to the new

Parameters:

js (JState)

setJSSensor(js)[source]

Updates the stateSensor to a new js.

Parameters:

js (JState)

process_angle_command(angle)[source]

This runs on new js before updating stateCommand

Return type:

float

Parameters:

angle (float)

process_velocity_command(speed)[source]

This runs on new js before updating stateCommand

Return type:

Optional[float]

Parameters:

speed (float)

process_effort_command(eff)[source]

This runs on new js before updating stateCommand

Return type:

float

Parameters:

eff (float)

set_effortCBK(msg)[source]

Updates stateCommand by providing only an effort. should be avoided as the timestamp will be set to now.

Parameters:

msg (Float64 | float)

get_fresh_sensor(reset=True)[source]

returns sensor data that is newer than the last time it was called. if the sensor data didn’t changed enough to trigger a refresh, this will be full of None. If a refresh occured, the None will be replaced by the non-None values in the new sensor data.

example: if you stop sending speed sensor data after sending a bunch of speeds. This speed will switch to None, it will not continue to be the last received speed. This last received speed is still available in stateSensor.

Return type:

JState

Parameters:

reset (bool)

get_freshCommand(reset=True)[source]

returns command data that is newer than the last time it was called. full of None is not newer

Return type:

JState

Parameters:

reset (bool)

class easy_robot_control.joint_state_interface.JointNode[source]

Bases: EliaNode

Lvl1

lvl0_remap

Type:    StateRemapper

Remapping around any joint state communication of lvl0

lvl2_remap

Type:    StateRemapper

Remapping around any joint state communication of lvl2

send_to_lvl0(states)[source]

Sends states to lvl0 (commands for motors). This function is executed every time data needs to be sent down. Change/overload this method with what you need

Parameters:

states (List[JState])

send_to_lvl2(states)[source]

Sends states to lvl2 (states for ik). This function is executed every time data needs to be sent up. Change/overload this method with what you need

Parameters:

states (List[JState])

js_from_lvl0(msg)[source]

Callback when a JointState arrives from the lvl0 (states from motor). Converts it into a list of states, then hands it to the general function

Parameters:

msg (JointState)

js_from_lvl2(msg)[source]

Callback when a JointState arrives from the lvl2 (commands from ik). Converts it into a list of states, then hands it to the general function

Parameters:

msg (JointState)

coming_from_lvl2(states)[source]

Processes incomming commands from lvl2 ik. Call this function after processing the ros message

Parameters:

states (List[JState])

coming_from_lvl0(states)[source]

Processes incomming sensor states from lvl0 motors. Call this function after processing the ros message. Always do super().coming_from_lvl0(states) before your code, Unless you know what you are doing

Parameters:

states (List[JState])

advertiserSRVCBK(req, res)[source]

Sends an JointState mainly to advertise the names of the joints

Return type:

ReturnJointState_Response

Parameters:
  • req (ReturnJointState_Request)

  • res (ReturnJointState_Response)

defined_undefined()[source]

Return joints with and without poistion data received yet

Returns:

Tuple(List[joint names that did not receive any data], List[joint names that have data])

Return type:

Tuple[List[str], List[str]]

angle_read_checkTMRCBK()[source]

Checks that all joints are receiving data. After 1s, if not warns the user, and starts the verbose check on the joint handler.

firstSpinCBK()[source]
robot_body_pose_cbk(msg)[source]
Parameters:

msg (Transform)

smoother(x)[source]

smoothes the interval [0, 1] to have a soft start and end (derivative is zero)

Return type:

ndarray[Any, dtype[+_ScalarType_co]]

Parameters:

x (ndarray[Any, dtype[_ScalarType_co]])

smooth_body_trans(request)[source]
Parameters:

request (Transform)

go_zero_allCBK(req, resp)[source]
Parameters:
  • req (Empty_Request)

  • resp (Empty_Response)

easy_robot_control.joint_state_interface.main(args=None)[source]

easy_robot_control.lazy_joint_state_publisher module

Overloading the joint_state_publisher package so it does not publish joint states that are not actively published

Lots of black magic being used

class easy_robot_control.lazy_joint_state_publisher.dummy_pub[source]

Bases: object

publish(msg)[source]
class easy_robot_control.lazy_joint_state_publisher.LazyJointStatePublisher(description_file)[source]

Bases: JointStatePublisher

source_cb(msg)[source]
delete_inactive_from_msg(msg)[source]

Deletes joints that are not part of self.active_joints from a message

Return type:

JointState

Parameters:

msg (JointState)

easy_robot_control.lazy_joint_state_publisher.main()[source]

easy_robot_control.leg_api module

Provides api anc controllers to control leg ik and joints directly

Author: Elian NEPPEL Lab: SRL, Moonshot team

easy_robot_control.leg_api.float_formatter()

S.format(*args, **kwargs) -> str

Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces (‘{’ and ‘}’).

class easy_robot_control.leg_api.Pose(time, xyz, quat)[source]

Bases: object

Parameters:
  • time (Time)

  • xyz (NDArray[Shape[3], floating])

  • quat (quaternion)

time

Type:    Time

xyz

Type:    NDArray[Shape[3], floating]

quat

Type:    quaternion

close2zero(atol=(1, 0.01))[source]
Return type:

bool

class easy_robot_control.leg_api.JointMini(joint_name, prefix, parent_leg)[source]

Bases: object

Parameters:
  • joint_name (str)

  • prefix (str)

  • parent_leg (Leg)

is_active()[source]
self_report()[source]
property effort

Optional[float]

Type:

rtype

property speed

Optional[float]

Type:

rtype

property angle

Optional[float]

Type:

rtype

apply_speed_target(speed)[source]

Moves the joint at a given speed using position command. It sends everincreasing angle target (this is for safety, so it stops when nothing happens).

The next angle target sent cannot be more than MAX_DELTA radian away from the current sensor angle (safe, because you can only do small movements with this method) If it is too far away, the speed value will decrease to match the max speed of the joint (not exactly, it will be a little higher).

Parameters:

speed (float | None) – approx speed value (max speed if for 1) or None

Return type:

None

apply_angle_target(angle)[source]

Sets angle target for the joint, and cancels speed command

Parameters:

angle (float) – angle target

Return type:

None

easy_robot_control.leg_api.T = TypeVar(T, NDArray, quaternion)

Type:    TypeVar

Invariant TypeVar constrained to nptyping.ndarray.NDArray and quaternion.quaternion.

class easy_robot_control.leg_api.Leg(number, parent)[source]

Bases: object

Helps you use lvl 1-2-3 of a leg

Parameters:
number

leg number

parent

parent node spinning

joint_name_list

list of joints belonging to the leg

connect_movement_clients()[source]
static do_i_exist(number, parent, timeout=1)[source]

Slow do not use to spam scan. Returns True if the leg is alive

Parameters:
  • number (int)

  • parent (EliaNode)

  • timeout (float)

self_report()[source]
Return type:

str

add_joints(all_joints)[source]
Return type:

List[JointMini]

Parameters:

all_joints (List[str])

look_for_joints()[source]

scans and updates the list of joints of this leg

go2zero()[source]

sends angle target of 0 on all joints

get_joint_obj(joint)[source]

Gets the corresponding joint object is exists

Parameters:

joint (int | str) – joint name or number (alphabetically ordered)

Return type:

Optional[JointMini]

get_angle(joint)[source]

Gets an angle from a joint

Parameters:

joint (int | str) – joint name or number (alphabetically ordered)

Returns:

last recieved angle as float

Return type:

Optional[float]

set_angle(angle, joint)[source]

Sends a angle to a joint

Parameters:
  • angle (float) – rad

  • joint (int | str) – joint name or number (alphabetically ordered)

Returns:

True if message sent

Return type:

bool

ik(xyz=None, quat=None)[source]

Publishes an ik target for the leg () relative to baselink. Motion stack lvl2

Parameters:
  • xyz (None | NDArray[Any, Any] | Sequence[float])

  • quat (quaternion | None)

Return type:

None

move(xyz: None | nptyping.ndarray.NDArray[Any, Any] | Sequence[float] = None, quat: quaternion.quaternion | None = None, mvt_type: Literal['shift', 'transl', 'rot', 'hop'] = 'shift', blocking: Literal[True] = True) rclpy.task.Future[source]
move(xyz: None | nptyping.ndarray.NDArray[Any, Any] | Sequence[float] = None, quat: quaternion.quaternion | None = None, mvt_type: Literal['shift', 'transl', 'rot', 'hop'] = 'shift', blocking: Literal[False] = False) motion_stack_msgs.srv._tf_service.TFService_Response
move(xyz=None, quat=None, mvt_type='shift', blocking=True)

Calls the leg’s movement service. Motion stack lvl3

Parameters:
  • xyz (None | NDArray[Any, Any] | Sequence[float]) – vector part of the tf

  • quat (quaternion | None) – quat of the tf

  • mvt_type (Literal['shift', 'transl', 'rot', 'hop']) – type of movement to call

  • blocking (bool) – if false returns a Future. Else returns the response

Return type:

Future | TFService_Response

Returns:

Return type:

Union[Future, TFService_Response]

Parameters:
  • xyz (None | NDArray[Any, Any] | Sequence[float])

  • quat (quaternion | None)

  • mvt_type (Literal['shift', 'transl', 'rot', 'hop'])

  • blocking (bool)

class easy_robot_control.leg_api.Ik2(leg)[source]

Bases: object

Provides ik2 methods given a leg

Parameters:

leg (Leg)

save_recording()[source]
run_task()[source]
property quat_now

Optional[quaternion]

Type:

rtype

property xyz_now

Optional[NDArray[Shape[3], floating]]

Type:

rtype

property now_pose

Optional[Pose]

Type:

rtype

reset()[source]

Resets the trajectory start point onto the current end effector position

Return type:

Pose

clear()[source]

Clears the trajectory start point

make_abs_pos(xyz, quat, ee_relative=False)[source]
Return type:

Optional[Pose]

Parameters:
  • xyz (NDArray[Shape[3], floating] | None)

  • quat (quaternion | None)

  • ee_relative (bool | None)

controlled_motion(xyz, quat, ee_relative=False)[source]

Continuously calls self.step_toward(…) in the task timer.

Cancels the previous task and future. Replaces it with a new function to execute and new future. Returns the assiciated future (you can cancel it, and know when it’s done).

Parameters:
  • xyz (NDArray[Shape[3], floating] | None) – target in mm

  • quat (quaternion | None) – target as quaternion

  • ee_relative (bool | None) – if the movement should bee performed relative to the end effector

Return type:

Future

Returns

Future assiciated with the movement’s task.

Return type:

Future

Parameters:
  • xyz (NDArray[Shape[3], floating] | None)

  • quat (quaternion | None)

  • ee_relative (bool | None)

step_toward(xyz, quat, ee_relative=False)[source]

Sends a single ik command to move toward the target. Not meant to reach the target!!!

This method is robust to IK errors and motor speed saturation. It will adapt its speed according to the robot response to keep track with the path.

The command will clamp not farther from the current EE than self.sphere_xyz_radius and self.sphere_quat_radius. Increase those values to allow for a wider margin of error (also leading to higher speed)

The math become imprecise with big deltas in quaternions. See clamp_xyz_quat(…) Do not use if self.last_pose.quat is opposite to quat. (idk what will happen but you wont like it)

Parameters:
  • xyz (NDArray[Shape[3], floating] | None) – target in mm

  • quat (quaternion | None) – target as quaternion

  • ee_relative (bool | None) – if the movement should bee performed relative to the end effector

Return type:

bool

offset(xyz, quat, ee_relative=False)[source]

Wrapper around self.step_toward(…), Origin is placed onto the EE. ee_relative specifies if the origin should have the same orientation as the EE

Parameters:
  • xyz (NDArray[Shape[3], floating] | None) – mm to move by

  • quat (quaternion | None) – quaternion to move by

  • ee_relative (bool | None) – True: movement origin is the EE. False: movement origin is the baselink.

easy_robot_control.leg_node module

This node is responsible for recieving targets with trajectories of the corresponding leg. It will performe smooth movements in the body center frame of reference or relative to the current end effector position. This node keeps track of the leg end effector to generate trajectories to the target.

Author: Elian NEPPEL Lab: SRL, Moonshot team

class easy_robot_control.leg_node.LegNode[source]

Bases: EliaNode

firstSpinCBK()[source]
publish_to_roll(roll=None)[source]

publishes roll value towards ik node

Parameters:

roll (float | None)

smart_roll_cbk(msg)[source]
Parameters:

msg (Float64)

publish_to_ik(xyz=None, quat=None)[source]

publishes target towards ik node

Parameters:
  • target – np.array float(3,)

  • xyz (ndarray[Any, dtype[_ScalarType_co]] | None)

  • quat (quaternion | None)

trajectory_executor()[source]

pops target from trajectory queue and publishes it. This follows and handle the trajectory_timer

Return type:

None

trajectory_finished_cbk()[source]

executes after the last target in the trajectory is processed

Return type:

None

queue_xyz_empty()[source]
Return type:

bool

queue_quat_empty()[source]
Return type:

bool

queue_roll_empty()[source]
Return type:

bool

pop_xyzq_from_traj(index=0)[source]

deletes and returns the first value of the trajectory_queue for coordinates and quaternions.

Parameters:

index (int) – if you wanna pop not the first but somewhere else

Returns:

np.array float(3,) - popped value

Return type:

value

Return type:

Tuple[Optional[ndarray[Any, dtype[+_ScalarType_co]]], Optional[quaternion]]

pop_roll_from_traj(index=0)[source]

Deletes and returns the first value of the trajectory_queue for the roll.

Parameters:

index (int) – if you wanna pop not the first but somewhere else

Returns:

np.array float(3,) - popped value

Return type:

value

Return type:

Optional[float]

get_final_xyz()[source]
Return type:

ndarray[Any, dtype[+_ScalarType_co]]

get_final_quat()[source]
Return type:

quaternion

get_final_target()[source]

returns the final position of where the leg is. Or will be at the end of the current trajectory_queue.

Returns:

np.array float(3,) - final coordinates

Return type:

end_point

Return type:

Tuple[ndarray[Any, dtype[+_ScalarType_co]], quaternion]

fuse_xyz_trajectory(xyz_traj=None)[source]
Parameters:

xyz_traj (ndarray[Any, dtype[_ScalarType_co]] | None)

fuse_quat_trajectory(quat_traj=None)[source]
Parameters:

quat_traj (quaternion | None)

fuse_roll_trajectory(roll_traj=None)[source]
Parameters:

roll_traj (ndarray[Any, dtype[_ScalarType_co]] | None)

add_to_trajectory(xyz_traj=None, quat_traj=None)[source]

Adds a trajectory RELATIVE TO THE BODY CENTER to the trajectory queue

Parameters:
  • new_traj – np.array float(:, 3) - xyz trajectory RELATIVE TO THE BODY CENTER

  • quat_traj (quaternion | None) – qt.quaternion shape(:) - quaternion trajectory RELATIVE TO THE BODY CENTER

  • xyz_traj (ndarray[Any, dtype[_ScalarType_co]] | None)

Return type:

None

send_most_recent_tip(request, response)[source]

Publish the last target sent

Parameters:
  • request (ReturnVect3_Request) – ReturnVect3.Request - Nothing

  • response (ReturnVect3_Response) – ReturnVect3.Response - Vector3 (float x3)

Returns:

ReturnVect3 - Vector3 (float x3)

Return type:

ReturnVect3_Response

smoother(x)[source]

smoothes the interval [0, 1] to have a soft start and end (derivative is zero)

Return type:

ndarray[Any, dtype[+_ScalarType_co]]

Parameters:

x (ndarray[Any, dtype[_ScalarType_co]])

smoother_complement(x)[source]

changes the interval [0, 1] to 0->1->0 and smoothes to have a soft start and end

Return type:

ndarray[Any, dtype[+_ScalarType_co]]

Parameters:

x (ndarray[Any, dtype[_ScalarType_co]])

rel_transl(xyz=None, quat=None)[source]

performs translation to the target relative to body

Parameters:
  • target – np.array float(3,) - target relative to the body center

  • quat (quaternion | None) – qt.quaternion - target quaternion relative to body center

  • xyz (ndarray | None)

Returns:

np.array float(3,) - target relative to the body center

Return type:

target

Return type:

int

static point_with_quat(vect)[source]
Parameters:

vect (ndarray[Any, dtype[_ScalarType_co]])

point_toward(vect)[source]
Return type:

int

Parameters:

vect (ndarray[Any, dtype[_ScalarType_co]])

point_wheel(direction)[source]
Return type:

None

Parameters:

direction (ndarray[Any, dtype[_ScalarType_co]])

shift(shift=None, quat=None)[source]

performs translation to the target relative to current position

Parameters:
  • target – np.array float(3,) - target relative to current position

  • shift (ndarray[Any, dtype[_ScalarType_co]] | None)

  • quat (quaternion | None)

Returns:

np.array float(3,) - target relative to current position

Return type:

target

Return type:

int

rel_hop(target)[source]

performs jump to the target relative to body

Parameters:

target (ndarray) – np.array float(3,) - target relative to the body center

Returns:

np.array float(3,) - target relative to the body center

Return type:

target

Return type:

ndarray[Any, dtype[+_ScalarType_co]]

tip_pos_received_cbk(msg)[source]

callback when a new end effector position is received

Parameters:

msg (Vector3) – real end effector position

Return type:

None

check_divergence()[source]

If the real end effector is not on the last target that was sent. Launches the timer to overwrite the target with the real position.

If target and end effector correpsond, cancel the timer to overwrite the target.

Return type:

None

overwrite_target()[source]

overwrites the last sent target with the real position of the end effector.

This will happen on startup, and when there is a problem on the real leg (cannot perform the movement) Small divergences are expected (in position and time), hence the timer and the check_divergence function.

Setting lastTarget to the currentTip all the time is a bas idea, it create overcorrections.

Return type:

None

wait_end_of_motion()[source]

waits for the trajectory to end. This function is very bad, but I don’t need nor have time to do something better.

We should keep track of which trajectory are beeing queued to improve

Return type:

None

append_trajectory(trajectory_function)[source]

The function will be executed before the next read of the trajectory sequentialy This avoids trajectory_function in multiple threads modifying indentical data simultaneously.

Parameters:
  • function (trajectory_function -) – function to execute

  • trajectory_function (Callable)

Returns:

holds the future results of the function if needed

Return type:

future

Return type:

Future

shift_cbk(request, response)[source]

Callback for leg shift motion

Parameters:
  • request (TFService_Request) – target relative to current end effector position

  • response (TFService_Response)

Returns:

success = True all the time

Return type:

TFService_Response

rel_transl_srv_cbk(request, response)[source]

Callback for leg translation motion

Parameters:
  • request (TFService_Request) – target relative to body

  • response (TFService_Response)

Returns:

success = True all the time

Return type:

TFService_Response

rel_hop_srv_cbk(request, response)[source]

Callback for leg hopping motion

Parameters:
  • request (TFService_Request) – target relative to body

  • response (TFService_Response)

Returns:

success = True all the time

Return type:

TFService_Response

rot_cbk(request, response)[source]

Callback for leg rotation motion

Parameters:
  • request (TFService_Request) – TF for the rotation and center of the rotation

  • response (TFService_Response)

Returns:

success = True all the time

Return type:

TFService_Response

point_cbk(request, response)[source]
Return type:

TFService_Response

Parameters:
  • request (TFService_Request)

  • response (TFService_Response)

easy_robot_control.leg_node.main(args=None)[source]

easy_robot_control.mover_node module

This node is responsible for synchronising several leg movement in order to move the cente body and perform steps.

Author: Elian NEPPEL Lab: SRL, Moonshot team

class easy_robot_control.mover_node.MoverNode[source]

Bases: EliaNode

firstSpinCBK()[source]
Return type:

None

go2_targetbodyCBK(req, res)[source]
Return type:

SendTargetBody_Response

Parameters:
  • req (SendTargetBody_Request)

  • res (SendTargetBody_Response)

get_targetsetCBK(req, res)[source]
Return type:

ReturnTargetSet_Response

Parameters:
  • req (ReturnTargetSet_Request)

  • res (ReturnTargetSet_Response)

update_tip_pos()[source]
Return type:

ndarray[Any, dtype[+_ScalarType_co]]

body_shift(shift)[source]
Return type:

None

Parameters:

shift (ndarray)

body_tfshift_cbk(request, response)[source]
Return type:

TFService_Response

Parameters:
  • request (TFService_Request)

  • response (TFService_Response)

multi_transl(target_set)[source]
Parameters:

target_set (ndarray)

multi_hop(target_set)[source]
Parameters:

target_set (ndarray)

multi_shift(target_set)[source]
Parameters:

target_set (ndarray)

multi_rotate(target_set, quat)[source]
Parameters:
  • target_set (ndarray)

  • quat (quaternion)

move_body_and_hop(body_xyz, target_set, body_quat=None)[source]
Parameters:
  • body_xyz (ndarray)

  • target_set (ndarray)

  • body_quat (quaternion | None)

easy_robot_control.mover_node.main(args=None)[source]