Skip to content

Commit 63fd810

Browse files
fireblondejws-1
andauthored
Cml day 3 (#262)
Co-authored-by: Jared Swift <j.w.swift@outlook.com>
1 parent b55959e commit 63fd810

File tree

10 files changed

+159
-75
lines changed

10 files changed

+159
-75
lines changed

common/navigation/lasr_person_following/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ find_package(catkin REQUIRED COMPONENTS
1414
genmsg
1515
actionlib_msgs
1616
actionlib
17+
geometry_msgs
1718
)
1819

1920
## System dependencies are found with CMake's conventions
@@ -73,6 +74,7 @@ add_action_files(
7374
generate_messages(
7475
DEPENDENCIES
7576
actionlib_msgs
77+
geometry_msgs
7678
)
7779

7880
################################################
@@ -163,6 +165,7 @@ include_directories(
163165
# in contrast to setup.py, you can choose the destination
164166
catkin_install_python(PROGRAMS
165167
nodes/person_following.py
168+
nodes/stop_listener.py
166169
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
167170
)
168171

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
22
#result definition
3+
geometry_msgs/Pose[] waypoints
34
---
45
#feedback

common/navigation/lasr_person_following/nodes/person_following.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
import warnings
1818

19+
from std_msgs.msg import Empty
20+
1921

2022
class PersonFollowingServer:
2123
_server: actionlib.SimpleActionServer
@@ -32,6 +34,10 @@ def __init__(self) -> None:
3234
"/move_base/set_parameters", Reconfigure
3335
)
3436

37+
self._dynamic_local_costmap = rospy.ServiceProxy(
38+
"/move_base/local_costmap/inflation_layer/set_parameters", Reconfigure
39+
)
40+
3541
self._update_params()
3642
rospy.sleep(1)
3743
print("Updated params")
@@ -78,6 +84,12 @@ def _update_params(self):
7884

7985
self._dynamic_recovery(config)
8086

87+
config = Config()
88+
config.bools.append(BoolParameter(name="enabled", value=1))
89+
config.doubles.append(DoubleParameter(name="inflation_radius", value=0.2))
90+
91+
self._dynamic_local_costmap(config)
92+
8193

8294
if __name__ == "__main__":
8395
rospy.init_node("person_following_server")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python3
2+
import rospy
3+
4+
from lasr_speech_recognition_msgs.msg import ( # type: ignore
5+
TranscribeSpeechAction,
6+
TranscribeSpeechGoal,
7+
)
8+
9+
from std_msgs.msg import Empty
10+
11+
import actionlib
12+
13+
if __name__ == "__main__":
14+
rospy.init_node("stop_listener")
15+
finished_pub = rospy.Publisher("/stop_listener/finished", Empty, queue_size=1)
16+
transcribe_speech_client = actionlib.SimpleActionClient(
17+
"transcribe_speech", TranscribeSpeechAction
18+
)
19+
transcribe_speech_client.wait_for_server()
20+
21+
while not rospy.is_shutdown():
22+
transcribe_speech_client.send_goal_and_wait(TranscribeSpeechGoal())
23+
result = transcribe_speech_client.get_result()
24+
if "stop" in result.sequence.lower():
25+
finished_pub.publish(Empty())
26+
rospy.spin()

common/navigation/lasr_person_following/src/lasr_person_following/person_following.py

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Point,
1212
)
1313

14-
from typing import Union, List
14+
from typing import Union, List, Tuple
1515

1616
from move_base_msgs.msg import MoveBaseAction, MoveBaseActionGoal, MoveBaseGoal
1717
from actionlib_msgs.msg import GoalStatus
@@ -40,6 +40,15 @@
4040

4141
from pal_interaction_msgs.msg import TtsGoal, TtsAction
4242

43+
from lasr_person_following.msg import (
44+
FollowAction,
45+
FollowGoal,
46+
FollowResult,
47+
FollowFeedback,
48+
)
49+
50+
from std_msgs.msg import Empty
51+
4352
MAX_VISION_DIST: float = 5.0
4453

4554

@@ -63,6 +72,7 @@ class PersonFollower:
6372
_tts_client_available: bool
6473
_transcribe_speech_client: actionlib.SimpleActionClient
6574
_transcribe_speech_client_available: bool
75+
_stop_listener_sub: rospy.Subscriber
6676

6777
# Services
6878
_make_plan: rospy.ServiceProxy
@@ -74,6 +84,9 @@ class PersonFollower:
7484
# Publishers
7585
_person_trajectory_pub: rospy.Publisher
7686

87+
# Waypoints
88+
_waypoints: List[PoseStamped]
89+
7790
def __init__(
7891
self,
7992
start_following_radius: float = 2.0,
@@ -139,6 +152,17 @@ def __init__(
139152
if not self._play_motion.wait_for_server(rospy.Duration.from_sec(10.0)):
140153
rospy.logwarn("Play motion client not available")
141154

155+
self._stop_listener_sub = rospy.Subscriber(
156+
"/stop_listener/finished", Empty, self._stop_listener_cb
157+
)
158+
159+
self._should_stop = False
160+
161+
self._waypoints = []
162+
163+
def _stop_listener_cb(self, msg: Empty) -> None:
164+
self._should_stop = True
165+
142166
def _tf_pose(self, pose: PoseStamped, target_frame: str):
143167
trans = self._buffer.lookup_transform(
144168
target_frame, pose.header.frame_id, rospy.Time(0), rospy.Duration(1.0)
@@ -258,23 +282,19 @@ def _recover_vision(self, robot_pose: PoseStamped, prev_pose: PoseStamped) -> bo
258282
):
259283
continue
260284
else:
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),
285+
goal_pose = self._tf_pose(
286+
PoseStamped(
287+
pose=Pose(
288+
position=Point(
289+
x=response.wave_position.point.x,
290+
y=response.wave_position.point.y,
291+
z=response.wave_position.point.z,
272292
),
273-
header=prev_pose.header,
293+
orientation=Quaternion(0, 0, 0, 1),
274294
),
275-
"map",
295+
header=prev_pose.header,
276296
),
277-
self._stopping_distance,
297+
"map",
278298
)
279299
if goal_pose is None:
280300
rospy.logwarn("Could not find a path to the person")
@@ -322,15 +342,15 @@ def _cancel_goal(self) -> None:
322342

323343
def _check_finished(self) -> bool:
324344
if self._tts_client_available:
325-
self._tts("Have we arrived?", wait=True)
345+
self._tts("Have we arrived? Please say Yes We Have Arrived", wait=True)
326346

327347
if self._transcribe_speech_client_available:
328348
self._transcribe_speech_client.send_goal_and_wait(
329349
TranscribeSpeechGoal()
330350
)
331351
transcription = self._transcribe_speech_client.get_result().sequence
332352

333-
return "yes" in transcription.lower()
353+
return "yes" in transcription.lower() or "arrived" in transcription.lower() or "arrive" in transcription.lower()
334354
return True
335355

336356
def _get_pose_on_path(
@@ -361,11 +381,14 @@ def _get_pose_on_path(
361381

362382
return chosen_pose
363383

364-
def _move_base(self, pose: PoseStamped) -> MoveBaseGoal:
384+
def _move_base(self, pose: PoseStamped, wait=False) -> MoveBaseGoal:
365385
goal: MoveBaseGoal = MoveBaseGoal()
366386
goal.target_pose = pose
367387
self._move_base_client.send_goal(goal)
368388

389+
if wait:
390+
self._move_base_client.wait_for_result()
391+
369392
return goal
370393

371394
def _tts(self, text: str, wait: bool) -> None:
@@ -378,17 +401,21 @@ def _tts(self, text: str, wait: bool) -> None:
378401
else:
379402
self._tts_client.send_goal(tts_goal)
380403

381-
def follow(self) -> None:
404+
def follow(self) -> FollowResult:
405+
406+
result = FollowResult()
382407

383408
person_trajectory: PoseArray = PoseArray()
384409
person_trajectory.header.frame_id = "odom"
385410
prev_track: Union[None, Person] = None
386411
prev_goal: Union[None, PoseStamped] = None
387412
last_goal_time: Union[None, rospy.Time] = None
388413
going_to_person: bool = False
389-
track_vels: List[float] = []
414+
track_vels: List[Tuple[float, float]] = []
390415
asking_time: rospy.Time = rospy.Time.now()
391416

417+
self._tts("I will follow you now. Please walk slowly!", wait=False)
418+
392419
while not rospy.is_shutdown():
393420

394421
tracks: PersonArray = rospy.wait_for_message("/people_tracked", PersonArray)
@@ -408,28 +435,7 @@ def follow(self) -> None:
408435
rospy.loginfo("Lost track of person, recovering...")
409436
person_trajectory = PoseArray()
410437
ask_back: bool = False
411-
412-
if prev_track is not None:
413-
robot_pose: PoseStamped = self._robot_pose_in_odom()
414-
if robot_pose:
415-
dist: float = self._euclidian_distance(
416-
robot_pose.pose, prev_track.pose
417-
)
418-
rospy.loginfo(f"Distance to last known position: {dist}")
419-
if dist >= MAX_VISION_DIST:
420-
ask_back = True
421-
else:
422-
ask_back = True
423-
else:
424-
ask_back = True
425-
426-
if not ask_back:
427-
self._recover_track(
428-
say=not self._recover_vision(robot_pose, prev_goal)
429-
)
430-
else:
431-
self._recover_track(say=True)
432-
438+
self._recover_track(say=True)
433439
prev_track = None
434440
continue
435441

@@ -475,6 +481,8 @@ def follow(self) -> None:
475481
"map",
476482
)
477483
self._move_base(goal_pose)
484+
485+
self._waypoints.append(goal_pose)
478486
prev_goal = goal_pose
479487
prev_track = track
480488
last_goal_time = rospy.Time.now()
@@ -503,9 +511,21 @@ def follow(self) -> None:
503511
# clear velocity buffer
504512
track_vels = []
505513

514+
# clear waypoints
515+
self._waypoints = []
516+
506517
if self._check_finished():
507518
rospy.loginfo("Finished following person")
508519
break
520+
elif self._move_base_client.get_state() in [GoalStatus.SUCCEEDED]:
521+
goal_pose = self._tf_pose(
522+
PoseStamped(pose=track.pose, header=tracks.header),
523+
"map",
524+
)
525+
self._move_base(goal_pose)
526+
prev_goal = goal_pose
527+
prev_track = track
509528
rospy.loginfo("")
510529
rospy.loginfo(np.mean([np.linalg.norm(vel) for vel in track_vels]))
511530
rospy.loginfo("")
531+
return result

common/vision/lasr_vision_cropped_detection/src/lasr_vision_cropped_detection/cropped_detection.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ def process_single_detection_request(
299299
depth_image_topic: str = "/xtion/depth_registered/points",
300300
yolo_2d_service_name: str = "/yolov8/detect",
301301
yolo_3d_service_name: str = "/yolov8/detect3d",
302-
robot_pose_topic: str = "/amcl_pose",
302+
robot_pose_topic: str = "/robot_pose",
303303
debug_topic: str = "/lasr_vision/cropped_detection/debug",
304304
) -> CDResponse:
305305
"""Dispatches a detection request to the appropriate bounding box/mask 2D or 3D cropped
@@ -311,7 +311,7 @@ def process_single_detection_request(
311311
depth_image_topic (str, optional): The topic to getn an RGBD image from. Defaults to "/xtion/depth_registered/points".
312312
yolo_2d_service_name (str, optional): Name of the 2D Yolo detection service. Defaults to "/yolov8/detect".
313313
yolo_3d_service_name (str, optional): Name of the 3D Yolo detection service. Defaults to "/yolov8/detect3d".
314-
robot_pose_topic (str, optional): Service to get the robot's current pose. Defaults to "/amcl_pose".
314+
robot_pose_topic (str, optional): Service to get the robot's current pose. Defaults to "/robot_pose".
315315
debug_topic (str, optional): Topic to publish results to for debugging. Defaults to "/lasr_vision/cropped_detection/debug".
316316
317317
Returns:

skills/config/motions.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ play_motion:
1010
points:
1111
- positions: [1.61, -0.93, -3.14, 1.83, -1.58, -0.53, 0.00]
1212
time_from_start: 0.0
13+
cml_arm_away:
14+
joints: [ arm_1_joint, arm_2_joint, arm_3_joint, arm_4_joint, arm_5_joint, arm_6_joint, arm_7_joint ]
15+
points:
16+
- positions: [ 2.65, -1.36, -1.23, 1.86, -1.36, 1.39, -0.01 ]
17+
time_from_start: 0.0
1318
open_gripper:
1419
joints: [gripper_left_finger_joint, gripper_right_finger_joint]
1520
points:

skills/src/lasr_skills/receive_object.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def __init__(self, object_name: Union[str, None] = None, vertical: bool = True):
147147
smach.StateMachine.add(
148148
"SAY_PLACE",
149149
Say(
150-
text=f"Please place the {object_name} in my end-effector. I will wait for a few seconds.",
150+
text=f"Please place the {object_name} in my hand. I will wait for a few seconds.",
151151
),
152152
transitions={
153153
"succeeded": "WAIT_5",
@@ -159,7 +159,7 @@ def __init__(self, object_name: Union[str, None] = None, vertical: bool = True):
159159
smach.StateMachine.add(
160160
"SAY_PLACE",
161161
Say(
162-
format_str="Please place the {} in my end-effector. I will wait for a few seconds.",
162+
format_str="Please place the {} in my hand. I will wait for a few seconds.",
163163
),
164164
transitions={
165165
"succeeded": "WAIT_5",
@@ -189,7 +189,7 @@ def __init__(self, object_name: Union[str, None] = None, vertical: bool = True):
189189
)
190190
smach.StateMachine.add(
191191
"FOLD_ARM",
192-
PlayMotion(motion_name="home"),
192+
PlayMotion(motion_name="cml_arm_away"),
193193
transitions={
194194
"succeeded": "succeeded",
195195
"aborted": "failed",

tasks/carry_my_luggage/launch/setup.launch

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@
1919
<rosparam command="load" file="$(find lasr_skills)/config/motions.yaml"/>
2020

2121
<!-- PERCEPTION -->
22-
<include file="$(find lasr_vision_yolov8)/launch/service.launch" />
22+
<!-- <include file="$(find lasr_vision_yolov8)/launch/service.launch" />-->
2323
<include file="$(find lasr_vision_cropped_detection)/launch/cropped_detection.launch"/>
2424
<include file="$(find lasr_vision_bodypix)/launch/bodypix.launch">
2525
<param name="preload" type="yaml" value='resnet50' />
2626
</include>
27+
28+
<!-- NAVIGATION -->
29+
<include file="$(find lasr_person_following)/launch/person_following.launch" />
30+
2731
</launch>

0 commit comments

Comments
 (0)