Apollo 11.0
自动驾驶开放平台
main.cc 文件参考
#include <getopt.h>
#include <cstddef>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
#include <csignal>
#include "cyber/common/file.h"
#include "cyber/common/time_conversion.h"
#include "cyber/init.h"
#include "cyber/tools/cyber_recorder/info.h"
#include "cyber/tools/cyber_recorder/player/player.h"
#include "cyber/tools/cyber_recorder/recorder.h"
#include "cyber/tools/cyber_recorder/recoverer.h"
#include "cyber/tools/cyber_recorder/spliter.h"
#include "gperftools/profiler.h"
#include "gperftools/heap-profiler.h"
#include "gperftools/malloc_extension.h"
main.cc 的引用(Include)关系图:

浏览源代码.

函数

void DisplayUsage (const std::string &binary)
 
void DisplayUsage (const std::string &binary, const std::string &command)
 
void DisplayUsage (const std::string &binary, const std::string &command, const std::string &options)
 
int main (int argc, char **argv)
 

变量

const char INFO_OPTIONS [] = "h"
 
const char RECORD_OPTIONS [] = "o:ac:k:i:m:hCH"
 
const char PLAY_OPTIONS [] = "f:ac:k:lr:b:e:s:d:p:h"
 
const char SPLIT_OPTIONS [] = "f:o:c:k:b:e:h"
 
const char RECOVER_OPTIONS [] = "f:o:h"
 

函数说明

◆ DisplayUsage() [1/3]

void DisplayUsage ( const std::string &  binary)

在文件 main.cc 第 60 行定义.

60 {
61 std::cout << "usage: " << binary << " <command> [<args>]\n"
62 << "The " << binary << " commands are:\n"
63 << "\tinfo\tShow information of an exist record.\n"
64 << "\tplay\tPlay an exist record.\n"
65 << "\trecord\tRecord same topic.\n"
66 << "\tsplit\tSplit an exist record.\n"
67 << "\trecover\tRecover an exist record.\n"
68 << std::endl;
69}

◆ DisplayUsage() [2/3]

void DisplayUsage ( const std::string &  binary,
const std::string &  command 
)

在文件 main.cc 第 71 行定义.

71 {
72 if (command == "info") {
73 std::cout << "usage: cyber_recorder info file" << std::endl;
74 std::cout << "usage: " << binary << " " << command << " [options]"
75 << std::endl;
76 DisplayUsage(binary, command, INFO_OPTIONS);
77 return;
78 }
79
80 std::cout << "usage: " << binary << " " << command << " [options]"
81 << std::endl;
82 if (command == "record") {
83 DisplayUsage(binary, command, RECORD_OPTIONS);
84 } else if (command == "play") {
85 DisplayUsage(binary, command, PLAY_OPTIONS);
86 } else if (command == "split") {
87 DisplayUsage(binary, command, SPLIT_OPTIONS);
88 } else if (command == "recover") {
89 DisplayUsage(binary, command, RECOVER_OPTIONS);
90 } else {
91 std::cout << "Unknown command: " << command << std::endl;
92 DisplayUsage(binary);
93 }
94}
const char SPLIT_OPTIONS[]
Definition main.cc:52
const char PLAY_OPTIONS[]
Definition main.cc:51
const char INFO_OPTIONS[]
Definition main.cc:49
const char RECORD_OPTIONS[]
Definition main.cc:50
const char RECOVER_OPTIONS[]
Definition main.cc:53
void DisplayUsage()

◆ DisplayUsage() [3/3]

void DisplayUsage ( const std::string &  binary,
const std::string &  command,
const std::string &  options 
)

在文件 main.cc 第 96 行定义.

