bancada-motores/Control/VF Control/slprj/speedgoat/_sharedutils/rt_TDelayInterpolate.cpp
Pedro Jose Romero Gombau 447269b383 Si
2024-10-28 11:36:48 +01:00

203 lines
5.3 KiB
C++

/*
* rt_TDelayInterpolate.cpp
*
* Academic License - for use in teaching, academic research, and meeting
* course requirements at degree granting institutions only. Not for
* government, commercial, or other organizational use.
*
* Code generation for model "VFControl".
*
* Model version : 1.1
* Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
* C++ source code generated on : Wed Oct 16 11:32:21 2024
* Created for block: <S3>/Transport Delay
*/
#include "rt_TDelayInterpolate.h"
#include <cfloat>
#include <cmath>
#include "rtwtypes.h"
/*
* Time delay interpolation routine
*
* The linear interpolation is performed using the formula:
*
* (t2 - tMinusDelay) (tMinusDelay - t1)
* u(t) = ----------------- * u1 + ------------------- * u2
* (t2 - t1) (t2 - t1)
*/
real_T rt_TDelayInterpolate(
real_T tMinusDelay, /* tMinusDelay = currentSimTime - delay */
real_T tStart,
real_T *uBuf,
int_T bufSz,
int_T *lastIdx,
int_T oldestIdx,
int_T newIdx,
real_T initOutput,
boolean_T discrete,
boolean_T minorStepAndTAtLastMajorOutput)
{
int_T i;
real_T yout, t1, t2, u1, u2;
real_T* tBuf = uBuf + bufSz;
/*
* If there is only one data point in the buffer, this data point must be
* the t= 0 and tMinusDelay > t0, it ask for something unknown. The best
* guess if initial output as well
*/
if ((newIdx == 0) && (oldestIdx ==0 ) && (tMinusDelay > tStart))
return initOutput;
/*
* If tMinusDelay is less than zero, should output initial value
*/
if (tMinusDelay <= tStart)
return initOutput;
/* For fixed buffer extrapolation:
* if tMinusDelay is small than the time at oldestIdx, if discrete, output
* tailptr value, else use tailptr and tailptr+1 value to extrapolate
* It is also for fixed buffer. Note: The same condition can happen for transport delay block where
* use tStart and and t[tail] other than using t[tail] and t[tail+1].
* See below
*/
if ((tMinusDelay <= tBuf[oldestIdx] ) ) {
if (discrete) {
return(uBuf[oldestIdx]);
} else {
int_T tempIdx= oldestIdx + 1;
if (oldestIdx == bufSz-1)
tempIdx = 0;
t1= tBuf[oldestIdx];
t2= tBuf[tempIdx];
u1= uBuf[oldestIdx];
u2= uBuf[tempIdx];
if (t2 == t1) {
if (tMinusDelay >= t2) {
yout = u2;
} else {
yout = u1;
}
} else {
real_T f1 = (t2-tMinusDelay) / (t2-t1);
real_T f2 = 1.0 - f1;
/*
* Use Lagrange's interpolation formula. Exact outputs at t1, t2.
*/
yout = f1*u1 + f2*u2;
}
return yout;
}
}
/*
* When block does not have direct feedthrough, we use the table of
* values to extrapolate off the end of the table for delays that are less
* than 0 (less then step size). This is not completely accurate. The
* chain of events is as follows for a given time t. Major output - look
* in table. Update - add entry to table. Now, if we call the output at
* time t again, there is a new entry in the table. For very small delays,
* this means that we will have a different answer from the previous call
* to the output fcn at the same time t. The following code prevents this
* from happening.
*/
if (minorStepAndTAtLastMajorOutput) {
/* pretend that the new entry has not been added to table */
if (newIdx != 0) {
if (*lastIdx == newIdx) {
(*lastIdx)--;
}
newIdx--;
} else {
if (*lastIdx == newIdx) {
*lastIdx = bufSz-1;
}
newIdx = bufSz - 1;
}
}
i = *lastIdx;
if (tBuf[i] < tMinusDelay) {
/* Look forward starting at last index */
while (tBuf[i] < tMinusDelay) {
/* May occur if the delay is less than step-size - extrapolate */
if (i == newIdx)
break;
i = ( i < (bufSz-1) ) ? (i+1) : 0;/* move through buffer */
}
} else {
/*
* Look backwards starting at last index which can happen when the
* delay time increases.
*/
while (tBuf[i] >= tMinusDelay) {
/*
* Due to the entry condition at top of function, we
* should never hit the end.
*/
i = (i > 0) ? i-1 : (bufSz-1); /* move through buffer */
}
i = ( i < (bufSz-1) ) ? (i+1) : 0;
}
*lastIdx = i;
if (discrete) {
/*
* tempEps = 128 * eps;
* localEps = max(tempEps, tempEps*fabs(tBuf[i]))/2;
*/
double tempEps = (DBL_EPSILON) * 128.0;
double localEps = tempEps * std::abs(tBuf[i]);
if (tempEps > localEps) {
localEps = tempEps;
}
localEps = localEps / 2.0;
if (tMinusDelay >= (tBuf[i] - localEps)) {
yout = uBuf[i];
} else {
if (i == 0) {
yout = uBuf[bufSz-1];
} else {
yout = uBuf[i-1];
}
}
} else {
if (i == 0) {
t1 = tBuf[bufSz-1];
u1 = uBuf[bufSz-1];
} else {
t1 = tBuf[i-1];
u1 = uBuf[i-1];
}
t2 = tBuf[i];
u2 = uBuf[i];
if (t2 == t1) {
if (tMinusDelay >= t2) {
yout = u2;
} else {
yout = u1;
}
} else {
real_T f1 = (t2-tMinusDelay) / (t2-t1);
real_T f2 = 1.0 - f1;
/*
* Use Lagrange's interpolation formula. Exact outputs at t1, t2.
*/
yout = f1*u1 + f2*u2;
}
}
return(yout);
}