Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   Equation for joystick input to Talons (http://www.chiefdelphi.com/forums/showthread.php?t=125816)

Racer26 05-02-2014 17:44

Re: Equation for joystick input to Talons
 
y = x^2, and then if (x < 0) y= y * -1?

or y = x^3

Simplest approach.

Ether 05-02-2014 18:43

Re: Equation for joystick input to Talons
 
Quote:

Originally Posted by ekapalka (Post 1337852)
I would really like to know if there's an alternative to doing it this way, though :)

Code:

Here is your XY data:

-1.000 -1.000
-0.600 -0.800
-0.500 -0.500
-0.100 -0.005
 0.000  0.000
 0.100  0.005
 0.500  0.500
 0.600  0.800
 1.000  1.000

Here is your (machine generated) LUT code:

double y(double x) {
if (x < -1.000) return error();
else if (x <= -0.600) {return -0.500 + x*(0.5000);}
else if (x <= -0.500) {return  1.000 + x*(3.0000);}
else if (x <= -0.100) {return  0.119 + x*(1.2375);}
else if (x <=  0.100) {return  0.000 + x*(0.0500);}
else if (x <=  0.500) {return -0.119 + x*(1.2375);}
else if (x <=  0.600) {return -1.000 + x*(3.0000);}
else if (x <=  1.000) {return  0.500 + x*(0.5000);}
else return error();
}


apalrd 05-02-2014 19:37

Re: Equation for joystick input to Talons
 
If you like using lookup tables (I come from an automotive world where everything is pretty much a table or surface), you can write a routine to do it.

I do it as a two-step process. First, I 'prelookup' the fractional index of the input. Then, I interpolate the output. I have a 2d (1 input 1 output) and 3d (2 input 1 output) interpolation block, you simply use two prelookup blocks for the two inputs.

Header (structs):
Code:

/*
STRUCTURES
*/
typedef struct {
float frac,
int num
} prelookup_t;

Prelookup function:
Code:

/*
prelookup
Finds the lt/gt points for a given X vector and the fraction between them
Returns prelookup struct which can be used by interp_2d or interp_3d
*/
prelookup_t prelookup(float x, float *x_tbl, char size)
{
        int num_cur = 0;
        while(1)
        {
                if((x_tbl[num_cur] > x) || ((num_cur + 1) >= size)) break;
                num_cur++;
        }

        int num_last = num_cur - 1;
        //Find fraction between num_cur and num_cur--
        float lt, gt, tmp, range;
        prelookup_t out;
        lt = x_tbl[num_last];
        gt = x_tbl[num_cur];
        tmp = x - lt;
        range = gt - lt;
        out.frac = tmp / range;
        out.num = num_cur;
        return out;
}

Interp 2d function:
Code:

/*
interp_2d
Looks up a point in the z-table based on the prelookup from an x table
Assumes that z_tbl is the same size as the X table
*/
float interp_2d(prelookup_t x, float *z_tbl)
{
        int num_last = x.num - 1;
       
        //Find the two points on the z table
        float lt, gt, range, z_out;
        lt = z_tbl[num_last];
        gt = z_tbl[x.num];
        range = gt - lt;
        z_out = (range * x.frac) + lt;
       
        return z_out;
}

Interp 3d function:
Code:

/*
interp_3d
Interpolate a surface in three dimensions (x,y,z)
Takes X and Y prelookups and Z table
X size of the Z table is required to properly index the array
*/
float interp_3d(prelookup_t x, prelookup_t y float* z_tbl, int sizex)
{
        int x_num_last, x_num_cur, y_num_last, y_num_cur;
        x_num_cur = x.cur;
        y_num_cur = y.cur;
        x_num_last = x_num_cur - 1;
        y_num_last = y_num_cur - 1;
        //Find the two points on the z table
        //This isn't a great algorithm, but here's what we do:
        //Find the value using y_num_last and the two x points weighted by x_frac
        //Find the value using y_num_cur and the two x points weighted by x_frac
        //Weight the two values by y_frac
        float z_fracl,z_fracg,z_out;
        //Find frac less
        lt = z_tbl[(x_num_last*sizex+y_num_last)];
        gt = z_tbl[(x_num_cur*sizex+y_num_last)];
        range = gt - lt;
        z_fracl = (range * x.frac) + lt;
        //Find frac greater
        lt = z_tbl[(x_num_last*sizex+y_num_cur)];
        gt = z_tbl[(x_num_cur*sizex+y_num_cur)];
        range = gt - lt;
        z_fracg = (range * x.frac) + lt;
        //Find final weighted result
        z_out = (z_fracg * y.frac) + (z_fracl * (1 - y.frac));
       
        return z_out;
}


You can then write an interp curve as a pair of arrays, x and z. X must be monotonic (strictly increasing), z does not have to be. It will first find the points of x that bound the given point X and the fraction between them (the prelookup step). Then it finds the corresponding z points and weights them with the fraction, returning Z (output).

Surfaces are similar, but you instead have 2 arrays (x and y) and a 2-dimensional array z. The sizes of x and the first dimension of z must match, and the size of y and the second dimension of z must match. The function needs to know the x size to index the array.

In this way, you can make some really easily change the response of the curve or surface based on how you want it to be, non-linearly (there is no dependence between x and y as there would be in a multi-variable equation).

For more than 3 dimensions, an interpolation is impractical. If you need more dimensions, you can use multiplied factors (curve with a variable as the input which scales the output).

Ether 05-02-2014 21:29

Re: Equation for joystick input to Talons
 

If you pre-compute the slope between each pair of points in the XY table and store those in an array, it makes the lookup marginally faster (and the code a lot cleaner). You can do this pre-computation at runtime at power-up, or after loading a table into memory from a config file.

Once you've got a table that you're pretty sure won't need to be tweaked or tuned, you can do the pre-computation offline and hard-code the coefficients into the lookup routine (as was done in my previous post - I have an app that does this, to avoid human error).



Greg McKaskle 06-02-2014 01:23

Re: Equation for joystick input to Talons
 
If using LV, the interpolate function in the array palette accepts an array of XY pairs that are your control points. You can then pass in the fractional index and it will perform the search/interp approach.

Be sure the array is sorted, though.

Greg McKaskle


All times are GMT -5. The time now is 22:01.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi