===== martypy.Marty ===== Python library to communicate with Marty the Robot V1 and V2 by Robotical Getting started:\\ 1) Import Marty from the martypy library\\ 2) Create a Marty object that connects the way you want\\ 3) Tell your Marty to dance from martypy import Marty my_marty = Marty("wifi","192.168.0.53") my_marty.dance() The tags 1️⃣ and 2️⃣ indicate when the method is available for Marty V1 1️⃣ and Marty V2 2️⃣ ===== Marty Objects ===== class Marty(object) ==== %%__%%init%%__%% ==== | __init__(method: str, locator: str = "", extra_client_types: dict = dict(), blocking: Union[bool, None] = None, *args, **kwargs) -> None Start a connection to Marty 1️⃣ 2️⃣ For example: * ''%%Marty("wifi", "192.168.86.53")%%'' to connect to Marty via WiFi on IP Address 192.168.0.53 * ''%%Marty("usb", "COM2")%%'' on a Windows computer with Marty connected by USB cable to COM2 * ''%%Marty("usb", "/dev/tty.SLAB_USBtoUART")%%'' on a Mac computer with Marty connected by USB cable to /dev/tty.SLAB_USBtoUART * ''%%Marty("exp", "/dev/ttyAMA0")%%'' on a Raspberry Pi computer with Marty connected by expansion cable to /dev/ttyAMA0 **Blocking Mode** Each command that makes Marty move (e.g. ''%%walk()%%'', ''%%dance()%%'', ''%%move_joint()%%'', but also ''%%hold_position()%%'') comes with two modes - blocking and non-blocking. Issuing a command in blocking mode will make your program pause until Marty physically stops moving. Only then the next line of your code will be executed. In non-blocking mode, each movement command simply tells Marty what to do and returns immediately, meaning that your code will continue to execute while Marty is moving. Every movement command takes an optional ''%%blocking%%'' argument that can be used to choose the mode for that call. If you plan to use the same mode all or most of the time, it is better to to use the ''%%Marty.set_blocking()%%'' method or use the ''%%blocking%%'' constructor argument. The latter defaults to ''%%True%%'' (blocking) if not provided. **Arguments**: * ''%%method%%'' - method of connecting to Marty - it may be: "usb", "wifi", "socket" (Marty V1) or "exp" (expansion port used to connect to a Raspberry Pi, etc) * ''%%locator%%'' - location to connect to, depending on the method of connection this is the serial port name, network (IP) Address or network name (hostname) of Marty that the computer should use to communicate with Marty. If ''%%method%%'' is ''%%"usb"%%'' and there is only a single Marty connected, ''%%locator%%'' can be left out and the Marty will be found automatically. If multiple Martys are detected, one of them will be chosen arbitrarily and connected to. * ''%%blocking%%'' - Default movement command mode for this ''%%Marty%%'' instance. * ''%%True%%'' (default): blocking mode * ''%%False%%'': non-blocking mode **Raises**: * MartyConfigException if the parameters are invalid * MartyConnectException if Marty couldn't be contacted ==== dance ==== | dance(side: str = 'right', move_time: int = 3000, blocking: Optional[bool] = None) -> bool Boogie, Marty! 1️⃣ 2️⃣ **Arguments**: * ''%%side%%'' - 'left' or 'right', which side to start on * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== celebrate ==== | celebrate(move_time: int = 4000, blocking: Optional[bool] = None) -> bool Coming soon! Same as ''%%wiggle()%%'' for now. 1️⃣ 2️⃣ **Arguments**: * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== wiggle ==== | wiggle(move_time: int = 4000, blocking: Optional[bool] = None) -> bool Wiggle 2️⃣ **Arguments**: * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== circle_dance ==== | circle_dance(side: str = 'right', move_time: int = 2500, blocking: Optional[bool] = None) -> bool Circle Dance 2️⃣ **Arguments**: * ''%%side%%'' - 'left' or 'right', which side to start on * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== walk ==== | walk(num_steps: int = 2, start_foot: str = 'auto', turn: int = 0, step_length: int = 25, move_time: int = 1500, blocking: Optional[bool] = None) -> bool Make Marty walk 1️⃣ 2️⃣ **Arguments**: * ''%%num_steps%%'' - how many steps to take * ''%%start_foot%%'' - 'left', 'right' or 'auto', start walking with this foot Note: 2️⃣ Unless you specify 'auto', all steps are taken with the same foot so it only makes sense to use the start_foot argument with ''%%num_steps=1%%''. * ''%%turn%%'' - How much to turn (-100 to 100 in degrees), 0 is straight. * ''%%step_length%%'' - How far to step (approximately in mm) * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== get_ready ==== | get_ready(blocking: Optional[bool] = None) -> bool Move Marty to the normal standing position and wiggle eyebrows 1️⃣ 2️⃣ Will also enable motors for Marty v1 1️⃣ **Arguments**: * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. **Returns**: True if Marty accepted the request ==== stand_straight ==== | stand_straight(move_time: int = 2000, blocking: Optional[bool] = None) -> bool Move Marty to the normal standing position 1️⃣ 2️⃣ **Arguments**: * ''%%move_time%%'' - How long (in milliseconds) Marty will take to reach the normal standing position. (Higher number means slower movement.) * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== eyes ==== | eyes(pose_or_angle: Union[str, int], move_time: int = 1000, blocking: Optional[bool] = None) -> bool Move the eyes to a pose or an angle 1️⃣ 2️⃣ **Arguments**: * ''%%pose_or_angle%%'' - 'angry', 'excited', 'normal', 'wide', or 'wiggle' 2️⃣ - alternatively this can be an angle in degrees (which can be a negative number) * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== kick ==== | kick(side: str = 'right', twist: int = 0, move_time: int = 2500, blocking: Optional[bool] = None) -> bool Kick one of Marty's feet 1️⃣ 2️⃣ **Arguments**: * ''%%side%%'' - 'left' or 'right', which foot to use * ''%%twist%%'' - the amount of twisting do do while kicking (in degrees) * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== arms ==== | arms(left_angle: int, right_angle: int, move_time: int, blocking: Optional[bool] = None) -> bool Move both of Marty's arms to angles you specify 1️⃣ 2️⃣ **Arguments**: * ''%%left_angle%%'' - Angle of the left arm (degrees -100 to 100) * ''%%right_angle%%'' - Position of the right arm (degrees -100 to 100) * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== lean ==== | lean(direction: str, amount: Optional[int] = None, move_time: int = 1000, blocking: Optional[bool] = None) -> bool Lean over in a direction 1️⃣ 2️⃣ **Arguments**: * ''%%direction%%'' - ''%%'left'%%'', ''%%'right'%%'', ''%%'forward'%%'', or ''%%'back'%%'' * ''%%amount%%'' - How much to lean. The defaults and the exact meaning is different between Marty V1 and V2: * 1️⃣ If not specified or ''%%None%%'', ''%%amount%%'' defaults to ''%%50%%'' (no specific unit). Limit is -60/60 in either direction. * 2️⃣ If not specified or ''%%None%%'', ''%%amount%%'' defaults to ''%%29%%'' degrees. Limit for foward and back is 45 and limit for left and right is 60. * ''%%move_time%%'' - How long this movement should last, in milliseconds. * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== sidestep ==== | sidestep(side: str, steps: int = 1, step_length: int = 35, move_time: int = 1000, blocking: Optional[bool] = None) -> bool Take sidesteps 1️⃣ 2️⃣ **Arguments**: * ''%%side%%'' - 'left' or 'right', direction to step in * ''%%steps%%'' - number of steps to take * ''%%step_length%%'' - how broad the steps are (up to 127) * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request ==== play_sound ==== | play_sound(name_or_freq_start: Union[str,int], freq_end: Optional[int] = None, duration: Optional[int] = None) -> bool Play a named sound (Marty V2 2️⃣) or make a tone (Marty V1 1️⃣) **Arguments**: * ''%%name_or_freq_start%%'' - name of the sound, e.g. 'excited' or 'no_way' 2️⃣ * ''%%name_or_freq_start%%'' - starting frequency, min 20, max 20000, Hz 1️⃣ * ''%%freq_end%%'' - ending frequency, min 20, max 20000, Hz 1️⃣ * ''%%duration%%'' - milliseconds, maximum 5000 1️⃣ **Returns**: True if Marty accepted the request ==== play_mp3 ==== def play_mp3(filename: str, progress_callback: Callable[[int, int], bool] = None) -> bool Play an mp3 file on the robot. 2️⃣ **Arguments**: * ''%%filename%%'' - the name of the mp3 file to play ==== send_file ==== def send_file(filename: str, progress_callback: Callable[[int, int], bool] = None, file_dest: str = "fs") -> bool Send a file to Marty. 2️⃣ **Arguments**: * ''%%filename%%'' - the name of the file to send * ''%%progress_callback%%'' - callback used to indicate how file send is progressing, callable takes three params which are bytesSent and totalBytes and returns a bool which should be True to continue the file upload or False to abort * ''%%file_dest%%'' - "fs" to upload to file system, "ricfw" for new RIC firmware **Returns**: True if the file was sent successfully Throws: - ''%%OSError%%'' - operating system exceptions May throw other exceptions so include a general exception handler ==== get_accelerometer ==== | get_accelerometer(axis: Optional[str] = None) -> float Get the latest value from the Marty's accelerometer 1️⃣ 2️⃣ **Arguments**: * ''%%axis%%'' - (optional) 'x', 'y' or 'z' OR no parameter at all (see returns below) **Returns**: * The acceleration value from the axis (if axis specified) * A tuple containing x, y and z values (if no axis) 2️⃣ Note that the returned value will be 0 if no value is available **Raises**: MartyCommandException if the axis is unknown ==== is_moving ==== | is_moving() -> bool Check if Marty is moving 2️⃣ **Arguments**: none **Returns**: True if Marty is moving ==== stop ==== | stop(stop_type: Optional[str] = None) -> bool Stop Marty's movement 1️⃣ 2️⃣ You can also control what way to "stop" you want with the parameter stop_type. For instance: * 'clear queue' to finish the current movement before stopping (clear any queued movements) * 'clear and stop' stop immediately (and clear queues) * 'clear and disable' 1️⃣ stop and disable the robot * 'clear and zero' stop and move back to get_ready pose * 'pause' pause motion * 'pause and disable' 1️⃣ pause motion and disable the robot **Arguments**: * ''%%stop_type%%'' - the way to stop - see the options above **Raises**: MartyCommandException if the stop_type is unknown ==== resume ==== | resume() -> bool Resume Marty's movement after a pause 2️⃣ **Returns**: True if Marty accepted the request ==== hold_position ==== | hold_position(hold_time: int, blocking: Optional[bool] = None) -> bool Hold Marty at its current position 2️⃣ **Arguments**: hold_time, time to hold position in milli-seconds - ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. Holding position counts as movement because Marty is using its motors to actively resist any attempts to move its joints. **Returns**: True if Marty accepted the request ==== is_paused ==== | is_paused() -> bool Check if Marty is paused 2️⃣ **Returns**: True if Marty is paused ==== is_blocking ==== | is_blocking() -> bool Check the default movement command behaviour of this Marty. 1️⃣ 2️⃣ **Returns**: ''%%True%%'' if movement commands block by default ==== set_blocking ==== | set_blocking(blocking: bool) Change whether movement commands default to blocking or non-blocking behaviour for this Marty. 1️⃣ 2️⃣ The blocking behaviour can also be specified on a per-command basis using the ''%%blocking=%%'' argument which takes precedence over Marty's overall setting. **Arguments**: * ''%%blocking%%'' - whether or not to block by default ==== move_joint ==== | move_joint(joint_name_or_num: Union[int, str], position: int, move_time: int, blocking: Optional[bool] = None) -> bool Move a specific joint to a position 1️⃣ 2️⃣ **Arguments**: * ''%%joint_name_or_num%%'' - joint to move, see the Marty.JOINT_IDS dictionary (can be name or number) * ''%%position%%'' - angle in degrees * ''%%move_time%%'' - how long this movement should last, in milliseconds * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. **Returns**: True if Marty accepted the request **Raises**: MartyCommandException if the joint_name_or_num is unknown ==== get_joint_position ==== | get_joint_position(joint_name_or_num: Union[int, str]) -> float Get the position (angle in degrees) of a joint 2️⃣ **Arguments**: * ''%%joint_name_or_num%%'' - see the Marty.JOINT_IDS dictionary (can be name or number) **Returns**: Angle of the joint in degrees **Raises**: MartyCommandException if the joint_name_or_num is unknown ==== get_joint_current ==== | get_joint_current(joint_name_or_num: Union[int, str]) -> float Get the current (in milli-Amps) of a joint 1️⃣ 2️⃣ This can be useful in detecting when the joint is working hard and is related to the force which the joint's motor is exerting to stay where it is **Arguments**: * ''%%joint_name_or_num%%'' - see the Marty.JOINT_IDS dictionary (can be name or number) **Returns**: the current of the joint in milli-Amps (this will be 0 if the joint current is unknown) **Raises**: MartyCommandException if the joint_name_or_num is unknown ==== get_joint_status ==== | get_joint_status(joint_name_or_num: Union[int, str]) -> int Get information about a joint 2️⃣ This can be helpful to find out if the joint is working correctly and if it is moving at the moment, etc **Arguments**: * ''%%joint_name_or_num%%'' - see the Marty.JOINT_IDS dictionary (can be name or number) **Returns**: a code number which is the sum of codes in the Marty.JOINT_STATUS dictionary will be 0 if the joint status is unknown **Raises**: MartyCommandException if the joint_name_or_num is unknown ==== get_distance_sensor ==== | get_distance_sensor() -> Union[int, float] Get the latest value from the distance sensor 1️⃣ 2️⃣ **Returns**: The distance sensor reading. The meaning of the returned value is different between Marty V1 and V2: - 1️⃣ Returns a raw distance sensor reading as a ''%%float%%''. - 2️⃣ Returns the distance in millimeters as ''%%int%%''. Both will return 0 if no distance sensor is found. ==== foot_on_ground ==== | foot_on_ground(add_on_or_side: str) -> bool Checks whether the foot is on a surface 2️⃣ **Arguments**: * ''%%add_on_or_side%%'' - Takes in the name of a color sensor, name of an IR sensor, ''%%'left'%%'' for the add on connected to the left foot, or ''%%'right'%%'' for the add on connected to the right foot. **Returns**: A boolean for whether the addon detects the ground. ''%%True%%'' for ground detected, ''%%False%%'' otherwise. ==== foot_obstacle_sensed ==== | foot_obstacle_sensed(add_on_or_side: str) -> bool Checks whether there is an obstacle in front of the foot 2️⃣ **Arguments**: * ''%%add_on_or_side%%'' - Takes in the name of a color sensor, name of an IR sensor, ''%%'left'%%'' for the add on connected to the left foot, or ''%%'right'%%'' for the add on connected to the right foot. **Returns**: A boolean for whether the addon detects and obstacle. ''%%True%%'' for obstacle detected, ''%%False%%'' otherwise. ==== get_obstacle_sensor_reading ==== | get_obstacle_sensor_reading(add_on_or_side: str) -> int Gets a raw obstacle sensor reading from an IR or color sensor 2️⃣ **Arguments**: * ''%%add_on_or_side%%'' - Takes in the name of a color sensor, name of an IR sensor, ''%%'left'%%'' for the add on connected to the left foot, or ''%%'right'%%'' for the add on connected to the right foot. **Returns**: Raw reading of obstacle sensor data from the add on. ==== get_ground_sensor_reading ==== | get_ground_sensor_reading(add_on_or_side: str) -> int Gets a raw ground sensor reading from an IR or color sensor 2️⃣ **Arguments**: * ''%%add_on_or_side%%'' - Takes in the name of a color sensor, name of an IR sensor, ''%%'left'%%'' for the add on connected to the left foot, or ''%%'right'%%'' for the add on connected to the right foot. **Returns**: Raw reading of ground sensor data from the add on. ==== get_battery_remaining ==== | get_battery_remaining() -> float Get the battery remaining percentage 2️⃣ **Returns**: The battery remaining capacity in percent ==== save_calibration ==== | save_calibration() -> bool Set the current motor positions as the zero positions 1️⃣ 2️⃣ BE CAREFUL, this can cause unexpected movement or self-interference ==== clear_calibration ==== | clear_calibration() -> bool Mark the current calibration as invalid 1️⃣ 2️⃣ This has no immediate physical effect. Marty will still remember the last calibration but will report that it needs to be calibrated again. (You may notice that a "Calibrate" button appears in the app for example.) ==== is_calibrated ==== | is_calibrated() -> bool Check if Marty is calibrated 2️⃣ ==== get_robot_status ==== | get_robot_status() -> Dict Get status of Marty the Robot 2️⃣ **Arguments**: none **Returns**: Dictionary containing: "workQCount" number of work items (movements) that are queued up - ''%%"isMoving"%%'' - True if Marty is moving - ''%%"isPaused"%%'' - True if Marty is paused - ''%%"isFwUpdating"%%'' - True if Marty is doing an update ==== get_joints ==== | get_joints() -> Dict Get information on all of Marty's joints 2️⃣ **Arguments**: none **Returns**: Dictionary containing dictionaries (one for each joint) each of which contain: - ''%%"IDNo"%%'' - the joint identification number (see Marty.JOINT_IDS) - ''%%"name"%%'' - the name of the joint - ''%%"pos"%%'' - the angle of the joint - ''%%"current"%%'' - the joint current (in milli-Amps) - ''%%"enabled"%%'' - True if the servo is enabled - ''%%"commsOK"%%'' - True if the servo is communicating ok - ''%%"flags"%%'' - joint status flags (see Marty.JOINT_STATUS) ==== get_power_status ==== | get_power_status() -> Dict Get information on Marty's battery and power supply 2️⃣ **Arguments**: none **Returns**: Dictionary containing: - ''%%"battRemainCapacityPercent"%%'' - remaining battery capacity in percent - ''%%"battTempDegC"%%'' - battery temperature in degrees C - ''%%"battRemainCapacityMAH"%%'' - remaining battery capacity in milli-Amp-Hours - ''%%"battFullCapacityMAH"%%'' - capacity of the battery when full in milli-Amp-Hours - ''%%"battCurrentMA"%%'' - current the battery is supplying (or being charged with) milli-Amps - ''%%"power5VOnTimeSecs"%%'' - number of seconds the power to joints and add-ons has been on - ''%%"powerUSBIsConnected"%%'' - True if USB is connected - ''%%"power5VIsOn"%%'' - True if power to the joints and add-ons is turned on Other values for internal use **Note:** Some keys may not be included if Marty reports that the corresponding information is not available. ==== get_add_ons_status ==== | get_add_ons_status() -> Dict Get latest information for all add-ons 2️⃣ **Arguments**: none **Returns**: Dictionary containing dictionaries (one for each add-on) each of which contain: - ''%%"IDNo"%%'' - the add-on identification number - ''%%"name"%%'' - the name of the add-on - ''%%"type"%%'' - the type of the add-on (see Marty.ADD_ON_TYPE_NAMES but it may not be in this list) - ''%%"whoAmITypeCode"%%'' - a code which can be used for further add-on identification - ''%%"valid"%%'' - True if the data is valid - ''%%"data"%%'' - 10 bytes of data from the add-on - the format of this data depends on the type of add-on ==== get_add_on_status ==== | get_add_on_status(add_on_name_or_id: Union[int, str]) -> Dict Get latest information for a single add-on 2️⃣ **Arguments**: * ''%%add_on_name_or_id%%'' - either the name or the id (number) of an add-on **Returns**: Dictionary containing: - ''%%"IDNo"%%'' - the add-on identification number - ''%%"valid"%%'' - True if the data is valid - ''%%"data"%%'' - 10 bytes of data from the add-on - the format of this data depends on the type of add-on ==== add_on_query ==== | add_on_query(add_on_name: str, data_to_write: bytes, num_bytes_to_read: int) -> Dict Write and read an add-on directly (raw-mode) 2️⃣ **Arguments**: * ''%%add_on_name%%'' - name of the add-on (see get_add_ons_status() at the top level or response to ''%%addon/list%%'' REST API command) * ''%%data_to_write%%'' - can be zero length if nothing is to be written, the first byte will generally be the register or opcode of the add-on * ''%%num_bytes_to_read%%'' - number of bytes to read from the device - can be zero **Returns**: Dict with keys including: "rslt" - the result which will be "ok" if the query succeeded "dataRead" - the data read from the add-on ==== get_system_info ==== | get_system_info() -> Dict Get information about Marty 2️⃣ **Arguments**: none **Returns**: Dictionary containing: - ''%%"HardwareVersion"%%'' - string containing the version of Marty hardware "1.0" for Marty V1 "2.0" for Marty V2 other values for later versions of Marty - ''%%"SystemName"%%'' - the name of the physical hardware in Marty - this will be RicFirmwareESP32 for Marty V2 and MartyV1 for Marty V1 - ''%%"SystemVersion"%%'' - a string in semantic versioning format with the version of Marty firmware (e.g. "1.2.3") - ''%%"SerialNo"%%'' - serial number of this Marty - ''%%"MAC"%%'' - the base MAC address of the Marty - ''%%"RicHwRevNo"%%'' - the revision number of the RIC hardware ==== set_marty_name ==== | set_marty_name(name: str) -> bool Set Marty's name 2️⃣ **Arguments**: name to call Marty **Returns**: True if successful in setting the name ==== get_marty_name ==== | get_marty_name() -> str Get Marty's name 2️⃣ **Arguments**: none **Returns**: the name given to Marty ==== is_marty_name_set ==== | is_marty_name_set() -> bool Check if Marty's name is set 2️⃣ **Arguments**: none **Returns**: True if Marty's name is set ==== get_hw_elems_list ==== | get_hw_elems_list() -> List Get a list of all of the hardware elements on Marty 2️⃣ **Arguments**: none **Returns**: List containing a dictionary for each hardware element, each element is in the form: - ''%%"name"%%'' - name of the hardware element - ''%%"type"%%'' - type of element, see Marty.HW_ELEM_TYPES, other types may appear as add-ons - ''%%"busName"%%'' - name of the bus the element is connected to - ''%%"addr"%%'' - address of the element if it is connected to a bus - ''%%"addrValid"%%'' - 1 if the address is valid, else 0 - ''%%"IDNo"%%'' - identification number of the element - ''%%"whoAmI"%%'' - string from the hardware which may contain additional identification - ''%%"whoAmITypeCode"%%'' - string indicating the type of hardware - ''%%"SN"%%'' - serial number of the hardware element - ''%%"versionStr"%%'' - version string of hardware element in semantic versioning (semver) format - ''%%"commsOK"%%'' - 1 if the element is communicating ok, 0 if not ==== send_ric_rest_cmd ==== | send_ric_rest_cmd(ricRestCmd: str) -> None Send a command in RIC REST format to Marty 2️⃣ This is a special purpose command which you can use to do advanced control of Marty **Arguments**: * ''%%ricRestCmd%%'' - string containing the command to send to Marty **Returns**: None ==== send_ric_rest_cmd_sync ==== | send_ric_rest_cmd_sync(ricRestCmd: str) -> Dict Send a command in RIC REST format to Marty and wait for reply 2️⃣ This is a special purpose command which you can use to do advanced control of Marty **Arguments**: * ''%%ricRestCmd%%'' - string containing the command to send to Marty **Returns**: Dictionary containing the response received from Marty ==== get_motor_current ==== | get_motor_current(motor_id: int) -> float Get current flowing through a joint motor 1️⃣ 2️⃣ **Arguments**: motor_id, integer >= 0 (non-negative) selects which motor to query **Returns**: Instantaneous current sense reading from motor ''%%motor_id%%'' ==== is_conn_ready ==== | is_conn_ready() -> bool Check if the robot is connected and the connection is ready to accept commands 2️⃣ **Arguments**: None **Returns**: True if the robot is connected and ready ==== disco_off ==== | disco_off(add_on: Union[Disco, str] = Disco.ALL) -> bool Turn disco add on LEDs off 2️⃣ **Arguments**: * ''%%add_on%%'' - add on name of which the function applies to **Returns**: True if Marty accepted the request ==== disco_pattern ==== | disco_pattern(pattern: int, add_on: Union[Disco, str] = Disco.ALL) -> bool Turn on a pattern of lights on the disco LED add on 2️⃣ **Arguments**: * ''%%pattern%%'' - 1 or 2, pattern of lights that user wants to use * ''%%add_on%%'' - add on name of which the function applies to **Returns**: True if Marty accepted the request ==== disco_color ==== | disco_color(color: Union[str, Tuple[int, int, int]] = 'white', add_on: Union[Disco, str] = Disco.ALL, region: Union[int, str] = 'all') -> bool Turn on disco add on LED lights to a specific color 2️⃣ **Arguments**: * ''%%color%%'' - color to switch the LEDs to; takes in a hex code, RGB tuple of integers between 0-255, or one of the built in colors: white, red, blue, yellow, green, teal, pink, purple, orange * ''%%add_on%%'' - add on name of which the function applies to * ''%%region%%'' - 0,1,2; region on the add on **Returns**: True if Marty accepted the request ===== Legacy MartyV1 commands ===== ==== enable_motors ==== | enable_motors(enable: bool = True, clear_queue: bool = True) -> bool Toggle power to motors 1️⃣ **Arguments**: * ''%%enable%%'' - True/False toggle * ''%%clear_queue%%'' - Default True, prevents unfinished but 'muted' motions from jumping as soon as motors are enabled ==== enable_safeties ==== | enable_safeties(enable: bool = True) -> bool Tell the board to turn on 'normal' safeties 1️⃣ ==== fall_protection ==== | fall_protection(enable: bool = True) -> bool Toggle fall protections 1️⃣ **Arguments**: * ''%%enable%%'' - True/False toggle ==== motor_protection ==== | motor_protection(enable: bool = True) -> bool Toggle motor current protections 1️⃣ **Arguments**: * ''%%enable%%'' - True/False toggle ==== battery_protection ==== | battery_protection(enable: bool = True) -> bool Toggle low battery protections 1️⃣ **Arguments**: * ''%%enable%%'' - True/False toggle ==== buzz_prevention ==== | buzz_prevention(enable: bool = True) -> bool Toggle motor buzz prevention 1️⃣ **Arguments**: * ''%%enable%%'' - True/False toggle ==== lifelike_behaviour ==== | lifelike_behaviour(enable: bool = True) -> bool Tell the robot whether it can or can't move now and then in a lifelike way when idle. 1️⃣ **Arguments**: * ''%%enable%%'' - True/False toggle ==== ros_command ==== | ros_command(*byte_array: int) -> bool Low level proxied access to the ROS Serial API between the modem and main controller 1️⃣ ==== keyframe ==== | keyframe(time: float, num_of_msgs: int, msgs) -> List[bytes] Takes in information about movements and generates keyframes returns a list of bytes 1️⃣ **Arguments**: * ''%%time%%'' - time (in seconds) taken to complete movement * ''%%num_of_msgs%%'' - number of commands sent * ''%%msgs%%'' - commands sent in the following format [(ID CMD), (ID CMD), etc...] ==== get_chatter ==== | get_chatter() -> bytes Return chatter topic data (variable length) 1️⃣ ==== get_firmware_version ==== | get_firmware_version() -> bool Ask the board to print the firmware version over chatter 1️⃣ ==== ros_serial_formatter ==== | ros_serial_formatter(topicID: int, send: bool = False, *message: int) -> List[int] Formats message into ROS serial format and returns formatted message as a list 1️⃣ Calls ros_command with the processed message if send is True. More information about the ROS serial format can be found here: http:%%//%%wiki.ros.org/rosserial/Overview/Protocol ==== pinmode_gpio ==== | pinmode_gpio(gpio: int, mode: str) -> bool Configure a GPIO pin 1️⃣ **Arguments**: * ''%%gpio%%'' - pin number between 0 and 7 * ''%%mode%%'' - choose from: 'digital in','analog in' or 'digital out' ==== write_gpio ==== | write_gpio(gpio: int, value: int) -> bool Write a value to a GPIO port 1️⃣ ==== digitalread_gpio ==== | digitalread_gpio(gpio: int) -> bool Read from GPIO 1️⃣ **Arguments**: GPIO pin number, >= 0 (non-negative) **Returns**: Returns High/Low state of a GPIO pin ==== set_parameter ==== | set_parameter(*byte_array: int) -> bool Set board parameters 1️⃣ **Arguments**: * ''%%byte_array%%'' - a list in the following format [paramID, params] ==== i2c_write ==== | i2c_write(*byte_array: int) -> bool Write a bytestream to the i2c port. 1️⃣ The first byte should be the address, following from that the datagram folows standard i2c spec ==== i2c_write_to_ric ==== | i2c_write_to_ric(address: int, byte_array: bytes) -> bool Write a formatted bytestream to the i2c port. 1️⃣ The bytestream is formatted in the ROS serial format. address: the other device's address ==== i2c_write_to_rick ==== | i2c_write_to_rick(address: int, byte_array: bytes) -> bool Write a formatted bytestream to the i2c port. 1️⃣ The bytestream is formatted in the ROS serial format. address: the other device's address ==== get_battery_voltage ==== | get_battery_voltage() -> float Get the voltage of the battery 1️⃣ **Returns**: The battery voltage reading as a float in Volts ==== hello ==== | hello(blocking: Optional[bool] = None) -> bool Zero joints and wiggle eyebrows 1️⃣ **Arguments**: * ''%%blocking%%'' - Blocking mode override; whether to wait for physical movement to finish before returning. Defaults to the value returned by ''%%self.is_blocking()%%''. ==== discover ==== | discover() -> List[str] Try and find us some Martys! 1️⃣ ===== Helper commands ===== You probably won't need to use these directly. ==== %%__%%del%%__%% ==== | __del__() -> None Marty is stopping ==== close ==== | close() -> None Close connection to Marty