20std::string timestamp() {
21 const auto now = std::chrono::system_clock::now();
22 const auto time = std::chrono::system_clock::to_time_t(now);
24 gmtime_r(&time, &utc_time);
25 const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
27 std::ostringstream value;
28 value << std::put_time(&utc_time,
"%Y%m%dT%H%M%S") <<
'_' << std::setfill(
'0') << std::setw(3) << milliseconds <<
'Z';
32int64_t nowNanoseconds() {
33 return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
39 const char* configured_directory = std::getenv(
"TRAJECTORY_OPTIMIZATION_BENCHMARK_DIR");
40 const std::filesystem::path directory = configured_directory !=
nullptr && *configured_directory !=
'\0'
41 ? std::filesystem::path(configured_directory)
42 : std::filesystem::temp_directory_path() /
"trajectory_optimization_benchmarks";
43 path_ = directory / (node_name +
'_' + timestamp() +
".csv");
45 std::error_code error;
46 std::filesystem::create_directories(directory, error);
48 throw std::runtime_error(
"could not create directory '" + directory.string() +
"': " + error.message());
53 throw std::runtime_error(
"could not open '" +
path_.string() +
"'");
55 stream_ <<
"schema_version,source,run_id,cycle,record_stamp_ns,ego_stamp_ns,reference_stamp_ns,route_stamp_ns,status,"
56 "published,ref_points,objects,sqp_iter,qp_iter,"
57 "qp_status,cycle_ms,preprocessing_ms,solve_wall_ms,postprocessing_ms,acados_total_ms,acados_lin_ms,"
58 "acados_sim_ms,acados_qp_ms,"
59 "acados_qp_solver_ms,acados_qp_xcond_ms,acados_reg_ms,acados_glob_ms,acados_preparation_ms,"
60 "acados_feedback_ms,cost,kkt,nlp_res,res_stat,res_eq,res_ineq,res_comp,"
61 "max_ineq_violation,max_ineq_stage,max_ineq_type,max_ineq_index,max_ineq_side,"
62 "max_eq_violation,max_eq_stage,max_eq_state\n";
72 ocp_nlp_solver* solver,
73 ocp_nlp_config* config,
77 bool collect_details) {
78 ocp_nlp_eval_cost(solver, input, output);
79 ocp_nlp_eval_residuals(solver, input, output);
80 ocp_nlp_get(solver,
"cost_value", &metrics.
cost_value);
81 ocp_nlp_get(solver,
"res_eq", &metrics.
res_eq);
82 ocp_nlp_get(solver,
"res_ineq", &metrics.
res_ineq);
84 if (!collect_details)
return;
86 ocp_nlp_get(solver,
"res_stat", &metrics.
res_stat);
87 ocp_nlp_get(solver,
"res_comp", &metrics.
res_comp);
90 auto readTime = [&](
const char* field,
double& destination_ms) {
91 double time_seconds = 0.0;
92 ocp_nlp_get(solver, field, &time_seconds);
93 destination_ms = time_seconds * 1000.0;
106 ocp_nlp_get(solver,
"sqp_iter", &metrics.
sqp_iter);
107 ocp_nlp_get(solver,
"qp_iter", &metrics.
qp_iter);
108 ocp_nlp_get(solver,
"qp_status", &metrics.
qp_status);
109 ocp_nlp_out_get(config, dims, output, 0,
"kkt_norm_inf", &metrics.
kkt_norm_inf);
113 ocp_nlp_solver* solver,
114 const ocp_nlp_dims* dims,
115 int obstacle_circles) {
118 for (
int stage = 0; stage <= dims->N; ++stage) {
119 std::vector<double> residuals(2 * dims->ni[stage]);
120 ocp_nlp_get_at_stage(solver, stage,
"ineq_fun", residuals.data());
121 for (
size_t index = 0; index < residuals.size(); ++index) {
130 for (
int stage = 0; stage < dims->N; ++stage) {
131 std::vector<double> residuals(dims->nx[stage + 1]);
132 ocp_nlp_get_at_stage(solver, stage,
"res_eq", residuals.data());
133 for (
size_t state = 0; state < residuals.size(); ++state) {
152 std::vector<int> bound_indices(nb);
153 ocp_nlp_get_at_stage(solver, metrics.
max_ineq_stage,
"idxb", bound_indices.data());
154 const int variable_index = bound_indices[index];
162 }
else if (index < nb + ng) {
164 }
else if (index < nb + ng + nh) {
165 const int h_index = index - nb - ng;
166 const int ego_circles = nh / (obstacle_circles + 2);
167 if (h_index < 2 * ego_circles) {
168 metrics.
max_ineq_type = h_index % 2 == 0 ?
"boundary_left" :
"boundary_right";
170 }
else if (h_index < (obstacle_circles + 2) * ego_circles) {
171 const int obstacle_index = h_index - 2 * ego_circles;
172 metrics.
max_ineq_type =
"obstacle_" + std::to_string(obstacle_index / ego_circles);
176 metrics.
max_ineq_index = h_index - (obstacle_circles + 2) * ego_circles;
186 stream_ << std::setprecision(17) << 5 <<
",runtime,," << metrics.
cycle <<
',' << nowNanoseconds() <<
',' << metrics.
ego_stamp_ns
Namespace for trajectory_optimization package.