1
+ #!/usr/bin/env python
2
+
3
+ import numpy as np
4
+ import tf
5
+ import tf .transformations as tfm
6
+ import rospy
7
+ import pdb
8
+ import copy
9
+ import time
10
+ import ros_helper
11
+ import franka_helper
12
+ import matplotlib .pyplot as plt
13
+
14
+ from franka_interface import ArmInterface
15
+ from geometry_msgs .msg import TransformStamped
16
+ from std_msgs .msg import Float32MultiArray , Bool , Int32
17
+ from visualization_msgs .msg import Marker
18
+ from models .system_params import SystemParams
19
+
20
+
21
+ def get_hand_orientation_in_base (contact_pose_homog ):
22
+ # current orientation
23
+ hand_normal_x = contact_pose_homog [0 ,0 ]
24
+ hand_normal_z = contact_pose_homog [2 ,0 ]
25
+ return - np .arctan2 (hand_normal_x , - hand_normal_z )
26
+
27
+ def update_sliding_velocity (x0 , z0 , contact_pose , contact_vel ,
28
+ torque_boundary_flag , ee_pos_contact_frame_old , LCONTACT , RATE ):
29
+
30
+ contact_pose_stamped = ros_helper .list2pose_stamped (contact_pose )
31
+ contact_pose_homog = ros_helper .matrix_from_pose (contact_pose_stamped )
32
+
33
+ # 2-D unit contact normal in world frame
34
+ e_n = contact_pose_homog [:3 , 0 ]
35
+ n2D = e_n [[0 ,2 ]]
36
+ e_n2D = n2D / np .sqrt (np .sum (n2D ** 2 ))
37
+
38
+ # 2-D unit contact tangent in world frame
39
+ e_t = contact_pose_homog [:3 , 1 ]
40
+ t2D = e_t [[0 ,2 ]]
41
+ e_t2D = t2D / np .sqrt (np .sum (t2D ** 2 ))
42
+
43
+ # xc and zc (with pivot at 0,0)
44
+ xc , zc = contact_pose [0 ] - x0 , contact_pose [2 ] - z0
45
+
46
+ if torque_boundary_flag == - 1 or ee_pos_contact_frame_old is None :
47
+
48
+ # 2-D angular velocity
49
+ theta_dot = contact_vel [4 ]
50
+
51
+ # compute velocity jacobian between world frame (x, z, tht) and contact frame (n, t, tht)
52
+ velocity_jacobian = np .vstack ([np .vstack ([e_n2D , e_t2D , np .array ([zc , - xc ])]).T ,
53
+ np .array ([0. , 0. , 1. ])])
54
+
55
+ # compute end effector velocity in contact frame
56
+ ee_vel_contact_frame = np .linalg .solve (velocity_jacobian ,
57
+ np .array ([contact_vel [0 ], contact_vel [2 ], theta_dot ]))
58
+
59
+ # find normal and tangential displacment
60
+ s = e_t2D [0 ]* xc + e_t2D [1 ]* zc
61
+ d = e_n2D [0 ]* xc + e_n2D [1 ]* zc
62
+
63
+ # find angle
64
+ tht = get_hand_orientation_in_base (contact_pose_homog )
65
+ tht_hand = tht
66
+
67
+ # generalized position
68
+ ee_pos_contact_frame = np .array ([d , s , tht ])
69
+
70
+ elif torque_boundary_flag == 0 :
71
+ print ("Not in contact" )
72
+ ee_pos_contact_frame = copy .deepcopy (ee_pos_contact_frame_old )
73
+ ee_vel_contact_frame = np .zeros_like (ee_pos_contact_frame )
74
+ tht_hand = ee_pos_contact_frame [- 1 ]
75
+
76
+ elif torque_boundary_flag == 1 or torque_boundary_flag == 2 :
77
+
78
+ d_old , s_old , theta_old = ee_pos_contact_frame_old [0
79
+ ], ee_pos_contact_frame_old [1 ], ee_pos_contact_frame_old [2 ]
80
+
81
+ if torque_boundary_flag == 1 :
82
+
83
+ xcontact = xc + 0.5 * LCONTACT * e_t2D [0 ]
84
+ zcontact = zc + 0.5 * LCONTACT * e_t2D [1 ]
85
+
86
+ if torque_boundary_flag == 2 :
87
+
88
+ xcontact = xc - 0.5 * LCONTACT * e_t2D [0 ]
89
+ zcontact = zc - 0.5 * LCONTACT * e_t2D [1 ]
90
+
91
+ # angle of hand
92
+ tht_hand = get_hand_orientation_in_base (contact_pose_homog )
93
+
94
+ # length of vector from pivot to (xcontact, zcontact)
95
+ lsquared = xcontact ** 2 + zcontact ** 2
96
+
97
+ # two possible values for sliding position of contact point
98
+ if lsquared < d_old ** 2 :
99
+ sp_contact = 0
100
+ sm_contact = 0
101
+ else :
102
+ sp_contact = np .sqrt (lsquared - d_old ** 2 )
103
+ sm_contact = - np .sqrt (lsquared - d_old ** 2 )
104
+
105
+ # two possible values for angle of object
106
+ thtp = np .arctan2 (xcontact , zcontact ) + np .arctan2 (sp_contact ,
107
+ np .abs (d_old ))
108
+ thtm = np .arctan2 (xcontact , zcontact ) + np .arctan2 (sm_contact ,
109
+ np .abs (d_old ))
110
+
111
+ # pick correct value of theta and s
112
+ if torque_boundary_flag == 1 :
113
+
114
+ if thtp > tht_hand and thtm < tht_hand :
115
+ s_contact = sp_contact
116
+ tht , s = thtp , s_contact - 0.5 * LCONTACT
117
+ elif thtp < tht_hand and thtm > tht_hand :
118
+ s_contact = sm_contact
119
+ tht , s = thtm , s_contact - 0.5 * LCONTACT
120
+ else :
121
+ thtp_err = np .abs (thtp - theta_old )
122
+ thtm_err = np .abs (thtm - theta_old )
123
+
124
+ if thtp_err < thtm_err :
125
+ s_contact = sp_contact
126
+ tht , s = thtp , s_contact - 0.5 * LCONTACT
127
+ else :
128
+ s_contact = sm_contact
129
+ tht , s = thtm , s_contact - 0.5 * LCONTACT
130
+
131
+ if torque_boundary_flag == 2 :
132
+
133
+ if thtp < tht_hand and thtm > tht_hand :
134
+ s_contact = sp_contact
135
+ tht , s = thtp , s_contact + 0.5 * LCONTACT
136
+ elif thtp > tht_hand and thtm < tht_hand :
137
+ s_contact = sm_contact
138
+ tht , s = thtm , s_contact + 0.5 * LCONTACT
139
+ else :
140
+ thtp_err = np .abs (thtp - theta_old )
141
+ thtm_err = np .abs (thtm - theta_old )
142
+
143
+ if thtp_err < thtm_err :
144
+ s_contact = sp_contact
145
+ tht , s = thtp , s_contact + 0.5 * LCONTACT
146
+ else :
147
+ s_contact = sm_contact
148
+ tht , s = thtm , s_contact + 0.5 * LCONTACT
149
+
150
+ # generalized position
151
+ ee_pos_contact_frame = np .array ([d_old , s , tht ])
152
+
153
+ ee_vel_contact_frame = (ee_pos_contact_frame -
154
+ ee_pos_contact_frame_old )/ RATE
155
+
156
+ else :
157
+ raise RuntimeError ("incorrect torque_boundary_flag value" )
158
+
159
+
160
+ return ee_vel_contact_frame , ee_pos_contact_frame , tht_hand
161
+
162
+ def pivot_xyz_callback (data ):
163
+ global pivot_xyz
164
+ pivot_xyz = [data .transform .translation .x ,
165
+ data .transform .translation .y ,
166
+ data .transform .translation .z ]
167
+
168
+ def torque_cone_boundary_test_callback (data ):
169
+ global torque_boundary_boolean
170
+ torque_boundary_boolean = data .data
171
+
172
+ def torque_cone_boundary_flag_callback (data ):
173
+ global torque_cone_boundary_flag
174
+ torque_cone_boundary_flag = data .data
175
+
176
+
177
+ if __name__ == '__main__' :
178
+
179
+ rospy .init_node ("sliding_estimator" )
180
+ arm = ArmInterface ()
181
+ rospy .sleep (0.5 )
182
+
183
+ sys_params = SystemParams ()
184
+ LCONTACT = sys_params .object_params ["L_CONTACT_MAX" ] # in yaml
185
+ RATE = sys_params .estimator_params ["RATE" ]
186
+ rate = rospy .Rate (RATE )
187
+
188
+ # initialize globals
189
+ pivot_xyz = None
190
+ torque_boundary_boolean = None
191
+ torque_cone_boundary_flag = None
192
+ ee_pos_contact_frame_old = None
193
+
194
+ # setting up subscribers
195
+ pivot_xyz_sub = rospy .Subscriber ("/pivot_frame" , TransformStamped , pivot_xyz_callback )
196
+ torque_cone_boundary_test_sub = rospy .Subscriber ("/torque_cone_boundary_test" ,
197
+ Bool , torque_cone_boundary_test_callback )
198
+ torque_cone_boundary_flag_sub = rospy .Subscriber ("/torque_cone_boundary_flag" ,
199
+ Int32 , torque_cone_boundary_flag_callback )
200
+
201
+ # setting up publishers
202
+ generalized_positions_pub = rospy .Publisher ('/generalized_positions' ,
203
+ Float32MultiArray , queue_size = 10 )
204
+ generalized_velocities_pub = rospy .Publisher ('/generalized_velocities' ,
205
+ Float32MultiArray , queue_size = 10 )
206
+
207
+ # define messages
208
+ position_msg , velocity_msg = Float32MultiArray (), Float32MultiArray ()
209
+
210
+ # # make sure subscribers are receiving commands
211
+ # print("Waiting for pivot estimate to stabilize")
212
+ # while pivot_xyz is None:
213
+ # rospy.sleep(0.1)
214
+
215
+ # print("Waiting for torque boundary check")
216
+ # while torque_boundary_boolean is None:
217
+ # pass
218
+
219
+ # print("Waiting for torque boundary check")
220
+ # while torque_cone_boundary_flag is None:
221
+ # pass
222
+
223
+
224
+ print ("Starting to publish sliding velocity/position" )
225
+ while not rospy .is_shutdown ():
226
+
227
+ if (pivot_xyz is not None ) and (torque_boundary_boolean is not None
228
+ ) and (torque_cone_boundary_flag is not None ):
229
+
230
+ # face_center franka pose
231
+ endpoint_pose_franka = arm .endpoint_pose ()
232
+
233
+ # face_center list
234
+ endpoint_pose_list = franka_helper .franka_pose2list (endpoint_pose_franka )
235
+
236
+ # face center velocity franka
237
+ endpoint_velocity = arm .endpoint_velocity ()
238
+
239
+ # face center velocity list
240
+ endpoint_velocity_list = franka_helper .franka_velocity2list (
241
+ endpoint_velocity )
242
+
243
+ # update sliding velocity
244
+ ee_vel_contact_frame , ee_pos_contact_frame , tht_hand = update_sliding_velocity (
245
+ pivot_xyz [0 ], pivot_xyz [2 ], endpoint_pose_list ,
246
+ endpoint_velocity_list , torque_cone_boundary_flag ,
247
+ ee_pos_contact_frame_old , LCONTACT , RATE )
248
+
249
+ # update messages
250
+ position_msg .data = ee_pos_contact_frame
251
+ velocity_msg .data = ee_vel_contact_frame
252
+ ee_pos_contact_frame_old = ee_pos_contact_frame
253
+
254
+ # publish
255
+ generalized_positions_pub .publish (position_msg )
256
+ generalized_velocities_pub .publish (velocity_msg )
257
+
258
+ rate .sleep ()
0 commit comments