Module inovopy.robot

Robot Module

This module provide a simple api for controlling inovo robot arm with predefinded iva protocal.

Class

  • InovoRobot: A class for interfacing with inovo robot arm

Example

from inovopy.robot import InovoRobot

bot = InovoRobot.default_iva("psu000")


Classes

class InovoRobot (tcp_stream: TcpStream,
inovo_ros: InovoRos,
logger: logging.Logger | str | None = None)
Expand source code
class InovoRobot(Loggable):
    """
    # InovoRobot
    An API class for controlling and access information from inovo robot arm system.

    # Usage
    ```python
    from inovopy.robot import InovoRobot

    bot = InovoRobot.default_iva("psu000")

    print(bot.get_current_transform())
    print(bot.get_current_jointcoord())
    ```
    """

    def __init__(
        self,
        tcp_stream: TcpStream,
        inovo_ros: InovoRos,
        logger: logging.Logger | str | None = None,
    ):
        super().__init__(logger)
        self.tcp_stream: TcpStream = tcp_stream
        self.inovo_ros: InovoRos = inovo_ros

    @classmethod
    def default_iva(
        cls, host: str, logger: logging.Logger | str | None = None
    ) -> "InovoRobot":
        """
        start the iva protocal by

        - start up a tcp listener
        - start a sequence on psu via rosbridge
        - accept a connection

        ## Parameter:
        - `host: str` : remote host to start sequence, aka psu's address

        ## Return:
        `InovoRobot` : the resulted api class
        """
        listener = TcpListener()

        inovo_ros: InovoRos = InovoRos(host=host)
        inovo_ros.runtime_start("iva")

        tcp_stream: TcpStream = listener.accept()
        del listener

        bot: InovoRobot = InovoRobot(
            tcp_stream=tcp_stream, inovo_ros=inovo_ros, logger=logger
        )
        return bot

    def read(self) -> str:
        """read a line"""
        return self.tcp_stream.read()

    def write(self, instruction: dict[str, str | float]):
        """
        write an instruction as str

        ## Parameter:
        - `instruction : dict[str, str|float]` : jsonable instruction dict
        """
        msg = json.dumps(instruction)
        self.tcp_stream.write(msg)

    def assert_res_ok(self):
        """read a message and assert that it is `OK`"""
        res = self.read()
        if res != "OK":
            raise IvaException(f'Expect resopnse to be "OK", but recieve {res}')

    def execute(self, robot_command: RobotCommand, enter_context: bool = False):
        """
        instruct the robot to execute a `inovopy.iva.RobotCommand`

        ## Parameter:
        - `robot_command: inovopy.iva.RobotCommand`: command to execute
        - `enter_context: bool`: whether the execution of command create a pop-able context

        ## Exception:
        `IvaException` raise if response is not `OK`
        """
        self.write(execute(robot_command=robot_command, enter_context=enter_context))
        self.assert_res_ok()

    def sleep(self, second: float):
        """
        instruct the robot to sleep for a specified time

        ## Parameter:
        - `second: float` : second to sleep
        """
        self.execute(RobotCommand.sleep(second=second))

    def set_param(
        self,
        speed: float | None = None,
        accel: float | None = None,
        blend_linear: float | None = None,
        blend_angular: float | None = None,
        tcp_speed_linear: float | None = None,
        tcp_speed_angular: float | None = None,
    ):
        """
        set the motion parameter of the robot

        ## Parameter
        - `speed : float`, in percent, range from `1` to `100`
        - `accel : float`, in precent, range from `1` to `100`
        - `blend_linear : float`, in mm, range from `1` to `1000`
        - `blend_angular : float`, in degree, range from `1` to `360`
        - `tcp_speed_linear : float`, in mm, range from `1` to `999`
        - `tcp_speed_angular : float`, in degree, range from `1` to `360`
        """
        robot_command = RobotCommand.set_parameter(
            speed=speed,
            accel=accel,
            blend_linear=blend_linear,
            blend_angular=blend_angular,
            tcp_speed_linear=tcp_speed_linear,
            tcp_speed_angular=tcp_speed_angular,
        )

        self.execute(robot_command=robot_command)

    def linear(self, target: Transform | JointCoord):
        """linear move to a target"""
        self.execute(target.as_linear())

    def linear_relative(self, target: Transform | JointCoord):
        """linear relative move to a target"""
        self.execute(target.as_linear_relative())

    def joint(self, target: Transform | JointCoord):
        """joint move to a target"""
        self.execute(target.as_joint())

    def joint_relative(self, target: Transform | JointCoord):
        """joint relative move to a target"""
        self.execute(target.as_joint_relative())

    def enqueue(self, robot_command: RobotCommand):
        """
        instruct the robot to enqueue a command

        ## Parameter
        - `robot_command: inovopy.iva.RobotCommand`: the command to enqueue
        """
        self.write(enqueue(robot_command=robot_command))
        self.assert_res_ok()

    def dequeue(self, enter_context: bool = False):
        """
        instruct the robot to dequeue all enqueued command

        ## Parameter
        - `enter_context: bool`: whether enter a context with the sequence or not
        """
        self.write(dequeue(enter_context=enter_context))
        self.assert_res_ok()

    def sequence(self, sequence: list[RobotCommand], enter_context: bool = False):
        """
        perform a sequence of `inovopy.iva.RobotCommand`

        ## Parameter
        - `enter_context: bool`: whether enter a context with the sequence or not
        """
        for step in sequence:
            self.enqueue(step)
        self.dequeue(enter_context=enter_context)

    def pop(self):
        """
        exit a context
        """
        self.write(pop())
        self.assert_res_ok()

    def io(self, io_command: IOCommand):
        """
        instruct the robot to perform a `inovopy.iva.IOCommand`

        ## Parameter
        - `io_command: inovopy.iva.IOCommand`: io commmand to perform

        ## Return
        `str` the respons
        """
        self.write(io(io_command=io_command))
        return self.read()

    def get_io_beckhoff(self, port: int) -> bool:
        """
        get beckhoff input port

        ## Parameter
        - `port: int`: input port to get, default `0-7`

        ## Return
        `bool` state of io
        """
        return self.io(IOCommand.get_digital(target="beckhoff", port=port)) == "True"

    def get_io_wrist(self, port: int) -> bool:
        """
        get wrist input port

        ## Parameter
        - `port: int`: input port to get, default `0-1`

        ## Return
        `bool` state of io
        """
        return self.io(IOCommand.get_digital(target="wrist", port=port)) == "True"

    def set_io_beckhoff(self, port: int, state: bool):
        """
        set beckhoff output port

        ## Parameter
        - `port: int`: output port to set, default `0-7`
        - `state: bool`: target state of the output
        """
        res = self.io(IOCommand.set_digital(target="beckhoff", port=port, state=state))
        assert res == "OK"

    def set_io_wrist(self, port: int, state: bool):
        """
        set wrist output port

        ## Parameter
        - `port: int`: output port to set, default `0-7`
        - `state: bool`: target state of the output
        """
        res = self.io(IOCommand.set_digital(target="wrist", port=port, state=state))
        assert res == "OK"

    def gripper(self, gripper_command: GripperCommand):
        self.write(gripper(gripper_command))

    def gipper_activate(self):
        """activate the gripper"""
        self.gripper(GripperCommand.activate())
        self.assert_res_ok()

    def gripper_get(self) -> float:
        """
        get the gripper width

        ## Return
        `float` in percentage
        """
        self.gripper(GripperCommand.get())
        return float(self.read()) * 100

    def gripper_set(self, label: str):
        """
        set a gripper to a predefine label


        #Parameter
        - `label: str`: the label to set to
        """
        self.gripper(GripperCommand.set(label=label))
        self.assert_res_ok()

    def get_current_transform(self) -> Transform:
        """
        get the current transform

        ## Return:
        `inovopy.geometry.transform.Transform` : current tranform
        """
        self.write(get_current("transform"))
        return Transform.from_robot(self.read())

    def get_current_joint(self) -> JointCoord:
        """
        get the current joint coordinate

        ## Return:
        `inovopy.geometry.jointcoord.JointCoord`: current joint coordinate
        """
        self.write(get_current("joint_coord"))
        return JointCoord.from_robot(self.read())

    def get_data(self, key: str) -> str:
        """
        get data with a key

        ## Parameter:
        - `key : str` : key for the data

        ## Return:
        - `str` value of the data
        - `str` containing `Error` will return if the key is not found
        """
        self.write(get_data(key=key))
        return self.read()

    @contextmanager
    def context(self, robot_command: RobotCommand):
        """
        enter a context with a robot command

        ## Parameter
        - `robot_command: inovopy.iva.RobotCommand` : the command to execute

        ## Context Manager
        when exit context `InovoRobot.pop` the context
        """
        self.execute(robot_command=robot_command, enter_context=True)
        try:
            yield
        finally:
            self.pop()

    @contextmanager
    def context_sequence(self, sequence: list[RobotCommand]):
        """
        enter a context with a robot command

        ## Parameter
        - `sequence: list[inovopy.iva.RobotCommand]` : the sequence to execute

        ## Context Manager
        when exit context `InovoRobot.pop` the context
        """
        self.sequence(sequence=sequence, enter_context=True)
        try:
            yield
        finally:
            self.pop()

