#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File : panda_robot_interfaces.py
# Author : Jiayuan Mao
# Email : maojiayuan@gmail.com
# Date : 03/30/2024
#
# This file is part of Project Concepts.
# Distributed under terms of the MIT license.
from typing import Optional, Tuple, Callable
import numpy as np
from concepts.hw_interface.franka.remote_client import FrankaRemoteClient
from concepts.simulator.pybullet.components.panda.panda_robot import PandaRobot
from concepts.dm.crowhat.robots.robot_interfaces import RobotControllerExecutionContext, RobotControllerExecutionFailed, PrimitiveRobotControllerInterface, ContactPrimitiveRobotControlInterface, RobotArmJointTrajectory
from concepts.dm.crowhat.pybullet_interfaces.pybullet_sim_interfaces import PyBulletSimulationControllerInterface, PyBulletPhysicalControllerInterface
__all__ = [
'PandaRobotPrimitiveControllerInterface', 'PandaRobotContactPrimitiveControllerInterface',
'PyBulletPandaRobotPrimitiveControllerInterface', 'PyBulletPandaRobotContactPrimitiveControllerInterface',
'PhysicalPandaRobotPrimitiveControllerInterface', 'PhysicalPandaRobotContactPrimitiveControllerInterface'
]
[docs]
class PandaRobotPrimitiveControllerInterface(PrimitiveRobotControllerInterface):
[docs]
def get_qpos(self) -> np.ndarray:
raise NotImplementedError
[docs]
def get_qvel(self) -> np.ndarray:
raise NotImplementedError
[docs]
def get_ee_pose(self) -> Tuple[np.ndarray, np.ndarray]:
raise NotImplementedError
[docs]
def move_home(self) -> bool:
raise NotImplementedError
[docs]
def move_qpos(self, qpos: np.ndarray) -> None:
raise NotImplementedError
[docs]
def move_qpos_trajectory(self, trajectory: RobotArmJointTrajectory) -> None:
raise NotImplementedError
[docs]
def open_gripper(self) -> None:
raise NotImplementedError
[docs]
def close_gripper(self) -> None:
raise NotImplementedError
[docs]
def grasp(self, width: float = 0.05, force: float = 40) -> None:
raise NotImplementedError
[docs]
class PyBulletPandaRobotPrimitiveControllerInterface(PandaRobotPrimitiveControllerInterface):
[docs]
def __init__(self, panda_robot):
super().__init__()
self._panda_robot = panda_robot
@property
def panda_robot(self) -> PandaRobot:
return self._panda_robot
[docs]
def get_qpos(self) -> np.ndarray:
return self.panda_robot.get_qpos()
[docs]
def get_qvel(self) -> np.ndarray:
raise NotImplementedError('qvel for panda robot is not implemented.')
[docs]
def get_ee_pose(self) -> Tuple[np.ndarray, np.ndarray]:
return self.panda_robot.get_ee_pose()
[docs]
def move_home(self, **kwargs) -> None:
self.get_update_default_parameters('move_home', kwargs)
with RobotControllerExecutionContext('move_home', **kwargs) as ctx:
ctx.monitor(self.panda_robot.move_home(**kwargs))
[docs]
def move_qpos(self, qpos: np.ndarray, **kwargs) -> None:
self.get_update_default_parameters('move_qpos', kwargs)
with RobotControllerExecutionContext('move_qpos', qpos, **kwargs) as ctx:
ctx.monitor(self.panda_robot.move_qpos(qpos, **kwargs))
[docs]
def move_pose(self, pos: np.ndarray, quat: np.ndarray, **kwargs) -> None:
self.get_update_default_parameters('move_pose', kwargs)
with RobotControllerExecutionContext('move_pose', pos, quat, **kwargs) as ctx:
ctx.monitor(self.panda_robot.move_pose(pos, quat, **kwargs))
[docs]
def move_qpos_trajectory(self, trajectory: RobotArmJointTrajectory, **kwargs) -> None:
self.get_update_default_parameters('move_qpos_trajectory', kwargs)
with RobotControllerExecutionContext('move_qpos_trajectory', trajectory, **kwargs) as ctx:
ctx.monitor(self.panda_robot.move_qpos_path_v2(trajectory, **kwargs))
[docs]
def open_gripper(self, **kwargs) -> None:
self.get_update_default_parameters('open_gripper', kwargs)
with RobotControllerExecutionContext('open_gripper', **kwargs) as ctx:
ctx.monitor(self.panda_robot.open_gripper_free(**kwargs))
[docs]
def close_gripper(self, **kwargs) -> None:
self.get_update_default_parameters('close_gripper', kwargs)
with RobotControllerExecutionContext('close_gripper', **kwargs) as ctx:
ctx.monitor(self.panda_robot.close_gripper_free(**kwargs))
[docs]
def grasp(self, width: float = 0.05, force: float = 40, **kwargs) -> None:
# NB(Jiayuan Mao @ 2024/03/30): width and force parameters are ignored in the PyBullet-based implementation because it uses magic attachments.
self.get_update_default_parameters('grasp', kwargs)
with RobotControllerExecutionContext('grasp', **kwargs) as ctx:
ctx.monitor(self.panda_robot.grasp(**kwargs))
[docs]
def attach_physical_interface(self, physical_interface: PyBulletPhysicalControllerInterface):
physical_interface.register_controller('move_home', self.move_home)
physical_interface.register_controller('move_qpos', self.move_qpos)
physical_interface.register_controller('move_pose', self.move_pose)
physical_interface.register_controller('move_qpos_trajectory', self.move_qpos_trajectory)
physical_interface.register_controller('open_gripper', self.open_gripper)
physical_interface.register_controller('close_gripper', self.close_gripper)
physical_interface.register_controller('grasp', self.grasp)
[docs]
def attach_simulation_interface(self, simulation_interface: PyBulletSimulationControllerInterface):
simulation_interface.register_controller('move_home', self.move_home)
simulation_interface.register_controller('move_qpos', self.move_qpos)
simulation_interface.register_controller('move_pose', self.move_pose)
simulation_interface.register_controller('move_qpos_trajectory', self.move_qpos_trajectory)
simulation_interface.register_controller('open_gripper', self.open_gripper)
simulation_interface.register_controller('close_gripper', self.close_gripper)
simulation_interface.register_controller('grasp', self.grasp)
[docs]
class PhysicalPandaRobotPrimitiveControllerInterface(PandaRobotPrimitiveControllerInterface):
[docs]
def __init__(self, panda_robot: FrankaRemoteClient):
super().__init__()
self._panda_robot = panda_robot
@property
def panda_robot(self) -> FrankaRemoteClient:
return self._panda_robot
[docs]
def get_qpos(self) -> np.ndarray:
return self.panda_robot.get_qpos()
[docs]
def get_qvel(self) -> np.ndarray:
return self.panda_robot.get_qvel()
[docs]
def get_ee_pose(self) -> Tuple[np.ndarray, np.ndarray]:
return self.panda_robot.get_ee_pose()
[docs]
def move_home(self) -> bool:
return self.panda_robot.move_home()
[docs]
def move_qpos(self, qpos: np.ndarray, **kwargs) -> None:
self.get_update_default_parameters('move_qpos', kwargs)
self.panda_robot.move_qpos(qpos, **kwargs)
[docs]
def move_qpos_trajectory(self, trajectory: RobotArmJointTrajectory, **kwargs) -> None:
self.get_update_default_parameters('move_qpos_trajectory', kwargs)
self.panda_robot.move_qpos_trajectory(trajectory, **kwargs)
[docs]
def open_gripper(self, **kwargs) -> None:
self.get_update_default_parameters('open_gripper', kwargs)
self.panda_robot.open_gripper(**kwargs)
[docs]
def close_gripper(self, **kwargs) -> None:
self.get_update_default_parameters('close_gripper', kwargs)
self.panda_robot.close_gripper(**kwargs)
[docs]
def grasp(self, width: float = 0.05, force: float = 40, **kwargs) -> None:
self.get_update_default_parameters('grasp', kwargs)
self.panda_robot.grasp(width, force, **kwargs)