40
40
41
41
from pal_interaction_msgs .msg import TtsGoal , TtsAction
42
42
43
-
44
43
MAX_VISION_DIST : float = 5.0
45
44
46
45
@@ -82,14 +81,16 @@ def __init__(
82
81
new_goal_threshold : float = 2.0 ,
83
82
stopping_distance : float = 1.0 ,
84
83
static_speed : float = 0.0015 ,
85
- max_speed : float = 0.5 ,
84
+ max_speed : float = 0.55 ,
85
+ asking_time_limit : float = 15.0 ,
86
86
):
87
87
self ._start_following_radius = start_following_radius
88
88
self ._start_following_angle = start_following_angle
89
89
self ._new_goal_threshold = new_goal_threshold
90
90
self ._stopping_distance = stopping_distance
91
91
self ._static_speed = static_speed
92
92
self ._max_speed = max_speed
93
+ self ._asking_time_limit = asking_time_limit
93
94
94
95
self ._track_id = None
95
96
@@ -237,12 +238,12 @@ def _detect_waving_person(self) -> DetectWaveResponse:
237
238
return DetectWaveResponse ()
238
239
239
240
# recover with vision, look around and check if person is waving
240
- def _recover_vision (self , prev_pose : PoseStamped ) -> bool :
241
+ def _recover_vision (self , robot_pose : PoseStamped , prev_pose : PoseStamped ) -> bool :
241
242
242
243
# cancel current goal
243
244
self ._cancel_goal ()
244
245
245
- self ._tts ("Can you wave at me so that i can try to find you easily " , wait = True )
246
+ self ._tts ("Please come into my view and wave so that I can find you" , wait = True )
246
247
247
248
for motion in self ._vision_recovery_motions :
248
249
rospy .loginfo (f"Performing motion: { motion } " )
@@ -257,27 +258,30 @@ def _recover_vision(self, prev_pose: PoseStamped) -> bool:
257
258
):
258
259
continue
259
260
else :
260
- goal_pose = self ._tf_pose (
261
- PoseStamped (
262
- pose = Pose (
263
- position = Point (
264
- x = response .wave_position .point .x ,
265
- y = response .wave_position .point .y ,
266
- z = response .wave_position .point .z ,
261
+ goal_pose = self ._get_pose_on_path (
262
+ self ._tf_pose (robot_pose , "map" ),
263
+ self ._tf_pose (
264
+ PoseStamped (
265
+ pose = Pose (
266
+ position = Point (
267
+ x = response .wave_position .point .x ,
268
+ y = response .wave_position .point .y ,
269
+ z = response .wave_position .point .z ,
270
+ ),
271
+ orientation = Quaternion (0 , 0 , 0 , 1 ),
267
272
),
268
- orientation = Quaternion ( 0 , 0 , 0 , 1 ) ,
273
+ header = prev_pose . header ,
269
274
),
270
- header = prev_pose . header ,
275
+ "map" ,
271
276
),
272
- "map" ,
273
- )
274
- goal_pose .pose .orientation = self ._compute_face_quat (
275
- prev_pose .pose , goal_pose .pose
277
+ self ._stopping_distance ,
276
278
)
277
- rospy .loginfo (goal_pose .pose .position )
278
- self ._move_base (goal_pose )
279
- return True
280
-
279
+ if goal_pose is None :
280
+ rospy .logwarn ("Could not find a path to the person" )
281
+ return False
282
+ else :
283
+ self ._move_base (goal_pose )
284
+ return True
281
285
return False
282
286
283
287
def _euclidian_distance (self , p1 : Pose , p2 : Pose ) -> float :
@@ -383,6 +387,7 @@ def follow(self) -> None:
383
387
last_goal_time : Union [None , rospy .Time ] = None
384
388
going_to_person : bool = False
385
389
track_vels : List [float ] = []
390
+ asking_time : rospy .Time = rospy .Time .now ()
386
391
387
392
while not rospy .is_shutdown ():
388
393
@@ -419,7 +424,9 @@ def follow(self) -> None:
419
424
ask_back = True
420
425
421
426
if not ask_back :
422
- self ._recover_track (say = not self ._recover_vision (prev_goal ))
427
+ self ._recover_track (
428
+ say = not self ._recover_vision (robot_pose , prev_goal )
429
+ )
423
430
else :
424
431
self ._recover_track (say = True )
425
432
@@ -444,8 +451,14 @@ def follow(self) -> None:
444
451
last_goal_time = rospy .Time .now ()
445
452
prev_track = track
446
453
447
- if np .mean ([np .linalg .norm (vel ) for vel in track_vels ]) > self ._max_speed :
454
+ # Check if the person is walking too fast and ask them to slow down only
455
+ # if you haven't asked them in the last 15 seconds
456
+ if (
457
+ np .mean ([np .linalg .norm (vel ) for vel in track_vels ]) > self ._max_speed
458
+ and (rospy .Time .now () - asking_time ).to_sec () > self ._asking_time_limit
459
+ ):
448
460
self ._tts ("Please walk slower, I am struggling to keep up" , wait = False )
461
+ asking_time = rospy .Time .now ()
449
462
450
463
# Distance to the previous pose
451
464
dist_to_prev = (
@@ -465,19 +478,22 @@ def follow(self) -> None:
465
478
prev_goal = goal_pose
466
479
prev_track = track
467
480
last_goal_time = rospy .Time .now ()
481
+ # retry goal if it was aborted
468
482
elif (
469
483
self ._move_base_client .get_state () in [GoalStatus .ABORTED ]
470
484
and prev_goal is not None
471
485
):
472
486
rospy .logwarn ("Goal was aborted, retrying" )
473
- rospy .logwarn ((rospy .Time .now () - last_goal_time ).to_sec ())
474
- rospy .logwarn (track .pose == prev_track .pose )
475
- rospy .logwarn ("" )
476
487
self ._move_base (prev_goal )
488
+ # check if the person has been static for too long
477
489
elif (
478
- np .mean ([np .linalg .norm (vel ) for vel in track_vels ])
479
- < self ._static_speed
480
- ) and len (track_vels ) == 10 :
490
+ (
491
+ np .mean ([np .linalg .norm (vel ) for vel in track_vels ])
492
+ < self ._static_speed
493
+ )
494
+ and len (track_vels ) == 10
495
+ and prev_track is not None
496
+ ):
481
497
rospy .logwarn (
482
498
"Person has been static for too long, going to them and stopping"
483
499
)
@@ -487,41 +503,6 @@ def follow(self) -> None:
487
503
# clear velocity buffer
488
504
track_vels = []
489
505
490
- robot_pose : PoseStamped = self ._robot_pose_in_odom ()
491
- dist : float = self ._euclidian_distance (track .pose , robot_pose .pose )
492
- rospy .loginfo (f"Distance to person: { dist } " )
493
-
494
- # If the person is too far away, go to them
495
- if dist > self ._stopping_distance :
496
- goal_pose = self ._get_pose_on_path (
497
- self ._tf_pose (robot_pose , "map" ),
498
- self ._tf_pose (
499
- PoseStamped (
500
- pose = track .pose ,
501
- header = tracks .header ,
502
- ),
503
- "map" ,
504
- ),
505
- self ._stopping_distance ,
506
- )
507
- # If we can't find a path, face them
508
- if goal_pose is None :
509
- rospy .logwarn ("Could not find a path to the person" )
510
- goal_pose = robot_pose
511
- goal_pose .pose .orientation = self ._compute_face_quat (
512
- robot_pose .pose , track .pose
513
- )
514
- goal_pose = self ._tf_pose (goal_pose , "map" )
515
- # Otherwise, face them
516
- else :
517
- goal_pose = robot_pose
518
- goal_pose .pose .orientation = self ._compute_face_quat (
519
- robot_pose .pose , track .pose
520
- )
521
- goal_pose = self ._tf_pose (goal_pose , "map" )
522
-
523
- self ._move_base (goal_pose )
524
-
525
506
if self ._check_finished ():
526
507
rospy .loginfo ("Finished following person" )
527
508
break
0 commit comments