diff --git a/pybullet_tree_sim/config/robot/fr3.yaml b/pybullet_tree_sim/config/robot/fr3.yaml
new file mode 100644
index 0000000..a17b235
--- /dev/null
+++ b/pybullet_tree_sim/config/robot/fr3.yaml
@@ -0,0 +1,3 @@
+arm_id: fr3
+hand: false
+# TODO: add the rest of the URDF args
\ No newline at end of file
diff --git a/pybullet_tree_sim/config/robot/linear_slider.yaml b/pybullet_tree_sim/config/robot/linear_slider.yaml
new file mode 100644
index 0000000..ac6111a
--- /dev/null
+++ b/pybullet_tree_sim/config/robot/linear_slider.yaml
@@ -0,0 +1,3 @@
+base_type: linear_slider
+base_parent: world
+base_prefix: linear_slider__
diff --git a/pybullet_tree_sim/config/robot/mock_pruner.yaml b/pybullet_tree_sim/config/robot/mock_pruner.yaml
new file mode 100644
index 0000000..08b284c
--- /dev/null
+++ b/pybullet_tree_sim/config/robot/mock_pruner.yaml
@@ -0,0 +1,5 @@
+eef_type: mock_pruner
+eef_parent: ur5e__
+eef_prefix: mock_pruner__
+tof0_offset_x: "0.02"
+tof1_offset_x: "-0.02"
\ No newline at end of file
diff --git a/pybullet_tree_sim/config/robot/robot.yaml b/pybullet_tree_sim/config/robot/robot.yaml
index e69de29..452ae03 100644
--- a/pybullet_tree_sim/config/robot/robot.yaml
+++ b/pybullet_tree_sim/config/robot/robot.yaml
@@ -0,0 +1,12 @@
+robot_stack:
+ # - linear_slider
+ - ur5e
+ - mock_pruner
+initial_joint_angles:
+ - 0.0
+ - 0.0
+ - 0.0
+ - 0.0
+ - 0.0
+ - 0.0
+disable_self_collisions: true
diff --git a/pybullet_tree_sim/config/robot/ur5e.yaml b/pybullet_tree_sim/config/robot/ur5e.yaml
new file mode 100644
index 0000000..3d976bf
--- /dev/null
+++ b/pybullet_tree_sim/config/robot/ur5e.yaml
@@ -0,0 +1,5 @@
+arm_type: ur5e
+# arm_parent: tool0
+arm_prefix: ur5e__
+tf_prefix: ur5e__
+ur_type: ur5e
diff --git a/pybullet_tree_sim/robot.py b/pybullet_tree_sim/robot.py
index 4128b7e..40a43ee 100644
--- a/pybullet_tree_sim/robot.py
+++ b/pybullet_tree_sim/robot.py
@@ -1,85 +1,154 @@
#!/usr/bin/env python3
-from pybullet_tree_sim.utils.pyb_utils import PyBUtils
import pybullet_tree_sim.utils.xacro_utils as xutils
+import pybullet_tree_sim.utils.yaml_utils as yutils
+from pybullet_tree_sim import CONFIG_PATH, URDF_PATH
from typing import Optional, Tuple
import numpy as np
import pybullet
from collections import namedtuple
+import os
+from zenlog import log
class Robot:
+
+ _robot_configs_path = os.path.join(CONFIG_PATH, "robot")
+ _robot_xacro_path = os.path.join(URDF_PATH, "robot", "generic", "robot.urdf.xacro")
+ _urdf_tmp_path = os.path.join(URDF_PATH, "tmp")
+
def __init__(
self,
pbclient,
- robot_type: str,
- robot_urdf_path: str,
- tool_link_name: str,
- end_effector_link_name: str,
- success_link_name: str,
- base_link_name: str,
- control_joints,
+ # robot_type: str,
+ # robot_urdf_path: str,
+ # tool_link_name: str,
+ # end_effector_link_name: str,
+ # success_link_name: str,
+ # base_link_name: str,
+ # control_joints,
robot_collision_filter_idxs,
- init_joint_angles: Optional[list] = None,
- pos=(0, 0, 0),
+ # init_joint_angles: Optional[list] = None,
+ position=(0, 0, 0),
orientation=(0, 0, 0, 1),
randomize_pose=False,
- verbose=1,
+ # verbose=1
+ **kwargs
) -> None:
- self.con = con
- self.robot_type = robot_type
- self.robot_urdf_path = robot_urdf_path
- self.tool_link_name = tool_link_name
- self.end_effector_link_name = end_effector_link_name
- self.success_link_name = success_link_name
- self.base_link_name = base_link_name
- self.init_joint_angles = init_joint_angles
- self.pos = pos
+ self.pbclient = pbclient
+ # self.robot_type = robot_type
+ # self.robot_urdf_path = robot_urdf_path
+ # self.tool_link_name = tool_link_name
+ # self.end_effector_link_name = end_effector_link_name
+ # self.success_link_name = success_link_name
+ # self.base_link_name = base_link_name
+ # self.init_joint_angles = init_joint_angles
+ self.pos = position
self.orientation = orientation
self.randomize_pose = randomize_pose
- self.joint_info = namedtuple(
- "jointInfo", ["id", "name", "type", "lowerLimit", "upperLimit", "maxForce", "maxVelocity", "controllable"]
- )
- # Pruning camera information
- self.camera_base_offset = np.array([0.063179, 0.077119, 0.0420027])
- self.verbose = verbose
+ # self.joint_info = namedtuple(
+ # "jointInfo",
+ # ["id", "name", "type", "lowerLimit", "upperLimit", "maxForce", "maxVelocity", "controllable"]
+ # )
+ # # Pruning camera information
+ # self.camera_base_offset = np.array(
+ # [0.063179, 0.077119, 0.0420027])
+ # self.verbose = verbose
- self.joints = None
+ # self.joints = None
self.robot = None
- self.control_joints = control_joints
- self.robot_collision_filter_idxs = robot_collision_filter_idxs
+ # self.control_joints = control_joints
+ # self.robot_collision_filter_idxs = robot_collision_filter_idxs
+ #
+ self._generate_robot_urdf()
self.setup_robot()
+
+ return
+
+ def _generate_robot_urdf(self):
+ # TODO: move this stuff to yaml file
+ # base_parent = f"world",
+ # base_prefix = f"linear_slider__",
+ # arm_parent = f"{base_prefix}tool0"
+ # arm_prefix = f"ur5__",
+ # eef_parent = f"{arm_prefix}tool0"
+ # eef_prefix = f"mock_pruner__",
+
+ robot_conf = {}
+
+ # Get robot stack params
+ robot_stack: list = yutils.load_yaml(os.path.join(self._robot_configs_path, "robot.yaml"))["robot_stack"]
+ # Add the required urdf args from yaml configs
+ log.warn(robot_stack)
+ for robot_part in robot_stack:
+ robot_part = robot_part.strip().lower()
+ # print(os.path.join(self._robot_configs_path, f"{robot_part}.yaml"))
+ robot_conf.update(yutils.load_yaml(os.path.join(self._robot_configs_path, f"{robot_part}.yaml")))
+
+ log.warn(robot_conf)
+ # Generate URDF from mappings
+ robot_urdf = xutils.load_urdf_from_xacro(
+ xacro_path=self._robot_xacro_path,
+ mappings=robot_conf
+ )
+
+ # UR_description uses filename="package://<>", and this doesn't work with pybullet
+ if robot_conf['arm_type'].startswith('ur'):
+ ur_absolute_mesh_path = '/opt/ros/humble/share/ur_description/meshes'
+ robot_urdf = robot_urdf.toprettyxml().replace(
+ f'filename="package://ur_description/meshes',
+ f'filename="{ur_absolute_mesh_path}'
+ )
+ else:
+ robot_urdf = robot_urdf.toprettyxml()
+ # Save the generated URDF
+ self.robot_urdf_path = os.path.join(self._urdf_tmp_path, "robot.urdf")
+ xutils.save_urdf(robot_urdf, urdf_path=self.robot_urdf_path)
+
+ # log.warn(modified_urdf)
+
return
def setup_robot(self):
if self.robot is not None:
- self.con.removeBody(self.robot)
+ self.pbclient.removeBody(self.robot)
del self.robot
- flags = self.con.URDF_USE_SELF_COLLISION
+ flags = self.pbclient.URDF_USE_SELF_COLLISION
if self.randomize_pose:
delta_pos = np.random.rand(3) * 0.0
delta_orientation = pybullet.getQuaternionFromEuler(np.random.rand(3) * np.pi / 180 * 5)
else:
- delta_pos = np.array([0.0, 0.0, 0.0])
+ delta_pos = np.array([0., 0., 0.])
delta_orientation = pybullet.getQuaternionFromEuler([0, 0, 0])
- self.pos, self.orientation = self.con.multiplyTransforms(
- self.pos, self.orientation, delta_pos, delta_orientation
+ self.pos, self.orientation = self.pbclient.multiplyTransforms(
+ self.pos,
+ self.orientation,
+ delta_pos,
+ delta_orientation
)
- self.robot = self.con.loadURDF(self.robot_urdf_path, self.pos, self.orientation, flags=flags, useFixedBase=True)
- self.num_joints = self.con.getNumJoints(self.robot)
+ self.robot = self.pbclient.loadURDF(
+ self.robot_urdf_path,
+ self.pos,
+ self.orientation,
+ flags=flags,
+ useFixedBase=True
+ )
+ self.num_joints = self.pbclient.getNumJoints(self.robot)
- # Get indices dynamically
- self.tool0_link_index = self.get_link_index(self.tool_link_name)
- self.end_effector_index = self.get_link_index(self.end_effector_link_name)
- self.success_link_index = self.get_link_index(self.success_link_name)
- self.base_index = self.get_link_index(self.base_link_name)
+ #Get indices dynamically
+ # self.tool0_link_index = self.get_link_index(self.tool_link_name)
+ # TODO: Get tool0 from the last element in the robot stack
+ self.tool0_link_index = self.get_link_index("mock_pruner__tool0")
+ # self.end_effector_index = self.get_link_index(self.end_effector_link_name)
+ # self.success_link_index = self.get_link_index(self.success_link_name)
+ self.base_index = self.get_link_index("ur5e__base_link")
self.set_collision_filter()
- # Setup robot info only once
+ #Setup robot info only once
if not self.joints:
self.joints = dict()
self.controllable_joints_idxs = []
@@ -90,7 +159,7 @@ def setup_robot(self):
self.joint_ranges = []
for i in range(self.num_joints):
- info = self.con.getJointInfo(self.robot, i)
+ info = self.pbclient.getJointInfo(self.robot, i)
jointID = info[0]
jointName = info[1].decode("utf-8")
jointType = info[2]
@@ -120,21 +189,21 @@ def setup_robot(self):
jointUpperLimit,
jointMaxForce,
jointMaxVelocity,
- controllable,
+ controllable
)
- if info.type == self.con.JOINT_REVOLUTE:
- self.con.setJointMotorControl2(
+ if info.type == self.pbclient.JOINT_REVOLUTE:
+ self.pbclient.setJointMotorControl2(
self.robot,
info.id,
- self.con.VELOCITY_CONTROL,
+ self.pbclient.VELOCITY_CONTROL,
targetVelocity=0,
force=0,
)
self.joints[info.name] = info
self.set_joint_angles_no_collision(self.init_joint_angles)
- self.con.stepSimulation()
+ self.pbclient.stepSimulation()
self.init_pos_ee = self.get_current_pose(self.end_effector_index)
self.init_pos_base = self.get_current_pose(self.base_index)
@@ -143,19 +212,23 @@ def setup_robot(self):
self.joint_angles = np.array(self.init_joint_angles).astype(np.float32)
self.achieved_pos = np.array(self.get_current_pose(self.end_effector_index)[0])
base_pos, base_or = self.get_current_pose(self.base_index)
+ return
def get_link_index(self, link_name):
- num_joints = self.con.getNumJoints(self.robot)
+ num_joints = self.pbclient.getNumJoints(self.robot)
for i in range(num_joints):
- info = self.con.getJointInfo(self.robot, i)
- child_link_name = info[12].decode("utf-8")
+ info = self.pbclient.getJointInfo(self.robot, i)
+ child_link_name = info[12].decode('utf-8')
+ log.warn(child_link_name)
+
if child_link_name == link_name:
- return i # return link index
+ return i # return link index
- base_link_name = self.con.getBodyInfo(self.robot)[0].decode("utf-8")
+ base_link_name = self.pbclient.getBodyInfo(self.robot)[0].decode('utf-8')
if base_link_name == link_name:
- return -1 # base link has index of -1
+ return -1 #base link has index of -1
raise ValueError(f"Link '{link_name}' not found in the robot URDF.")
+
def reset_robot(self):
if self.robot is None:
@@ -164,14 +237,14 @@ def reset_robot(self):
self.set_joint_angles_no_collision(self.init_joint_angles)
def remove_robot(self):
- self.con.removeBody(self.robot)
+ self.pbclient.removeBody(self.robot)
self.robot = None
def set_joint_angles_no_collision(self, joint_angles) -> None:
assert len(joint_angles) == len(self.control_joints)
for i, name in enumerate(self.control_joints):
joint = self.joints[name]
- self.con.resetJointState(self.robot, joint.id, joint_angles[i], targetVelocity=0)
+ self.pbclient.resetJointState(self.robot, joint.id, joint_angles[i], targetVelocity=0)
def set_joint_angles(self, joint_angles) -> None:
"""Set joint angles using pybullet motor control"""
@@ -187,14 +260,13 @@ def set_joint_angles(self, joint_angles) -> None:
indexes.append(joint.id)
forces.append(joint.maxForce)
- self.con.setJointMotorControlArray(
- self.robot,
- indexes,
- self.con.POSITION_CONTROL,
+ self.pbclient.setJointMotorControlArray(
+ self.robot, indexes,
+ self.pbclient.POSITION_CONTROL,
targetPositions=joint_angles,
targetVelocities=[0] * len(poses),
positionGains=[0.05] * len(poses),
- forces=forces,
+ forces=forces
)
def set_joint_velocities(self, joint_velocities) -> None:
@@ -210,35 +282,35 @@ def set_joint_velocities(self, joint_velocities) -> None:
indexes.append(joint.id)
forces.append(joint.maxForce)
- self.con.setJointMotorControlArray(
- self.robot,
- indexes,
- controlMode=self.con.VELOCITY_CONTROL,
- targetVelocities=joint_velocities,
- )
+ self.pbclient.setJointMotorControlArray(self.robot,
+ indexes,
+ controlMode=self.pbclient.VELOCITY_CONTROL,
+ targetVelocities=joint_velocities,
+ )
# TODO: Use proprty decorator for getters?
def get_joint_velocities(self):
- j = self.con.getJointStates(self.robot, self.controllable_joints_idxs)
+ j = self.pbclient.getJointStates(self.robot, self.controllable_joints_idxs)
joints = tuple((i[1] for i in j))
return joints # type: ignore
def get_joint_angles(self):
"""Return joint angles"""
print(self.control_joints, self.controllable_joints_idxs)
- j = self.con.getJointStates(self.robot, self.controllable_joints_idxs)
+ j = self.pbclient.getJointStates(self.robot, self.controllable_joints_idxs)
joints = tuple((i[0] for i in j))
return joints
def get_current_pose(self, index):
"""Returns current pose of the index"""
- link_state = self.con.getLinkState(self.robot, index, computeForwardKinematics=True)
+ link_state = self.pbclient.getLinkState(self.robot, index, computeForwardKinematics=True)
position, orientation = link_state[4], link_state[5]
return position, orientation
def get_current_vel(self, index):
"""Returns current pose of the index."""
- link_state = self.con.getLinkState(self.robot, index, computeLinkVelocity=True, computeForwardKinematics=True)
+ link_state = self.pbclient.getLinkState(self.robot, index, computeLinkVelocity=True,
+ computeForwardKinematics=True)
trans, ang = link_state[6], link_state[7]
return trans, ang
@@ -251,27 +323,17 @@ def get_condition_number(self):
def calculate_ik(self, position, orientation):
"""Calculates joint angles from end effector position and orientation using inverse kinematics"""
- joint_angles = self.con.calculateInverseKinematics(
- self.robot,
- self.end_effector_index,
- position,
- orientation,
- jointDamping=[0.01] * len(self.control_joints),
- upperLimits=self.joint_upper_limits,
- lowerLimits=self.joint_lower_limits,
- jointRanges=self.joint_ranges, # , restPoses=self.init_joint_angles
+ joint_angles = self.pbclient.calculateInverseKinematics(
+ self.robot, self.end_effector_index, position, orientation,
+ jointDamping=[0.01] * len(self.control_joints), upperLimits=self.joint_upper_limits,
+ lowerLimits=self.joint_lower_limits, jointRanges=self.joint_ranges # , restPoses=self.init_joint_angles
)
return joint_angles
def calculate_jacobian(self):
- jacobian = self.con.calculateJacobian(
- self.robot,
- self.tool0_link_index,
- [0, 0, 0],
- self.get_joint_angles(),
- [0] * len(self.control_joints),
- [0] * len(self.control_joints),
- )
+ jacobian = self.pbclient.calculateJacobian(self.robot, self.tool0_link_index, [0, 0, 0],
+ self.get_joint_angles(),
+ [0]*len(self.control_joints), [0]*len(self.control_joints))
jacobian = np.vstack(jacobian)
return jacobian
@@ -282,7 +344,9 @@ def calculate_joint_velocities_from_ee_velocity(self, end_effector_velocity):
joint_velocities = np.matmul(inv_jacobian, end_effector_velocity).astype(np.float32)
return joint_velocities, jacobian
- def calculate_joint_velocities_from_ee_velocity_dls(self, end_effector_velocity, damping_factor: float = 0.05):
+ def calculate_joint_velocities_from_ee_velocity_dls(self,
+ end_effector_velocity,
+ damping_factor: float = 0.05):
"""Calculate joint velocities from end effector velocity using damped least squares"""
jacobian = self.calculate_jacobian()
identity_matrix = np.eye(jacobian.shape[0])
@@ -293,47 +357,51 @@ def calculate_joint_velocities_from_ee_velocity_dls(self, end_effector_velocity,
return joint_velocities, jacobian
# TODO: Make camera a separate class?
- def create_camera_transform(self, pos, orientation, pan, tilt, xyz_offset) -> np.ndarray:
+ def create_camera_transform(self, world_position, world_orientation, camera: "Camera") -> np.ndarray:
"""Create rotation matrix for camera"""
base_offset_tf = np.identity(4)
- base_offset_tf[:3, 3] = self.camera_base_offset + xyz_offset
+ base_offset_tf[:3, 3] = camera.xyz_offset
ee_transform = np.identity(4)
- ee_rot_mat = np.array(self.con.getMatrixFromQuaternion(orientation)).reshape(3, 3)
+ ee_rot_mat = np.array(self.pbclient.getMatrixFromQuaternion(world_orientation)).reshape(3, 3)
+ # log.debug(f"EE Rot Mat:\n{ee_rot_mat}")
+
ee_transform[:3, :3] = ee_rot_mat
- ee_transform[:3, 3] = pos
+ ee_transform[:3, 3] = world_position
tilt_tf = np.identity(4)
- tilt_rot = np.array([[1, 0, 0], [0, np.cos(tilt), -np.sin(tilt)], [0, np.sin(tilt), np.cos(tilt)]])
+ tilt_rot = np.array([[1, 0, 0], [0, np.cos(camera.tilt), -np.sin(camera.tilt)], [0, np.sin(camera.tilt), np.cos(camera.tilt)]])
tilt_tf[:3, :3] = tilt_rot
pan_tf = np.identity(4)
- pan_rot = np.array([[np.cos(pan), 0, np.sin(pan)], [0, 1, 0], [-np.sin(pan), 0, np.cos(pan)]])
+ pan_rot = np.array([[np.cos(camera.pan), 0, np.sin(camera.pan)], [0, 1, 0], [-np.sin(camera.pan), 0, np.cos(camera.pan)]])
pan_tf[:3, :3] = pan_rot
tf = ee_transform @ pan_tf @ tilt_tf @ base_offset_tf
return tf
# TODO: Better types for getCameraImage
- def get_view_mat_at_curr_pose(self, pan, tilt, xyz_offset) -> np.ndarray:
+ def get_view_mat_at_curr_pose(self, camera: "Camera") -> np.ndarray:
"""Get view matrix at current pose"""
- pose, orientation = self.get_current_pose(self.tool0_link_index)
+ pos, orientation = self.get_current_pose(camera.tf_frame_index)
+ # log.debug(f"tool0 Pose: {pose}, Orientation: {Rotation.from_quat(orientation).as_euler('xyz')}")
- camera_tf = self.create_camera_transform(pose, orientation, pan, tilt, xyz_offset)
+ camera_tf = self.create_camera_transform(pos, orientation, camera)
# Initial vectors
camera_vector = np.array([0, 0, 1]) @ camera_tf[:3, :3].T #
up_vector = np.array([0, 1, 0]) @ camera_tf[:3, :3].T #
- # Rotated vectors
- # print(camera_vector, up_vector)
- view_matrix = self.con.computeViewMatrix(camera_tf[:3, 3], camera_tf[:3, 3] + 0.1 * camera_vector, up_vector)
+
+ # log.debug(f"cam vec, up vec:\n{camera_vector}, {up_vector}")
+
+ view_matrix = self.pbclient.computeViewMatrix(camera_tf[:3, 3], camera_tf[:3, 3] + 0.1 * camera_vector, up_vector)
return view_matrix
- def get_camera_location(self):
- pose, orientation = self.get_current_pose(self.tool0_link_index)
+ def get_camera_location(self, camera: "Camera"): # TODO: get transform from dictionary. choose between rgb or tof frames
+ pose, orientation = self.get_current_pose(camera.tf_frame_index)
tilt = np.pi / 180 * 8
- camera_tf = self.create_camera_transform(pose, orientation, tilt)
+ camera_tf = self.create_camera_transform(camera=camera)
return camera_tf
# Collision checking
@@ -341,24 +409,23 @@ def get_camera_location(self):
def set_collision_filter(self):
"""Disable collision between pruner and arm"""
for i in self.robot_collision_filter_idxs:
- self.con.setCollisionFilterPair(self.robot, self.robot, i[0], i[1], 0)
+ self.pbclient.setCollisionFilterPair(self.robot, self.robot, i[0], i[1], 0)
def unset_collision_filter(self):
"""Enable collision between pruner and arm"""
for i in self.robot_collision_filter_idxs:
- self.con.setCollisionFilterPair(self.robot, self.robot, i[0], i[1], 1)
-
+ self.pbclient.setCollisionFilterPair(self.robot, self.robot, i[0], i[1], 1)
def disable_self_collision(self):
for i in range(self.num_joints):
for j in range(self.num_joints):
if i != j:
- self.con.setCollisionFilterPair(self.robot, self.robot, i, j, 0)
+ self.pbclient.setCollisionFilterPair(self.robot, self.robot, i, j, 0)
def enable_self_collision(self):
for i in range(self.num_joints):
for j in range(self.num_joints):
if i != j:
- self.con.setCollisionFilterPair(self.robot, self.robot, i, j, 1)
+ self.pbclient.setCollisionFilterPair(self.robot, self.robot, i, j, 1)
def check_collisions(self, collision_objects) -> Tuple[bool, dict]:
"""Check if there are any collisions between the robot and the environment
@@ -366,10 +433,10 @@ def check_collisions(self, collision_objects) -> Tuple[bool, dict]:
"""
collision_info = {"collisions_acceptable": False, "collisions_unacceptable": False}
- collision_acceptable_list = ["SPUR", "WATER_BRANCH"]
- collision_unacceptable_list = ["TRUNK", "BRANCH", "SUPPORT"]
+ collision_acceptable_list = ['SPUR', 'WATER_BRANCH']
+ collision_unacceptable_list = ['TRUNK', 'BRANCH', 'SUPPORT']
for type in collision_acceptable_list:
- collisions_acceptable = self.con.getContactPoints(bodyA=self.robot, bodyB=collision_objects[type])
+ collisions_acceptable = self.pbclient.getContactPoints(bodyA=self.robot, bodyB=collision_objects[type])
if collisions_acceptable:
for i in range(len(collisions_acceptable)):
if collisions_acceptable[i][-6] < 0:
@@ -379,7 +446,7 @@ def check_collisions(self, collision_objects) -> Tuple[bool, dict]:
break
for type in collision_unacceptable_list:
- collisions_unacceptable = self.con.getContactPoints(bodyA=self.robot, bodyB=collision_objects[type])
+ collisions_unacceptable = self.pbclient.getContactPoints(bodyA=self.robot, bodyB=collision_objects[type])
for i in range(len(collisions_unacceptable)):
if collisions_unacceptable[i][-6] < 0:
collision_info["collisions_unacceptable"] = True
@@ -388,7 +455,7 @@ def check_collisions(self, collision_objects) -> Tuple[bool, dict]:
break
if not collision_info["collisions_unacceptable"]:
- collisons_self = self.con.getContactPoints(bodyA=self.robot, bodyB=self.robot)
+ collisons_self = self.pbclient.getContactPoints(bodyA=self.robot, bodyB=self.robot)
collisions_unacceptable = collisons_self
for i in range(len(collisions_unacceptable)):
if collisions_unacceptable[i][-6] < -0.001:
@@ -406,9 +473,8 @@ def check_success_collision(self, body_b) -> bool:
"""Check if there are any collisions between the robot and the environment
Returns: Boolw
"""
- collisions_success = self.con.getContactPoints(
- bodyA=self.robot, bodyB=body_b, linkIndexA=self.success_link_index
- )
+ collisions_success = self.pbclient.getContactPoints(bodyA=self.robot, bodyB=body_b,
+ linkIndexA=self.success_link_index)
for i in range(len(collisions_success)):
if collisions_success[i][-6] < 0.05:
if self.verbose > 1:
@@ -420,30 +486,32 @@ def check_success_collision(self, body_b) -> bool:
def set_collision_filter_tree(self, collision_objects):
for i in collision_objects.values():
for j in range(self.num_joints):
- self.con.setCollisionFilterPair(self.robot, i, j, 0, 0)
+ self.pbclient.setCollisionFilterPair(self.robot, i, j, 0, 0)
def unset_collision_filter_tree(self, collision_objects):
for i in collision_objects.values():
for j in range(self.num_joints):
- self.con.setCollisionFilterPair(self.robot, i, j, 0, 1)
+ self.pbclient.setCollisionFilterPair(self.robot, i, j, 0, 1)
def main():
from pybullet_tree_sim.utils.pyb_utils import PyBUtils
- pbutils = PyBUtils(renders=True)
-
+ import time
+ pbutils = PyBUtils(renders=False)
+
robot = Robot(
- pbclient=pbutils.pbclient,
- robot_type='ur5e',
- robot_urdf_path="",
- tool_link_name="mock_pruner__tool0",
- base_link_name="linear_slider__base_link",
-
+ pbclient = pbutils.pbclient,
+ robot_type="ur5e",
+ base_link_type="linear_slider",
+ end_effector_type="mock_pruner",
+
)
- print(robot)
+
+ time.sleep(10)
return
+
if __name__ == "__main__":
main()
diff --git a/pybullet_tree_sim/urdf/end_effectors/mock_pruner/macro/mock_pruner_macro.urdf.xacro b/pybullet_tree_sim/urdf/end_effectors/mock_pruner/macro/mock_pruner_macro.urdf.xacro
index ea65f78..054dc1a 100644
--- a/pybullet_tree_sim/urdf/end_effectors/mock_pruner/macro/mock_pruner_macro.urdf.xacro
+++ b/pybullet_tree_sim/urdf/end_effectors/mock_pruner/macro/mock_pruner_macro.urdf.xacro
@@ -2,12 +2,13 @@
+
-
+
@@ -24,13 +25,13 @@
-
+
-
+
@@ -54,9 +55,9 @@
-
+
-
+
diff --git a/pybullet_tree_sim/urdf/end_effectors/mock_pruner/mock_pruner.urdf.xacro b/pybullet_tree_sim/urdf/end_effectors/mock_pruner/mock_pruner.urdf.xacro
index 088906c..7b3b0e2 100644
--- a/pybullet_tree_sim/urdf/end_effectors/mock_pruner/mock_pruner.urdf.xacro
+++ b/pybullet_tree_sim/urdf/end_effectors/mock_pruner/mock_pruner.urdf.xacro
@@ -3,36 +3,37 @@
-
+
-
+
+
+
+
-
+
-
+
-
+
-
-
-
+
diff --git a/pybullet_tree_sim/urdf/robot/generic/robot.urdf.xacro b/pybullet_tree_sim/urdf/robot/generic/robot.urdf.xacro
index b9f01a6..0300edf 100644
--- a/pybullet_tree_sim/urdf/robot/generic/robot.urdf.xacro
+++ b/pybullet_tree_sim/urdf/robot/generic/robot.urdf.xacro
@@ -13,9 +13,9 @@
-
+
-
+
@@ -39,22 +39,22 @@
mock_sensor_commands="$(arg mock_sensor_commands)"
/>
-
+
-
+
-
+
-
+
@@ -188,24 +188,26 @@
-->
-
+
-
+
-
-
+
+
+
diff --git a/pybullet_tree_sim/urdf/tmp/robot.urdf b/pybullet_tree_sim/urdf/tmp/robot.urdf
new file mode 100644
index 0000000..311409a
--- /dev/null
+++ b/pybullet_tree_sim/urdf/tmp/robot.urdf
@@ -0,0 +1,603 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ur_robot_driver/URPositionHardwareInterface
+ 0.0.0.0
+
+
+
+ False
+ 50001
+ 50002
+ 0.0.0.0
+ 50004
+ 50003
+ ur5e__
+ True
+ 2000
+ 0.03
+ False
+ calib_12788084448423163542
+ 0
+ 0
+ 115200
+ 1
+ 1.5
+ 3.5
+ /tmp/ttyUR
+ 54321
+ 2
+
+
+
+
+
+
+ 0.0
+
+
+
+
+
+
+
+
+
+ -1.57
+
+
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+
+
+
+
+
+ -1.57
+
+
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pybullet_tree_sim/utils/ur5_utils.py b/pybullet_tree_sim/utils/ur5_utils.py
index d598b16..844ef82 100644
--- a/pybullet_tree_sim/utils/ur5_utils.py
+++ b/pybullet_tree_sim/utils/ur5_utils.py
@@ -411,36 +411,36 @@ def get_current_vel(self, index: int) -> Tuple[Tuple[float, float, float], Tuple
trans, ang = link_state[6], link_state[7]
return trans, ang
- def create_camera_transform(self, pos, orientation, pan, tilt, xyz_offset) -> np.ndarray:
+ def create_camera_transform(self, world_position, world_orientation, camera: "Camera") -> np.ndarray:
"""Create rotation matrix for camera"""
base_offset_tf = np.identity(4)
- base_offset_tf[:3, 3] = self.camera_base_offset + xyz_offset
+ base_offset_tf[:3, 3] = camera.xyz_offset
ee_transform = np.identity(4)
- ee_rot_mat = np.array(self.con.getMatrixFromQuaternion(orientation)).reshape(3, 3)
+ ee_rot_mat = np.array(self.con.getMatrixFromQuaternion(world_orientation)).reshape(3, 3)
# log.debug(f"EE Rot Mat:\n{ee_rot_mat}")
ee_transform[:3, :3] = ee_rot_mat
- ee_transform[:3, 3] = pos
+ ee_transform[:3, 3] = world_position
tilt_tf = np.identity(4)
- tilt_rot = np.array([[1, 0, 0], [0, np.cos(tilt), -np.sin(tilt)], [0, np.sin(tilt), np.cos(tilt)]])
+ tilt_rot = np.array([[1, 0, 0], [0, np.cos(camera.tilt), -np.sin(camera.tilt)], [0, np.sin(camera.tilt), np.cos(camera.tilt)]])
tilt_tf[:3, :3] = tilt_rot
pan_tf = np.identity(4)
- pan_rot = np.array([[np.cos(pan), 0, np.sin(pan)], [0, 1, 0], [-np.sin(pan), 0, np.cos(pan)]])
+ pan_rot = np.array([[np.cos(camera.pan), 0, np.sin(camera.pan)], [0, 1, 0], [-np.sin(camera.pan), 0, np.cos(camera.pan)]])
pan_tf[:3, :3] = pan_rot
tf = ee_transform @ pan_tf @ tilt_tf @ base_offset_tf
return tf
# TODO: Better types for getCameraImage
- def get_view_mat_at_curr_pose(self, pan, tilt, xyz_offset) -> np.ndarray:
+ def get_view_mat_at_curr_pose(self, camera: "Camera") -> np.ndarray:
"""Get view matrix at current pose"""
- pose, orientation = self.get_current_pose(self.tool0_link_index)
+ pos, orientation = self.get_current_pose(camera.tf_frame_index)
# log.debug(f"tool0 Pose: {pose}, Orientation: {Rotation.from_quat(orientation).as_euler('xyz')}")
- camera_tf = self.create_camera_transform(pose, orientation, pan, tilt, xyz_offset)
+ camera_tf = self.create_camera_transform(pos, orientation, camera)
# Initial vectors
camera_vector = np.array([0, 0, 1]) @ camera_tf[:3, :3].T #
@@ -452,12 +452,12 @@ def get_view_mat_at_curr_pose(self, pan, tilt, xyz_offset) -> np.ndarray:
return view_matrix
def get_camera_location(
- self, tf_name: str
+ self, camera: "Camera"
): # TODO: get transform from dictionary. choose between rgb or tof frames
- pose, orientation = self.get_current_pose(self.tool0_link_index)
+ pose, orientation = self.get_current_pose(camera.tf_frame_index)
tilt = np.pi / 180 * 8
- camera_tf = self.create_camera_transform(pose, orientation, tilt)
+ camera_tf = self.create_camera_transform(camera=camera)
return camera_tf
def get_condition_number(self) -> float: