Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tablet tool #306

Merged
merged 44 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7357d0c
Init tablet tool support
hello-fazil Mar 5, 2024
f304ea3
First pass collision and stow for tablet
hello-fazil Mar 6, 2024
5c68db3
Fixed homing and stowing with tablet
hello-fazil Mar 6, 2024
6102303
Add dynamixel group level set_velocity API
hello-fazil Mar 6, 2024
7c93851
lock wrist_roll joint for tablet tool
hello-fazil Mar 6, 2024
d6ee4e0
Add more collision pair links and joints mapping, included pre stove …
hello-fazil Mar 8, 2024
e3c97b6
Check if joint pose changed before collision stop reset
hello-fazil Mar 9, 2024
2b04904
Added todo
hello-fazil Mar 9, 2024
15eae5c
Implemented a collision pair min distance aware joints
hello-fazil Mar 12, 2024
6ce0df0
Add more collision pairs
hello-fazil Mar 12, 2024
de1a1d2
fix wrist yaw collision pairs
hello-fazil Mar 12, 2024
a3f55dc
Remove Gamepad stowing block in loop
hello-fazil Mar 16, 2024
4cdf27e
update homing stow pose for tablet tool
hello-fazil Mar 16, 2024
1c6bb9b
Add tablet orientation set APIs
hello-fazil Mar 20, 2024
725caae
Add debug latency prints
hello-fazil Mar 21, 2024
ded47bb
wip new triangle mesh edges based intersection
hello-fazil Mar 21, 2024
d3d6b93
New edge detection algorithm working
hello-fazil Mar 22, 2024
374b16e
Add random sampling to improve efficiency
hello-fazil Mar 22, 2024
f7f7133
Increase collision monitor rate to 100hz
hello-fazil Mar 22, 2024
7aa1ed6
wip
hello-fazil Mar 26, 2024
e2e24a2
Normalized joint cfg based collision reset
hello-fazil Mar 27, 2024
9fcb13e
WIp
hello-fazil Mar 28, 2024
9acd879
init prototype
hello-fazil Mar 28, 2024
7864263
Collision mgmt Process communications working
hello-fazil Mar 28, 2024
71f6819
improvements
hello-fazil Mar 29, 2024
8a28f2b
Make clean process exit
hello-fazil Mar 29, 2024
1687dbb
exit error handling improvements
hello-fazil Mar 29, 2024
da44fa0
enable safety twice
hello-fazil Mar 29, 2024
d02f6cb
improvements
hello-fazil Mar 29, 2024
07a0621
Increase braking distance k
hello-fazil Mar 29, 2024
0907776
Change shared variables to lightweight Queues
hello-fazil Mar 29, 2024
68d643c
WIP
hello-fazil Apr 4, 2024
6c4f107
Improvements
hello-fazil Apr 5, 2024
e731bce
Improvements
hello-fazil Apr 13, 2024
0bede14
Implement barycentric triangle edge points sampling
hello-fazil Apr 15, 2024
87bb773
clean up
hello-fazil Apr 15, 2024
14ca568
clean up
hello-fazil Apr 15, 2024
d3d6487
Tablet improvements
hello-fazil Apr 15, 2024
e044954
Tablet forced collision stop implementation
hello-fazil Apr 15, 2024
35beb41
Cleanup
hello-fazil Apr 15, 2024
cc7d0d3
Merge pull request #305 from hello-robot/feature/collision_mgmt_multi…
hello-fazil Apr 15, 2024
aeabd21
Remove misc files
hello-fazil Apr 15, 2024
52305cf
Get braking joint config on collision
hello-fazil Apr 15, 2024
3ae0a33
Disable collision mgmt while homing and stowing
hello-fazil May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions body/stretch_body/dynamixel_hello_XL430.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ def __init__(self, name, chain=None, usb=None):
self.total_range = abs(self.ticks_to_world_rad(self.params['range_t'][0]) - self.ticks_to_world_rad(self.params['range_t'][1]))
self.in_collision_stop = {'pos': False, 'neg': False}
self.ts_collision_stop = {'pos': 0.0, 'neg': 0.0}
self.forced_collision_stop_override = {'pos': False, 'neg':False}
self._in_collision_stop_override = False
except KeyError:
self.motor=None

Expand Down Expand Up @@ -449,17 +451,29 @@ def step_collision_avoidance(self,in_collision):
# print('Invalid IN_COLLISION for joint %s'%self.name)
# return

if True in self.forced_collision_stop_override.values():
if not self._in_collision_stop_override:
self.quick_stop()
self._in_collision_stop_override = True
return