97 {
98 for (char option : options) {
99 switch (option) {
100 case 'f':
101 std::cout << "\t-f, --file <file>\t\t\tinput record file" << std::endl;
102 break;
103 case 'o':
104 std::cout << "\t-o, --output <file>\t\t\toutput record file"
105 << std::endl;
106 break;
107 case 'a':
108 std::cout << "\t-a, --all\t\t\t\t" << command << " all" << std::endl;
109 break;
110 case 'c':
111 std::cout << "\t-c, --white-channel <name>\t\tonly " << command
112 << " the specified channel" << std::endl;
113 break;
114 case 'k':
115 std::cout << "\t-k, --black-channel <name>\t\tnot " << command
116 << " the specified channel" << std::endl;
117 break;
118 case 'l':
119 std::cout << "\t-l, --loop\t\t\t\tloop " << command << std::endl;
120 break;
121 case 'r':
122 std::cout << "\t-r, --rate <1.0>\t\t\tmultiply the " << command
123 << " rate by FACTOR" << std::endl;
124 break;
125 case 'b':
126 std::cout << "\t-b, --begin 2018-07-01-00:00:00\t" << command
127 << " the record begin at" << std::endl;
128 break;
129 case 'e':
130 std::cout << "\t-e, --end 2018-07-01-00:01:00\t\t" << command
131 << " the record end at" << std::endl;
132 break;
133 case 's':
134 std::cout << "\t-s, --start <seconds>\t\t\t" << command
135 << " started at n seconds" << std::endl;
136 break;
137 case 'd':
138 std::cout << "\t-d, --delay <seconds>\t\t\t" << command
139 << " delayed n seconds" << std::endl;
140 break;
141 case 'p':
142 std::cout << "\t-p, --preload <seconds>\t\t\t" << command
143 << " after trying to preload n second(s)" << std::endl;
144 break;
145 case 'i':
146 std::cout << "\t-i, --segment-interval <seconds>\t" << command
147 << " segmented every n second(s)" << std::endl;
148 break;
149 case 'm':
150 std::cout << "\t-m, --segment-size <MB>\t\t\t" << command
151 << " segmented every n megabyte(s)" << std::endl;
152 break;
153 case 'h':
154 std::cout << "\t-h, --help\t\t\t\tshow help message" << std::endl;
155 break;
156 case 'H':
157 std::cout << "\t-H, --heap-profule\t\t\t\tprofile heap info" \
158 << std::endl;
159 break;
160 case 'C':
161 std::cout << "\t-C, --cpu-profule\t\t\t\tprofile cpu info" << std::endl;
162 break;
163 case ':':
164 break;
165 default:
166 std::cout << "unknown option: -" << option;
167 break;
168 }
169 }
170}

◆ main()

int main ( int  argc,
char **  argv 
)

在文件 main.cc 第 172 行定义.

