leader_follower.cpp
Go to the documentation of this file.
1 /**************************************************************************************************
2  Software License Agreement (BSD License)
3 
4  Copyright (c) 2011-2013, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without modification, are permitted
8  provided that the following conditions are met:
9 
10  *Redistributions of source code must retain the above copyright notice, this list of
11  conditions and the following disclaimer.
12  *Redistributions in binary form must reproduce the above copyright notice, this list of
13  conditions and the following disclaimer in the documentation and/or other materials provided
14  with the distribution.
15  *Neither the name of the University of Aveiro nor the names of its contributors may be used to
16  endorse or promote products derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ***************************************************************************************************/
27 #include "ros/ros.h"
28 #include "tf/tf.h"
29 #include "leader_follower.h"
30 
31 #define DEG2RAD 0.01745
32 
33 
34 
35 /*******
36 this node manages the choice of a leader and how the robot should follow it
37 ********/
38 
39 void target_pose_callback(const nav_msgs::Odometry::ConstPtr& msg){
40  double distance_from_target = 2.0;
41  double orientation = tf::getYaw(msg->pose.pose.orientation) + 1.57;
42  double x_position = -msg->pose.pose.position.y - cos(orientation)*distance_from_target;
43  double y_position = msg->pose.pose.position.x - sin(orientation)*distance_from_target;
44 
45  ROS_INFO("x pos:%f, y pos:%f",x_position,y_position);
46 
47  goal.target_pose.header.frame_id = "/map";
48  goal.target_pose.header.stamp = ros::Time::now();
49 
50  goal.target_pose.pose.position.x = x_position;//goal.target_pose.pose.position.x + 0.1;//-msg->pose.pose.position.y;
51  goal.target_pose.pose.position.y = y_position;//goal.target_pose.pose.position.y + 0.1;//msg->pose.pose.position.x;
52  goal.target_pose.pose.orientation = tf::createQuaternionMsgFromYaw(orientation);
53 
54 }
55 
57 
59  // candidate_[dyn_objects->object_id] = *dyn_objects;
60  // ROS_INFO("received dyn_objects id:%d",dyn_objects->object_id);
63  if(leader_id == dyn_objects->object_id && start_to_follow){
64  if(leader_path.poses.size() > 0){
65  //ROS_INFO("msg stamp:%d",dyn_objects->header.stamp.toSec());
66  //ROS_INFO("last path stamp:%d",leader_path.poses.back().header.stamp.toSec());
67  tlast = leader_path.poses.back().header.stamp.toSec();
68  tnow = ros::Time::now().toSec();
69  d = tnow - tlast;
70  //ROS_INFO("elapsed time: %d",d);
72  if(d > 2.0){
73  leader_pose.pose.position.x = dyn_objects->pose.x;
74  leader_pose.pose.position.y = dyn_objects->pose.y;
75  leader_pose.pose.orientation = tf::createQuaternionMsgFromYaw(dyn_objects->pose.theta + 1.57);
76  leader_pose.header.stamp = ros::Time::now();
77  leader_path.poses.push_back(leader_pose);
78  }
79  }
80  else{
82  path_initialized = true;
83  leader_pose.pose.position.x = dyn_objects->pose.x;
84  leader_pose.pose.position.y = dyn_objects->pose.y;
85  leader_pose.pose.orientation = tf::createQuaternionMsgFromYaw(dyn_objects->pose.theta + 1.57);
86  leader_pose.header.stamp = ros::Time::now();
87  leader_path.poses.push_back(leader_pose);
88  }
89 
91  // try{
92  // listener->waitForTransform("/robot_0/base_link", "/Hiro", ros::Time(0), ros::Duration(10.0));
93  // listener->lookupTransform("/robot_0/base_link", "/Hiro", ros::Time(0), transform);
94  // // listener->lookupTransform("/robot_0/base_link", "/Hiro", ros::Time::now()/*(0)*/, transform);
95  // // no_track_error=false;
96  // }
97  // catch (tf::TransformException ex){
98  // // cmd_vel.angular.z = 0; //if the kinect loose traking of the person, stop the wheelchair.
99  // // cmd_vel.linear.x = 0;
100  // // no_track_error=true;
101  // ROS_ERROR("%s",ex.what());
102  // }
103 
104  // ROS_INFO("robotx:%f,roboty:%f,objx:%f,objy:%f",
105  // robot_pose.pose.pose.position.x, robot_pose.pose.pose.position.y,
106  // dyn_objects->pose.x, dyn_objects->pose.y);
107  //
108  // dist = euclidean_dist(
109  // robot_pose.pose.pose.position.x, robot_pose.pose.pose.position.y,
110  // dyn_objects->pose.x, dyn_objects->pose.y);
111  //
112  // theta = atan2(
113  // robot_pose.pose.pose.position.x - dyn_objects->pose.x,
114  // robot_pose.pose.pose.position.y - dyn_objects->pose.y);
115  //
116  // //controller part
117  // dist = sqrt(pow(transform.getOrigin().x(), 2) + pow(transform.getOrigin().y(), 2));
118  // theta = atan2(transform.getOrigin().y(),transform.getOrigin().x());
119  //
120  // ROS_INFO("distance:%f, theta:%f",dist,theta);
121  // if (dist>=dmin && dist<=dmax && theta>=-theta_max && theta<=theta_max)
122  // {
123  // cmd_vel.angular.z = 1.6 * (theta/theta_max) ;
124  // cmd_vel.linear.x = 1.2 * (dist-dmin)/(dmax-dmin);
125  // ROS_INFO("cmd ang:%f, cmd lin:%f",cmd_vel.angular.z,cmd_vel.linear.x);
126  // robot_cmd_vel.publish(cmd_vel);
127  // }
128  // else
129  // {
130  // cmd_vel.angular.z = 0;
131  // cmd_vel.linear.x = 0;
132  // }
133  }
134 }
135 
136 // void ar_pose_callback(const ar_pose::ARMarkers::ConstPtr& markers){
137 // //receives a list of marker and chooses a leader and send pose as goal
138 // // num_markers = markers->markers.size();
139 //
140 // num_markers = 1;
141 // // ROS_INFO("number of markers: [%d]", num_markers);
142 //
143 // for(int i=0; i< num_markers; i++){
144 //
145 // //feeding pose structure from ar_pose
146 // source_pose.header = markers->markers[i].header;
147 // source_pose.pose = markers->markers[i].pose.pose;
148 // marker_id = markers->markers[i].id;
149 //
150 // ROS_INFO("before listener");
151 // //transform pose to /map frame
152 // try{
153 // ros::Time now = ros::Time::now();
154 // listener->waitForTransform("/prosilica_optical_frame", "/map", source_pose.header.stamp, ros::Duration(10.0));
155 // // listener.waitForTransform("/usb_cam", "/map", source_pose.header.stamp, ros::Duration(10.0));
156 // listener->transformPose("/map",source_pose,target_pose);
157 // }
158 // catch (tf::TransformException ex) {
159 // ROS_ERROR("%s", ex.what());
160 // return;
161 // }
162 //
163 // goal.target_pose.header.frame_id = "/map";
164 // goal.target_pose.header.stamp = ros::Time::now();
165 // goal.target_pose.pose = target_pose.pose;
166 // }
167 // }
168 
169 void leader_goal_callback(const geometry_msgs::PoseStamped::ConstPtr & msg){
170 // ROS_INFO("got leader goal pose");
171 // leader_goal = *msg;
172  int temp_id = msg->pose.position.z;
173  leader_goal[temp_id].pose = msg->pose;
174  leader_goal[temp_id].header = msg->header;
175 }
176 
177 void robot_goal_callback(const geometry_msgs::PoseStamped::ConstPtr & msg){
178 // ROS_INFO("got robot goal pose");
179 // robot_goal = *msg;
180  robot_goal.pose = msg->pose;
181  robot_goal.header = msg->header;
182 }
183 
184 void robot_pose_callback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr & msg){
185 // ROS_INFO("got robot pose");
186 // robot_pose = *msg;
187  robot_pose.pose = msg->pose;
188  robot_pose.header = msg->header;
189 }
190 
191 int main(int argc, char **argv)
192 {
193  ros::init(argc, argv, "leader_follower");
194  ros::NodeHandle n;
195 
196  //used in transformations
197  tf::TransformListener _listener;
198  listener = &_listener;
199 
200  //initialize leader_path
201  leader_path.header.stamp = ros::Time::now();
202  leader_path.header.frame_id = "/map";
203 
204  //tell the action client that we want to spin a thread by default
205 // MoveBaseClient ac("robot_0/move_base", true);
206 
207  //subscribers
208  // pose_subscriber = n.subscribe("/robot_1/base_pose_ground_truth", 15, &target_pose_callback);
209  // ar_pose_sub = n.subscribe("/ar_pose_marker", 15, &ar_pose_callback);
210  dyn_objects_subscriber = n.subscribe("dynamic_objects", 100, &dyn_objects_callback);
211  leader_goal_subscriber = n.subscribe("leader_goal_pose",10,&leader_goal_callback);
212  robot_goal_subscriber = n.subscribe("/robot_0/goal", 1, &robot_goal_callback);
213  robot_pose_subscriber = n.subscribe("/robot_0/amcl_pose", 1, &robot_pose_callback);
214 
215  //publishers
216  pathPublisher = n.advertise<nav_msgs::Path>("leader_path", 1);
217  robot_cmd_vel = n.advertise<geometry_msgs::Twist>("/robot_0/cmd_vel",1);
218  next_posePublisher = n.advertise<geometry_msgs::PoseStamped>("/robot_0/leader_next_pose", 1);
219 
220 //wait for the action server to come up
221 // while(!ac.waitForServer(ros::Duration(5.0))){
222 // ROS_INFO("Waiting for the move_base action server to come up");
223 // }
224 
225  //initialize struct
226  for(int i = 0; i < 4; i++){//number of markers
227  leader_goal[i].pose.position.x = 99;
228  leader_goal[i].pose.position.y = 99;
229  }
230 
231  ros::Rate loop_rate(10);
232 
233  while (ros::ok()){
234 
237  robot_pose.pose.pose.position.x,robot_pose.pose.pose.position.y,
238  robot_goal.pose.position.x,robot_goal.pose.position.y);
239 
241  if(leader_found){
243  leader_pose.pose.position.x,leader_pose.pose.position.y,
244  leader_goal[leader_id].pose.position.x,leader_goal[leader_id].pose.position.y);
245  }
246 // goals_distance = euclidean_dist(
247 // candidate_[i].pose.position.x,candidate_[i].pose.position.y,
248 // robot_goal.pose.position.x,robot_goal.pose.position.y);
249 
250 // ROS_INFO("goal distances, robot:%.1f, leader:%f.1",robot2goal_distance,leader2goal_distance);
252  for(int i = 0; i < 4; i++){//number of markers
254  leader_goal[i].pose.position.x,leader_goal[i].pose.position.y,
255  robot_goal.pose.position.x,robot_goal.pose.position.y);
256  ROS_INFO("candidate id:%d, goals:%f",i,goals_distance);
257 
259  //if(i == 0) goals_distance = 2;
260 
261  if(goals_distance < 3.0){
262 // //candidate is a leader
263  leader_found = true;
264  if(leader_id != i){
265  leader_id = i;
266  ROS_INFO("found new leader, id:%d",leader_id);
267  //using z coordinate to obtain id
268  path_initialized = false;
269  start_to_follow = false;
270  //initialize path structure
271  leader_path.header.stamp = ros::Time::now();
272  leader_path.header.frame_id = "/map";
273  leader_path.poses.clear();
274  }
275  //check if leader is closer to the goal than the robot is
276 // ROS_INFO("leader2goal dist: %f, robot2goal dist: %f", leader2goal_distance, robot2goal_distance);
277  if(/*leader2goal_distance > 1.0 && leader2goal_distance < 1.0*robot2goal_distance*/true){
278  ROS_INFO("leader %d is closer, start to follow",leader_id);
279  start_to_follow = true;
280  }
281  break; //can skip candidate search as leader has been found
282  }
283  }
284 
285  //leader decision part
286 // if(goals_distance < 5.0){
287 // if(leader_found){
288 // //leader found
289 // if(leader_id != leader_goal.pose.position.z){ ///check if it is a new leader
290 // ROS_INFO("found leader, id:%d",leader_id);
291 // //using z coordinate to obtain id
292 // leader_id = leader_goal.pose.position.z;
293 // path_initialized = false;
294 // start_to_follow = false;
295 // //initialize path structure
296 // leader_path.header.stamp = ros::Time::now();
297 // leader_path.header.frame_id = "/map";
298 // leader_path.poses.clear();
299 // }
300 // //check if leader is closer to the goal than the robot is
301 // ROS_INFO("leader2goal dist: %f, robot2goal dist: %f", leader2goal_distance, robot2goal_distance);
302 // if(leader2goal_distance > 1.0 && leader2goal_distance < 1.0*robot2goal_distance){
303 // ROS_INFO("leader is closer, start to follow");
304 // start_to_follow = true;
305 // }
306 // }
307 
308  if(path_initialized){
309  if(send_goal){
311  goal.target_pose.header.frame_id = "/map";
312  goal.target_pose.header.stamp = ros::Time::now();
313  goal.target_pose.pose.position.x = leader_path.poses[0].pose.position.x;
314  goal.target_pose.pose.position.y = leader_path.poses[0].pose.position.y;
315  goal.target_pose.pose.orientation = leader_path.poses[0].pose.orientation;
316 
318  next_pose.header.frame_id = "/map";
319  next_pose.header.stamp = ros::Time::now();
320  next_pose.pose = goal.target_pose.pose;
321  next_posePublisher.publish(next_pose);
322 
323  ROS_INFO("Sending goal");
324  // ac.sendGoal(goal);
325  send_goal = false;
326  }
327 
328 // ROS_INFO("robotx:%f,roboty:%f,goalx:%f,goaly:%f",
329 // robot_pose.pose.pose.position.x, robot_pose.pose.pose.position.y,
330 // leader_path.poses[0].pose.position.x, leader_path.poses[0].pose.position.y);
331 
333  double distance_to_pose = euclidean_dist(
334  robot_pose.pose.pose.position.x, robot_pose.pose.pose.position.y,
335  goal.target_pose.pose.position.x, goal.target_pose.pose.position.y);
336 // ROS_INFO("ROBOT DISTANCE TO GOAL: %f", distance_to_pose);
337 
339 // if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED){
340  if(distance_to_pose < 2.0){
341  if(leader_path.poses.size() > 1){
342  leader_path.poses.erase(leader_path.poses.begin());
343  send_goal = true;
344  }
345  }
346  }
347 
348  pathPublisher.publish(leader_path);
349  ros::spinOnce();
350  loop_rate.sleep();
351 
352 
353  }
354  return 0;
355 }
356 
geometry_msgs::PoseStamped next_pose
geometry_msgs::PoseStamped robot_goal
move_base_msgs::MoveBaseGoal goal
void dyn_objects_callback(const trajectory_simulator::TrajectoryObservation::ConstPtr &dyn_objects)
uint leader_id
void target_pose_callback(const nav_msgs::Odometry::ConstPtr &msg)
bool leader_found
geometry_msgs::PoseWithCovarianceStamped robot_pose
ros::Subscriber dyn_objects_subscriber
void robot_pose_callback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &msg)
void robot_goal_callback(const geometry_msgs::PoseStamped::ConstPtr &msg)
nav_msgs::Path leader_path
ros::Subscriber robot_goal_subscriber
ros::Subscriber leader_goal_subscriber
double tnow
double euclidean_dist(double x1, double y1, double x2, double y2)
Definition: ar_human_proc.h:64
double leader2goal_distance
tf::TransformListener * listener
geometry_msgs::PoseStamped leader_pose
double d
int main(int argc, char **argv)
ros::Publisher robot_cmd_vel
boost::shared_ptr< ::trajectory_simulator::TrajectoryObservation_< ContainerAllocator > const > ConstPtr
double robot2goal_distance
geometry_msgs::PoseStamped leader_goal[4]
ros::Subscriber robot_pose_subscriber
void leader_goal_callback(const geometry_msgs::PoseStamped::ConstPtr &msg)
ros::Publisher pathPublisher
bool send_goal
bool start_to_follow
ros::Publisher next_posePublisher
double goals_distance
bool path_initialized
double tlast


leader_follower
Author(s): Procopio Silveira Stein
autogenerated on Mon Mar 2 2015 01:32:08