InovoRobot

An API class for controlling and access information from inovo robot arm system.

Usage

from inovopy.robot import InovoRobot

bot = InovoRobot.default_iva("psu000")

print(bot.get_current_transform())
print(bot.get_current_jointcoord())

Ancestors

Static methods

def default_iva(host: str, logger: logging.Logger | str | None = None) ‑> InovoRobot

start the iva protocal by

  • start up a tcp listener
  • start a sequence on psu via rosbridge
  • accept a connection

Parameter:

  • host: str : remote host to start sequence, aka psu's address

Return:

InovoRobot : the resulted api class

Methods

def assert_res_ok(self)
Expand source code
def assert_res_ok(self):
    """read a message and assert that it is `OK`"""
    res = self.read()
    if res != "OK":
        raise IvaException(f'Expect resopnse to be "OK", but recieve {res}')

read a message and assert that it is OK

def context(self,
robot_command: RobotCommand)
Expand source code
@contextmanager
def context(self, robot_command: RobotCommand):
    """
    enter a context with a robot command

    ## Parameter
    - `robot_command: inovopy.iva.RobotCommand` : the command to execute

    ## Context Manager
    when exit context `InovoRobot.pop` the context
    """
    self.execute(robot_command=robot_command, enter_context=True)
    try:
        yield
    finally:
        self.pop()