172 {
173 std::string binary = GetFileName(std::string(argv[0]));
174 if (argc < 2) {
175 DisplayUsage(binary);
176 return -1;
177 }
178 const std::string command(argv[1]);
179 std::string file_path;
180 if (argc >= 3) {
181 file_path = std::string(argv[2]);
182 }
183
184 int long_index = 0;
185 const std::string short_opts = "f:c:k:o:alr:b:e:s:d:p:i:m:hCH";
186 static const struct option long_opts[] = {
187 {"files", required_argument, nullptr, 'f'},
188 {"white-channel", required_argument, nullptr, 'c'},
189 {"black-channel", required_argument, nullptr, 'k'},
190 {"output", required_argument, nullptr, 'o'},
191 {"all", no_argument, nullptr, 'a'},
192 {"loop", no_argument, nullptr, 'l'},
193 {"rate", required_argument, nullptr, 'r'},
194 {"begin", required_argument, nullptr, 'b'},
195 {"end", required_argument, nullptr, 'e'},
196 {"start", required_argument, nullptr, 's'},
197 {"delay", required_argument, nullptr, 'd'},
198 {"preload", required_argument, nullptr, 'p'},
199 {"segment-interval", required_argument, nullptr, 'i'},
200 {"segment-size", required_argument, nullptr, 'm'},
201 {"help", no_argument, nullptr, 'h'},
202 {"cpu-profile", no_argument, nullptr, 'C'},
203 {"heap-profule", no_argument, nullptr, 'H'}};
204
205 std::vector<std::string> opt_file_vec;
206 std::vector<std::string> opt_output_vec;
207 std::vector<std::string> opt_white_channels;
208 std::vector<std::string> opt_black_channels;
209 static bool enable_cpu_profile = false;
210 static bool enable_heap_profile = false;
211 bool opt_all = false;
212 bool opt_loop = false;
213 float opt_rate = 1.0f;
214 uint64_t opt_begin = 0;
215 uint64_t opt_end = std::numeric_limits<uint64_t>::max();
216 double opt_start = 0;
217 uint64_t opt_delay = 0;
218 uint32_t opt_preload = 3;
219 auto opt_header = HeaderBuilder::GetHeader();
220
221 do {
222 int opt =
223 getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index);
224 if (opt == -1) {
225 break;
226 }
227 switch (opt) {
228 case 'C':
229 enable_cpu_profile = true;
230 break;
231 case 'H':
232 enable_heap_profile = true;
233 break;
234 case 'f':
235 opt_file_vec.emplace_back(std::string(optarg));
236 for (int i = optind; i < argc; i++) {
237 if (*argv[i] != '-') {
238 opt_file_vec.emplace_back(std::string(argv[i]));
239 } else {
240 break;
241 }
242 }
243 break;
244 case 'c':
245 opt_white_channels.emplace_back(std::string(optarg));
246 for (int i = optind; i < argc; i++) {
247 if (*argv[i] != '-') {
248 opt_white_channels.emplace_back(std::string(argv[i]));
249 } else {
250 break;
251 }
252 }
253 break;
254 case 'k':
255 opt_black_channels.emplace_back(std::string(optarg));
256 for (int i = optind; i < argc; i++) {
257 if (*argv[i] != '-') {
258 opt_black_channels.emplace_back(std::string(argv[i]));
259 } else {
260 break;
261 }
262 }
263 break;
264 case 'o':
265 opt_output_vec.push_back(std::string(optarg));
266 break;
267 case 'a':
268 opt_all = true;
269 break;
270 case 'l':
271 opt_loop = true;
272 break;
273 case 'r':
274 try {
275 opt_rate = std::stof(optarg);
276 } catch (const std::invalid_argument& ia) {
277 std::cout << "Invalid argument: -r/--rate " << std::string(optarg)
278 << std::endl;
279 return -1;
280 } catch (const std::out_of_range& e) {
281 std::cout << "Argument is out of range: -r/--rate "
282 << std::string(optarg) << std::endl;
283 return -1;
284 }
285 break;
286 case 'b':
287 opt_begin =
288 StringToUnixSeconds(std::string(optarg)) * 1000 * 1000 * 1000ULL;
289 break;
290 case 'e':
291 opt_end =
292 StringToUnixSeconds(std::string(optarg)) * 1000 * 1000 * 1000ULL;
293 break;
294 case 's':
295 try {
296 opt_start = std::stod(optarg);
297 } catch (const std::invalid_argument& ia) {
298 std::cout << "Invalid argument: -s/--start " << std::string(optarg)
299 << std::endl;
300 return -1;
301 } catch (const std::out_of_range& e) {
302 std::cout << "Argument is out of range: -s/--start "
303 << std::string(optarg) << std::endl;
304 return -1;
305 }
306 break;
307 case 'd':
308 try {
309 opt_delay = std::stoi(optarg);
310 } catch (std::invalid_argument& ia) {
311 std::cout << "Invalid argument: -d/--delay " << std::string(optarg)
312 << std::endl;
313 return -1;
314 } catch (const std::out_of_range& e) {
315 std::cout << "Argument is out of range: -d/--delay "
316 << std::string(optarg) << std::endl;
317 return -1;
318 }
319 break;
320 case 'p':
321 try {
322 opt_preload = std::stoi(optarg);
323 } catch (std::invalid_argument& ia) {
324 std::cout << "Invalid argument: -p/--preload " << std::string(optarg)
325 << std::endl;
326 return -1;
327 } catch (const std::out_of_range& e) {
328 std::cout << "Argument is out of range: -p/--preload "
329 << std::string(optarg) << std::endl;
330 return -1;
331 }
332 break;
333 case 'i':
334 try {
335 int interval_s = std::stoi(optarg);
336 if (interval_s < 0) {
337 std::cout << "Argument is less than zero: -i/--segment-interval "
338 << std::string(optarg) << std::endl;
339 return -1;
340 }
341 opt_header.set_segment_interval(interval_s * 1000000000ULL);
342 } catch (std::invalid_argument& ia) {
343 std::cout << "Invalid argument: -i/--segment-interval "
344 << std::string(optarg) << std::endl;
345 return -1;
346 } catch (const std::out_of_range& e) {
347 std::cout << "Argument is out of range: -i/--segment-interval "
348 << std::string(optarg) << std::endl;
349 return -1;
350 }
351 break;
352 case 'm':
353 try {
354 int size_mb = std::stoi(optarg);
355 if (size_mb < 0) {
356 std::cout << "Argument is less than zero: -m/--segment-size "
357 << std::string(optarg) << std::endl;
358 return -1;
359 }
360 opt_header.set_segment_raw_size(size_mb * 1024 * 1024ULL);
361 } catch (std::invalid_argument& ia) {
362 std::cout << "Invalid argument: -m/--segment-size "
363 << std::string(optarg) << std::endl;
364 return -1;
365 } catch (const std::out_of_range& e) {
366 std::cout << "Argument is out of range: -m/--segment-size "
367 << std::string(optarg) << std::endl;
368 return -1;
369 }
370 break;
371 case 'h':
372 DisplayUsage(binary, command);
373 return 0;
374 default:
375 break;
376 }
377 } while (true);
378
379 // cyber_recorder info
380 if (command == "info") {
381 if (file_path.empty()) {
382 std::cout << "usage: cyber_recorder info file" << std::endl;
383 return -1;
384 }
385 ::apollo::cyber::Init(argv[0]);
386 Info info;
387 bool info_result = info.Display(file_path);
388 return info_result ? 0 : -1;
389 } else if (command == "recover") {
390 if (opt_file_vec.empty()) {
391 std::cout << "MUST specify file option (-f)." << std::endl;
392 return -1;
393 }
394 if (opt_file_vec.size() > 1 || opt_output_vec.size() > 1) {
395 std::cout << "TOO many input/output file option (-f/-o)." << std::endl;
396 return -1;
397 }
398 if (opt_output_vec.empty()) {
399 std::string default_output_file = opt_file_vec[0] + ".recover";
400 opt_output_vec.push_back(default_output_file);
401 }
402 ::apollo::cyber::Init(argv[0]);
403 Recoverer recoverer(opt_file_vec[0], opt_output_vec[0]);
404 bool recover_result = recoverer.Proc();
405 return recover_result ? 0 : -1;
406 }
407
408 if (command == "play") {
409 if (opt_file_vec.empty()) {
410 std::cout << "MUST specify file option (-f)." << std::endl;
411 return -1;
412 }
413 ::apollo::cyber::Init(argv[0]);
414 PlayParam play_param;
415 play_param.is_play_all_channels = opt_all || opt_white_channels.empty();
416 play_param.is_loop_playback = opt_loop;
417 play_param.play_rate = opt_rate;
418 play_param.begin_time_ns = opt_begin;
419 play_param.end_time_ns = opt_end;
420 play_param.start_time_s = opt_start;
421 play_param.delay_time_s = opt_delay;
422 play_param.preload_time_s = opt_preload;
423 play_param.files_to_play.insert(opt_file_vec.begin(), opt_file_vec.end());
424 play_param.black_channels.insert(opt_black_channels.begin(),
425 opt_black_channels.end());
426 play_param.channels_to_play.insert(opt_white_channels.begin(),
427 opt_white_channels.end());
428 Player player(play_param);
429 const bool play_result = player.Init() && player.Start();
430 return play_result ? 0 : -1;
431 } else if (command == "record") {
432 if (opt_white_channels.empty() && !opt_all) {
433 std::cout
434 << "MUST specify channels option (-c) or all channels option (-a)."
435 << std::endl;
436 return -1;
437 }
438 if (opt_output_vec.size() > 1) {
439 std::cout << "TOO many output file option (-o)." << std::endl;
440 return -1;
441 }
442 if (opt_output_vec.empty()) {
443 std::string default_output_file =
444 UnixSecondsToString(time(nullptr), "%Y%m%d%H%M%S") + ".record";
445 opt_output_vec.push_back(default_output_file);
446 }
447 ::apollo::cyber::Init(argv[0]);
448 auto recorder = std::make_shared<Recorder>(opt_output_vec[0], opt_all,
449 opt_white_channels,
450 opt_black_channels, opt_header);
451 std::signal(SIGTERM, [](int sig){
453 if (enable_cpu_profile) {
454 ProfilerStop();
455 }
456 if (enable_heap_profile) {
457 HeapProfilerDump("Befor shutdown");
458 HeapProfilerStop();
459 }
460 });
461
462 std::signal(SIGINT, [](int sig){
464 if (enable_cpu_profile) {
465 ProfilerStop();
466 }
467 if (enable_heap_profile) {
468 HeapProfilerDump("Befor shutdown");
469 HeapProfilerStop();
470 }
471 });
472
473 auto base_name = std::string(argv[0]) + std::string(".prof");
474 if (enable_cpu_profile) {
475 ProfilerStart(base_name.c_str());
476 }
477 if (enable_heap_profile) {
478 HeapProfilerStart(base_name.c_str());
479 }
480 bool record_result = recorder->Start();
481 if (record_result) {
482 while (!::apollo::cyber::IsShutdown()) {
483 std::this_thread::sleep_for(std::chrono::milliseconds(100));
484 }
485 record_result = recorder->Stop();
486 }
487 return record_result ? 0 : -1;
488 } else if (command == "split") {
489 if (opt_file_vec.empty()) {
490 std::cout << "Must specify file option (-f)." << std::endl;
491 return -1;
492 }
493 if (opt_file_vec.size() > 1 || opt_output_vec.size() > 1) {
494 std::cout << "Too many input/output file option (-f/-o)." << std::endl;
495 return -1;
496 }
497 if (opt_output_vec.empty()) {
498 std::string default_output_file = opt_file_vec[0] + ".split";
499 opt_output_vec.push_back(default_output_file);
500 }
501 ::apollo::cyber::Init(argv[0]);
502 Spliter spliter(opt_file_vec[0], opt_output_vec[0], opt_white_channels,
503 opt_black_channels, opt_begin, opt_end);
504 bool split_result = spliter.Proc();
505 return split_result ? 0 : -1;
506 }
507
508 // unknown command
509 DisplayUsage(binary, command);
510 return -1;
511}
static proto::Header GetHeader()
Build a default record header.
bool Display(const std::string &file)
Definition info.cc:34
std::string GetFileName(const std::string &path, const bool remove_extension)
Definition file.cc:401
uint64_t StringToUnixSeconds(const std::string &time_str, const std::string &format_str="%Y-%m-%d %H:%M:%S")
std::string UnixSecondsToString(uint64_t unix_seconds, const std::string &format_str="%Y-%m-%d-%H:%M:%S")
void OnShutdown(int sig)
Definition init.cc:90
bool IsShutdown()
Definition state.h:46
bool Init(const char *binary_name, const std::string &dag_info)
Definition init.cc:99
std::set< std::string > black_channels
Definition play_param.h:41
std::set< std::string > files_to_play
Definition play_param.h:39
std::set< std::string > channels_to_play
Definition play_param.h:40

变量说明

◆ INFO_OPTIONS

const char INFO_OPTIONS[] = "h"

在文件 main.cc 第 49 行定义.

◆ PLAY_OPTIONS

const char PLAY_OPTIONS[] = "f:ac:k:lr:b:e:s:d:p:h"

在文件 main.cc 第 51 行定义.

◆ RECORD_OPTIONS

const char RECORD_OPTIONS[] = "o:ac:k:i:m:hCH"

在文件 main.cc 第 50 行定义.

◆ RECOVER_OPTIONS

const char RECOVER_OPTIONS[] = "f:o:h"

在文件 main.cc 第 53 行定义.

◆ SPLIT_OPTIONS

const char SPLIT_OPTIONS[] = "f:o:c:k:b:e:h"

在文件 main.cc 第 52 行定义.