Skip to content

Commit a372638

Browse files
Copy pasta implementation of least squares script to behaviour tree
- NOTE: tank_least_squares.py should be re-homed and given some love
1 parent 4a3d77a commit a372638

2 files changed

Lines changed: 553 additions & 67 deletions

File tree

arm_commander/commander_moveit.py

Lines changed: 117 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
import sys, copy, threading, time, signal, math, traceback, timeit, numbers, logging
1717
from collections import defaultdict
18+
import numpy as np
19+
from scipy.spatial.transform import Rotation as R
20+
import tf.transformations
1821
import rospy, tf, tf2_ros, tf2_geometry_msgs
1922
from tf2_msgs.msg import TFMessage
2023
import moveit_commander
@@ -34,6 +37,8 @@
3437

3538
from moveit_calibration_detector.srv import TargetDimension, IsTargetDetected
3639

40+
from .tank_least_squares import TankLeastSquares
41+
3742
class GeneralCommander():
3843
"""
3944
GeneralCommander: an interface for robot commander, with this class specifically interfacing
@@ -1253,7 +1258,72 @@ def is_target_visible(self, timeout:float=10.0) -> bool:
12531258
time.sleep(0.5)
12541259
return False
12551260

1256-
def capture_target_sequence(self, script_file:str) -> bool:
1261+
def init_transform_listener(self):
1262+
print("Setting up (inside) the listener...")
1263+
if self.tf_buffer is None:
1264+
print("The listener is not set up")
1265+
self.tf_buffer = tf2_ros.Buffer()
1266+
self.tf_listener = tf2_ros.TransformListener(self.tf_buffer)
1267+
print("The listener is NOW set up")
1268+
1269+
def get_transform_as_pose(self, tf_buffer, from_frame, to_frame):
1270+
try:
1271+
transform = tf_buffer.lookup_transform(from_frame, to_frame, rospy.Time(0), rospy.Duration(1))
1272+
if transform is None:
1273+
return None
1274+
1275+
pose = Pose()
1276+
pose.position.x = transform.transform.translation.x
1277+
pose.position.y = transform.transform.translation.y
1278+
pose.position.z = transform.transform.translation.z
1279+
pose.orientation.x = transform.transform.rotation.x
1280+
pose.orientation.y = transform.transform.rotation.y
1281+
pose.orientation.z = transform.transform.rotation.z
1282+
pose.orientation.w = transform.transform.rotation.w
1283+
print(f"The position between ({from_frame} and {to_frame}) is: {pose.position}")
1284+
except tf2_ros.LookupException as e:
1285+
rospy.logerr(f'Lookup exception received: {e}')
1286+
return None
1287+
except tf.ExtrapolationException as e:
1288+
rospy.logerr(f'Extrapolation exception received: {e}')
1289+
return None
1290+
return pose
1291+
1292+
def capture_joints(self):
1293+
print("Setting up the listener...")
1294+
self.init_transform_listener()
1295+
try:
1296+
object_pose = self.get_transform_as_pose(self.tf_buffer, 'camera_color_optical_frame', 'handeye_target')
1297+
effector_pose = self.get_transform_as_pose(self.tf_buffer, 'base_link', 'tool0')
1298+
except tf.ExtrapolationException as e:
1299+
rospy.logerr(f'Extrapolation exception received: {e}')
1300+
return
1301+
1302+
if object_pose is None or effector_pose is None:
1303+
return
1304+
1305+
T_obj_xyz = np.array([object_pose.position.x, object_pose.position.y, object_pose.position.z])
1306+
obj_rpy = tf.transformations.euler_from_quaternion([object_pose.orientation.x, object_pose.orientation.y, object_pose.orientation.z, object_pose.orientation.w])
1307+
T_obj_rpy = np.array(obj_rpy)
1308+
T_obj = np.eye(4)
1309+
T_obj[:3, 3] = T_obj_xyz
1310+
r = R.from_euler('xyz', T_obj_rpy)
1311+
T_obj[:3, :3] = r.as_matrix()
1312+
1313+
T_eff_xyz = np.array([effector_pose.position.x, effector_pose.position.y, effector_pose.position.z])
1314+
eff_rpy = tf.transformations.euler_from_quaternion([effector_pose.orientation.x, effector_pose.orientation.y, effector_pose.orientation.z, effector_pose.orientation.w])
1315+
T_eff_rpy = np.array(eff_rpy)
1316+
T_eff = np.eye(4)
1317+
T_eff[:3, 3] = T_eff_xyz
1318+
r = R.from_euler('xyz', T_eff_rpy)
1319+
T_eff[:3, :3] = r.as_matrix()
1320+
1321+
# list of rows of T_obj
1322+
object_pose_list = T_obj.flatten().tolist()
1323+
effector_pose_list = T_eff.flatten().tolist()
1324+
self.capture_results.append({'effector_wrt_world': effector_pose_list, 'object_wrt_sensor': object_pose_list})
1325+
1326+
def capture_target_sequence(self, script_file:str):
12571327

12581328
import yaml
12591329
# Read
@@ -1263,6 +1333,7 @@ def capture_target_sequence(self, script_file:str) -> bool:
12631333
joint_values = joint_state_dict['joint_values']
12641334
print(f"Number of locations read: {len(joint_values)}")
12651335

1336+
self.capture_results = []
12661337
for idx, joint_position in enumerate(joint_values):
12671338
print(f"Moving to joint position {idx+1}/{len(joint_values)}: {joint_position}\n")
12681339

@@ -1272,13 +1343,12 @@ def capture_target_sequence(self, script_file:str) -> bool:
12721343
except Exception as e:
12731344
print(f"Failed to move to joint position {idx+1}/{len(joint_values)}: {joint_position}")
12741345
print(e)
1275-
return False
1346+
return []
12761347

12771348
time.sleep(1)
1349+
self.capture_joints()
12781350

1279-
return True
1280-
1281-
1351+
return self.capture_results
12821352

12831353
def calibrate_tank(self, reference_frame:str=None, reference_pose:Pose=None) -> Pose:
12841354
self.move_to_named_pose('named_poses.stow', True)
@@ -1301,8 +1371,13 @@ def calibrate_tank(self, reference_frame:str=None, reference_pose:Pose=None) ->
13011371
tag_1_script = ''
13021372
tag_2_script = ''
13031373
tag_3_script = ''
1374+
tag_1_samples = []
1375+
tag_2_samples = []
1376+
tag_3_samples = []
1377+
tank_id = ''
13041378

13051379
if reference_frame.endswith('0'):
1380+
tank_id = '0'
13061381
tank_ready_named_pose = 'named_poses.tank-0'
13071382
tag_1 = 'named_poses.tag-D'
13081383
tag_2 = 'named_poses.tag-E'
@@ -1313,6 +1388,7 @@ def calibrate_tank(self, reference_frame:str=None, reference_pose:Pose=None) ->
13131388
tag_3_script = tag_F_script
13141389

13151390
elif reference_frame.endswith('1'):
1391+
tank_id = '1'
13161392
tank_ready_named_pose = 'named_poses.tank-1'
13171393
tag_1 = 'named_poses.tag-A'
13181394
tag_2 = 'named_poses.tag-B'
@@ -1337,91 +1413,65 @@ def calibrate_tank(self, reference_frame:str=None, reference_pose:Pose=None) ->
13371413
# Move to Tag 1
13381414
self.move_to_named_pose(tag_1, True)
13391415
# -- Ensure tag is visible
1340-
self.is_target_visible(timeout=10.0)
1416+
if self.is_target_visible(timeout=10.0) == False:
1417+
rospy.logerr('The commander (calibrate_tank): tag 1 not visible')
1418+
return center
13411419
# -- Calibration sequence for tag_1
1342-
sequence_result = self.capture_target_sequence(tag_1_script)
1343-
if not sequence_result:
1420+
tag_1_samples = self.capture_target_sequence(tag_1_script)
1421+
if len(tag_1_samples) == 0:
13441422
rospy.logerr('The commander (calibrate_tank): failed to capture the target sequence for tag 1')
1345-
# TODO: return to safe pose
1423+
self.move_to_named_pose(tank_ready_named_pose, True)
1424+
self.move_to_named_pose('named_poses.ready', True)
13461425
return center
13471426

13481427
# Move to Tag 2
1428+
self.move_to_named_pose(tank_ready_named_pose, True)
13491429
self.move_to_named_pose(tag_2, True)
13501430
# -- Ensure tag is visible
1351-
self.is_target_visible(timeout=10.0)
1431+
if self.is_target_visible(timeout=10.0) == False:
1432+
rospy.logerr('The commander (calibrate_tank): tag 2 not visible')
1433+
return center
13521434
# -- Calibration sequence for tag_2
1353-
sequence_result = self.capture_target_sequence(tag_2_script)
1354-
if not sequence_result:
1435+
tag_2_samples = self.capture_target_sequence(tag_2_script)
1436+
if len(tag_2_samples) == 0:
13551437
rospy.logerr('The commander (calibrate_tank): failed to capture the target sequence for tag 1')
1356-
# TODO: return to safe pose
1438+
self.move_to_named_pose(tank_ready_named_pose, True)
1439+
self.move_to_named_pose('named_poses.ready', True)
13571440
return center
13581441

13591442
# Move to Tag 3
1443+
self.move_to_named_pose(tank_ready_named_pose, True)
13601444
self.move_to_named_pose(tag_3, True)
13611445
# -- Ensure tag is visible
1362-
self.is_target_visible(timeout=10.0)
1446+
if self.is_target_visible(timeout=10.0) == False:
1447+
rospy.logerr('The commander (calibrate_tank): tag 3 not visible')
1448+
return center
13631449
# -- Calibration sequence for tag_3
1364-
sequence_result = self.capture_target_sequence(tag_3_script)
1365-
if not sequence_result:
1450+
tag_3_samples = self.capture_target_sequence(tag_3_script)
1451+
if len(tag_3_samples) == 0:
13661452
rospy.logerr('The commander (calibrate_tank): failed to capture the target sequence for tag 1')
1367-
# TODO: return to safe pose
1453+
self.move_to_named_pose(tank_ready_named_pose, True)
1454+
self.move_to_named_pose('named_poses.ready', True)
13681455
return center
13691456

1457+
# -- Process the captured samples
1458+
why = TankLeastSquares(tank_id, tag_1_samples, tag_2_samples, tag_3_samples)
1459+
center = why.get_tank_center_pose()
1460+
# transform center to world_tf
1461+
center_posestamped = PoseStamped()
1462+
center_posestamped.header.frame_id = 'base_link'
1463+
center_posestamped.header.stamp = rospy.Time.now()
1464+
center_posestamped.pose = center
1465+
1466+
self.init_transform_listener()
1467+
transformed_pose = self.tf_buffer.transform(center_posestamped, self.WORLD_REFERENCE_LINK, rospy.Duration(1))
1468+
center = transformed_pose.pose
1469+
13701470
# Move to Tank Ready Pose
13711471
self.move_to_named_pose(tank_ready_named_pose, True)
13721472
self.move_to_named_pose('named_poses.stow', True)
13731473

1374-
if reference_frame.endswith('0'):
1375-
# lookup transform from /robot_footprint to /tank_center
1376-
center_tf = self.tf_buffer.lookup_transform(self.WORLD_REFERENCE_LINK, 'tank_center', rospy.Time(0), rospy.Duration(4.0))
1377-
center.position.x = center_tf.transform.translation.x
1378-
center.position.y = center_tf.transform.translation.y
1379-
center.position.z = center_tf.transform.translation.z
1380-
center.orientation.x = center_tf.transform.rotation.x
1381-
center.orientation.y = center_tf.transform.rotation.y
1382-
center.orientation.z = center_tf.transform.rotation.z
1383-
center.orientation.w = center_tf.transform.rotation.w
1384-
1385-
print(f'Calibrating tank {reference_frame} with WORLD_REFERENCE_LINK {self.WORLD_REFERENCE_LINK} and center: {center}')
1386-
#input('Press Enter to continue...')
1387-
1388-
#center.position.x = -0.029
1389-
#center.position.y = -1.184
1390-
#center.position.z = 0.197
1391-
#center.orientation.x = 0.009
1392-
#center.orientation.y = 0.003
1393-
#center.orientation.z = 0.999
1394-
#center.orientation.w = -0.036
1395-
#- Rotation: in Quaternion [0.009, 0.003, 0.999, -0.036]
1396-
elif reference_frame.endswith('1'):
1397-
# lookup transform from /robot_footprint to /tank_center
1398-
center_tf = self.tf_buffer.lookup_transform(self.WORLD_REFERENCE_LINK, 'tank_center', rospy.Time(0), rospy.Duration(4.0))
1399-
center.position.x = center_tf.transform.translation.x
1400-
center.position.y = center_tf.transform.translation.y
1401-
center.position.z = center_tf.transform.translation.z
1402-
center.orientation.x = center_tf.transform.rotation.x
1403-
center.orientation.y = center_tf.transform.rotation.y
1404-
center.orientation.z = center_tf.transform.rotation.z
1405-
center.orientation.w = center_tf.transform.rotation.w
1406-
1407-
print(f'Calibrating tank {reference_frame} with WORLD_REFERENCE_LINK {self.WORLD_REFERENCE_LINK} and center: {center}')
1408-
#input('Press Enter to continue...')
1409-
1410-
#center.position.x = -0.006
1411-
#center.position.y = 1.188
1412-
#center.position.z = 0.218
1413-
#center.orientation.x = -0.000
1414-
#center.orientation.y = 0.000
1415-
#center.orientation.z = 0.007
1416-
#center.orientation.w = 1.000
1417-
#- Rotation: in Quaternion [-0.000, 0.000, 0.007, 1.000]
1418-
14191474
return center
1420-
1421-
1422-
# returns a list of current objects that have been added to the commander
1423-
""" Returns a list of current objects that have been added to the commander
1424-
"""
14251475

14261476
def list_object_names(self) -> list:
14271477
return self.scene.get_known_object_names()

0 commit comments

Comments
 (0)