enter a context with a robot command

Parameter

  • robot_command: inovopy.iva.RobotCommand : the command to execute

Context Manager

when exit context InovoRobot.pop() the context

def context_sequence(self,
sequence: list[RobotCommand])
Expand source code
@contextmanager
def context_sequence(self, sequence: list[RobotCommand]):
    """
    enter a context with a robot command

    ## Parameter
    - `sequence: list[inovopy.iva.RobotCommand]` : the sequence to execute

    ## Context Manager
    when exit context `InovoRobot.pop` the context
    """
    self.sequence(sequence=sequence, enter_context=True)
    try:
        yield
    finally:
        self.pop()

enter a context with a robot command

Parameter

  • sequence: list[inovopy.iva.RobotCommand] : the sequence to execute

Context Manager

when exit context InovoRobot.pop() the context

def dequeue(self, enter_context: bool = False)
Expand source code
def dequeue(self, enter_context: bool = False):
    """
    instruct the robot to dequeue all enqueued command

    ## Parameter
    - `enter_context: bool`: whether enter a context with the sequence or not
    """
    self.write(dequeue(enter_context=enter_context))
    self.assert_res_ok()

instruct the robot to dequeue all enqueued command

Parameter

  • enter_context: bool: whether enter a context with the sequence or not
def enqueue(self,
robot_command: RobotCommand)
Expand source code
def enqueue(self, robot_command: RobotCommand):
    """
    instruct the robot to enqueue a command

    ## Parameter
    - `robot_command: inovopy.iva.RobotCommand`: the command to enqueue
    """
    self.write(enqueue(robot_command=robot_command))
    self.assert_res_ok()

instruct the robot to enqueue a command

Parameter

  • robot_command: inovopy.iva.RobotCommand: the command to enqueue
def execute(self,
robot_command: RobotCommand,
enter_context: bool = False)
Expand source code
def execute(self, robot_command: RobotCommand, enter_context: bool = False):
    """
    instruct the robot to execute a `inovopy.iva.RobotCommand`

    ## Parameter:
    - `robot_command: inovopy.iva.RobotCommand`: command to execute
    - `enter_context: bool`: whether the execution of command create a pop-able context

    ## Exception:
    `IvaException` raise if response is not `OK`
    """
    self.write(execute(robot_command=robot_command, enter_context=enter_context))
    self.assert_res_ok()

instruct the robot to execute a RobotCommand

Parameter:

  • robot_command: inovopy.iva.RobotCommand: command to execute
  • enter_context: bool: whether the execution of command create a pop-able context

Exception:

IvaException raise if response is not OK

