Background
Exploring my passion project involves analyzing an RC aircraft control input device. In the realm of this hobby, there is a common feature known as "stick expo" where control sticks vary in sensitivity based on their position. As I delve into this, I've come across some academic papers that are beyond my mathematical grasp.
I have devised a method to approximate the stick expo curve by taking samples and using linear interpolation between them. Now, I am seeking the most effective set of sample points for optimal results.
If we examine the growth curve typically seen in this scenario, it reveals both linear and curvy sections. While the current samples are equidistant from each other, I believe adjusting the density based on the rate of change can enhance resolution in curvier segments by reallocating points from straighter regions.
Is there a way to measure the margin of error? And if so, can we determine the ideal sample points for a given function with a fixed number of samples?
Reference Code
The code snippet below illustrates how a pre-calculated set of points is utilized to estimate an output value in C++.
/* Assumptions:
* 1. The _points[] data member contains at least 2 defined Points.
* 2. All defined Points have x and y values within certain limits.
* 3. The Points in the array are arranged in ascending order of x values.
*/
int InterpolatedCurve::value( int x ) {
if( _points[0].x >= x ) { return _points[0].y; }
for( unsigned int i = 1; i < _point_count; i++ ) {
if( _points[i].x >= x ) {
return map(x, _points[i-1].x, _points[i].x,
_points[i-1].y, _points[i].y);
}
}
// This is an error condition that is not otherwise reported.
// It won't happen as long as the points are set up correctly.
return x;
}
// Example map function (borrowed from Arduino site)
long map( long x, long x1, long x2, long y1, long y2 ) {
return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
}
While my main project is in C++, I'm utilizing a Google spreadsheet to generate numerical data as I brainstorm this dilemma.
// x: Input value between -1 and 1
// s: Scaling factor for curve between 0 (linear) and 1 (maximum curve)
// c: Tunable constant
function expo_fn( x, s, c ) {
s = typeof s !== 'undefined' ? s : 1.0;
c = typeof c !== 'undefined' ? c : 4.0;
var k = c * ((c - 1.0) * s*s*s + s)/c + 1.0;
return ((k - 1.0) * x*x*x*x*x + x)/k;
};
The following function generates evenly distributed (yet suboptimal) points between input values of -1 and 1. These outputs were transformed into integers for analysis, with a 'factor' parameter determining the level of curvature in the generated curve.
function Point( x, y ) {
this.x = x;
this.y = y;
};
function compute_points_iso( count, factor ) {
var points = [];
for( var i = 0; i < count; ++i ) {
var x = 2.0/(count - 1.0) * i - 1.0;
var y = expo_fn(x, factor);
points.push(new Point(x,y));
}
return points;
};
Relevant Academic Work
My exploration led me to this research paper detailing an algorithm for selecting significant data points. Though my current program faces challenges, I am dedicated to refining it further and will share updates once progress is made.