orca.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is based on the Agent.cpp form the RVO2 library. See original copyright information below.
00003  */
00004 
00005 
00006 /*
00007  *  Agent.cpp
00008  *  RVO2 Library.
00009  *
00010  *
00011  *  Copyright (C) 2008-10 University of North Carolina at Chapel Hill.
00012  *  All rights reserved.
00013  *
00014  *  Permission to use, copy, modify, and distribute this software and its
00015  *  documentation for educational, research, and non-profit purposes, without
00016  *  fee, and without a written agreement is hereby granted, provided that the
00017  *  above copyright notice, this paragraph, and the following four paragraphs
00018  *  appear in all copies.
00019  *
00020  *  Permission to incorporate this software into commercial products may be
00021  *  obtained by contacting the University of North Carolina at Chapel Hill.
00022  *
00023  *  This software program and documentation are copyrighted by the University of
00024  *  North Carolina at Chapel Hill. The software program and documentation are
00025  *  supplied "as is", without any accompanying services from the University of
00026  *  North Carolina at Chapel Hill or the authors. The University of North
00027  *  Carolina at Chapel Hill and the authors do not warrant that the operation of
00028  *  the program will be uninterrupted or error-free. The end-user understands
00029  *  that the program was developed for research purposes and is advised not to
00030  *  rely exclusively on the program for any reason.
00031  *
00032  *  IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR ITS
00033  *  EMPLOYEES OR THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
00034  *  SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
00035  *  ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
00036  *  UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED
00037  *  OF THE POSSIBILITY OF SUCH DAMAGE.
00038  *
00039  *  THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
00040  *  DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00041  *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
00042  *  STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS
00043  *  ON AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND
00044  *  THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
00045  *  ENHANCEMENTS, OR MODIFICATIONS.
00046  *
00047  *  Please send all BUG REPORTS to:
00048  *
00049  *  geom@cs.unc.edu
00050  *
00051  *  The authors may be contacted via:
00052  *
00053  *  Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, and
00054  *  Dinesh Manocha
00055  *  Dept. of Computer Science
00056  *  Frederick P. Brooks Jr. Computer Science Bldg.
00057  *  3175 University of N.C.
00058  *  Chapel Hill, N.C. 27599-3175
00059  *  United States of America
00060  *
00061  *  http://gamma.cs.unc.edu/RVO2/
00062  *
00063  */
00064 
00065 #include "collvoid_local_planner/orca.h"
00066 
00067 namespace collvoid{
00068 
00069 
00070   Line createOrcaLine(Agent* me, Agent* other, double trunc_time, double timestep, double left_pref, double cur_allowed_error){
00071 
00072     Vector2 relativePosition = other->getPosition() - me->getPosition();
00073     double combinedRadius = me->getRadius() + other->getRadius();// - cur_allowed_error_; //why al
00074 
00075     return createOrcaLine(combinedRadius, relativePosition, me->getVelocity(), other->getVelocity(),trunc_time, timestep, left_pref, cur_allowed_error, other->controlled_);
00076   }  
00077   
00078   Line createOrcaLine(double combinedRadius, const Vector2& relativePosition, const Vector2& me_vel, const Vector2& other_vel, double trunc_time, double timestep, double left_pref, double cur_allowed_error, bool controlled){
00079 
00080     double invTimeHorizon = 1.0f / trunc_time;
00081     if (collvoid::abs(other_vel) < EPSILON){
00082       invTimeHorizon = 1.0f / 2.0;
00083       //      return createStationaryAgent(me, other);
00084     }
00085     
00086 
00087     //const Vector2 relativePosition = other->getPosition() - me->getPosition();
00088     const Vector2 relativeVelocity = me_vel - other_vel;
00089     const double distSq = absSqr(relativePosition);
00090     //double combinedRadius = me->getRadius() + other->getRadius();// - cur_allowed_error_; //why allowed_error???
00091     double combinedRadiusSq = sqr(combinedRadius);
00092 
00093     Line line;
00094     Vector2 u;
00095 
00096     if (distSq > combinedRadiusSq) {
00097       combinedRadius += cur_allowed_error; //TODO Does this work? Maybe add uncertainty here
00098       combinedRadiusSq = sqr(combinedRadius);
00099       /* No collision. */
00100       const Vector2 w = relativeVelocity - invTimeHorizon * relativePosition;
00101       /* Vector from cutoff center to relative velocity. */
00102       const double wLengthSq = absSqr(w);
00103 
00104       const double dotProduct1 = w * relativePosition;
00105 
00106       if (dotProduct1 < 0.0f && sqr(dotProduct1) > combinedRadiusSq * wLengthSq) {
00107         /* Project on cut-off circle. */
00108         const double wLength = std::sqrt(wLengthSq);
00109         const Vector2 unitW = w / wLength;
00110 
00111         line.dir = Vector2(unitW.y(), -unitW.x());
00112         u = (combinedRadius * invTimeHorizon - wLength) * unitW;
00113       } else {
00114         /* Project on legs. */
00115         const double leg = std::sqrt(distSq - combinedRadiusSq);
00116 
00117         if (det(relativePosition, w) > -left_pref) { //define left_pref
00118           /* Project on left leg. */
00119           line.dir = Vector2(relativePosition.x() * leg - relativePosition.y() * combinedRadius, relativePosition.x() * combinedRadius + relativePosition.y() * leg) / distSq;
00120         } else {
00121           /* Project on right leg. */
00122           line.dir = -Vector2(relativePosition.x() * leg + relativePosition.y() * combinedRadius, -relativePosition.x() * combinedRadius + relativePosition.y() * leg) / distSq;
00123         }
00124 
00125         const double dotProduct2 = relativeVelocity * line.dir;
00126 
00127         u = dotProduct2 * line.dir - relativeVelocity;
00128       }
00129     } else {
00130       /* Collision. Project on cut-off circle of time timeStep. */
00131       const double invTimeStep = 1.0f/timestep;
00132       /* Vector from cutoff center to relative velocity. */
00133       const Vector2 w = relativeVelocity - invTimeStep * relativePosition;
00134 
00135       const double wLength = abs(w);
00136       const Vector2 unitW = w / wLength;
00137       //ROS_ERROR("collision");
00138       line.dir = Vector2(unitW.y(), -unitW.x());
00139       u = (combinedRadius * invTimeStep - wLength) * unitW;
00140     }
00141 
00142     double factor = 0.5;
00143     if (!controlled) {
00144       factor = 1.0;
00145     }
00146     line.point = me_vel + factor * u;
00147     //ROS_ERROR("%s = line: (%f,%f), dir (%f,%f)",nh.getNamespace().c_str(),line.point.x(),line.point.y(),line.dir.x(),line.dir.y());
00148     return line;
00149   }
00150 
00151   Line createStationaryAgent(Agent* me, Agent* other) {
00152     double dist = collvoid::abs(me->getPosition() - other->getPosition());
00153     Line line;
00154     Vector2 relative_position = other->getPosition() - me->getPosition();
00155     line.point = normalize(relative_position) * (dist - me->getRadius() - other->getRadius() - 0.05);// TODO 5 cm security
00156 
00157     line.dir = Vector2 (-normalize(relative_position).y(),normalize(relative_position).x()) ; 
00158     
00159     return line;
00160   
00161   }
00162 
00163 
00164   void addAccelerationConstraintsXY(double max_vel_x, double acc_lim_x, double max_vel_y, double acc_lim_y, Vector2 cur_vel, double heading, double sim_period, bool holo_robot, std::vector<Line>& additional_orca_lines){
00165     double max_lim_x, max_lim_y, min_lim_x, min_lim_y;
00166     Line line_x_back, line_x_front, line_y_left, line_y_right;
00167   
00168     Vector2 dir_front =  Vector2(cos(heading), sin(heading));
00169     Vector2 dir_right =  Vector2(dir_front.y(),-dir_front.x());
00170     if(holo_robot) {
00171 
00172       cur_vel = rotateVectorByAngle(cur_vel.x(), cur_vel.y(), -heading);
00173 
00174       double cur_x = cur_vel.x();
00175       double cur_y = cur_vel.y();
00176 
00177       
00178       max_lim_x = std::min(max_vel_x, cur_x + sim_period * acc_lim_x);
00179       max_lim_y = std::min(max_vel_y, cur_y + sim_period * acc_lim_y);
00180       min_lim_x = std::max(-max_vel_x, cur_x - sim_period * acc_lim_x);
00181       min_lim_y = std::max(-max_vel_y, cur_y - sim_period * acc_lim_y);
00182 
00183       //      ROS_ERROR("Cur cvel (%f, %f) Max limints x = %f, %f, y = %f, %f", cur_x, cur_y, max_lim_x, min_lim_x, max_lim_y, min_lim_y);
00184 
00185       line_x_front.point = dir_front * max_lim_x;
00186       line_x_front.dir =  -dir_right;
00187 
00188       line_x_back.point = dir_front * min_lim_x;
00189       line_x_back.dir = dir_right;
00190   
00191   
00192       additional_orca_lines.push_back(line_x_front);
00193       additional_orca_lines.push_back(line_x_back);
00194   
00195       line_y_left.point = -dir_right * max_lim_y;
00196       line_y_left.dir = -dir_front;
00197 
00198       line_y_right.point = -dir_right * min_lim_y;
00199       line_y_right.dir = dir_front;
00200   
00201   
00202       additional_orca_lines.push_back(line_y_left);
00203       additional_orca_lines.push_back(line_y_right);
00204     }
00205     else {
00206 
00207       double cur_x = collvoid::abs(cur_vel);
00208       max_lim_x = std::min(max_vel_x, cur_x + sim_period * acc_lim_x);
00209       min_lim_x = std::max(-max_vel_x, cur_x - sim_period * acc_lim_x);
00210 
00211       line_x_front.point = dir_front * max_lim_x;
00212       line_x_front.dir =  -dir_right;
00213       
00214       line_x_back.point = dir_front * min_lim_x;
00215       line_x_back.dir = dir_right;
00216   
00217       //ROS_ERROR("Max limints x = %f, %f", max_lim_x, min_lim_x); 
00218       additional_orca_lines.push_back(line_x_front);
00219       additional_orca_lines.push_back(line_x_back);
00220   
00221      
00222     }
00223   }
00224   
00225   void addMovementConstraintsDiffSimple(double max_track_speed, double heading, std::vector<Line>& additional_orca_lines) {
00226     Line maxVel1;
00227     Line maxVel2;
00228 
00229     Vector2 dir =  Vector2(cos(heading), sin(heading));
00230     maxVel1.point = 0.95*max_track_speed * Vector2(-dir.y(),dir.x());
00231     maxVel1.dir = -dir;
00232     maxVel2.dir = dir;
00233     maxVel2.point = -max_track_speed * Vector2(-dir.y(),dir.x());
00234     additional_orca_lines.push_back(maxVel1);
00235     additional_orca_lines.push_back(maxVel2);
00236     // Line line;
00237     // line.point = -2*max_track_speed * Vector2(cos(heading), sin(heading));
00238     // line.dir = normalize(maxVel2.point);
00239     // additional_orca_lines.push_back(line);
00240     // Line line2;
00241     // line2.point = 10*max_track_speed * Vector2(cos(heading), sin(heading));
00242     // line2.dir = rotateVectorByAngle(-normalize(maxVel2.point), -0.2);
00243     // additional_orca_lines.push_back(line2);
00244     // Line line3;
00245     // line3.point = 10*max_track_speed * Vector2(cos(heading), sin(heading));
00246     // line3.dir = rotateVectorByAngle(-normalize(maxVel2.point), 0.2);
00247     // additional_orca_lines.push_back(line3);
00248 
00249 
00250   }
00251 
00252   void addMovementConstraintsDiff(double error, double T,  double max_vel_x, double max_vel_th, double heading, double v_max_ang, std::vector<Line>& additional_orca_lines){
00253     
00254     // double steps2 = 180;
00255     // std::cout << error<< std::endl;
00256     // for (double i = -M_PI / 2.0; i <= M_PI / 2.0; i += M_PI/steps2) {
00257     //   double speed = calculateMaxTrackSpeedAngle(T,i, error, max_vel_x, max_vel_th, v_max_ang);
00258     //   //double vstarErr = calcVstarError(T,i,0.01);
00259     //   std::cout << speed*cos(i) << "," << speed * sin(i) << ";";
00260     //   //std::cout << speed << " vstar Err " << vstarErr <<" ang " << i <<std::endl;
00261     // }
00262     // std::cout << std::endl;
00263 
00264     // for (double i = -M_PI / 2.0; i <= M_PI / 2.0; i += M_PI/steps2) {
00265     //   double speed = calculateMaxTrackSpeedAngle(T,i, error, max_vel_x, max_vel_th, v_max_ang);
00266     //   std::cout << speed << "," << i << std::endl;
00267     // }
00268     // std::cout << std::endl;
00269 
00270 
00271     double min_theta = M_PI / 2.0;
00272     double max_track_speed = calculateMaxTrackSpeedAngle(T,min_theta, error, max_vel_x, max_vel_th, v_max_ang);
00273 
00274     Vector2 first_point = max_track_speed * Vector2(cos(heading - min_theta), sin(heading - min_theta));
00275     double steps = 10.0;
00276     double step_size = - M_PI / steps;
00277     // Line line;
00278     // line.point = -max_track_speed * Vector2(cos(heading), sin(heading));
00279     // line.dir = normalize(first_point);
00280     // additional_orca_lines.push_back(line);
00281 
00282 
00283     for (int i=1; i<=(int)steps; i++) {
00284     
00285       Line line;
00286       double cur_ang = min_theta + i* step_size;
00287       Vector2 second_point = Vector2(cos(heading - cur_ang), sin(heading - cur_ang));
00288       double track_speed = calculateMaxTrackSpeedAngle(T,cur_ang, error, max_vel_x, max_vel_th, v_max_ang);
00289       second_point = track_speed * second_point;
00290       line.point = first_point;
00291       line.dir = normalize(second_point - first_point);
00292       additional_orca_lines.push_back(line);
00293       //    ROS_DEBUG("line point 1 x, y, %f, %f, point 2 = %f,%f",first_point.x(),first_point.y(),second_point.x(),second_point.y());
00294       first_point = second_point;
00295     }
00296   }
00297 
00298   double beta(double T, double theta, double v_max_ang){
00299     return - ((2.0 * T * T * sin(theta)) / theta) * v_max_ang;
00300   }
00301 
00302   double gamma(double T, double theta, double error, double v_max_ang) {
00303     return ((2.0 * T * T * (1.0 - cos(theta))) / (theta * theta)) * v_max_ang * v_max_ang - error * error;
00304   }
00305 
00306   double calcVstar(double vh, double theta){
00307     return vh * ((theta * sin(theta))/(2.0 * (1.0 - cos(theta))));
00308   }
00309 
00310   double calcVstarError(double T,double theta, double error) {
00311     return calcVstar(error/T,theta) * sqrt((2.0*(1.0-cos(theta)))/(2.0*(1.0-cos(theta))-collvoid::sqr(sin(theta))));
00312   }
00313 
00314   double calculateMaxTrackSpeedAngle(double T, double theta, double error, double max_vel_x, double max_vel_th, double v_max_ang){
00315     if (fabs(theta) <= EPSILON)
00316       return max_vel_x;
00317     if (fabs(theta/T) <= max_vel_th) {
00318       double vstar_error = calcVstarError(T,theta,error);
00319       if (vstar_error <= v_max_ang) { 
00320         //return 0;
00321         return std::min(vstar_error * (2.0 * (1.0 - cos(theta))) / (theta*sin(theta)),max_vel_x);
00322       }
00323       else {
00324         double a, b, g;
00325         a = T * T;
00326         b = beta(T,theta,v_max_ang);
00327         g = gamma(T,theta,error, v_max_ang);
00328         //return 1;
00329         return std::min((-b+sqrt(collvoid::sqr(b)-4*collvoid::sqr(a)*g))/ (2.0 * g), max_vel_x);
00330       }
00331     }
00332     else
00333       //  return 2;
00334       return std::min(sign(theta)*error*max_vel_th/theta,max_vel_x);
00335   }
00336 
00337 
00338 
00339   
00340 
00341   bool linearProgram1(const std::vector<Line>& lines, size_t lineNo, float radius, const Vector2& optVelocity, bool dirOpt, Vector2& result)
00342   {
00343     const float dotProduct = lines[lineNo].point * lines[lineNo].dir;
00344     const float discriminant = sqr(dotProduct) + sqr(radius) - absSqr(lines[lineNo].point);
00345     
00346     if (discriminant < 0.0f) {
00347       /* Max speed circle fully invalidates line lineNo. */
00348       return false;
00349     }
00350     
00351     const float sqrtDiscriminant = std::sqrt(discriminant);
00352     float tLeft = -dotProduct - sqrtDiscriminant;
00353     float tRight = -dotProduct + sqrtDiscriminant;
00354     
00355     for (size_t i = 0; i < lineNo; ++i) {
00356       const float denominator = det(lines[lineNo].dir, lines[i].dir);
00357       const float numerator = det(lines[i].dir, lines[lineNo].point - lines[i].point);
00358 
00359       if (std::fabs(denominator) <= EPSILON) {
00360         /* Lines lineNo and i are (almost) parallel. */
00361         if (numerator < 0.0f) {
00362           return false;
00363         } else {
00364           continue;
00365         }
00366       }
00367 
00368       const float t = numerator / denominator;
00369 
00370       if (denominator >= 0.0f) {
00371         /* Line i bounds line lineNo on the right. */
00372         tRight = std::min(tRight, t);
00373       } else {
00374         /* Line i bounds line lineNo on the left. */
00375         tLeft = std::max(tLeft, t);
00376       }
00377 
00378       if (tLeft > tRight) {
00379         return false;
00380       }
00381     }
00382 
00383     if (dirOpt) {
00384       /* Optimize direction. */
00385       if (optVelocity * lines[lineNo].dir > 0.0f) {
00386         /* Take right extreme. */
00387         result = lines[lineNo].point + tRight * lines[lineNo].dir;
00388       } else {
00389         /* Take left extreme. */
00390         result = lines[lineNo].point + tLeft * lines[lineNo].dir;
00391       }
00392     } else {
00393       /* Optimize closest point. */
00394       const float t = lines[lineNo].dir * (optVelocity - lines[lineNo].point);
00395 
00396       if (t < tLeft) {
00397         result = lines[lineNo].point + tLeft * lines[lineNo].dir;
00398       } else if (t > tRight) {
00399         result = lines[lineNo].point + tRight * lines[lineNo].dir;
00400       } else {
00401         result = lines[lineNo].point + t * lines[lineNo].dir;
00402       }
00403     }
00404 
00405     return true;
00406   }
00407 
00408   size_t linearProgram2(const std::vector<Line>& lines, float radius, const Vector2& optVelocity, bool dirOpt, Vector2& result)
00409   {
00410     if (dirOpt) {
00411       /* 
00412        * Optimize direction. Note that the optimization velocity is of unit
00413        * length in this case.
00414        */
00415       result = optVelocity * radius;
00416     } else if (absSqr(optVelocity) > sqr(radius)) {
00417       /* Optimize closest point and outside circle. */
00418       result = normalize(optVelocity) * radius;
00419     } else {
00420       /* Optimize closest point and inside circle. */
00421       result = optVelocity;
00422     }
00423 
00424     for (size_t i = 0; i < lines.size(); ++i) {
00425       if (det(lines[i].dir, lines[i].point - result) > 0.0f) {
00426         /* Result does not satisfy constraint i. Compute new optimal result. */
00427         const Vector2 tempResult = result;
00428         if (!linearProgram1(lines, i, radius, optVelocity, dirOpt, result)) {
00429           result = tempResult;
00430           return i;
00431         }
00432       }
00433     }
00434 
00435     return lines.size();
00436   }
00437 
00438   void linearProgram3(const std::vector<Line>& lines, size_t numObstLines, size_t beginLine, float radius, Vector2& result)
00439   {
00440     float distance = 0.0f;
00441 
00442     for (size_t i = beginLine; i < lines.size(); ++i) {
00443       if (det(lines[i].dir, lines[i].point - result) > distance) {
00444         /* Result does not satisfy constraint of line i. */
00445         std::vector<Line> projLines(lines.begin(), lines.begin() + numObstLines);
00446 
00447         for (size_t j = numObstLines; j < i; ++j) {
00448           Line line;
00449 
00450           float determinant = det(lines[i].dir, lines[j].dir);
00451 
00452           if (std::fabs(determinant) <= EPSILON) {
00453             /* Line i and line j are parallel. */
00454             if (lines[i].dir * lines[j].dir > 0.0f) {
00455               /* Line i and line j point in the same direction. */
00456               continue;
00457             } else {
00458               /* Line i and line j point in opposite direction. */
00459               line.point = 0.5f * (lines[i].point + lines[j].point);
00460             }
00461           } else {
00462             line.point = lines[i].point + (det(lines[j].dir, lines[i].point - lines[j].point) / determinant) * lines[i].dir;
00463           }
00464 
00465           line.dir = normalize(lines[j].dir - lines[i].dir);
00466           projLines.push_back(line);
00467         }
00468 
00469         const Vector2 tempResult = result;
00470         if (linearProgram2(projLines, radius, Vector2(-lines[i].dir.y(), lines[i].dir.x()), true, result) < projLines.size()) {
00471           /* This should in principle not happen.  The result is by definition
00472            * already in the feasible region of this linear program. If it fails,
00473            * it is due to small floating point error, and the current result is
00474            * kept.
00475            */
00476           result = tempResult;
00477         }
00478 
00479         distance = det(lines[i].dir, lines[i].point - result);
00480       }
00481     }
00482   }
00483 
00484 
00485 
00486 
00487 }
00488 
00489   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


collvoid_local_planner
Author(s): Daniel Claes
autogenerated on Sun Aug 25 2013 10:10:23