def get_current_joint(self) ‑> JointCoord
Expand source code
def get_current_joint(self) -> JointCoord:
    """
    get the current joint coordinate

    ## Return:
    `inovopy.geometry.jointcoord.JointCoord`: current joint coordinate
    """
    self.write(get_current("joint_coord"))
    return JointCoord.from_robot(self.read())

get the current joint coordinate

Return:

JointCoord: current joint coordinate

def get_current_transform(self) ‑> Transform
Expand source code
def get_current_transform(self) -> Transform:
    """
    get the current transform

    ## Return:
    `inovopy.geometry.transform.Transform` : current tranform
    """
    self.write(get_current("transform"))
    return Transform.from_robot(self.read())

get the current transform

Return:

Transform : current tranform

def get_data(self, key: str) ‑> str
Expand source code
def get_data(self, key: str) -> str:
    """
    get data with a key

    ## Parameter:
    - `key : str` : key for the data

    ## Return:
    - `str` value of the data
    - `str` containing `Error` will return if the key is not found
    """
    self.write(get_data(key=key))
    return self.read()

get data with a key

Parameter:

  • key : str : key for the data

Return:

  • str value of the data
  • str containing Error will return if the key is not found
def get_io_beckhoff(self, port: int) ‑> bool
Expand source code
def get_io_beckhoff(self, port: int) -> bool:
    """
    get beckhoff input port

    ## Parameter
    - `port: int`: input port to get, default `0-7`

    ## Return
    `bool` state of io
    """
    return self.io(IOCommand.get_digital(target="beckhoff", port=port)) == "True"

get beckhoff input port

Parameter

  • port: int: input port to get, default 0-7

Return

bool state of io

def get_io_wrist(self, port: int) ‑> bool
Expand source code
def get_io_wrist(self, port: int) -> bool:
    """
    get wrist input port

    ## Parameter
    - `port: int`: input port to get, default `0-1`

    ## Return
    `bool` state of io
    """
    return self.io(IOCommand.get_digital(target="wrist", port=port)) == "True"

get wrist input port

Parameter

  • port: int: input port to get, default 0-1

Return

bool state of io

def gipper_activate(self)
Expand source code
def gipper_activate(self):
    """activate the gripper"""
    self.gripper(GripperCommand.activate())
    self.assert_res_ok()

activate the gripper

def gripper(self,
gripper_command: GripperCommand)
Expand source code
def gripper(self, gripper_command: GripperCommand):
    self.write(gripper(gripper_command))
def gripper_get(self) ‑> float
Expand source code
def gripper_get(self) -> float:
    """
    get the gripper width

    ## Return
    `float` in percentage
    """
    self.gripper(GripperCommand.get())
    return float(self.read()) * 100

get the gripper width

Return

float in percentage

def gripper_set(self, label: str)
Expand source code
def gripper_set(self, label: str):
    """
    set a gripper to a predefine label


    #Parameter
    - `label: str`: the label to set to
    """
    self.gripper(GripperCommand.set(label=label))
    self.assert_res_ok()

set a gripper to a predefine label

Parameter

  • label: str: the label to set to
def io(self,
io_command: IOCommand)
Expand source code
def io(self, io_command: IOCommand):
    """
    instruct the robot to perform a `inovopy.iva.IOCommand`

    ## Parameter
    - `io_command: inovopy.iva.IOCommand`: io commmand to perform

    ## Return
    `str` the respons
    """
    self.write(io(io_command=io_command))
    return self.read()

instruct the robot to perform a IOCommand

Parameter

  • io_command: inovopy.iva.IOCommand: io commmand to perform

Return

str the respons

def joint(self,
target: Transform | JointCoord)
Expand source code
def joint(self, target: Transform | JointCoord):
    """joint move to a target"""
    self.execute(target.as_joint())

joint move to a target

def joint_relative(self,
target: Transform | JointCoord)
Expand source code
def joint_relative(self, target: Transform | JointCoord):
    """joint relative move to a target"""
    self.execute(target.as_joint_relative())

joint relative move to a target

def linear(self,
target: Transform | JointCoord)
Expand source code
def linear(self, target: Transform | JointCoord):
    """linear move to a target"""
    self.execute(target.as_linear())

linear move to a target

def linear_relative(self,
target: Transform | JointCoord)
Expand source code
def linear_relative(self, target: Transform | JointCoord):
    """linear relative move to a target"""
    self.execute(target.as_linear_relative())

linear relative move to a target

