6 from smach
import State,StateMachine
7 from move_base_msgs.msg
import MoveBaseAction, MoveBaseGoal
8 from geometry_msgs.msg
import PoseWithCovarianceStamped, PoseArray ,PointStamped
9 from std_msgs.msg
import Empty
10 from tf
import TransformListener
16 from geometry_msgs.msg
import PoseStamped
20 if waypoint.header.frame_id == target_frame:
23 if not hasattr(changePose,
'listener'):
24 changePose.listener = tf.TransformListener()
26 tmp.header.frame_id = waypoint.header.frame_id
27 tmp.pose = waypoint.pose.pose
29 changePose.listener.waitForTransform(
30 target_frame, tmp.header.frame_id, rospy.Time(0), rospy.Duration(3.0))
31 pose = changePose.listener.transformPose(target_frame, tmp)
32 ret = PoseWithCovarianceStamped()
33 ret.header.frame_id = target_frame
34 ret.pose.pose = pose.pose
37 rospy.loginfo(
"CAN'T TRANSFORM POSE TO {} FRAME".format(target_frame))
42 output_file_path = rospkg.RosPack().get_path(
'follow_waypoints')+
"/saved_path/pose.csv" 47 State.__init__(self, outcomes=[
'success'], input_keys=[
'waypoints'])
48 self.
frame_id = rospy.get_param(
'~goal_frame_id',
'map')
51 self.
duration = rospy.get_param(
'~wait_duration', 0.0)
54 rospy.loginfo(
'Connecting to move_base...')
55 self.client.wait_for_server()
56 rospy.loginfo(
'Connected to move_base.')
57 rospy.loginfo(
'Starting a tf listner.')
58 self.
tf = TransformListener()
65 for waypoint
in waypoints:
68 rospy.loginfo(
'The waypoint queue has been reset.')
72 goal.target_pose.header.frame_id = self.
frame_id 73 goal.target_pose.pose.position = waypoint.pose.pose.position
74 goal.target_pose.pose.orientation = waypoint.pose.pose.orientation
75 rospy.loginfo(
'Executing move_base goal to position (x,y): %s, %s' %
76 (waypoint.pose.pose.position.x, waypoint.pose.pose.position.y))
77 rospy.loginfo(
"To cancel the goal: 'rostopic pub -1 /move_base/cancel actionlib_msgs/GoalID -- {}'")
78 self.client.send_goal(goal)
80 self.client.wait_for_result()
81 rospy.loginfo(
"Waiting for %f sec..." % self.
duration)
87 now = rospy.Time.now()
90 distance = math.sqrt(pow(waypoint.pose.pose.position.x-trans[0],2)+pow(waypoint.pose.pose.position.y-trans[1],2))
94 """Used to publish waypoints as pose array so that you can see them in rviz, etc.""" 96 poses.header.frame_id = rospy.get_param(
'~goal_frame_id',
'map')
97 poses.poses = [pose.pose.pose
for pose
in waypoints]
102 State.__init__(self, outcomes=[
'success'], input_keys=[
'waypoints'], output_keys=[
'waypoints'])
110 def wait_for_path_reset():
111 """thread worker function""" 113 while not rospy.is_shutdown():
114 data = rospy.wait_for_message(
'/path_reset', Empty)
115 rospy.loginfo(
'Recieved path RESET message')
120 reset_thread = threading.Thread(target=wait_for_path_reset)
136 def wait_for_path_ready():
137 """thread worker function""" 138 data = rospy.wait_for_message(
'/path_ready', Empty)
139 rospy.loginfo(
'Recieved path READY message')
141 with open(output_file_path,
'w')
as file:
142 for current_pose
in waypoints:
143 file.write(str(current_pose.pose.pose.position.x) +
',' + str(current_pose.pose.pose.position.y) +
',' + str(current_pose.pose.pose.position.z) +
',' + str(current_pose.pose.pose.orientation.x) +
',' + str(current_pose.pose.pose.orientation.y) +
',' + str(current_pose.pose.pose.orientation.z) +
',' + str(current_pose.pose.pose.orientation.w)+
'\n')
144 rospy.loginfo(
'poses written to '+ output_file_path)
145 ready_thread = threading.Thread(target=wait_for_path_ready)
152 def wait_for_start_journey():
153 """thread worker function""" 154 data_from_start_journey = rospy.wait_for_message(
'start_journey', Empty)
155 rospy.loginfo(
'Recieved path READY start_journey')
156 with open(output_file_path,
'r') as file: 157 reader = csv.reader(file, delimiter = ',')
160 current_pose = PoseWithCovarianceStamped()
161 current_pose.pose.pose.position.x = float(row[0])
162 current_pose.pose.pose.position.y = float(row[1])
163 current_pose.pose.pose.position.z = float(row[2])
164 current_pose.pose.pose.orientation.x = float(row[3])
165 current_pose.pose.pose.orientation.y = float(row[4])
166 current_pose.pose.pose.orientation.z = float(row[5])
167 current_pose.pose.pose.orientation.w = float(row[6])
168 waypoints.append(current_pose)
173 start_journey_thread = threading.Thread(target=wait_for_start_journey)
174 start_journey_thread.start()
177 rospy.loginfo(
"Waiting to recieve waypoints via Pose msg on topic %s" % topic)
178 rospy.loginfo(
"To start following waypoints: 'rostopic pub /path_ready std_msgs/Empty -1'")
180 rospy.loginfo(
"To start following saved waypoints: 'rostopic pub /start_journey std_msgs/Empty -1'")
186 pose = rospy.wait_for_message(topic, PoseWithCovarianceStamped, timeout=1)
187 except rospy.ROSException
as e:
188 if 'timeout exceeded' in e.message:
192 rospy.loginfo(
"Recieved new waypoint")
202 State.__init__(self, outcomes=[
'success'])
205 rospy.loginfo(
'###############################')
206 rospy.loginfo(
'##### REACHED FINISH GATE #####')
207 rospy.loginfo(
'###############################')
211 rospy.init_node(
'follow_waypoints')
213 sm = StateMachine(outcomes=[
'success'])
216 StateMachine.add(
'GET_PATH',
GetPath(),
217 transitions={
'success':
'FOLLOW_PATH'},
218 remapping={
'waypoints':
'waypoints'})
220 transitions={
'success':
'PATH_COMPLETE'},
221 remapping={
'waypoints':
'waypoints'})
223 transitions={
'success':
'GET_PATH'})
225 outcome = sm.execute()
def execute(self, userdata)
def convert_PoseWithCovArray_to_PoseArray(waypoints)
def initialize_path_queue(self)
def execute(self, userdata)
def changePose(waypoint, target_frame)
def execute(self, userdata)