Apollo 11.0
自动驾驶开放平台
smoother_util.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
21#include "gflags/gflags.h"
22
23#include "cyber/common/file.h"
24#include "cyber/common/log.h"
33
34DEFINE_string(input_file, "", "input file with format x,y per line");
35DEFINE_string(output_file, "", "output file with format x,y per line");
36DEFINE_double(smooth_length, 200, "Smooth this amount of length ");
37
38namespace apollo {
39namespace planning {
40
45
47 public:
48 explicit SmootherUtil(const std::string& filename) : filename_(filename) {
49 std::ifstream ifs(filename.c_str(), std::ifstream::in);
50 std::string point_str;
51 while (std::getline(ifs, point_str)) {
52 size_t idx = point_str.find(',');
53 if (idx == std::string::npos) {
54 continue;
55 }
56 auto x_str = point_str.substr(0, idx);
57 auto y_str = point_str.substr(idx + 1);
58 raw_points_.emplace_back(std::stod(x_str), std::stod(y_str));
59 }
60 ACHECK(cyber::common::GetProtoFromFile(FLAGS_smoother_config_filename,
61 &config_))
62 << "Failed to read smoother config file: "
63 << FLAGS_smoother_config_filename;
64 }
65
66 bool Smooth() {
67 if (raw_points_.size() <= 2) {
68 AERROR << "the original point size is " << raw_points_.size();
69 return false;
70 }
71 size_t i = 1;
72 {
73 std::vector<ReferencePoint> ref_points;
74 double s = 0.0;
75 for (; s < FLAGS_smooth_length && i < raw_points_.size(); ++i) {
76 LineSegment2d segment(raw_points_[i - 1], raw_points_[i]);
77 ref_points.emplace_back(MapPathPoint(raw_points_[i], segment.heading()),
78 0.0, 0.0);
79 s += segment.length();
80 }
81 ReferenceLine init_ref(ref_points);
82 // Prefer "std::make_unique" to direct use of "new".
83 // Reference "https://herbsutter.com/gotw/_102/" for details.
84 auto smoother_ptr =
85 std::make_unique<QpSplineReferenceLineSmoother>(config_);
86 auto anchors =
87 CreateAnchorPoints(init_ref.reference_points().front(), init_ref);
88 smoother_ptr->SetAnchorPoints(anchors);
89 ReferenceLine smoothed_init_ref;
90 if (!smoother_ptr->Smooth(init_ref, &smoothed_init_ref)) {
91 AERROR << "smooth initial reference line failed";
92 return false;
93 }
94 ref_points_ = smoothed_init_ref.reference_points();
95 }
96 for (; i < raw_points_.size(); ++i) {
97 double s = 0.0;
98 size_t j = ref_points_.size() - 1;
99 while (j > 0 && s < FLAGS_smooth_length / 2.0) {
100 s += DistanceXY(ref_points_[j - 1], ref_points_[j]);
101 --j;
102 }
103 ReferenceLine prev_half_ref(ref_points_.begin() + j, ref_points_.end());
104 ref_points_.erase(ref_points_.begin() + j, ref_points_.end());
106 prev_half_ref.XYToSL(raw_points_[i], &sl);
107 while (sl.s() <= prev_half_ref.Length() && i + 1 < raw_points_.size()) {
108 prev_half_ref.XYToSL(raw_points_[i + 1], &sl);
109 ++i;
110 }
111 s = 0.0;
112 j = i;
113 auto ref_points = prev_half_ref.reference_points();
114 while (j + 1 < raw_points_.size() && s < FLAGS_smooth_length / 2.0) {
115 Vec2d vec = raw_points_[j + 1] - raw_points_[j];
116 s += vec.Length();
117 ref_points.emplace_back(MapPathPoint(raw_points_[j], vec.Angle()), 0.0,
118 0.0);
119 ++j;
120 }
121 i = j;
122 ReferenceLine local_ref(ref_points);
123 auto anchors = CreateAnchorPoints(ref_points.front(), local_ref);
124 // Prefer "std::make_unique" to direct use of "new".
125 // Reference "https://herbsutter.com/gotw/_102/" for details.
126 auto smoother_ptr =
127 std::make_unique<QpSplineReferenceLineSmoother>(config_);
128 smoother_ptr->SetAnchorPoints(anchors);
129 ReferenceLine smoothed_local_ref;
130 if (!smoother_ptr->Smooth(local_ref, &smoothed_local_ref)) {
131 AERROR << "Failed to smooth reference line";
132 return false;
133 }
134 ref_points_.insert(ref_points_.end(),
135 smoothed_local_ref.reference_points().begin(),
136 smoothed_local_ref.reference_points().end());
137 }
138 return true;
139 }
140
141 void Export(const std::string& filename) {
142 std::ofstream ofs(filename.c_str());
143 if (ofs.fail()) {
144 AERROR << "Fail to open file " << filename;
145 return;
146 }
147 ofs.precision(6);
148 double s = 0.0;
149 // skip the first point and the last point
150 for (size_t i = 1; i + 1 < ref_points_.size(); ++i) {
151 const auto& point = ref_points_[i];
152 ofs << std::fixed << "{\"kappa\": " << point.kappa() << ", \"s\": " << s
153 << ", \"theta\": " << point.heading() << ", \"x\":" << point.x()
154 << ", \"y\":" << point.y() << ", \"dkappa\":" << point.dkappa()
155 << "}";
156 s += DistanceXY(point, ref_points_[i + 1]);
157 }
158 ofs.close();
159 AINFO << "Smoothed result saved to " << filename;
160 }
161
162 private:
163 std::vector<AnchorPoint> CreateAnchorPoints(const ReferencePoint& init_point,
164 const ReferenceLine& ref_line) {
165 std::vector<AnchorPoint> anchor_points;
166 int num_of_anchors = std::max(
167 2, static_cast<int>(
168 ref_line.Length() / config_.max_constraint_interval() + 0.5));
169 std::vector<double> anchor_s;
170 common::util::uniform_slice(0.0, ref_line.Length(), num_of_anchors - 1,
171 &anchor_s);
173 if (!ref_line.XYToSL(init_point, &sl)) {
174 AERROR << "Failed to project init point to reference line";
175 return anchor_points;
176 }
177 bool set_init_point = false;
178 for (const double s : anchor_s) {
179 if (s + config_.max_constraint_interval() / 2.0 < sl.s()) {
180 continue;
181 }
182 ReferencePoint ref_point;
183 if (!set_init_point) {
184 set_init_point = true;
185 ref_point = init_point;
186 } else {
187 ref_point = ref_line.GetReferencePoint(s);
188 }
189 AnchorPoint anchor;
190 anchor.path_point.set_x(ref_point.x());
191 anchor.path_point.set_y(ref_point.y());
192 anchor.path_point.set_z(0.0);
193 anchor.path_point.set_s(s);
194 anchor.path_point.set_theta(ref_point.heading());
195 anchor.path_point.set_kappa(ref_point.kappa());
196 anchor.lateral_bound = config_.max_lateral_boundary_bound();
197 anchor.longitudinal_bound = config_.longitudinal_boundary_bound();
198 anchor_points.emplace_back(anchor);
199 }
200 anchor_points.front().longitudinal_bound = 0;
201 anchor_points.front().lateral_bound = 0;
202 anchor_points.front().enforced = true;
203 anchor_points.back().longitudinal_bound = 0;
204 anchor_points.back().lateral_bound = 0;
205 anchor_points.back().enforced = true;
206 return anchor_points;
207 }
208
209 private:
210 std::string filename_;
211 std::vector<common::math::Vec2d> raw_points_;
212 std::vector<ReferencePoint> ref_points_;
213 ReferenceLine smoothed_ref_;
214 ReferenceLineSmootherConfig config_;
215};
216
217} // namespace planning
218} // namespace apollo
219
220int main(int argc, char* argv[]) {
221 google::InitGoogleLogging(argv[0]);
222 google::ParseCommandLineFlags(&argc, &argv, true);
223
224 if (FLAGS_input_file.empty()) {
225 AERROR << "need to provide --input_file";
226 return 0;
227 }
228 apollo::planning::SmootherUtil smoother_util(FLAGS_input_file);
229 if (!smoother_util.Smooth()) {
230 AERROR << "Failed to smooth a the line";
231 }
232 if (FLAGS_output_file.empty()) {
233 FLAGS_output_file = FLAGS_input_file + ".smoothed";
234 AINFO << "Output file not provided, set to: " << FLAGS_output_file;
235 }
236 smoother_util.Export(FLAGS_output_file);
237 return 0;
238}
double length() const
Get the length of the line segment.
double heading() const
Get the heading of the line segment.
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
void set_x(const double x)
Setter for x component
Definition vec2d.h:60
double Length() const
Gets the length of the vector
Definition vec2d.cc:33
double Angle() const
Gets the angle between the vector and the positive x semi-axis
Definition vec2d.cc:37
ReferencePoint GetReferencePoint(const double s) const
bool XYToSL(const common::math::Vec2d &xy_point, common::SLPoint *const sl_point, double warm_start_s=-1.0) const
Transvert Cartesian coordinates to Frenet.
const std::vector< ReferencePoint > & reference_points() const
SmootherUtil(const std::string &filename)
void Export(const std::string &filename)
Planning module main class.
#define ACHECK(cond)
Definition log.h:80
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
Some util functions.
double DistanceXY(const U &u, const V &v)
calculate the distance beteween Point u and Point v, which are all have member function x() and y() i...
Definition util.h:97
void uniform_slice(const T start, const T end, uint32_t num, std::vector< T > *sliced)
uniformly slice a segment [start, end] to num + 1 pieces the result sliced will contain the n + 1 poi...
Definition util.h:74
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
class register implement
Definition arena_queue.h:37
int main(int argc, char *argv[])
DEFINE_string(input_file, "", "input file with format x,y per line")
DEFINE_double(smooth_length, 200, "Smooth this amount of length ")
Defines the Vec2d class.