2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file interpolation.h
|
|
|
|
*
|
|
|
|
* @date Oct 17, 2013
|
2017-01-03 03:05:22 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2017
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef INTERPOLATION_3D_H_
|
|
|
|
#define INTERPOLATION_3D_H_
|
|
|
|
|
2016-06-29 20:01:53 -07:00
|
|
|
#include <math.h>
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "datalogging.h"
|
2016-06-29 20:01:53 -07:00
|
|
|
#include "efilib.h"
|
|
|
|
#include "obd_error_codes.h"
|
2016-06-29 22:01:38 -07:00
|
|
|
#include "error_handling.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2017-03-27 19:55:22 -07:00
|
|
|
#ifndef DEBUG_INTERPOLATION
|
2018-03-04 19:55:24 -08:00
|
|
|
#define DEBUG_INTERPOLATION FALSE
|
2017-03-27 19:55:22 -07:00
|
|
|
#endif
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#define INTERPOLATION_A(x1, y1, x2, y2) ((y1 - y2) / (x1 - x2))
|
|
|
|
|
|
|
|
int findIndex(const float array[], int size, float value);
|
2017-05-28 21:02:22 -07:00
|
|
|
int findIndexMsg(const char *msg, const float array[], int size, float value);
|
2017-06-06 20:11:29 -07:00
|
|
|
void ensureArrayIsAscending(const char *msg, const float array[], int size);
|
2015-07-10 06:01:56 -07:00
|
|
|
int findIndex2(const float array[], unsigned size, float value);
|
2017-08-01 13:27:16 -07:00
|
|
|
float interpolateClamped(float x1, float y1, float x2, float y2, float x);
|
2016-01-09 12:01:41 -08:00
|
|
|
float interpolateMsg(const char *msg, float x1, float y1, float x2, float y2, float x);
|
2019-01-16 05:24:37 -08:00
|
|
|
float interpolate2d(const char *msg, float value, const float bin[], const float values[], int size);
|
2016-06-29 20:01:53 -07:00
|
|
|
|
|
|
|
int needInterpolationLogging(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Two-dimensional table lookup with linear interpolation
|
|
|
|
*/
|
2019-06-10 09:38:32 -07:00
|
|
|
template<typename vType, typename kType>
|
|
|
|
float interpolate3d(float x, const kType xBin[], int xBinSize, float y, const kType yBin[], int yBinSize, vType* map[]) {
|
2016-06-29 20:01:53 -07:00
|
|
|
if (cisnan(x)) {
|
2018-01-23 09:05:14 -08:00
|
|
|
warning(CUSTOM_INTEPOLATE_ERROR_3, "%.2f: x is NaN in interpolate3d", x);
|
2016-06-29 20:01:53 -07:00
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
if (cisnan(y)) {
|
2018-01-23 09:05:14 -08:00
|
|
|
warning(CUSTOM_INTEPOLATE_ERROR_2, "%.2f: y is NaN in interpolate3d", y);
|
2016-06-29 20:01:53 -07:00
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
|
2017-05-28 21:02:22 -07:00
|
|
|
int xIndex = findIndexMsg("x", xBin, xBinSize, x);
|
2016-06-29 20:01:53 -07:00
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("X index=%d\r\n", xIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2017-05-28 21:02:22 -07:00
|
|
|
int yIndex = findIndexMsg("y", yBin, yBinSize, y);
|
2016-06-29 20:01:53 -07:00
|
|
|
if (xIndex < 0 && yIndex < 0) {
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("X and Y are smaller than smallest cell in table: %d\r\n", xIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2016-06-29 20:01:53 -07:00
|
|
|
return map[0][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xIndex < 0) {
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("X is smaller than smallest cell in table: %dr\n", xIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2016-06-29 20:01:53 -07:00
|
|
|
if (yIndex == yBinSize - 1)
|
|
|
|
return map[0][yIndex];
|
2019-06-10 09:38:32 -07:00
|
|
|
kType keyMin = yBin[yIndex];
|
|
|
|
kType keyMax = yBin[yIndex + 1];
|
|
|
|
vType rpmMinValue = map[0][yIndex];
|
|
|
|
vType rpmMaxValue = map[0][yIndex + 1];
|
2016-06-29 20:01:53 -07:00
|
|
|
|
|
|
|
return interpolateMsg("3d", keyMin, rpmMinValue, keyMax, rpmMaxValue, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (yIndex < 0) {
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("Y is smaller than smallest cell in table: %d\r\n", yIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2018-08-19 08:27:59 -07:00
|
|
|
if (xIndex == xBinSize - 1)
|
|
|
|
return map[xIndex][0];
|
2019-06-10 09:38:32 -07:00
|
|
|
kType key1 = xBin[xIndex];
|
|
|
|
kType key2 = xBin[xIndex + 1];
|
|
|
|
vType value1 = map[xIndex][0];
|
|
|
|
vType value2 = map[xIndex + 1][0];
|
2018-08-19 08:27:59 -07:00
|
|
|
|
|
|
|
return interpolateMsg("out3d", key1, value1, key2, value2, x);
|
2016-06-29 20:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (xIndex == xBinSize - 1 && yIndex == yBinSize - 1) {
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("X and Y are larger than largest cell in table: %d %d\r\n", xIndex, yIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2016-06-29 20:01:53 -07:00
|
|
|
return map[xBinSize - 1][yBinSize - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xIndex == xBinSize - 1) {
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("TODO BETTER LOGGING x overflow %d\r\n", yIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2018-08-19 08:27:59 -07:00
|
|
|
// here yIndex is less than yBinSize - 1, we've checked that condition already
|
|
|
|
|
2019-06-10 09:38:32 -07:00
|
|
|
kType key1 = yBin[yIndex];
|
|
|
|
kType key2 = yBin[yIndex + 1];
|
|
|
|
vType value1 = map[xIndex][yIndex];
|
|
|
|
vType value2 = map[xIndex][yIndex + 1];
|
2018-08-19 08:27:59 -07:00
|
|
|
|
|
|
|
return interpolateMsg("out3d", key1, value1, key2, value2, y);
|
2016-06-29 20:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (yIndex == yBinSize - 1) {
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging())
|
|
|
|
printf("Y is larger than largest cell in table: %d\r\n", yIndex);
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2018-08-19 08:27:59 -07:00
|
|
|
// here xIndex is less than xBinSize - 1, we've checked that condition already
|
|
|
|
|
2019-06-10 09:38:32 -07:00
|
|
|
kType key1 = xBin[xIndex];
|
|
|
|
kType key2 = xBin[xIndex + 1];
|
|
|
|
vType value1 = map[xIndex][yIndex];
|
|
|
|
vType value2 = map[xIndex + 1][yIndex];
|
2018-08-19 08:27:59 -07:00
|
|
|
|
|
|
|
return interpolateMsg("out3d", key1, value1, key2, value2, x);
|
2016-06-29 20:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* first we find the interpolated value for this RPM
|
|
|
|
*/
|
|
|
|
int rpmMaxIndex = xIndex + 1;
|
|
|
|
|
2019-06-10 09:38:32 -07:00
|
|
|
kType xMin = xBin[xIndex];
|
|
|
|
kType xMax = xBin[xIndex + 1];
|
|
|
|
vType rpmMinKeyMinValue = map[xIndex][yIndex];
|
|
|
|
vType rpmMaxKeyMinValue = map[xIndex + 1][yIndex];
|
2016-06-29 20:01:53 -07:00
|
|
|
|
2019-06-10 09:38:32 -07:00
|
|
|
vType keyMinValue = interpolateMsg("", xMin, rpmMinKeyMinValue, xMax, rpmMaxKeyMinValue, x);
|
2016-06-29 20:01:53 -07:00
|
|
|
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging()) {
|
2018-01-23 09:05:14 -08:00
|
|
|
printf("X=%.2f:\r\nrange %.2f - %.2f\r\n", x, xMin, xMax);
|
|
|
|
printf("X interpolation range %.2f %.2f result %.2f\r\n", rpmMinKeyMinValue, rpmMaxKeyMinValue, keyMinValue);
|
2016-06-29 20:01:53 -07:00
|
|
|
}
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2016-06-29 20:01:53 -07:00
|
|
|
|
|
|
|
int keyMaxIndex = yIndex + 1;
|
2019-06-10 09:38:32 -07:00
|
|
|
kType keyMin = yBin[yIndex];
|
|
|
|
kType keyMax = yBin[keyMaxIndex];
|
|
|
|
vType rpmMinKeyMaxValue = map[xIndex][keyMaxIndex];
|
|
|
|
vType rpmMaxKeyMaxValue = map[rpmMaxIndex][keyMaxIndex];
|
2016-06-29 20:01:53 -07:00
|
|
|
|
2019-06-10 09:38:32 -07:00
|
|
|
vType keyMaxValue = interpolateMsg("3d", xMin, rpmMinKeyMaxValue, xMax, rpmMaxKeyMaxValue, x);
|
2016-06-29 20:01:53 -07:00
|
|
|
|
|
|
|
#if DEBUG_INTERPOLATION
|
|
|
|
if (needInterpolationLogging()) {
|
2018-01-23 09:05:14 -08:00
|
|
|
printf("key=%.2f:\r\nrange %.2f - %.2f\r\n", y, keyMin, keyMax);
|
|
|
|
printf("key interpolation range %.2f %.2f result %.2f\r\n", rpmMinKeyMaxValue, rpmMaxKeyMaxValue, keyMaxValue);
|
2016-06-29 20:01:53 -07:00
|
|
|
}
|
2018-01-02 11:33:22 -08:00
|
|
|
#endif /* DEBUG_INTERPOLATION */
|
2016-06-29 20:01:53 -07:00
|
|
|
|
|
|
|
float result = interpolateMsg("3d", keyMin, keyMinValue, keyMax, keyMaxValue, y);
|
|
|
|
return result;
|
|
|
|
}
|
2017-06-11 12:06:05 -07:00
|
|
|
void setCurveValue(float bins[], float values[], int size, float key, float value);
|
2015-07-10 06:01:56 -07:00
|
|
|
void initInterpolation(Logging *sharedLogger);
|
|
|
|
|
|
|
|
class FastInterpolation {
|
|
|
|
public:
|
|
|
|
FastInterpolation();
|
|
|
|
FastInterpolation(float x1, float y1, float x2, float y2);
|
|
|
|
void init(float x1, float y1, float x2, float y2);
|
2019-06-08 06:51:36 -07:00
|
|
|
float getValue(float x) const;
|
2015-07-10 06:01:56 -07:00
|
|
|
private:
|
|
|
|
float a, b;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* INTERPOLATION_3D_H_ */
|