trajectory_optimization v1.3.1
Loading...
Searching...
No Matches
performance_logger.cpp
Go to the documentation of this file.
1// Copyright Institute for Automotive Engineering (ika), RWTH Aachen University
2// SPDX-License-Identifier: Apache-2.0
3
4#include <algorithm>
5#include <chrono>
6#include <cstdlib>
7#include <ctime>
8#include <iomanip>
9#include <sstream>
10#include <stdexcept>
11
13
15
16namespace {
17
18std::string timestamp() {
19 const auto now = std::chrono::system_clock::now();
20 const auto time = std::chrono::system_clock::to_time_t(now);
21 std::tm utc_time{};
22 gmtime_r(&time, &utc_time);
23 const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
24
25 std::ostringstream value;
26 value << std::put_time(&utc_time, "%Y%m%dT%H%M%S") << '_' << std::setfill('0') << std::setw(3) << milliseconds << 'Z';
27 return value.str();
28}
29
30int64_t nowNanoseconds() {
31 return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
32}
33
34} // namespace
35
36PerformanceLogger::PerformanceLogger(const std::string& node_name) {
37 const char* configured_directory = std::getenv("TRAJECTORY_OPTIMIZATION_BENCHMARK_DIR");
38 const std::filesystem::path directory = configured_directory != nullptr && *configured_directory != '\0'
39 ? std::filesystem::path(configured_directory)
40 : std::filesystem::temp_directory_path() / "trajectory_optimization_benchmarks";
41 path_ = directory / (node_name + '_' + timestamp() + ".csv");
42
43 std::error_code error;
44 std::filesystem::create_directories(directory, error);
45 if (error) {
46 throw std::runtime_error("could not create directory '" + directory.string() + "': " + error.message());
47 }
48
49 stream_.open(path_, std::ios::out | std::ios::trunc);
50 if (!stream_) {
51 throw std::runtime_error("could not open '" + path_.string() + "'");
52 }
53 stream_ << "schema_version,source,run_id,cycle,record_stamp_ns,ego_stamp_ns,reference_stamp_ns,route_stamp_ns,status,"
54 "published,ref_points,objects,sqp_iter,qp_iter,"
55 "qp_status,cycle_ms,preprocessing_ms,solve_wall_ms,postprocessing_ms,acados_total_ms,acados_lin_ms,"
56 "acados_sim_ms,acados_qp_ms,"
57 "acados_qp_solver_ms,acados_qp_xcond_ms,acados_reg_ms,acados_glob_ms,acados_preparation_ms,"
58 "acados_feedback_ms,cost,kkt,nlp_res,res_stat,res_eq,res_ineq,res_comp\n";
59 stream_.flush();
60}
61
66
68 ocp_nlp_solver* solver,
69 ocp_nlp_config* config,
70 ocp_nlp_dims* dims,
71 ocp_nlp_in* input,
72 ocp_nlp_out* output) {
73 auto readTime = [&](const char* field, double& destination_ms) {
74 double time_seconds = 0.0;
75 ocp_nlp_get(solver, field, &time_seconds);
76 destination_ms = time_seconds * 1000.0;
77 };
78
79 readTime("time_tot", metrics.acados_total_ms);
80 readTime("time_lin", metrics.acados_lin_ms);
81 readTime("time_sim", metrics.acados_sim_ms);
82 readTime("time_qp", metrics.acados_qp_ms);
83 readTime("time_qp_solver_call", metrics.acados_qp_solver_ms);
84 readTime("time_qp_xcond", metrics.acados_qp_xcond_ms);
85 readTime("time_reg", metrics.acados_reg_ms);
86 readTime("time_glob", metrics.acados_glob_ms);
87 readTime("time_preparation", metrics.acados_preparation_ms);
88 readTime("time_feedback", metrics.acados_feedback_ms);
89 ocp_nlp_get(solver, "sqp_iter", &metrics.sqp_iter);
90 ocp_nlp_get(solver, "qp_iter", &metrics.qp_iter);
91 ocp_nlp_get(solver, "qp_status", &metrics.qp_status);
92 ocp_nlp_out_get(config, dims, output, 0, "kkt_norm_inf", &metrics.kkt_norm_inf);
93
94 ocp_nlp_eval_cost(solver, input, output);
95 ocp_nlp_eval_residuals(solver, input, output);
96 ocp_nlp_get(solver, "cost_value", &metrics.cost_value);
97 ocp_nlp_get(solver, "res_stat", &metrics.res_stat);
98 ocp_nlp_get(solver, "res_eq", &metrics.res_eq);
99 ocp_nlp_get(solver, "res_ineq", &metrics.res_ineq);
100 ocp_nlp_get(solver, "res_comp", &metrics.res_comp);
101 metrics.nlp_res = std::max({metrics.res_stat, metrics.res_eq, metrics.res_ineq, metrics.res_comp});
102}
103
105 stream_ << std::setprecision(17) << 4 << ",runtime,," << metrics.cycle << ',' << nowNanoseconds() << ',' << metrics.ego_stamp_ns
106 << ',' << metrics.reference_stamp_ns << ',' << metrics.route_stamp_ns << ',' << metrics.status << ','
107 << (metrics.published ? 1 : 0) << ',' << metrics.reference_points << ',' << metrics.objects << ',' << metrics.sqp_iter
108 << ',' << metrics.qp_iter << ',' << metrics.qp_status << ',' << metrics.cycle_ms << ',' << metrics.preprocessing_ms
109 << ',' << metrics.solve_wall_ms << ',' << metrics.postprocessing_ms << ',' << metrics.acados_total_ms << ','
110 << metrics.acados_lin_ms << ',' << metrics.acados_sim_ms << ',' << metrics.acados_qp_ms << ','
111 << metrics.acados_qp_solver_ms << ',' << metrics.acados_qp_xcond_ms << ',' << metrics.acados_reg_ms << ','
112 << metrics.acados_glob_ms << ',' << metrics.acados_preparation_ms << ',' << metrics.acados_feedback_ms << ','
113 << metrics.cost_value << ',' << metrics.kkt_norm_inf << ',' << metrics.nlp_res << ',' << metrics.res_stat << ','
114 << metrics.res_eq << ',' << metrics.res_ineq << ',' << metrics.res_comp << '\n';
115
117 stream_.flush();
119 }
120}
121
122} // namespace trajectory_optimization
PerformanceLogger(const std::string &node_name)
Creates a CSV performance log for the given node.
void write(const PerformanceMetrics &metrics)
Appends one set of performance metrics to the CSV log.
static void collectSolverStatistics(PerformanceMetrics &metrics, ocp_nlp_solver *solver, ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *input, ocp_nlp_out *output)
Reads timing, iteration, cost, and residual statistics from acados.
~PerformanceLogger()
Flushes and closes the performance log.
Namespace for trajectory_optimization package.