LCOV - code coverage report
Current view: top level - utils - DebugPrint.h Hit Total Coverage
Test: doc-coverage.info Lines: 4 11 36.4 %
Date: 2026-04-20 18:26:22

          Line data    Source code
       1             : #ifndef CONTROLS_UTILS_DEBUG_PRINT_H
       2             : #define CONTROLS_UTILS_DEBUG_PRINT_H
       3             : 
       4             : #include <algorithm>
       5             : #include <iomanip>
       6             : #include <sstream>
       7             : #include <string>
       8             : 
       9             : #include "utils/Transforms.h"
      10             : 
      11             : constexpr int PRINT_PRECISION = 3;
      12           0 : inline const Eigen::IOFormat EigFmt(PRINT_PRECISION, 0, ", ", ";\n", "", "", "[", "]");
      13             : 
      14             : /**
      15             :  * @brief Formats any Eigen matrix/vector as a string.
      16             :  *        Vectors (single column) are printed transposed as a row.
      17             :  */
      18             : template <typename Derived>
      19           1 : std::string fmt_eigen(const Eigen::MatrixBase<Derived>& m) {
      20             :     std::ostringstream oss;
      21             :     oss << std::fixed;
      22             :     if (m.cols() == 1) {
      23             :         oss << m.transpose().format(EigFmt);
      24             :     } else {
      25             :         oss << m.format(EigFmt);
      26             :     }
      27             :     return oss.str();
      28             : }
      29             : 
      30             : /**
      31             :  * @brief Formats a Pose as "pos=[x, y, z] rpy=[r, p, y] deg".
      32             :  */
      33           1 : inline std::string fmt_pose(const Pose& pose) {
      34             :     Vector6d n = pose2n(pose);
      35             :     n.tail<3>() *= RAD2DEG;
      36             :     std::ostringstream oss;
      37             :     oss << std::fixed << std::setprecision(PRINT_PRECISION) << "pos=" << n.head<3>().transpose().format(EigFmt)
      38             :         << " rpy=" << n.tail<3>().transpose().format(EigFmt) << " deg";
      39             :     return oss.str();
      40             : }
      41             : 
      42             : /**
      43             :  * @brief Formats a State (pose + twist + acceleration) as a multi-line string.
      44             :  */
      45           1 : inline std::string fmt_state(const State& state) {
      46             :     Vector6d n = pose2n(state.pose);
      47             :     n.tail<3>() *= RAD2DEG;
      48             :     std::ostringstream oss;
      49             :     oss << std::fixed << std::setprecision(PRINT_PRECISION) << "pose=" << n.transpose().format(EigFmt)
      50             :         << " (xyz m, rpy deg)\n"
      51             :         << "twist=" << state.twist.transpose().format(EigFmt) << "\n"
      52             :         << "accel=" << state.acceleration.transpose().format(EigFmt);
      53             :     return oss.str();
      54             : }
      55             : 
      56             : // ── Box-drawing table helpers ──────────────────────────────────────────
      57             : 
      58           0 : inline void fmt_hline(std::ostringstream& s, int w, const char* l, const char* r) {
      59             :     s << l;
      60             :     for (int i = 0; i < w; ++i) s << "\xe2\x94\x80";
      61             :     s << r << "\n";
      62             : }
      63             : 
      64           0 : inline void fmt_row(std::ostringstream& s, int w, const std::string& content) {
      65             :     int pad = w - static_cast<int>(content.size());
      66             :     s << "\xe2\x94\x82" << content << std::string(std::max(pad, 0), ' ') << "\xe2\x94\x82\n";
      67             : }
      68             : 
      69           0 : inline std::string fmt_f(double v, int w = 7, int prec = 2) {
      70             :     std::ostringstream s;
      71             :     s << std::fixed << std::setprecision(prec) << std::setw(w) << v;
      72             :     return s.str();
      73             : }
      74             : 
      75           0 : inline std::string fmt_v3(const char* lbl, double a, double b, double c, const char* tag = "") {
      76             :     std::ostringstream r;
      77             :     r << "    " << std::setw(14) << std::left << lbl << std::right << "[" << fmt_f(a, 8) << "," << fmt_f(b, 8) << ","
      78             :       << fmt_f(c, 8) << "]";
      79             :     if (tag[0]) r << "  " << tag;
      80             :     return r.str();
      81             : }
      82             : 
      83           0 : inline std::string fmt_v6(const char* lbl, double a, double b, double c, double d, double e, double g) {
      84             :     std::ostringstream r;
      85             :     r << "    " << std::setw(10) << std::left << lbl << std::right << "[" << fmt_f(a) << "," << fmt_f(b) << ","
      86             :       << fmt_f(c) << "," << fmt_f(d) << "," << fmt_f(e) << "," << fmt_f(g) << "]";
      87             :     return r.str();
      88             : }
      89             : 
      90           0 : inline std::string fmt_scalar(const char* lbl, double v) {
      91             :     std::ostringstream r;
      92             :     r << "    " << std::setw(18) << std::left << lbl << std::right << fmt_f(v, 8);
      93             :     return r.str();
      94             : }
      95             : 
      96             : /**
      97             :  * @brief Formats a vehicle config struct as a boxed table string.
      98             :  *
      99             :  * Templated to avoid a hard dependency on ControlsROS2Wrapper::Params.
     100             :  */
     101             : template <typename Params>
     102           1 : std::string fmt_config(const Params& c) {
     103             :     static constexpr int W = 68;
     104             :     auto hl                = [](std::ostringstream& s, const char* l, const char* r) { fmt_hline(s, W, l, r); };
     105             :     auto r                 = [](std::ostringstream& s, const std::string& content) { fmt_row(s, W, content); };
     106             : 
     107             :     // clang-format off
     108             :     std::ostringstream os;
     109             :     os << "\n";
     110             : 
     111             :     hl(os, "\xe2\x94\x8c", "\xe2\x94\x90");
     112             :     r(os, "  Vehicle Configuration");
     113             :     hl(os, "\xe2\x94\x9c", "\xe2\x94\xa4");
     114             : 
     115             :     r(os, "  Dynamics");
     116             :     r(os, fmt_scalar("mass", c.mass));
     117             :     r(os, fmt_scalar("buoyancy_factor", c.buoyancy_factor));
     118             :     r(os, fmt_v3("inertia",    c.i_xx,     c.i_yy,      c.i_zz,     "xx yy zz"));
     119             :     r(os, fmt_v3("",           c.i_xy,     c.i_xz,      c.i_yz,     "xy xz yz"));
     120             :     r(os, fmt_v3("added_mass", c.ma_x,     c.ma_y,      c.ma_z,     "x  y  z"));
     121             :     r(os, fmt_v3("",           c.ma_roll,  c.ma_pitch,   c.ma_yaw,   "r  p  w"));
     122             :     r(os, fmt_v3("lin_drag",   c.dl_x,     c.dl_y,      c.dl_z,     "x  y  z"));
     123             :     r(os, fmt_v3("",           c.dl_roll,  c.dl_pitch,   c.dl_yaw,   "r  p  w"));
     124             :     r(os, fmt_v3("nl_drag",    c.dnl_x,    c.dnl_y,     c.dnl_z,    "x  y  z"));
     125             :     r(os, fmt_v3("",           c.dnl_roll, c.dnl_pitch,  c.dnl_yaw,  "r  p  w"));
     126             :     r(os, fmt_v3("r_bb",       c.rbb_x,    c.rbb_y,     c.rbb_z));
     127             :     r(os, fmt_v3("r_gb",       c.rgb_x,    c.rgb_y,     c.rgb_z));
     128             : 
     129             :     hl(os, "\xe2\x94\x9c", "\xe2\x94\xa4");
     130             :     r(os, "  Controller");
     131             :     r(os, fmt_scalar("ff", c.ff_gain));
     132             :     r(os, fmt_scalar("fb", c.fb_gain));
     133             :     r(os, fmt_scalar("buoyancy", c.buoyancy_gain));
     134             :     r(os, "    scheduling        " + std::string(c.surface_gain_scheduling ? "ON" : "OFF") + "  (threshold " + fmt_f(c.surface_threshold, 4) + ")");
     135             :     r(os, "");
     136             :     r(os, "                       x      y      z      r      p      w");
     137             :     r(os, fmt_v6("ax_gain", c.axis_gain_x, c.axis_gain_y, c.axis_gain_z, c.axis_gain_roll, c.axis_gain_pitch, c.axis_gain_yaw));
     138             :     r(os, fmt_v6("Kp",      c.kp_x,       c.kp_y,       c.kp_z,       c.kp_roll,       c.kp_pitch,       c.kp_yaw));
     139             :     r(os, fmt_v6("Ki",      c.ki_x,       c.ki_y,       c.ki_z,       c.ki_roll,       c.ki_pitch,       c.ki_yaw));
     140             :     r(os, fmt_v6("Kd",      c.kd_x,       c.kd_y,       c.kd_z,       c.kd_roll,       c.kd_pitch,       c.kd_yaw));
     141             :     r(os, fmt_v6("Kp_sf",   c.kp_x_surface, c.kp_y_surface, c.kp_z_surface, c.kp_roll_surface, c.kp_pitch_surface, c.kp_yaw_surface));
     142             :     r(os, fmt_v6("Ki_sf",   c.ki_x_surface, c.ki_y_surface, c.ki_z_surface, c.ki_roll_surface, c.ki_pitch_surface, c.ki_yaw_surface));
     143             :     r(os, fmt_v6("Kd_sf",   c.kd_x_surface, c.kd_y_surface, c.kd_z_surface, c.kd_roll_surface, c.kd_pitch_surface, c.kd_yaw_surface));
     144             : 
     145             :     hl(os, "\xe2\x94\x9c", "\xe2\x94\xa4");
     146             :     r(os, "  Trajectory Limits");
     147             :     r(os, "                       vel      acc     jerk");
     148             :     r(os, fmt_v3("xy",  c.max_xy_vel,  c.max_xy_acc,  c.max_xy_jerk));
     149             :     r(os, fmt_v3("z",   c.max_z_vel,   c.max_z_acc,   c.max_z_jerk));
     150             :     r(os, fmt_v3("yaw", c.max_yaw_vel, c.max_yaw_acc, c.max_yaw_jerk));
     151             :     r(os, fmt_scalar("slow_down_gain", c.slow_down_gain));
     152             : 
     153             :     hl(os, "\xe2\x94\x9c", "\xe2\x94\xa4");
     154             :     r(os, "  Thrust Allocation");
     155             :     r(os, fmt_v3("cg_offset", c.cg_offset_x, c.cg_offset_y, c.cg_offset_z));
     156             :     hl(os, "\xe2\x94\x94", "\xe2\x94\x98");
     157             :     // clang-format on
     158             : 
     159             :     return os.str();
     160             : }
     161             : 
     162             : #endif  // CONTROLS_UTILS_DEBUG_PRINT_H

Generated by: LCOV version 1.14