/ru/navigation/trajectoryplanner.cpp

https://bitbucket.org/VladimirL/robotutils · C++ · 213 lines · 155 code · 30 blank · 28 comment · 35 complexity · ef98214e91554f52ed35544d28b0b1f7 MD5 · raw file

  1. #include "trajectoryplanner.h"
  2. bool isAngleBetweenTwoAngles(float angle, float start_angle, float end_angle)
  3. {
  4. bool angle_match = false;
  5. // ?? ???????
  6. if ((angle>=start_angle)&&(angle<=end_angle)) {
  7. angle_match = true;
  8. } else {
  9. angle_match = false;
  10. }
  11. return angle_match;
  12. }
  13. float TrajectoryElement::getDistanceToPoint(const RobotPosition &element_pos, const QPointF &point)
  14. {
  15. float result = 10000000.0f;
  16. if (type==ElementType_Line) {
  17. // ?????????? ?? ???????
  18. QPointF end_pos = getEndpointPosition(element_pos);
  19. QVector2D v1(point-element_pos);
  20. QVector2D v2(end_pos-element_pos);
  21. float product = QVector2D::dotProduct(v1,v2);
  22. QPointF p = QPointF(element_pos) + (end_pos-element_pos)*(product/v2.lengthSquared());
  23. float line_sign = sign(float(v1.x()*v2.y()-v1.y()*v2.x()));
  24. if ((product>=0.0)&&((product/v2.lengthSquared())<=1.0)) {
  25. // ????? ????? ??????
  26. result = line_sign*QVector2D(p-point).length();
  27. } else {
  28. // ????? ???????
  29. if (product<0) // ?????
  30. result = line_sign*QVector2D(element_pos-point).length();
  31. else // ??????
  32. result = line_sign*QVector2D(end_pos-point).length();
  33. }
  34. } else if (type==ElementType_Arc) {
  35. // ?????????? ?? ????
  36. // ?????????? ????? ??????????
  37. QPointF rot = getArcCenter(element_pos);
  38. // ??????? ????? ? ?????? ????????? ? rot
  39. QPointF pos = (point-rot);
  40. QPointF start_pos = (element_pos-rot);
  41. // ?????????? ????????? ???? ????
  42. float start_angle_offset = Angle(atan2(start_pos.y(), start_pos.x()));
  43. float start_angle = Angle(atan2(start_pos.y(), start_pos.x())-start_angle_offset).to2PIFormat();
  44. start_angle = 0;
  45. // ???????? ????
  46. float angle_wise = sign(angle)*sign(R);
  47. float end_angle = Angle(fabs(angle)).to2PIFormat();
  48. // ?????????? ???? ????? ?????? ? ???????
  49. float point_angle1 = 0;
  50. float point_angle2 = 0;
  51. if (angle_wise>0) {
  52. point_angle1 = PIx2-Angle(atan2(pos.y(), pos.x()) - start_angle_offset).to2PIFormat(); // ???? ?? ?????? ? ?????
  53. point_angle2 = PIx2-Angle(atan2(pos.y(), pos.x())+PI - start_angle_offset).to2PIFormat(); // ??????????????? ????
  54. } else {
  55. point_angle1 = Angle(atan2(pos.y(), pos.x()) - start_angle_offset).to2PIFormat(); // ???? ?? ?????? ? ?????
  56. point_angle2 = Angle(atan2(pos.y(), pos.x())+PI - start_angle_offset).to2PIFormat(); // ??????????????? ????
  57. }
  58. //qDebug()<<point_angle1;
  59. // ??????? ???????? ?? ??? ???? ? ????????
  60. bool angle_match_short = false;
  61. bool angle_match_long = false;
  62. if (fabs(angle)<PIx2) {
  63. //
  64. angle_match_long = isAngleBetweenTwoAngles(point_angle1, start_angle, end_angle);
  65. angle_match_short = isAngleBetweenTwoAngles(point_angle2, start_angle, end_angle);
  66. } else { // ???? ?????? ??? PI*2 ?? 100% ???????????
  67. angle_match_short = true;
  68. }
  69. //qDebug()<<angle_match_long;
  70. // ?????????? ??????????
  71. if (angle_match_short) {
  72. // ?????????? ?? ?????? - ??????
  73. result = R+angle_wise*QVector2D(pos).length();
  74. } else if (angle_match_long) { // ?????????? ?? ?????? + ??????
  75. result = R-angle_wise*QVector2D(pos).length();
  76. } else {
  77. // ????????? ?????????? ?? ????? ?? ???? ?????
  78. // ??? ?? ????????????
  79. }
  80. }
  81. return result;
  82. }
  83. RobotPosition TrajectoryElement::getEndpointPosition(const RobotPosition &start_pos)
  84. {
  85. RobotPosition pos;
  86. if (type==ElementType_Line) {
  87. pos.a = start_pos.a;
  88. pos.x = start_pos.x + line_length*cos(pos.a);
  89. pos.y = start_pos.y + line_length*sin(pos.a);
  90. } else if (type==ElementType_Arc) {
  91. pos.a = start_pos.a - angle*sign(R);
  92. // ????? ?????? ??????? ???????
  93. QPointF rot = getArcCenter(start_pos);
  94. //qDebug()<<rot;
  95. float an = -angle*sign(R);
  96. //qDebug()<<an;
  97. // ???????
  98. float tx = rot.x()+(start_pos.x-rot.x())*cos(an)-(start_pos.y-rot.y())*sin(an);
  99. float ty = rot.y()+(start_pos.x-rot.x())*sin(an)+(start_pos.y-rot.y())*cos(an);
  100. pos.x = tx;
  101. pos.y = ty;
  102. } else if (type==ElementType_Rotation) {
  103. pos.a = start_pos.a+angle;
  104. pos.x = start_pos.x;
  105. pos.y = start_pos.y;
  106. }
  107. pos.speed = endpoint_speed;
  108. return pos;
  109. }
  110. RobotPosition TrajectoryElement::interpolatePosition(const RobotPosition &start_pos, float value)
  111. {
  112. RobotPosition pos;
  113. if (type==ElementType_Line) {
  114. pos.a = start_pos.a;
  115. pos.x = start_pos.x + line_length*cos(pos.a)*value;
  116. pos.y = start_pos.y + line_length*sin(pos.a)*value;
  117. } else if (type==ElementType_Arc) {
  118. float an = -angle*sign(R)*value;
  119. pos.a = start_pos.a - an;
  120. // ????? ?????? ??????? ???????
  121. QPointF rot = getArcCenter(start_pos);
  122. //qDebug()<<rot;
  123. //qDebug()<<an;
  124. // ???????
  125. float tx = rot.x()+(start_pos.x-rot.x())*cos(an)-(start_pos.y-rot.y())*sin(an);
  126. float ty = rot.y()+(start_pos.x-rot.x())*sin(an)+(start_pos.y-rot.y())*cos(an);
  127. pos.x = tx;
  128. pos.y = ty;
  129. } else if (type==ElementType_Rotation) {
  130. pos.a = start_pos.a+angle*value;
  131. pos.x = start_pos.x;
  132. pos.y = start_pos.y;
  133. }
  134. pos.speed = startpoint_speed*(1.0-value)+endpoint_speed*value;
  135. return pos;
  136. }
  137. QPointF TrajectoryElement::getArcCenter(const RobotPosition &start_pos)
  138. {
  139. return QPointF(start_pos.x-R*cos(start_pos.a+PId2), start_pos.y-R*sin(start_pos.a+PId2));
  140. }
  141. float ITrajectoryPlanner::getTrajectoryLength(const Trajectory &trajectory)
  142. {
  143. float res = 0;
  144. for (int i=0; i<trajectory.size(); i++) {
  145. if (trajectory.elements[i].type==ElementType_Arc) {
  146. res += sqr((trajectory.elements[i].R * trajectory.elements[i].angle * 10.0f)); // ???? ????? ????????????????, ??? ??????, ??????? ??? ??????
  147. //res += abs(trajectory[i].R * trajectory[i].angle );
  148. } else
  149. if (trajectory.elements[i].type==ElementType_Line) {
  150. res += fabs(trajectory.elements[i].line_length);
  151. }
  152. }
  153. return res;
  154. }
  155. float TrajectoryElement::getElementLength()
  156. {
  157. if (type==ElementType_Line)
  158. return fabs(line_length);
  159. if (type==ElementType_Arc)
  160. return fabs(R*angle);
  161. return 0.0f;
  162. }
  163. float Trajectory::getDistanceToPoint(const RobotPosition &start_pos, const QPointF &point)
  164. {
  165. RobotPosition element_position = start_pos;
  166. int size = elements.size();
  167. float min_size = 10000000.0;
  168. for (int i=0; i<size; i++) {
  169. float dist = elements[i].getDistanceToPoint(element_position, point);
  170. if (fabs(dist)<fabs(min_size)) {
  171. min_size = dist;
  172. }
  173. element_position = elements[i].getEndpointPosition(element_position);
  174. //qDebug()<<QString("%1 %2;%3").arg(i).arg(element_position.x).arg(element_position.y);
  175. }
  176. return min_size;
  177. }
  178. void Trajectory::appendTrajectory(const Trajectory &trajectory)
  179. {
  180. for (int i=0; i<trajectory.size(); i++) {
  181. elements.push_back(trajectory.elements[i]);
  182. }
  183. }