Apollo 11.0
自动驾驶开放平台
spiral_smoother_util.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 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"
28
29DEFINE_string(input_file, "", "input file with format x,y per line");
30DEFINE_string(output_file, "", "output file with format x,y per line");
31DEFINE_double(smooth_length, 200.0, "Smooth this amount of length ");
32DEFINE_double(minimum_point_spacing, 5.0,
33 "The minimum distance for input points.");
34
35namespace apollo {
36namespace planning {
37
39 public:
40 static std::vector<Eigen::Vector2d> ReadCoordinatesFromFile(
41 const std::string& filename) {
42 std::vector<Eigen::Vector2d> raw_points;
43 std::ifstream ifs(filename.c_str(), std::ifstream::in);
44 std::string point_str;
45
46 auto spacing_thres =
47 FLAGS_minimum_point_spacing * FLAGS_minimum_point_spacing;
48
49 while (std::getline(ifs, point_str)) {
50 size_t idx = point_str.find(',');
51 if (idx == std::string::npos) {
52 continue;
53 }
54 auto x_str = point_str.substr(0, idx);
55 auto y_str = point_str.substr(idx + 1);
56
57 auto x = std::stod(x_str);
58 auto y = std::stod(y_str);
59
60 if (raw_points.size() > 0) {
61 auto last_x = raw_points.back().x();
62 auto last_y = raw_points.back().y();
63
64 auto dx = x - last_x;
65 auto dy = y - last_y;
66 if (dx * dx + dy * dy < spacing_thres) {
67 continue;
68 }
69 }
70 raw_points.emplace_back(x, y);
71 }
72 return raw_points;
73 }
74
75 static bool Smooth(std::vector<Eigen::Vector2d> raw_points,
76 std::vector<common::PathPoint>* ptr_smooth_points) {
77 if (raw_points.size() <= 2) {
78 AERROR << "the original point size is " << raw_points.size();
79 return false;
80 }
81
82 std::vector<Eigen::Vector2d> processed_points;
83 processed_points.push_back(raw_points.front());
84
85 for (const Eigen::Vector2d& p : raw_points) {
86 Eigen::Vector2d d = p - processed_points.back();
87 if (d.norm() < FLAGS_minimum_point_spacing) {
88 continue;
89 }
90 processed_points.push_back(p);
91 }
92
93 if (processed_points.size() < 2) {
94 processed_points.push_back(raw_points.back());
95 }
96
97 Eigen::Vector2d start_point = processed_points.front();
98 std::for_each(processed_points.begin(), processed_points.end(),
99 [&start_point](Eigen::Vector2d& p) { p = p - start_point; });
100
102 ACHECK(
103 cyber::common::GetProtoFromFile("modules/planning/planning_component/"
104 "conf/spiral_smoother_config.pb.txt",
105 &config));
106
107 std::vector<double> opt_theta;
108 std::vector<double> opt_kappa;
109 std::vector<double> opt_dkappa;
110 std::vector<double> opt_s;
111 std::vector<double> opt_x;
112 std::vector<double> opt_y;
113
114 SpiralReferenceLineSmoother spiral_smoother(config);
115 auto res = spiral_smoother.SmoothStandAlone(processed_points, &opt_theta,
116 &opt_kappa, &opt_dkappa, &opt_s,
117 &opt_x, &opt_y);
118
119 if (!res) {
120 AWARN << "Optimization failed; the result may not be smooth";
121 } else {
122 AINFO << "Optimal solution found";
123 }
124
125 std::for_each(opt_x.begin(), opt_x.end(),
126 [&start_point](double& x) { x += start_point.x(); });
127 std::for_each(opt_y.begin(), opt_y.end(),
128 [&start_point](double& y) { y += start_point.y(); });
129
130 *ptr_smooth_points =
131 spiral_smoother.Interpolate(opt_theta, opt_kappa, opt_dkappa, opt_s,
132 opt_x, opt_y, config.resolution());
133
134 return true;
135 }
136
137 static void Export(const std::string& filename,
138 const std::vector<common::PathPoint>& smoothed_points) {
139 std::ofstream ofs(filename.c_str());
140 if (ofs.fail()) {
141 AERROR << "Fail to open file " << filename;
142 return;
143 }
144 ofs.precision(12);
145 // skip the first point and the last point
146 for (size_t i = 1; i + 1 < smoothed_points.size(); ++i) {
147 const auto& point = smoothed_points[i];
148 ofs << std::fixed << "{\"kappa\": " << point.kappa()
149 << ", \"s\": " << point.s() << ", \"theta\": " << point.theta()
150 << ", \"x\":" << point.x() << ", \"y\":" << point.y()
151 << ", \"dkappa\":" << point.dkappa() << "}";
152 }
153 ofs.close();
154 AINFO << "Smoothed result saved to " << filename;
155 }
156};
157
158} // namespace planning
159} // namespace apollo
160
161int main(int argc, char* argv[]) {
162 google::InitGoogleLogging(argv[0]);
163 google::ParseCommandLineFlags(&argc, &argv, true);
164
165 if (FLAGS_input_file.empty()) {
166 AERROR << "need to provide --input_file";
167 return 0;
168 }
169
170 std::vector<Eigen::Vector2d> raw_points =
172 FLAGS_input_file);
173
174 std::vector<apollo::common::PathPoint> smooth_points;
175 auto res =
176 apollo::planning::SpiralSmootherUtil::Smooth(raw_points, &smooth_points);
177 if (!res) {
178 AERROR << "Failed to smooth a the line";
179 }
180
181 if (FLAGS_output_file.empty()) {
182 FLAGS_output_file = FLAGS_input_file + ".smoothed";
183 AINFO << "Output file not provided, set to: " << FLAGS_output_file;
184 }
186 smooth_points);
187 return 0;
188}
std::vector< common::PathPoint > Interpolate(const std::vector< double > &theta, const std::vector< double > &kappa, const std::vector< double > &dkappa, const std::vector< double > &s, const std::vector< double > &x, const std::vector< double > &y, const double resolution) const
int SmoothStandAlone(std::vector< Eigen::Vector2d > point2d, std::vector< double > *ptr_theta, std::vector< double > *ptr_kappa, std::vector< double > *ptr_dkappa, std::vector< double > *ptr_s, std::vector< double > *ptr_x, std::vector< double > *ptr_y) const
static bool Smooth(std::vector< Eigen::Vector2d > raw_points, std::vector< common::PathPoint > *ptr_smooth_points)
static void Export(const std::string &filename, const std::vector< common::PathPoint > &smoothed_points)
static std::vector< Eigen::Vector2d > ReadCoordinatesFromFile(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
#define AWARN
Definition log.h:43
Some util functions.
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_double(smooth_length, 200.0, "Smooth this amount of length ")
DEFINE_string(input_file, "", "input file with format x,y per line")