forked from MiyagiRonin/auto_parking
-
Notifications
You must be signed in to change notification settings - Fork 0
/
line_circle_connection.cc
99 lines (88 loc) · 3.64 KB
/
line_circle_connection.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "line_circle_connection.h"
#include "apollo_math/math_utils.h"
using namespace apollo::common::math;
bool LineCircleLine(const Pose& start, double kappa, LineCirclePath* result) {
double start_x = start.pos.x();
double start_y = start.pos.y();
double start_theta = start.theta;
double start_sin_theta = start.dir.y();
double start_cos_theta = start.dir.x();
if(start_y < 0.0) return false;
if(start_x > 0.0 && start_theta > 0.5 * M_PI) return false;
if(start_x < 0.0 && start_theta < 0.5 * M_PI) return false;
//Symmetric transformation.
bool is_symmetric = false;
if(start_x < 0.0) {
start_x = -start_x;
start_theta = NormalizeAngle(M_PI - start_theta);
start_cos_theta = -start_cos_theta;
is_symmetric = true;
}
const double R = 1.0/kappa;
const double theta = 0.5 * M_PI - start_theta;
const double c = -theta * R;
const double delta_x = -2.0 * R * Square(std::sin(theta * 0.5));
const double delta_y = - R * std::sin(theta);
const double l1 = -(start_x + delta_x) / start_cos_theta;
const double l2 = -(start_y + l1 * start_sin_theta + delta_y);
if(c > 0.0 || l1 > 0.0) return false;
//Fill results.
result->start = start;
result->lengths = {l1, c, l2};
result->types = {'S', is_symmetric ? 'L' : 'R', 'S'};
result->kappas = {0.0, kappa, 0.0};
Pose end1 = {start.pos + l1 * start.dir, start.theta, start.dir};
Pose end2 = GetPoseAlongArc(end1, kappa, c, result->kappas[1]);
Pose end3 = {end2.pos + l2 * end2.dir, end2.theta, end2.dir};
result->ends = {end1, end2, end3};
return true;
}
bool LineCircleOrCircleLine(const Pose& start, const Pose& end, double max_kappa, LineCirclePath* result) {
// Transfer end to origin.
const double delta_x = start.pos.x() - end.pos.x();
const double delta_y = start.pos.y() - end.pos.y();
double x = delta_x * end.dir.x() + delta_y * end.dir.y();
double y = delta_y * end.dir.x() - delta_x * end.dir.y();
double theta = NormalizeAngle(start.theta - end.theta);
if (x < 0.0) return false;
if (y > 0.0 && theta > 0.5 * M_PI) return false;
if (y < 0.0 && theta < -0.5 * M_PI) return false;
// Symmetric transformation.
bool is_symmetric = false;
if (y < 0.0) {
y = -y;
theta = -theta;
is_symmetric = true;
}
const double l1 = x - y / std::tan(theta);
if (l1 < 0.0) return false;
const double l2 = y / std::sin(theta);
if (l1 < l2) {
//Line-Circle.
const double kappa = std::tan(0.5 * theta) / l1;
if(kappa > max_kappa) return false;
//Fill results.
result->start = start;
result->lengths = {l1-l2, -theta/kappa};
result->kappas = {0.0, kappa};
result->types = {'S', is_symmetric ? 'R' : 'L'};
Pose end1 = {start.pos + result->lengths[0] * start.dir, start.theta, start.dir};
Pose end2 = GetPoseAlongArc(end1, result->kappas[1], result->lengths[1], result->types[1]);
result->ends = {end1, end2};
return true;
} else {
// Circle-Line.
const double kappa = std::tan(0.5 * theta) / l2;
if (kappa > max_kappa) return false;
// Fill results.
result->start = start;
result->lengths = {-theta/kappa, l2 - l1};
result->kappas = {kappa, 0.0};
result->types = {is_symmetric ? 'R' : 'L', 'S'};
Pose end1 = GetPoseAlongArc(start, result->kappas[0], result->lengths[0], result->types[0]);
Pose end2 = {end1.pos + end1.dir* result->lengths[1], end1.theta, end1.dir};
result->ends = {end1, end2};
return true;
}
return false;
}