if not True in self.forced_collision_stop_override.values():
self._in_collision_stop_override = False


for dir in ['pos','neg']:
if in_collision[dir] and not self.in_collision_stop[dir]:
# Stop current motion
self.ts_collision_stop[dir] = time.time()
self.quick_stop()
if not self.was_runstopped:
self.quick_stop()
self.in_collision_stop[dir] = True

#Reset if out of collision (at least 1s after collision)
if self.in_collision_stop[dir] and not in_collision[dir] and time.time()-self.ts_collision_stop[dir]>1.0:
if self.in_collision_stop[dir] and not in_collision[dir] and time.time()-self.ts_collision_stop[dir]>1:
self.in_collision_stop[dir] = False


def get_braking_distance(self,acc=None):
"""Compute distance to brake the joint from the current velocity"""
v_curr = self.status['vel']
Expand Down Expand Up @@ -585,6 +599,14 @@ def set_velocity(self,v_des,a_des=None):
self.enable_torque()
v = min(self.params['motion']['max']['vel'],abs(v_des))

if self.forced_collision_stop_override['pos'] and v_des>0:
self.logger.warning(f"set_velocity in Forced Collision stop. Motion disabled in direction {'pos'} for {self.name}. Not executing move_to")
return

if self.forced_collision_stop_override['neg'] and v_des<0:
self.logger.warning(f"set_velocity in Forced Collision stop. Motion disabled in direction {'neg'} for {self.name}. Not executing move_to")
return

if self.in_collision_stop['pos'] and v_des>0:
self.logger.warning('set_velocity in collision . Motion disabled in direction %s for %s. Not executing set_velocity'%('pos',self.name))
return
Expand Down Expand Up @@ -707,6 +729,13 @@ def move_to(self,x_des, v_des=None, a_des=None):
print('Dynamixel not calibrated:', self.name)
return

if self.forced_collision_stop_override['pos'] and self.status['pos']<x_des:
self.logger.warning(f"move_to in Forced Collision stop. Motion disabled in direction {'pos'} for {self.name}. Not executing move_to")
return

if self.forced_collision_stop_override['neg'] and self.status['pos']>x_des:
self.logger.warning(f"move_to in Forced Collision stop. Motion disabled in direction {'neg'} for {self.name}. Not executing move_to")
return

if self.in_collision_stop['pos'] and self.status['pos']<x_des:
self.logger.warning('move_to in collision. Motion disabled in direction %s for %s. Not executing move_to'%('pos',self.name))
Expand Down
26 changes: 20 additions & 6 deletions body/stretch_body/end_of_arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ def move_by(self, joint, x_r, v_r=None, a_r=None):
"""
with self.pt_lock:
self.motors[joint].move_by(x_r, v_r, a_r)

def set_velocity(self, joint, v_r, a_r=None):
"""
joint: name of joint (string)
v_r: commanded velocity (rad/s).
a_r: acceleration motion profile (rad/s^2)
"""
with self.pt_lock:
self.motors[joint].set_velocity(v_r, a_r)

def pose(self,joint, p,v_r=None, a_r=None):
"""
Expand All @@ -76,6 +85,9 @@ def pose(self,joint, p,v_r=None, a_r=None):
def stow(self):
pass #Override by specific tool

def pre_stow(self,robot=None):
pass #Override by specific tool

def home(self, joint=None):
"""
Home to hardstops
Expand All @@ -98,7 +110,7 @@ def is_tool_present(self,class_name):
return True
return False

def get_joint_configuration(self,braked=False):
def get_joint_configuration(self,brake_joints={}):
"""
Construct a dictionary of tools current pose (for robot_collision_mgmt)
Keys match joint names in URDF
Expand All @@ -109,14 +121,16 @@ def get_joint_configuration(self,braked=False):
jn = self.urdf_map[j]
motor = self.get_joint(jn)
dx = 0.0
if braked:
try:
try:
if brake_joints[j]:
dx = self.params['collision_mgmt']['k_brake_distance'][jn] * motor.get_braking_distance()
except KeyError:
dx=0
except KeyError:
dx=0
ret[j] = motor.status['pos'] + dx
return ret


def pre_stow(self,robot=None):
pass



122 changes: 122 additions & 0 deletions body/stretch_body/end_of_arm_tools.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from stretch_body.end_of_arm import *
import threading
import time

# ############# STRETCH RE1 / RE2 #######################
class ToolNone(EndOfArm):
Expand Down Expand Up @@ -73,6 +75,10 @@ def home(self):
self.motors['wrist_roll'].move_to(0)
self.motors['wrist_yaw'].home()

def pre_stow(self,robot=None):
if 'wrist_pitch' in self.end_of_arm.joints:
self.end_of_arm.move_to('wrist_pitch', self.end_of_arm.params['stow']['wrist_pitch'])

# ##########################################################3#
class EOA_Wrist_DW3_Tool_NIL(EndOfArm):
"""
Expand All @@ -99,6 +105,11 @@ def home(self):
self.motors['wrist_roll'].move_to(self.params['stow']['wrist_roll'])
self.motors['wrist_yaw'].home()

def pre_stow(self,robot=None):
if robot:
robot.end_of_arm.move_to('wrist_pitch', robot.end_of_arm.params['stow']['wrist_pitch'])
else:
self.end_of_arm.move_to('wrist_pitch', self.end_of_arm.params['stow']['wrist_pitch'])

class EOA_Wrist_DW3_Tool_SG3(EndOfArm):
"""
Expand All @@ -122,8 +133,119 @@ def stow(self):
self.move_to('wrist_roll', self.params['stow']['wrist_roll'])
self.move_to('wrist_yaw', self.params['stow']['wrist_yaw'])
self.move_to('stretch_gripper', self.params['stow']['stretch_gripper'])

def home(self):
self.motors['wrist_pitch'].move_to(self.params['stow']['wrist_pitch'])
self.motors['wrist_roll'].move_to(self.params['stow']['wrist_roll'])
self.motors['wrist_yaw'].home()
self.motors['stretch_gripper'].home()

def pre_stow(self,robot=None):
if robot:
robot.end_of_arm.move_to('wrist_pitch', robot.end_of_arm.params['stow']['wrist_pitch'])
else:
self.end_of_arm.move_to('wrist_pitch', self.end_of_arm.params['stow']['wrist_pitch'])

class EOA_Wrist_DW3_Tool_Tablet_12in(EndOfArm):
"""
Wrist Yaw / Pitch / Roll + 12in Tablet
"""
def __init__(self, name='eoa_wrist_dw3_tool_tablet_12in'):
EndOfArm.__init__(self, name)
self.portrait_orientation = self.params['portrait_orientation']
#This maps from the name of a joint in the URDF to the name of the joint in Stretch Body
#It is used by CollisionMgmt
self.urdf_map={
'joint_wrist_yaw':'wrist_yaw',
'joint_wrist_pitch': 'wrist_pitch',
'joint_wrist_roll':'wrist_roll' #Not mapping fingers for collision mgmt yet
}

def move_by(self, joint, x_r, v_r=None, a_r=None, enable_wrist_roll = False):
# Lock wrist roll by default
if joint=='wrist_roll':
if enable_wrist_roll:
return EndOfArm.move_by(self, joint, x_r, v_r, a_r)
else:
return None
return EndOfArm.move_by(self, joint, x_r, v_r, a_r)

def move_to(self, joint, x_r, v_r=None, a_r=None, enable_wrist_roll = False):
# Lock wrist roll by default
if joint=='wrist_roll':
if enable_wrist_roll:
return EndOfArm.move_by(self, joint, x_r, v_r, a_r)
else:
return None
return EndOfArm.move_to(self, joint, x_r, v_r, a_r)

def set_velocity(self, joint, v_r, a_r=None, enable_wrist_roll = False):
# Lock wrist roll by default
if joint=='wrist_roll':
if enable_wrist_roll:
return EndOfArm.set_velocity(self, joint, v_r, a_r)
else:
return None
return EndOfArm.set_velocity(self, joint, v_r, a_r)

def pre_stow(self,robot=None):
if robot:
if robot.lift.status['pos'] > 0.9:
robot.lift.move_by(-0.2)
robot.push_command()
time.sleep(0.25)
while robot.lift.motor.status['is_moving']:
time.sleep(0.1)

if not (2 > self.motors['wrist_yaw'].status['pos'] > 0):
self.move_to('wrist_pitch',-1.57)

def switch_to_portrait_mode(self):
self.portrait_orientation = True
self.reset_tablet_orientation()

def switch_to_landscape_mode(self):
self.portrait_orientation = False
self.reset_tablet_orientation()

def reset_tablet_orientation(self):
if self.portrait_orientation:
self.motors['wrist_roll'].move_to(1.57)
else:
self.motors['wrist_roll'].move_to(self.params['stow']['wrist_roll'])

def stow(self):
# Fold Arm, Wrist yaw turns left making the tabled screen face forward.
print('--------- Stowing %s ----'%self.name)
self.reset_tablet_orientation()
self.move_to('wrist_yaw', self.params['stow']['wrist_yaw'])
time.sleep(1)
self.move_to('wrist_pitch', self.params['stow']['wrist_pitch'])
time.sleep(1)

def home(self):
# Tablet should face completely downwards during homing
self.motors['wrist_pitch'].move_to(-1.57)
while self.motors['wrist_pitch'].motor.is_moving():
time.sleep(0.2)
self.reset_tablet_orientation()
self.motors['wrist_yaw'].home()
self.motors['wrist_pitch'].move_to(self.params['stow']['wrist_pitch'])
self.motors['wrist_yaw'].move_to(1.57)
time.sleep(2)

def step_sentry(self, robot):
super().step_sentry(robot)
if robot.collision.running:
wrist_p = self.get_joint('wrist_pitch').status['pos']
wrist_y = self.get_joint('wrist_yaw').status['pos']
# TODO: Add more special conditions around this part
if wrist_p > -0.2 and wrist_y < 0.18:
# print("In Special Stop")
self.get_joint('wrist_yaw').forced_collision_stop_override = {'pos': False, 'neg':True}
self.get_joint('wrist_pitch').forced_collision_stop_override = {'pos': True, 'neg':False}

else:
# print("Out Special Stop")
self.get_joint('wrist_yaw').forced_collision_stop_override = {'pos': False, 'neg':False}
self.get_joint('wrist_pitch').forced_collision_stop_override = {'pos': False, 'neg':False}
2 changes: 1 addition & 1 deletion body/stretch_body/gamepad_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def main():
for k in state.keys():
print(k, ' : ', state[k])
print('------------------------------')
time.sleep(1.0)
time.sleep(0.1)
except (KeyboardInterrupt, SystemExit):
pass

Expand Down
29 changes: 14 additions & 15 deletions body/stretch_body/gamepad_joints.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,6 @@ def command_stick_to_motion(self, x, robot):
x (float): Range [-1.0,+1.0], control servo speed
robot (robot.Robot): Valid robot instance
"""
if 'wrist' in self.name:
motor = robot.end_of_arm.get_joint(self.name)
if 'head' in self.name:
motor = robot.head.get_joint(self.name)
if abs(x)<self.dead_zone:
x = 0
acc = self.acc
Expand All @@ -452,7 +448,10 @@ def command_stick_to_motion(self, x, robot):
v = self._process_stick_to_vel(x)
if self.precision_mode:
v = v*self.precision_scale_down
motor.set_velocity(v, acc)
if 'wrist' in self.name:
robot.end_of_arm.set_velocity(self.name,v, acc)
if 'head' in self.name:
robot.head.set_velocity(self.name,v, acc)
self._prev_set_vel_ts = time.time()

def command_button_to_motion(self,direction, robot):
Expand All @@ -462,17 +461,19 @@ def command_button_to_motion(self,direction, robot):
direction (int): Direction integer -1 or +1
robot (robot.Robot): Valid robot instance
"""
if 'wrist' in self.name:
motor = robot.end_of_arm.get_joint(self.name)
if 'head' in self.name:
motor = robot.head.get_joint(self.name)
vel = self.max_vel
if self.precision_mode:
vel = vel*self.precision_scale_down
if direction==1:
motor.set_velocity(vel, self.acc)
if 'head' in self.name:
robot.head.set_velocity(self.name, vel, self.acc)
if 'wrist' in self.name:
robot.end_of_arm.set_velocity(self.name, vel, self.acc)
elif direction==-1:
motor.set_velocity(-1*vel, self.acc)
if 'head' in self.name:
robot.head.set_velocity(self.name, -1*vel, self.acc)
if 'wrist' in self.name:
robot.end_of_arm.set_velocity(self.name, -1*vel, self.acc)
self._prev_set_vel_ts = time.time()

def stop_motion(self, robot):
Expand All @@ -483,11 +484,9 @@ def stop_motion(self, robot):
robot (robot.Robot): Valid robot instance
"""
if 'wrist' in self.name:
motor = robot.end_of_arm.get_joint(self.name)
robot.end_of_arm.set_velocity(self.name,0,self.params['motion']['max']['accel'])
if 'head' in self.name:
motor = robot.head.get_joint(self.name)

motor.set_velocity(0,self.params['motion']['max']['accel'])
robot.head.set_velocity(self.name,0,self.params['motion']['max']['accel'])

def _process_stick_to_vel(self, x):
x = -1*x
Expand Down
Loading