Apollo 10.0
自动驾驶开放平台
trajectory_analyzer.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <algorithm>
20#include <cmath>
21#include <utility>
22
23#include "Eigen/Core"
24
25#include "cyber/common/log.h"
30
33
34namespace apollo {
35namespace control {
36namespace {
37
38// Squared distance from the point to (x, y).
39double PointDistanceSquare(const TrajectoryPoint &point, const double x,
40 const double y) {
41 const double dx = point.path_point().x() - x;
42 const double dy = point.path_point().y() - y;
43 return dx * dx + dy * dy;
44}
45
46PathPoint TrajectoryPointToPathPoint(const TrajectoryPoint &point) {
47 if (point.has_path_point()) {
48 return point.path_point();
49 } else {
50 return PathPoint();
51 }
52}
53
54} // namespace
55
57 const planning::ADCTrajectory *planning_published_trajectory) {
58 header_time_ = planning_published_trajectory->header().timestamp_sec();
59 seq_num_ = planning_published_trajectory->header().sequence_num();
60
61 for (int i = 0; i < planning_published_trajectory->trajectory_point_size();
62 ++i) {
63 trajectory_points_.push_back(
64 planning_published_trajectory->trajectory_point(i));
65 auto *path_point = trajectory_points_.back().mutable_path_point();
66 if (!path_point->has_z()) {
67 path_point->set_z(0.0);
68 }
69 }
70}
71
73 const double y) const {
74 CHECK_GT(trajectory_points_.size(), 0U);
75
76 double d_min = PointDistanceSquare(trajectory_points_.front(), x, y);
77 size_t index_min = 0;
78
79 for (size_t i = 1; i < trajectory_points_.size(); ++i) {
80 double d_temp = PointDistanceSquare(trajectory_points_[i], x, y);
81 if (d_temp < d_min) {
82 d_min = d_temp;
83 index_min = i;
84 }
85 }
86
87 size_t index_start = index_min == 0 ? index_min : index_min - 1;
88 size_t index_end =
89 index_min + 1 == trajectory_points_.size() ? index_min : index_min + 1;
90
91 const double kEpsilon = 0.001;
92 if (index_start == index_end ||
93 std::fabs(trajectory_points_[index_start].path_point().s() -
94 trajectory_points_[index_end].path_point().s()) <= kEpsilon) {
95 return TrajectoryPointToPathPoint(trajectory_points_[index_start]);
96 }
97
98 return FindMinDistancePoint(trajectory_points_[index_start],
99 trajectory_points_[index_end], x, y);
100}
101
102// reference: Optimal trajectory generation for dynamic street scenarios in a
103// Frenét Frame,
104// Moritz Werling, Julius Ziegler, Sören Kammel and Sebastian Thrun, ICRA 2010
105// similar to the method in this paper without the assumption the "normal"
106// vector
107// (from vehicle position to ref_point position) and reference heading are
108// perpendicular.
109void TrajectoryAnalyzer::ToTrajectoryFrame(const double x, const double y,
110 const double theta, const double v,
111 const PathPoint &ref_point,
112 double *ptr_s, double *ptr_s_dot,
113 double *ptr_d,
114 double *ptr_d_dot) const {
115 double dx = x - ref_point.x();
116 double dy = y - ref_point.y();
117
118 double cos_ref_theta = std::cos(ref_point.theta());
119 double sin_ref_theta = std::sin(ref_point.theta());
120
121 // the sin of diff angle between vector (cos_ref_theta, sin_ref_theta) and
122 // (dx, dy)
123 double cross_rd_nd = cos_ref_theta * dy - sin_ref_theta * dx;
124 *ptr_d = cross_rd_nd;
125
126 // the cos of diff angle between vector (cos_ref_theta, sin_ref_theta) and
127 // (dx, dy)
128 double dot_rd_nd = dx * cos_ref_theta + dy * sin_ref_theta;
129 *ptr_s = ref_point.s() + dot_rd_nd;
130
131 double delta_theta = theta - ref_point.theta();
132 double cos_delta_theta = std::cos(delta_theta);
133 double sin_delta_theta = std::sin(delta_theta);
134
135 *ptr_d_dot = v * sin_delta_theta;
136
137 double one_minus_kappa_r_d = 1 - ref_point.kappa() * (*ptr_d);
138 if (one_minus_kappa_r_d <= 0.0) {
139 AERROR << "TrajectoryAnalyzer::ToTrajectoryFrame "
140 "found fatal reference and actual difference. "
141 "Control output might be unstable:"
142 << " ref_point.kappa:" << ref_point.kappa()
143 << " ref_point.x:" << ref_point.x()
144 << " ref_point.y:" << ref_point.y() << " car x:" << x
145 << " car y:" << y << " *ptr_d:" << *ptr_d
146 << " one_minus_kappa_r_d:" << one_minus_kappa_r_d;
147 // currently set to a small value to avoid control crash.
148 one_minus_kappa_r_d = 0.01;
149 }
150
151 *ptr_s_dot = v * cos_delta_theta / one_minus_kappa_r_d;
152}
153
158
160 const double t) const {
161 auto func_comp = [](const TrajectoryPoint &point,
162 const double relative_time) {
163 return point.relative_time() < relative_time;
164 };
165
166 auto it_low = std::lower_bound(trajectory_points_.begin(),
167 trajectory_points_.end(), t, func_comp);
168
169 if (it_low == trajectory_points_.begin()) {
170 return trajectory_points_.front();
171 }
172
173 if (it_low == trajectory_points_.end()) {
174 return trajectory_points_.back();
175 }
176
177 if (FLAGS_query_forward_time_point_only) {
178 return *it_low;
179 } else {
180 auto it_lower = it_low - 1;
181 if (it_low->relative_time() - t < t - it_lower->relative_time()) {
182 return *it_low;
183 }
184 return *it_lower;
185 }
186}
187
189 const double x, const double y) const {
190 double d_min = PointDistanceSquare(trajectory_points_.front(), x, y);
191 size_t index_min = 0;
192
193 for (size_t i = 1; i < trajectory_points_.size(); ++i) {
194 double d_temp = PointDistanceSquare(trajectory_points_[i], x, y);
195 if (d_temp < d_min) {
196 d_min = d_temp;
197 index_min = i;
198 }
199 }
200 return trajectory_points_[index_min];
201}
202
203const std::vector<TrajectoryPoint> &TrajectoryAnalyzer::trajectory_points()
204 const {
205 return trajectory_points_;
206}
207
208PathPoint TrajectoryAnalyzer::FindMinDistancePoint(const TrajectoryPoint &p0,
209 const TrajectoryPoint &p1,
210 const double x,
211 const double y) const {
212 // given the fact that the discretized trajectory is dense enough,
213 // we assume linear trajectory between consecutive trajectory points.
214 auto dist_square = [&p0, &p1, &x, &y](const double s) {
215 double px = common::math::lerp(p0.path_point().x(), p0.path_point().s(),
216 p1.path_point().x(), p1.path_point().s(), s);
217 double py = common::math::lerp(p0.path_point().y(), p0.path_point().s(),
218 p1.path_point().y(), p1.path_point().s(), s);
219 double dx = px - x;
220 double dy = py - y;
221 return dx * dx + dy * dy;
222 };
223
224 PathPoint p = p0.path_point();
225 double s = common::math::GoldenSectionSearch(dist_square, p0.path_point().s(),
226 p1.path_point().s());
227 p.set_s(s);
228 p.set_x(common::math::lerp(p0.path_point().x(), p0.path_point().s(),
229 p1.path_point().x(), p1.path_point().s(), s));
230 p.set_y(common::math::lerp(p0.path_point().y(), p0.path_point().s(),
231 p1.path_point().y(), p1.path_point().s(), s));
232 p.set_theta(common::math::slerp(p0.path_point().theta(), p0.path_point().s(),
233 p1.path_point().theta(), p1.path_point().s(),
234 s));
235 // approximate the curvature at the intermediate point
236 p.set_kappa(common::math::lerp(p0.path_point().kappa(), p0.path_point().s(),
237 p1.path_point().kappa(), p1.path_point().s(),
238 s));
239 return p;
240}
241
243 const double rear_to_com_distance) {
244 CHECK_GT(trajectory_points_.size(), 0U);
245 for (size_t i = 0; i < trajectory_points_.size(); ++i) {
246 auto com = ComputeCOMPosition(rear_to_com_distance,
247 trajectory_points_[i].path_point());
248 trajectory_points_[i].mutable_path_point()->set_x(com.x());
249 trajectory_points_[i].mutable_path_point()->set_y(com.y());
250 }
251}
252
254 const double rear_to_com_distance, const PathPoint &path_point) const {
255 // Initialize the vector for coordinate transformation of the position
256 // reference point
257 Eigen::Vector3d v;
258 const double cos_heading = std::cos(path_point.theta());
259 const double sin_heading = std::sin(path_point.theta());
260 v << rear_to_com_distance * cos_heading, rear_to_com_distance * sin_heading,
261 0.0;
262 // Original position reference point at center of rear-axis
263 Eigen::Vector3d pos_vec(path_point.x(), path_point.y(), path_point.z());
264 // Transform original position with vector v
265 Eigen::Vector3d com_pos_3d = v + pos_vec;
266 // Return transfromed x and y
267 return common::math::Vec2d(com_pos_3d[0], com_pos_3d[1]);
268}
269
270} // namespace control
271} // namespace apollo
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
common::TrajectoryPoint QueryNearestPointByPosition(const double x, const double y) const
query a point of trajectory that its position is closest to the given position.
common::math::Vec2d ComputeCOMPosition(const double rear_to_com_distance, const common::PathPoint &path_point) const
Compute the position of center of mass(COM) of the vehicle, given the distance from rear wheels to th...
TrajectoryAnalyzer()=default
constructor
const std::vector< common::TrajectoryPoint > & trajectory_points() const
get all points of the trajectory
void TrajectoryTransformToCOM(const double rear_to_com_distance)
Transform the current trajectory points to the center of mass(COM) of the vehicle,...
common::PathPoint QueryMatchedPathPoint(const double x, const double y) const
query a point on trajectory that its position is closest to the given position.
common::TrajectoryPoint QueryNearestPointByAbsoluteTime(const double t) const
query a point of trajectory that its absolute time is closest to the give time.
void ToTrajectoryFrame(const double x, const double y, const double theta, const double v, const common::PathPoint &matched_point, double *ptr_s, double *ptr_s_dot, double *ptr_d, double *ptr_d_dot) const
convert a position with theta and speed to trajectory frame,
std::vector< common::TrajectoryPoint > trajectory_points_
common::TrajectoryPoint QueryNearestPointByRelativeTime(const double t) const
query a point of trajectory that its relative time is closest to the give time.
Linear interpolation functions.
#define AERROR
Definition log.h:44
Math-related util functions.
T lerp(const T &x0, const double t0, const T &x1, const double t1, const double t)
Linear interpolation between two points of type T.
double GoldenSectionSearch(const std::function< double(double)> &func, const double lower_bound, const double upper_bound, const double tol)
Given a unimodal function defined on the interval, find a value on the interval to minimize the funct...
Definition search.cc:25
double slerp(const double a0, const double t0, const double a1, const double t1, const double t)
Spherical linear interpolation between two angles.
class register implement
Definition arena_queue.h:37
Search-related functions.
optional uint32 sequence_num
Definition header.proto:16
optional double timestamp_sec
Definition header.proto:9
repeated apollo::common::TrajectoryPoint trajectory_point
optional apollo::common::Header header
Defines the TrajectoryAnalyzer class.