41 #ifdef DO_PERFORMANCE_BENCHMARK
43 #define PERFORMANCE_BENCHMARK CTimeLoggerEntry tle(tl_holo, __CURRENT_FUNCTION_NAME__);
45 #define PERFORMANCE_BENCHMARK
52 #define COMMON_PTG_DESIGN_PARAMS \
53 const double vxi = m_nav_dyn_state.curVelLocal.vx, vyi = m_nav_dyn_state.curVelLocal.vy; \
54 const double vf_mod = internal_get_v(dir); \
55 const double vxf = vf_mod*cos(dir), vyf = vf_mod* sin(dir); \
56 const double T_ramp = internal_get_T_ramp(dir);
59 static double calc_trans_distance_t_below_Tramp_abc_analytic(
double t,
double a,
double b,
double c)
64 if (
t == 0.0)
return .0;
68 const double discr =
b*
b - 4 *
a*
c;
69 if (std::abs(discr)<1e-6)
71 const double r = -
b / (2 *
a);
73 dist =
r*std::abs(
r)*0.5 - (
r -
t)*std::abs(
r -
t)*0.5;
79 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);
81 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);
82 dist = int_t - int_t0;
99 const unsigned int NUM_STEPS = 15;
103 double feval_t = std::sqrt(
c);
106 const double At = T / (NUM_STEPS);
108 for (
unsigned int i = 0; i < NUM_STEPS; i++)
112 double dd =
a*
t*
t +
b*
t +
c;
118 feval_tp1 = sqrt(dd);
121 d += At*(feval_t+ feval_tp1)*0.5;
135 double ret = calc_trans_distance_t_below_Tramp_abc_analytic(
t,
a,
b,
c);
151 const double c = (vxi*vxi + vyi*vyi);
152 if (std::abs(k2)>
eps || std::abs(k4)>
eps)
154 const double a = ((k2*k2)*4.0 + (k4*k4)*4.0);
155 const double b = (k2*vxi*4.0 + k4*vyi*4.0);
158 if (std::abs(
b)<
eps && std::abs(
c)<
eps) {
160 const double int_t = sqrt(
a)*(
t*
t)*0.5;
164 return calc_trans_distance_t_below_Tramp_abc(
t,
a,
b,
c);
168 return std::sqrt(
c)*
t;
174 m_pathStepCountCache.assign(m_alphaValuesCount, -1);
182 m_alphaValuesCount = 31;
205 const int WN = 25, WV = 30;
209 cfg.
write(sSection,
"T_ramp_max",T_ramp_max, WN,WV,
"Max duration of the velocity interpolation since a vel_cmd is issued [s].");
210 cfg.
write(sSection,
"v_max_mps",V_MAX, WN,WV,
"Maximum linear velocity for trajectories [m/s].");
211 cfg.
write(sSection,
"w_max_dps",
mrpt::utils::RAD2DEG(W_MAX), WN,WV,
"Maximum angular velocity for trajectories [deg/s].");
212 cfg.
write(sSection,
"turningRadiusReference",turningRadiusReference, WN,WV,
"An approximate dimension of the robot (not a critical parameter) [m].");
214 cfg.
write(sSection,
"expr_V", expr_V, WN, WV,
"Math expr for |V| as a function of `dir`,`V_MAX`,`W_MAX`,`T_ramp_max`.");
215 cfg.
write(sSection,
"expr_W", expr_W, WN, WV,
"Math expr for |omega| (disregarding the sign, only the module) as a function of `dir`,`V_MAX`,`W_MAX`,`T_ramp_max`.");
216 cfg.
write(sSection,
"expr_T_ramp", expr_T_ramp, WN, WV,
"Math expr for `T_ramp` as a function of `dir`,`V_MAX`,`W_MAX`,`T_ramp_max`.");
226 return mrpt::format(
"PTG_Holo_Blend_Tramp=%.03f_Vmax=%.03f_Wmax=%.03f",T_ramp_max,V_MAX,W_MAX);
245 in >> T_ramp_max >> V_MAX >> W_MAX >> turningRadiusReference;
247 double dummy_maxAllowedDirAngle;
248 in >> dummy_maxAllowedDirAngle;
251 in >> expr_V >> expr_W >> expr_T_ramp;
270 out << T_ramp_max << V_MAX << W_MAX << turningRadiusReference;
271 out << expr_V << expr_W << expr_T_ramp;
281 const double err_threshold = 1e-3;
282 const double T_ramp = T_ramp_max;
283 const double vxi = m_nav_dyn_state.curVelLocal.vx, vyi = m_nav_dyn_state.curVelLocal.vy;
291 q[1]=V_MAX*
x/sqrt(
x*
x+
y*
y);
292 q[2]=V_MAX*
y/sqrt(
x*
x+
y*
y);
296 bool sol_found =
false;
297 for (
int iters=0;!sol_found && iters<25;iters++)
299 const double TR_ = 1.0/(T_ramp);
300 const double TR2_ = 1.0/(2*T_ramp);
306 r[0] = 0.5*T_ramp *( vxi +
q[1] ) + (
q[0]-T_ramp)*
q[1] -
x;
307 r[1] = 0.5*T_ramp *( vyi +
q[2] ) + (
q[0]-T_ramp)*
q[2] -
y;
311 r[0] = vxi *
q[0] +
q[0]*
q[0] * TR2_ * (
q[1]-vxi) -
x;
312 r[1] = vyi *
q[0] +
q[0]*
q[0] * TR2_ * (
q[2]-vyi) -
y;
314 const double alpha = atan2(
q[2],
q[1]);
316 r[2] =
q[1]*
q[1]+
q[2]*
q[2] - V_MAXsq;
325 J(0,0) =
q[1]; J(0,1) = 0.5*T_ramp+
q[0]; J(0,2) = 0.0;
326 J(1,0) =
q[2]; J(1,1) = 0.0; J(1,2) = 0.5*T_ramp+
q[0];
330 J(0,0) = vxi +
q[0]*TR_*(
q[1]-vxi); J(0,1) = TR2_*
q[0]*
q[0]; J(0,2) = 0.0;
331 J(1,0) = vyi +
q[0]*TR_*(
q[2]-vyi); J(1,1) = 0.0; J(1,2) = TR2_*
q[0]*
q[0];
333 J(2,0) = 0.0; J(2,1) = 2*
q[1]; J(2,2) = 2*
q[2];
335 Eigen::Vector3d q_incr = J.householderQr().solve(
r);
339 sol_found = (err_mod<err_threshold);
342 if (sol_found &&
q[0]>=.0)
344 const double alpha = atan2(
q[2],
q[1]);
347 const double solved_t =
q[0];
348 const unsigned int solved_step = solved_t/PATH_TIME_STEP;
349 const double found_dist = this->getPathDist(out_k, solved_step);
351 out_d = found_dist / this->refDistance;
363 return inverseMap_WS2TP(
x,
y,k,d);
376 cmd->
vel = internal_get_v(dir_local);
378 cmd->
ramp_time = internal_get_T_ramp(dir_local);
381 return mrpt::kinematics::CVehicleVelCmdPtr(cmd);
386 if (m_pathStepCountCache.size() > k && m_pathStepCountCache[k] > 0)
387 return m_pathStepCountCache[k];
390 if (!getPathStepForDist(k,this->refDistance,step)) {
391 THROW_EXCEPTION_FMT(
"Could not solve closed-form distance for k=%u",
static_cast<unsigned>(k));
394 if (m_pathStepCountCache.size() != m_alphaValuesCount) {
395 m_pathStepCountCache.assign(m_alphaValuesCount, -1);
397 m_pathStepCountCache[k] = step;
403 const double t = PATH_TIME_STEP*step;
407 const double TR2_ = 1.0/(2*T_ramp);
412 p.x = vxi *
t +
t*
t * TR2_ * (vxf - vxi);
413 p.y = vyi *
t +
t*
t * TR2_ * (vyf - vyi);
417 p.x = T_ramp *0.5*(vxi + vxf) + (
t - T_ramp) * vxf;
418 p.y = T_ramp *0.5*(vyi + vyf) + (
t - T_ramp) * vyf;
422 const double wi = m_nav_dyn_state.curVelLocal.omega;
427 const double a = TR2_ * (wf - wi),
b = (wi),
c = -dir;
435 const double t_solve = std::max(r1,r2);
439 p.phi = wi*
t +
t*
t* TR2_ * (wf-wi);
445 const double t_solve = (dir - T_ramp *0.5*(wi + wf))/wf + T_ramp;
449 p.phi = T_ramp *0.5*(wi + wf) + (
t - T_ramp) * wf;
455 const double t = PATH_TIME_STEP*step;
459 const double TR2_ = 1.0/(2*T_ramp);
461 const double k2 = (vxf-vxi)*TR2_;
462 const double k4 = (vyf-vyi)*TR2_;
466 return calc_trans_distance_t_below_Tramp(k2,k4,vxi,vyi,
t);
470 const double dist_trans = (
t-T_ramp) * V_MAX + calc_trans_distance_t_below_Tramp(k2,k4,vxi,vyi,T_ramp);
482 const double TR2_ = 1.0/(2*T_ramp);
484 const double k2 = (vxf-vxi)*TR2_;
485 const double k4 = (vyf-vyi)*TR2_;
490 const double dist_trans_T_ramp = calc_trans_distance_t_below_Tramp(k2,k4,vxi,vyi,T_ramp);
491 double t_solved = -1;
493 if (dist>=dist_trans_T_ramp)
496 t_solved = T_ramp + (dist-dist_trans_T_ramp)/V_MAX;
508 if (std::abs(k2)<
eps && std::abs(k4)<
eps)
511 t_solved = (dist)/V_MAX;
515 const double a = ((k2*k2)*4.0+(k4*k4)*4.0);
516 const double b = (k2*vxi*4.0+k4*vyi*4.0);
517 const double c = (vxi*vxi+vyi*vyi);
520 if (std::abs(
b)<
eps && std::abs(
c)<
eps)
523 t_solved = sqrt(2.0)*1.0/pow(
a,1.0/4.0)*sqrt(dist);
537 t_solved = T_ramp*0.6;
538 for (
int iters=0;iters<10;iters++)
540 double err = calc_trans_distance_t_below_Tramp_abc(t_solved,
a,
b,
c) - dist;
541 const double diff = std::sqrt(
a*t_solved*t_solved+
b*t_solved+
c);
543 t_solved -= (err) / diff;
546 if (std::abs(err)<1e-3)
563 const double R = m_robotRadius;
567 const double TR2_ = 1.0 / (2 * T_ramp);
568 const double TR_2 = T_ramp*0.5;
569 const double T_ramp_thres099 = T_ramp*0.99;
570 const double T_ramp_thres101 = T_ramp*1.01;
579 const double k2 = (vxf - vxi)*TR2_;
580 const double k4 = (vyf - vyi)*TR2_;
583 const double a = (k2*k2 + k4*k4);
584 const double b = (k2*vxi*2.0 + k4*vyi*2.0);
585 const double c = -(k2*ox*2.0 + k4*oy*2.0 - vxi*vxi - vyi*vyi);
586 const double d = -(ox*vxi*2.0 + oy*vyi*2.0);
587 const double e = -
R*
R + ox*ox + oy*oy;
590 int num_real_sols = 0;
597 else if (std::abs(
b)>
eps) {
606 const double discr = d*d - 4 *
c*e;
610 roots[0] = (-d + sqrt(discr)) / (2 *
c);
611 roots[1] = (-d - sqrt(discr)) / (2 *
c);
618 for (
int i = 0; i<num_real_sols; i++)
620 if (roots[i] == roots[i] &&
623 roots[i] <= T_ramp*1.01)
625 if (sol_t<0) sol_t = roots[i];
631 if (sol_t<0 || sol_t>T_ramp_thres101)
636 const double c1 = TR_2*(vxi - vxf) - ox;
637 const double c2 = TR_2*(vyi - vyf) - oy;
639 const double a = vf_mod*vf_mod;
640 const double b = 2 * (c1*vxf + c2*vyf);
641 const double c = c1*c1 + c2*c2 -
R*
R;
643 const double discr =
b*
b - 4 *
a*
c;
646 const double sol_t0 = (-
b + sqrt(discr)) / (2 *
a);
647 const double sol_t1 = (-
b - sqrt(discr)) / (2 *
a);
650 if (sol_t0<T_ramp && sol_t1<T_ramp) sol_t = -1.0;
651 else if (sol_t0<T_ramp && sol_t1 >= T_ramp_thres099) sol_t = sol_t1;
652 else if (sol_t1<T_ramp && sol_t0 >= T_ramp_thres099) sol_t = sol_t0;
653 else if (sol_t1 >= T_ramp_thres099 && sol_t0 >= T_ramp_thres099) sol_t =
std::min(sol_t0, sol_t1);
663 dist = calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi, sol_t);
664 else dist = (sol_t - T_ramp) * V_MAX + calc_trans_distance_t_below_Tramp(k2, k4, vxi, vyi, T_ramp);
667 internal_TPObsDistancePostprocess(ox, oy, dist, tp_obstacle_k);
674 for (
unsigned int k = 0; k < m_alphaValuesCount; k++)
676 updateTPObstacleSingle(ox, oy, k, tp_obstacles[k]);
699 const size_t nSteps = getPathStepCount(path_k);
700 const double max_t = PATH_TIME_STEP * (nSteps * 0.7 );
706 return PATH_TIME_STEP;
713 turningRadiusReference(0.30)
719 turningRadiusReference(0.30)
731 std::map<std::string, double *> symbols;
733 symbols[
"V_MAX"] = &
V_MAX;
734 symbols[
"W_MAX"] = &
W_MAX;
778 #ifdef DO_PERFORMANCE_BENCHMARK
#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 MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT(variableName, variableType, targetVariable, configFileObject, sectionNameStr)
#define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES_NO_DEFAULT(variableName, variableType, targetVariable, configFileObject, sectionNameStr)
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.
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). 0 means forward.
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...
A PTG for circular-shaped robots with holonomic kinematics.
void internal_initialize(const std::string &cacheFilename=std::string(), const bool verbose=true) MRPT_OVERRIDE
Must be called after setting all PTG parameters and before requesting converting obstacles to TP-Spac...
virtual double maxTimeInVelCmdNOP(int path_k) const MRPT_OVERRIDE
Only for PTGs supporting supportVelCmdNOP(): this is the maximum time (in seconds) for which the path...
double internal_get_v(const double dir) const
Evals expr_v.
std::vector< int > m_pathStepCountCache
mrpt::math::CRuntimeCompiledExpression m_expr_v
void onNewNavDynamicState() MRPT_OVERRIDE
Invoked when m_nav_dyn_state has changed; gives the PTG the opportunity to react and parameterize pat...
mrpt::math::CRuntimeCompiledExpression m_expr_T_ramp
bool PTG_IsIntoDomain(double x, double y) const MRPT_OVERRIDE
Returns the same than inverseMap_WS2TP() but without any additional cost.
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.
size_t getPathStepCount(uint16_t k) const MRPT_OVERRIDE
Access path k ([0,N-1]=>[-pi,pi] in alpha): number of discrete "steps" along the trajectory.
bool getPathStepForDist(uint16_t k, double dist, uint32_t &out_step) const MRPT_OVERRIDE
Access path k ([0,N-1]=>[-pi,pi] in alpha): largest step count for which the traversed distance is < ...
static double eps
Mathematical "epsilon", to detect ill-conditioned situations (e.g. 1/0) (Default: 1e-4)
void getPathPose(uint16_t k, uint32_t step, mrpt::math::TPose2D &p) const MRPT_OVERRIDE
Access path k ([0,N-1]=>[-pi,pi] in alpha): pose of the vehicle at discrete step step.
bool inverseMap_WS2TP(double x, double y, int &out_k, double &out_d, double tolerance_dist=0.10) const MRPT_OVERRIDE
Computes the closest (alpha,d) TP coordinates of the trajectory point closest to the Workspace (WS) C...
void updateTPObstacleSingle(double ox, double oy, uint16_t k, double &tp_obstacle_k) const MRPT_OVERRIDE
Like updateTPObstacle() but for one direction only (k) in TP-Space.
void updateTPObstacle(double ox, double oy, std::vector< double > &tp_obstacles) const MRPT_OVERRIDE
Updates the radial map of closest TP-Obstacles given a single obstacle point at (ox,...
void internal_processNewRobotShape() MRPT_OVERRIDE
Will be called whenever the robot shape is set / updated.
double getPathStepDuration() const MRPT_OVERRIDE
Returns the duration (in seconds) of each "step".
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...
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
static double PATH_TIME_STEP
Duration of each PTG "step" (default: 10e-3=10 ms)
double internal_get_w(const double dir) const
Evals expr_w.
std::string getDescription() const MRPT_OVERRIDE
Gets a short textual description of the PTG and its parameters.
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
mrpt::math::CRuntimeCompiledExpression m_expr_w
virtual mrpt::kinematics::CVehicleVelCmdPtr directionToMotionCommand(uint16_t k) const MRPT_OVERRIDE
Converts a discretized "alpha" value into a feasible motion command or action.
virtual void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &sSection) const MRPT_OVERRIDE
This method saves the options to a ".ini"-like file or memory-stored string list.
virtual bool supportVelCmdNOP() const MRPT_OVERRIDE
Returns true if it is possible to stop sending velocity commands to the robot and,...
virtual mrpt::kinematics::CVehicleVelCmdPtr getSupportedKinematicVelocityCommand() const MRPT_OVERRIDE
Returns an empty kinematic velocity command object of the type supported by this PTG.
virtual void loadFromConfigFile(const mrpt::utils::CConfigFileBase &cfg, const std::string &sSection) MRPT_OVERRIDE
Parameters accepted by this base class:
virtual void loadDefaultParams() MRPT_OVERRIDE
Loads a set of default parameters; provided exclusively for the PTG-configurator tool.
double getPathDist(uint16_t k, uint32_t step) const MRPT_OVERRIDE
Access path k ([0,N-1]=>[-pi,pi] in alpha): traversed distance at discrete step step.
void internal_construct_exprs()
void internal_deinitialize() MRPT_OVERRIDE
This must be called to de-initialize the PTG if some parameter is to be changed.
void loadShapeFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string §ion)
void internal_shape_loadFromStream(mrpt::utils::CStream &in)
void internal_shape_saveToStream(mrpt::utils::CStream &out) const
void loadDefaultParams() MRPT_OVERRIDE
Loads a set of default parameters; provided exclusively for the PTG-configurator tool.
void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &sSection) const MRPT_OVERRIDE
This method saves the options to a ".ini"-like file or memory-stored string list.
This is the base class for any user-defined PTG.
uint16_t alpha2index(double alpha) const
Discrete index value for the corresponding alpha value.
uint16_t m_alphaValuesCount
The number of discrete values for "alpha" between -PI and +PI.
virtual void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &sSection) const MRPT_OVERRIDE
This method saves the options to a ".ini"-like file or memory-stored string list.
virtual void internal_writeToStream(mrpt::utils::CStream &out) const
double index2alpha(uint16_t k) const
Alpha value for the discrete corresponding value.
virtual void loadFromConfigFile(const mrpt::utils::CConfigFileBase &cfg, const std::string &sSection) MRPT_OVERRIDE
Parameters accepted by this base class:
virtual void loadDefaultParams()
Loads a set of default parameters into the PTG.
virtual void internal_readFromStream(mrpt::utils::CStream &in)
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, const data_t &value, const int name_padding_width=-1, const int value_padding_width=-1, const std::string &comment=std::string())
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X),...
GLclampf GLclampf GLclampf alpha
GLdouble GLdouble GLdouble r
GLubyte GLubyte GLubyte a
GLsizei const GLchar ** string
GLdouble GLdouble GLdouble GLdouble q
bool BASE_IMPEXP isFinite(float f) MRPT_NO_THROWS
Returns true if the number is non infinity.
int round(const T value)
Returns the closer integer (int) to x.
int BASE_IMPEXP solve_poly2(double a, double b, double c, double &r1, double &r2) MRPT_NO_THROWS
Solves equation a*x^2 + b*x + c = 0.
int BASE_IMPEXP solve_poly3(double *x, double a, double b, double c) MRPT_NO_THROWS
Solves cubic equation x^3 + a*x^2 + b*x + c = 0.
int BASE_IMPEXP solve_poly4(double *x, double a, double b, double c, double d) MRPT_NO_THROWS
Solves quartic equation x^4 + a*x^3 + b*x^2 + c*x + d = 0 by Dekart-Euler method.
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
#define MRPT_CHECK_NORMAL_NUMBER(val)
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
T square(const T x)
Inline function for the square of a number.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
int signWithZero(T x)
Returns the sign of X as "0", "1" or "-1".
double DEG2RAD(const double x)
Degrees to radians.
double RAD2DEG(const double x)
Radians to degrees.
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.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
unsigned __int16 uint16_t
unsigned __int32 uint32_t