mrs_lib
Various reusable classes, functions and utilities for use in MRS projects
Loading...
Searching...
No Matches
quadratic_throttle_model.h
1#ifndef QUADRATIC_THRUST_MODEL_H
2#define QUADRATIC_THRUST_MODEL_H
3
4#include <cmath>
5#include <mrs_lib/param_loader.h>
6
7namespace mrs_lib
8{
9
10 namespace quadratic_throttle_model
11 {
12
14 {
15 motor_params_t() = default;
16
17 motor_params_t(int n_motors, double a, double b) : n_motors(n_motors), a(a), b(b), c(0), type(type_t::legacy), an(0), bn(0), cn(0)
18 {
19 }
20
21 motor_params_t(int n_motors, double a, double b, double c)
22 : n_motors(n_motors), a(a), b(b), c(c), type(type_t::full_quadratic), an(a * n_motors), bn(b * n_motors), cn(c * n_motors)
23 {
24 if (a < 1e-6)
25 type = type_t::linear;
26 }
27
28 void initialize(mrs_lib::ParamLoader& pl)
29 {
30 // motor params are not prefixed, since they are common to more nodes
31 pl.loadParam<double>("motor_params/a", a);
32 pl.loadParam<double>("motor_params/b", b);
33 type = type_t::legacy;
34 const auto c_loaded = pl.loadParam("motor_params/c", c, 0.0);
35 pl.loadParam("motor_params/n_motors", n_motors);
36
37 if (c_loaded)
38 {
39 type = type_t::full_quadratic;
40 an = a * n_motors;
41 bn = b * n_motors;
42 cn = c * n_motors;
43
44 if (a < 1e-6)
45 type = type_t::linear;
46 }
47 }
48
49 int n_motors;
50 double a;
51 double b;
52 double c;
53 enum class type_t
54 {
55 legacy,
56 full_quadratic,
57 linear,
58 } type;
59
60 // helper pre-computed constants
61 double an;
62 double bn;
63 double cn;
64 };
65
66 double inline throttleToForce(const motor_params_t& motor_params, const double throttle)
67 {
68 if (motor_params.type == motor_params_t::type_t::full_quadratic || motor_params.type == motor_params_t::type_t::linear)
69 // F = N*( a*T^2 + b*T + c )
70 return motor_params.n_motors * (motor_params.a * throttle * throttle + motor_params.b * throttle + motor_params.c);
71 else
72 // F = N*( (T - b)/a )^2
73 return motor_params.n_motors * pow((throttle - motor_params.b) / motor_params.a, 2);
74 }
75
76 double inline forceToThrottle(const motor_params_t& motor_params, const double force)
77 {
78 if (motor_params.type == motor_params_t::type_t::linear || motor_params.a < 1e-6)
79 {
80 // F = N*( b*T + c )
81 // F = b*N*T + c*N
82 // 0 = b*N*T + c*N - F
83 // T = ( F - c*N ) / ( b*N )
84 if (motor_params.bn < 1e-6)
85 {
86 // RCLCPP_ERROR_THROTTLE(1.0, "forceToThrottle: The N*b parameter is too small!");
87 return 0.0;
88 }
89 return (force - motor_params.cn) / motor_params.bn;
90 } else if (motor_params.type == motor_params_t::type_t::full_quadratic)
91 {
92 // F = N*( a*T^2 + b*T + c )
93 // F = a*N*^2 + b*N*T + c*N
94 // 0 = a*N*T^2 + b*N*T + ( c*N - F )
95 // a' = a*N, b' = b*N, c' = c*N - F
96
97 const double cp = motor_params.cn - force;
98 double discriminant = motor_params.bn * motor_params.bn - 4.0 * motor_params.an * cp;
99 // TODO: add some warning here
100 if (discriminant < 0.0)
101 {
102 // RCLCPP_ERROR_THROTTLE(1.0, "forceToThrottle: Discriminant of throttle solution is negative, setting zero!");
103 discriminant = 0;
104 }
105 // only the right half of the parabole is used, so only root1 is necessary
106 const double root1 = (-motor_params.bn + std::sqrt(discriminant)) / (2 * motor_params.an);
107 /* const double root2 = (- motor_params.bn - std::sqrt( discriminant )) / (2 * motor_params.an); */
108 return std::clamp(root1, 0.0, 1.0);
109 } else
110 // the legacy computation
111 return sqrt(force / motor_params.n_motors) * motor_params.a + motor_params.b;
112 }
113
114 } // namespace quadratic_throttle_model
115
116} // namespace mrs_lib
117
118#endif // QUADRATIC_THRUST_MODEL_H
Convenience class for loading parameters from rosparam server.
Definition param_loader.h:46
bool loadParam(const std::string &name, T &out_value, const T &default_value)
Loads a parameter from the rosparam server with a default value.
Definition param_loader.hpp:304
All mrs_lib functions, classes, variables and definitions are contained in this namespace.
Definition attitude_converter.h:24
Definition quadratic_throttle_model.h:14