def pop(self)
Expand source code
def pop(self):
    """
    exit a context
    """
    self.write(pop())
    self.assert_res_ok()

exit a context

def read(self) ‑> str
Expand source code
def read(self) -> str:
    """read a line"""
    return self.tcp_stream.read()

read a line

def sequence(self,
sequence: list[RobotCommand],
enter_context: bool = False)
Expand source code
def sequence(self, sequence: list[RobotCommand], enter_context: bool = False):
    """
    perform a sequence of `inovopy.iva.RobotCommand`

    ## Parameter
    - `enter_context: bool`: whether enter a context with the sequence or not
    """
    for step in sequence:
        self.enqueue(step)
    self.dequeue(enter_context=enter_context)

perform a sequence of RobotCommand

Parameter

  • enter_context: bool: whether enter a context with the sequence or not
def set_io_beckhoff(self, port: int, state: bool)
Expand source code
def set_io_beckhoff(self, port: int, state: bool):
    """
    set beckhoff output port

    ## Parameter
    - `port: int`: output port to set, default `0-7`
    - `state: bool`: target state of the output
    """
    res = self.io(IOCommand.set_digital(target="beckhoff", port=port, state=state))
    assert res == "OK"

set beckhoff output port

Parameter

  • port: int: output port to set, default 0-7
  • state: bool: target state of the output
def set_io_wrist(self, port: int, state: bool)
Expand source code
def set_io_wrist(self, port: int, state: bool):
    """
    set wrist output port

    ## Parameter
    - `port: int`: output port to set, default `0-7`
    - `state: bool`: target state of the output
    """
    res = self.io(IOCommand.set_digital(target="wrist", port=port, state=state))
    assert res == "OK"

set wrist output port

Parameter

  • port: int: output port to set, default 0-7
  • state: bool: target state of the output
def set_param(self,
speed: float | None = None,
accel: float | None = None,
blend_linear: float | None = None,
blend_angular: float | None = None,
tcp_speed_linear: float | None = None,
tcp_speed_angular: float | None = None)
Expand source code
def set_param(
    self,
    speed: float | None = None,
    accel: float | None = None,
    blend_linear: float | None = None,
    blend_angular: float | None = None,
    tcp_speed_linear: float | None = None,
    tcp_speed_angular: float | None = None,
):
    """
    set the motion parameter of the robot

    ## Parameter
    - `speed : float`, in percent, range from `1` to `100`
    - `accel : float`, in precent, range from `1` to `100`
    - `blend_linear : float`, in mm, range from `1` to `1000`
    - `blend_angular : float`, in degree, range from `1` to `360`
    - `tcp_speed_linear : float`, in mm, range from `1` to `999`
    - `tcp_speed_angular : float`, in degree, range from `1` to `360`
    """
    robot_command = RobotCommand.set_parameter(
        speed=speed,
        accel=accel,
        blend_linear=blend_linear,
        blend_angular=blend_angular,
        tcp_speed_linear=tcp_speed_linear,
        tcp_speed_angular=tcp_speed_angular,
    )

    self.execute(robot_command=robot_command)

set the motion parameter of the robot

Parameter

  • speed : float, in percent, range from 1 to 100
  • accel : float, in precent, range from 1 to 100
  • blend_linear : float, in mm, range from 1 to 1000
  • blend_angular : float, in degree, range from 1 to 360
  • tcp_speed_linear : float, in mm, range from 1 to 999
  • tcp_speed_angular : float, in degree, range from 1 to 360
def sleep(self, second: float)
Expand source code
def sleep(self, second: float):
    """
    instruct the robot to sleep for a specified time

    ## Parameter:
    - `second: float` : second to sleep
    """
    self.execute(RobotCommand.sleep(second=second))

instruct the robot to sleep for a specified time

Parameter:

  • second: float : second to sleep
def write(self, instruction: dict[str, str | float])
Expand source code
def write(self, instruction: dict[str, str | float]):
    """
    write an instruction as str

    ## Parameter:
    - `instruction : dict[str, str|float]` : jsonable instruction dict
    """
    msg = json.dumps(instruction)
    self.tcp_stream.write(msg)

write an instruction as str

Parameter:

  • instruction : dict[str, str|float] : jsonable instruction dict

Inherited members

class IvaException (*args, **kwargs)
Expand source code
class IvaException(Exception):
    """
    # Iva Exception
    """

Iva Exception

Ancestors

  • builtins.Exception
  • builtins.BaseException