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
static double calc_trans_distance_t_below_Tramp_abc_numeric(double T, double a, double b, double c)
#define PERFORMANCE_BENCHMARK
#define COMMON_PTG_DESIGN_PARAMS
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
This class allows loading and storing values and vectors of different types from a configuration text...
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.
double eval() const
Evaluates the current value of the precompiled formula.
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...
double rot_speed
: (rad/s) rotational speed for rotating such as the robot slowly faces forward.
double ramp_time
: Blending time between current and target time.
double dir_local
: direction, relative to the current robot heading (radians).
std::shared_ptr< CVehicleVelCmd > Ptr
A PTG for circular-shaped robots with holonomic kinematics.
void internal_deinitialize() override
This must be called to de-initialize the PTG if some parameter is to be changed.
double internal_get_v(const double dir) const
Evals expr_v.
void onNewNavDynamicState() override
Invoked when m_nav_dyn_state has changed; gives the PTG the opportunity to react and parameterize pat...
std::vector< int > m_pathStepCountCache
virtual double maxTimeInVelCmdNOP(int path_k) const override
Only for PTGs supporting supportVelCmdNOP(): this is the maximum time (in seconds) for which the path...
virtual mrpt::kinematics::CVehicleVelCmd::Ptr getSupportedKinematicVelocityCommand() const override
Returns an empty kinematic velocity command object of the type supported by this PTG.
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.
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.
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
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.
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...
virtual bool supportVelCmdNOP() const override
Returns true if it is possible to stop sending velocity commands to the robot and,...
virtual void loadDefaultParams() override
Loads a set of default parameters; provided exclusively for the PTG-configurator tool.
virtual void loadFromConfigFile(const mrpt::config::CConfigFileBase &cfg, const std::string &sSection) override
Parameters accepted by this base class:
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,...
std::string getDescription() const override
Gets a short textual description of the PTG and its parameters.
double getPathStepDuration() const override
Returns the duration (in seconds) of each "step".
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...
virtual ~CPTG_Holo_Blend()
double internal_get_T_ramp(const double dir) const
Evals expr_T_ramp.
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...
mrpt::expr::CRuntimeCompiledExpression m_expr_v
mrpt::expr::CRuntimeCompiledExpression m_expr_w
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.
void internal_processNewRobotShape() override
Will be called whenever the robot shape is set / updated.
double internal_get_w(const double dir) const
Evals expr_w.
virtual mrpt::kinematics::CVehicleVelCmd::Ptr directionToMotionCommand(uint16_t k) const override
Converts a discretized "alpha" value into a feasible motion command or action.
static double eps
Mathematical "epsilon", to detect ill-conditioned situations (e.g.
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.
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
bool PTG_IsIntoDomain(double x, double y) const override
Returns the same than inverseMap_WS2TP() but without any additional cost.
static double PATH_TIME_STEP
Duration of each PTG "step" (default: 10e-3=10 ms)
mrpt::expr::CRuntimeCompiledExpression m_expr_T_ramp
void internal_construct_exprs()
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
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 < ...
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.
void loadShapeFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion)
void internal_shape_loadFromStream(mrpt::serialization::CArchive &in)
void loadDefaultParams() override
Loads a set of default parameters; provided exclusively for the PTG-configurator tool.
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.
void internal_shape_saveToStream(mrpt::serialization::CArchive &out) const
This is the base class for any user-defined PTG.
uint16_t alpha2index(double alpha) const
Discrete index value for the corresponding alpha value.
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.
uint16_t m_alphaValuesCount
The number of discrete values for "alpha" between -PI and +PI.
virtual void internal_writeToStream(mrpt::serialization::CArchive &out) const
virtual void internal_readFromStream(mrpt::serialization::CArchive &in)
double index2alpha(uint16_t k) const
Alpha value for the discrete corresponding value.
virtual void loadFromConfigFile(const mrpt::config::CConfigFileBase &cfg, const std::string &sSection) override
Parameters accepted by this base class:
virtual void loadDefaultParams()
Loads a set of default parameters into the PTG.
Virtual base class for "archives": classes abstracting I/O streams.
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X),...
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
#define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES_NO_DEFAULT( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
#define MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
#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...
#define MRPT_LOAD_HERE_CONFIG_VAR( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
#define ASSERT_(f)
Defines an assertion mechanism.
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
#define MRPT_CHECK_NORMAL_NUMBER(v)
Throws an exception if the number is NaN, IND, or +/-INF, or return the same number otherwise.
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
GLclampf GLclampf GLclampf alpha
GLdouble GLdouble GLdouble r
GLubyte GLubyte GLubyte a
GLsizei const GLchar ** string
GLdouble GLdouble GLdouble GLdouble q
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
int round(const T value)
Returns the closer integer (int) to x.
int solve_poly2(double a, double b, double c, double &r1, double &r2) noexcept
Solves equation a*x^2 + b*x + c = 0.
int solve_poly3(double *x, double a, double b, double c) noexcept
Solves cubic equation x^3 + a*x^2 + b*x + c = 0.
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.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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.
int signWithZero(T x)
Returns the sign of X as "0", "1" or "-1".
T square(const T x)
Inline function for the square of a number.
double RAD2DEG(const double x)
Radians to degrees.
double DEG2RAD(const double x)
Degrees to radians.
unsigned __int16 uint16_t
unsigned __int32 uint32_t