42 #ifdef DO_PERFORMANCE_BENCHMARK 44 #define PERFORMANCE_BENCHMARK \ 45 CTimeLoggerEntry tle(tl_holo, __CURRENT_FUNCTION_NAME__); 47 #define PERFORMANCE_BENCHMARK 55 #define COMMON_PTG_DESIGN_PARAMS \ 56 const double vxi = m_nav_dyn_state.curVelLocal.vx, \ 57 vyi = m_nav_dyn_state.curVelLocal.vy; \ 58 const double vf_mod = internal_get_v(dir); \ 59 const double vxf = vf_mod * cos(dir), vyf = vf_mod * sin(dir); \ 60 const double T_ramp = internal_get_T_ramp(dir); 63 static double calc_trans_distance_t_below_Tramp_abc_analytic(
double t,
double a,
double b,
double c)
68 if (
t == 0.0)
return .0;
72 const double discr =
b*
b - 4 *
a*
c;
73 if (std::abs(discr)<1e-6)
75 const double r = -
b / (2 *
a);
77 dist =
r*std::abs(
r)*0.5 - (
r -
t)*std::abs(
r -
t)*0.5;
83 const double int_t = (
t*(1.0 / 2.0) + (
b*(1.0 / 4.0)) /
a)*sqrt(
c +
b*
t +
a*(
t*
t)) + 1.0 / pow(
a, 3.0 / 2.0)*log(1.0 / sqrt(
a)*(
b*(1.0 / 2.0) +
a*
t) + sqrt(
c +
b*
t +
a*(
t*
t)))*(
a*
c - (
b*
b)*(1.0 / 4.0))*(1.0 / 2.0);
85 const double int_t0 = (
b*sqrt(
c)*(1.0 / 4.0)) /
a + 1.0 / pow(
a, 3.0 / 2.0)*log(1.0 / sqrt(
a)*(
b + sqrt(
a)*sqrt(
c)*2.0)*(1.0 / 2.0))*(
a*
c - (
b*
b)*(1.0 / 4.0))*(1.0 / 2.0);
86 dist = int_t - int_t0;
99 double T,
double a,
double b,
double c)
104 const unsigned int NUM_STEPS = 15;
108 double feval_t = std::sqrt(
c);
111 const double At = T / (NUM_STEPS);
113 for (
unsigned int i = 0; i < NUM_STEPS; i++)
117 double dd =
a *
t *
t +
b *
t +
c;
123 feval_tp1 = sqrt(dd);
126 d += At * (feval_t + feval_tp1) * 0.5;
137 double t,
double a,
double b,
double c)
142 double ret = calc_trans_distance_t_below_Tramp_abc_analytic(
t,
a,
b,
c);
153 double k2,
double k4,
double vxi,
double vyi,
double t)
160 const double c = (vxi * vxi + vyi * vyi);
161 if (std::abs(k2) >
eps || std::abs(k4) >
eps)
163 const double a = ((k2 * k2) * 4.0 + (k4 * k4) * 4.0);
164 const double b = (k2 * vxi * 4.0 + k4 * vyi * 4.0);
167 if (std::abs(
b) <
eps && std::abs(
c) <
eps)
170 const double int_t = sqrt(
a) * (
t *
t) * 0.5;
175 return calc_trans_distance_t_below_Tramp_abc(
t,
a,
b,
c);
180 return std::sqrt(
c) *
t;
186 m_pathStepCountCache.assign(m_alphaValuesCount, -1);
194 m_alphaValuesCount = 31;
207 T_ramp_max,
double, T_ramp_max, cfg, sSection);
209 v_max_mps,
double, V_MAX, cfg, sSection);
211 w_max_dps,
double, W_MAX, cfg, sSection);
222 const int WN = 25, WV = 30;
227 sSection,
"T_ramp_max", T_ramp_max, WN, WV,
228 "Max duration of the velocity interpolation since a vel_cmd is issued " 231 sSection,
"v_max_mps", V_MAX, WN, WV,
232 "Maximum linear velocity for trajectories [m/s].");
235 "Maximum angular velocity for trajectories [deg/s].");
237 sSection,
"turningRadiusReference", turningRadiusReference, WN, WV,
238 "An approximate dimension of the robot (not a critical parameter) " 242 sSection,
"expr_V", expr_V, WN, WV,
243 "Math expr for |V| as a function of " 244 "`dir`,`V_MAX`,`W_MAX`,`T_ramp_max`.");
246 sSection,
"expr_W", expr_W, WN, WV,
247 "Math expr for |omega| (disregarding the sign, only the module) as a " 248 "function of `dir`,`V_MAX`,`W_MAX`,`T_ramp_max`.");
250 sSection,
"expr_T_ramp", expr_T_ramp, WN, WV,
251 "Math expr for `T_ramp` as a function of " 252 "`dir`,`V_MAX`,`W_MAX`,`T_ramp_max`.");
262 "PTG_Holo_Blend_Tramp=%.03f_Vmax=%.03f_Wmax=%.03f", T_ramp_max, V_MAX,
283 in >> T_ramp_max >> V_MAX >> W_MAX >> turningRadiusReference;
286 double dummy_maxAllowedDirAngle;
287 in >> dummy_maxAllowedDirAngle;
291 in >> expr_V >> expr_W >> expr_T_ramp;
305 out << T_ramp_max << V_MAX << W_MAX << turningRadiusReference;
306 out << expr_V << expr_W << expr_T_ramp;
310 double x,
double y,
int& out_k,
double& out_d,
double tolerance_dist)
const 317 const double err_threshold = 1e-3;
318 const double T_ramp = T_ramp_max;
319 const double vxi = m_nav_dyn_state.curVelLocal.vx,
320 vyi = m_nav_dyn_state.curVelLocal.vy;
328 q[0] = T_ramp_max * 1.1;
329 q[1] = V_MAX *
x / sqrt(
x *
x +
y *
y);
330 q[2] = V_MAX *
y / sqrt(
x *
x +
y *
y);
333 double err_mod = 1e7;
334 bool sol_found =
false;
335 for (
int iters = 0; !sol_found && iters < 25; iters++)
337 const double TR_ = 1.0 / (T_ramp);
338 const double TR2_ = 1.0 / (2 * T_ramp);
344 r[0] = 0.5 * T_ramp * (vxi +
q[1]) + (
q[0] - T_ramp) *
q[1] -
x;
345 r[1] = 0.5 * T_ramp * (vyi +
q[2]) + (
q[0] - T_ramp) *
q[2] -
y;
349 r[0] = vxi *
q[0] +
q[0] *
q[0] * TR2_ * (
q[1] - vxi) -
x;
350 r[1] = vyi *
q[0] +
q[0] *
q[0] * TR2_ * (
q[2] - vyi) -
y;
352 const double alpha = atan2(
q[2],
q[1]);
354 r[2] =
q[1] *
q[1] +
q[2] *
q[2] - V_MAXsq;
364 J(0, 1) = 0.5 * T_ramp +
q[0];
368 J(1, 2) = 0.5 * T_ramp +
q[0];
372 J(0, 0) = vxi +
q[0] * TR_ * (
q[1] - vxi);
373 J(0, 1) = TR2_ *
q[0] *
q[0];
375 J(1, 0) = vyi +
q[0] * TR_ * (
q[2] - vyi);
377 J(1, 2) = TR2_ *
q[0] *
q[0];
383 Eigen::Vector3d q_incr = J.householderQr().solve(
r);
387 sol_found = (err_mod < err_threshold);
390 if (sol_found &&
q[0] >= .0)
392 const double alpha = atan2(
q[2],
q[1]);
395 const double solved_t =
q[0];
396 const unsigned int solved_step = solved_t / PATH_TIME_STEP;
397 const double found_dist = this->getPathDist(out_k, solved_step);
399 out_d = found_dist / this->refDistance;
412 return inverseMap_WS2TP(
x,
y, k, d);
427 cmd->
vel = internal_get_v(dir_local);
429 cmd->
ramp_time = internal_get_T_ramp(dir_local);
437 if (m_pathStepCountCache.size() > k && m_pathStepCountCache[k] > 0)
438 return m_pathStepCountCache[k];
441 if (!getPathStepForDist(k, this->refDistance, step))
444 "Could not solve closed-form distance for k=%u",
445 static_cast<unsigned>(k));
448 if (m_pathStepCountCache.size() != m_alphaValuesCount)
450 m_pathStepCountCache.assign(m_alphaValuesCount, -1);
452 m_pathStepCountCache[k] = step;
459 const double t = PATH_TIME_STEP * step;
463 const double TR2_ = 1.0 / (2 * T_ramp);
468 p.x = vxi *
t +
t *
t * TR2_ * (vxf - vxi);
469 p.y = vyi *
t +
t *
t * TR2_ * (vyf - vyi);
473 p.x = T_ramp * 0.5 * (vxi + vxf) + (
t - T_ramp) * vxf;
474 p.y = T_ramp * 0.5 * (vyi + vyf) + (
t - T_ramp) * vyf;
478 const double wi = m_nav_dyn_state.curVelLocal.omega;
483 const double a = TR2_ * (wf - wi),
b = (wi),
c = -
dir;
494 const double t_solve = std::max(r1, r2);
498 p.phi = wi *
t +
t *
t * TR2_ * (wf - wi);
504 const double t_solve = (
dir - T_ramp * 0.5 * (wi + wf)) / wf + T_ramp;
508 p.phi = T_ramp * 0.5 * (wi + wf) + (
t - T_ramp) * wf;
514 const double t = PATH_TIME_STEP * step;
518 const double TR2_ = 1.0 / (2 * T_ramp);
520 const double k2 = (vxf - vxi) * TR2_;
521 const double k4 = (vyf - vyi) * TR2_;
525 return calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi,
t);
529 const double dist_trans =
530 (
t - T_ramp) * V_MAX +
531 calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi, T_ramp);
544 const double TR2_ = 1.0 / (2 * T_ramp);
546 const double k2 = (vxf - vxi) * TR2_;
547 const double k4 = (vyf - vyi) * TR2_;
552 const double dist_trans_T_ramp =
553 calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi, T_ramp);
554 double t_solved = -1;
556 if (dist >= dist_trans_T_ramp)
559 t_solved = T_ramp + (dist - dist_trans_T_ramp) / V_MAX;
571 if (std::abs(k2) <
eps && std::abs(k4) <
eps)
574 t_solved = (dist) / V_MAX;
578 const double a = ((k2 * k2) * 4.0 + (k4 * k4) * 4.0);
579 const double b = (k2 * vxi * 4.0 + k4 * vyi * 4.0);
580 const double c = (vxi * vxi + vyi * vyi);
583 if (std::abs(
b) <
eps && std::abs(
c) <
eps)
586 t_solved = sqrt(2.0) * 1.0 / pow(
a, 1.0 / 4.0) * sqrt(dist);
604 t_solved = T_ramp * 0.6;
607 for (
int iters = 0; iters < 10; iters++)
609 double err = calc_trans_distance_t_below_Tramp_abc(
613 std::sqrt(
a * t_solved * t_solved +
b * t_solved +
c);
614 ASSERT_(std::abs(diff) > 1e-40);
615 t_solved -= (err) / diff;
616 if (t_solved < 0) t_solved = .0;
617 if (std::abs(err) < 1e-3)
break;
632 double ox,
double oy,
uint16_t k,
double& tp_obstacle_k)
const 634 const double R = m_robotRadius;
638 const double TR2_ = 1.0 / (2 * T_ramp);
639 const double TR_2 = T_ramp * 0.5;
640 const double T_ramp_thres099 = T_ramp * 0.99;
641 const double T_ramp_thres101 = T_ramp * 1.01;
653 const double k2 = (vxf - vxi) * TR2_;
654 const double k4 = (vyf - vyi) * TR2_;
657 const double a = (k2 * k2 + k4 * k4);
658 const double b = (k2 * vxi * 2.0 + k4 * vyi * 2.0);
659 const double c = -(k2 * ox * 2.0 + k4 * oy * 2.0 - vxi * vxi - vyi * vyi);
660 const double d = -(ox * vxi * 2.0 + oy * vyi * 2.0);
661 const double e = -
R *
R + ox * ox + oy * oy;
664 int num_real_sols = 0;
665 if (std::abs(
a) >
eps)
672 else if (std::abs(
b) >
eps)
682 const double discr = d * d - 4 *
c * e;
686 roots[0] = (-d + sqrt(discr)) / (2 *
c);
687 roots[1] = (-d - sqrt(discr)) / (2 *
c);
695 for (
int i = 0; i < num_real_sols; i++)
697 if (roots[i] == roots[i] &&
698 std::isfinite(roots[i]) && roots[i] >= .0 &&
699 roots[i] <= T_ramp * 1.01)
709 if (sol_t < 0 || sol_t > T_ramp_thres101)
714 const double c1 = TR_2 * (vxi - vxf) - ox;
715 const double c2 = TR_2 * (vyi - vyf) - oy;
717 const double a = vf_mod * vf_mod;
718 const double b = 2 * (c1 * vxf + c2 * vyf);
719 const double c = c1 * c1 + c2 * c2 -
R *
R;
721 const double discr =
b *
b - 4 *
a *
c;
724 const double sol_t0 = (-
b + sqrt(discr)) / (2 *
a);
725 const double sol_t1 = (-
b - sqrt(discr)) / (2 *
a);
728 if (sol_t0 < T_ramp && sol_t1 < T_ramp)
730 else if (sol_t0 < T_ramp && sol_t1 >= T_ramp_thres099)
732 else if (sol_t1 < T_ramp && sol_t0 >= T_ramp_thres099)
734 else if (sol_t1 >= T_ramp_thres099 && sol_t0 >= T_ramp_thres099)
740 if (sol_t < 0)
return;
745 dist = calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi, sol_t);
747 dist = (sol_t - T_ramp) * V_MAX +
748 calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi, T_ramp);
751 internal_TPObsDistancePostprocess(ox, oy, dist, tp_obstacle_k);
755 double ox,
double oy, std::vector<double>& tp_obstacles)
const 759 for (
unsigned int k = 0; k < m_alphaValuesCount; k++)
761 updateTPObstacleSingle(ox, oy, k, tp_obstacles[k]);
783 const size_t nSteps = getPathStepCount(path_k);
793 : T_ramp_max(-1.0), V_MAX(-1.0), W_MAX(-1.0), turningRadiusReference(0.30)
800 : turningRadiusReference(0.30)
809 std::map<std::string, double*> symbols;
811 symbols[
"V_MAX"] = &
V_MAX;
812 symbols[
"W_MAX"] = &
W_MAX;
843 const std::string& cacheFilename,
const bool verbose)
856 expr_T_ramp, std::map<std::string, double>(),
"expr_T_ramp");
858 #ifdef DO_PERFORMANCE_BENCHMARK double index2alpha(uint16_t k) const
Alpha value for the discrete corresponding value.
void internal_initialize(const std::string &cacheFilename=std::string(), const bool verbose=true) override
Must be called after setting all PTG parameters and before requesting converting obstacles to TP-Spac...
GLclampf GLclampf GLclampf alpha
void loadDefaultParams() override
Loads a set of default parameters; provided exclusively for the PTG-configurator tool.
virtual void internal_writeToStream(mrpt::serialization::CArchive &out) const
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
unsigned __int16 uint16_t
double RAD2DEG(const double x)
Radians to degrees.
virtual void saveToConfigFile(mrpt::config::CConfigFileBase &cfg, const std::string &sSection) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...
#define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES_NO_DEFAULT( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
std::string getDescription() const override
Gets a short textual description of the PTG and its parameters.
double getPathDist(uint16_t k, uint32_t step) const override
Access path k ([0,N-1]=>[-pi,pi] in alpha): traversed distance at discrete step step.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
double DEG2RAD(const double x)
Degrees to radians.
bool getPathStepForDist(uint16_t k, double dist, uint32_t &out_step) const override
Access path k ([0,N-1]=>[-pi,pi] in alpha): largest step count for which the traversed distance is < ...
GLdouble GLdouble GLdouble GLdouble q
bool PTG_IsIntoDomain(double x, double y) const override
Returns the same than inverseMap_WS2TP() but without any additional cost.
void internal_shape_saveToStream(mrpt::serialization::CArchive &out) const
int signWithZero(T x)
Returns the sign of X as "0", "1" or "-1".
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
void internal_deinitialize() override
This must be called to de-initialize the PTG if some parameter is to be changed.
static double calc_trans_distance_t_below_Tramp(double k2, double k4, double vxi, double vyi, double t)
Axiliary function for computing the line-integral distance along the trajectory, handling special cas...
void internal_construct_exprs()
virtual double maxTimeInVelCmdNOP(int path_k) const override
Only for PTGs supporting supportVelCmdNOP(): this is the maximum time (in seconds) for which the path...
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
T square(const T x)
Inline function for the square of a number.
double internal_get_v(const double dir) const
Evals expr_v.
void getPathPose(uint16_t k, uint32_t step, mrpt::math::TPose2D &p) const override
Access path k ([0,N-1]=>[-pi,pi] in alpha): pose of the vehicle at discrete step step.
virtual void loadDefaultParams()
Loads a set of default parameters into the PTG.
#define ASSERT_(f)
Defines an assertion mechanism.
double ramp_time
: Blending time between current and target time.
This is the base class for any user-defined PTG.
This class allows loading and storing values and vectors of different types from a configuration text...
A PTG for circular-shaped robots with holonomic kinematics.
#define MRPT_CHECK_NORMAL_NUMBER(v)
Throws an exception if the number is NaN, IND, or +/-INF, or return the same number otherwise...
double dir_local
: direction, relative to the current robot heading (radians).
double getPathStepDuration() const override
Returns the duration (in seconds) of each "step".
mrpt::expr::CRuntimeCompiledExpression m_expr_v
std::vector< int > m_pathStepCountCache
double internal_get_w(const double dir) const
Evals expr_w.
virtual void loadDefaultParams() override
Loads a set of default parameters; provided exclusively for the PTG-configurator tool.
int solve_poly4(double *x, double a, double b, double c, double d) noexcept
Solves quartic equation x^4 + a*x^3 + b*x^2 + c*x + d = 0 by Dekart-Euler method. ...
void register_symbol_table(const std::map< std::string, double *> &variables)
Can be used before calling compile() to register additional variables by means of pointers instead of...
void onNewNavDynamicState() override
Invoked when m_nav_dyn_state has changed; gives the PTG the opportunity to react and parameterize pat...
void updateTPObstacle(double ox, double oy, std::vector< double > &tp_obstacles) const override
Updates the radial map of closest TP-Obstacles given a single obstacle point at (ox,oy)
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
virtual bool supportVelCmdNOP() const override
Returns true if it is possible to stop sending velocity commands to the robot and, still, the robot controller will be able to keep following the last sent trajectory ("NOP" velocity commands).
GLsizei const GLchar ** string
void write(const std::string §ion, const std::string &name, enum_t value, const int name_padding_width=-1, const int value_padding_width=-1, const std::string &comment=std::string())
void compile(const std::string &expression, const std::map< std::string, double > &variables=std::map< std::string, double >(), const std::string &expr_name_for_error_reporting=std::string())
Initializes the object by compiling an expression.
bool inverseMap_WS2TP(double x, double y, int &out_k, double &out_d, double tolerance_dist=0.10) const override
Computes the closest (alpha,d) TP coordinates of the trajectory point closest to the Workspace (WS) C...
#define MRPT_LOAD_CONFIG_VAR( variableName, variableType, configFileObject, sectionNameStr)
An useful macro for loading variables stored in a INI-like file under a key with the same name that t...
void updateTPObstacleSingle(double ox, double oy, uint16_t k, double &tp_obstacle_k) const override
Like updateTPObstacle() but for one direction only (k) in TP-Space.
static double calc_trans_distance_t_below_Tramp_abc(double t, double a, double b, double c)
Axiliary function for calc_trans_distance_t_below_Tramp() and others.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
static double calc_trans_distance_t_below_Tramp_abc_numeric(double T, double a, double b, double c)
Virtual base class for "archives": classes abstracting I/O streams.
GLdouble GLdouble GLdouble r
virtual void loadFromConfigFile(const mrpt::config::CConfigFileBase &cfg, const std::string &sSection) override
Parameters accepted by this base class:
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
static double PATH_TIME_STEP
Duration of each PTG "step" (default: 10e-3=10 ms)
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
double eval() const
Evaluates the current value of the precompiled formula.
double internal_get_T_ramp(const double dir) const
Evals expr_T_ramp.
virtual void internal_readFromStream(mrpt::serialization::CArchive &in)
mrpt::expr::CRuntimeCompiledExpression m_expr_T_ramp
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
void internal_processNewRobotShape() override
Will be called whenever the robot shape is set / updated.
#define PERFORMANCE_BENCHMARK
#define MRPT_LOAD_HERE_CONFIG_VAR( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
void loadShapeFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion)
size_t getPathStepCount(uint16_t k) const override
Access path k ([0,N-1]=>[-pi,pi] in alpha): number of discrete "steps" along the trajectory.
static double eps
Mathematical "epsilon", to detect ill-conditioned situations (e.g.
virtual void loadFromConfigFile(const mrpt::config::CConfigFileBase &cfg, const std::string &sSection) override
Parameters accepted by this base class:
std::shared_ptr< CVehicleVelCmd > Ptr
#define MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
unsigned __int32 uint32_t
virtual ~CPTG_Holo_Blend()
GLubyte GLubyte GLubyte a
virtual void saveToConfigFile(mrpt::config::CConfigFileBase &cfg, const std::string &sSection) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...
double rot_speed
: (rad/s) rotational speed for rotating such as the robot slowly faces forward.
int solve_poly3(double *x, double a, double b, double c) noexcept
Solves cubic equation x^3 + a*x^2 + b*x + c = 0.
virtual mrpt::kinematics::CVehicleVelCmd::Ptr directionToMotionCommand(uint16_t k) const override
Converts a discretized "alpha" value into a feasible motion command or action.
virtual mrpt::kinematics::CVehicleVelCmd::Ptr getSupportedKinematicVelocityCommand() const override
Returns an empty kinematic velocity command object of the type supported by this PTG.
#define COMMON_PTG_DESIGN_PARAMS
uint16_t m_alphaValuesCount
The number of discrete values for "alpha" between -PI and +PI.
void internal_shape_loadFromStream(mrpt::serialization::CArchive &in)
void saveToConfigFile(mrpt::config::CConfigFileBase &cfg, const std::string &sSection) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...
uint16_t alpha2index(double alpha) const
Discrete index value for the corresponding alpha value.
int solve_poly2(double a, double b, double c, double &r1, double &r2) noexcept
Solves equation a*x^2 + b*x + c = 0.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
mrpt::expr::CRuntimeCompiledExpression m_expr_w
int round(const T value)
Returns the closer integer (int) to x.