AiboPet's AiboHack Site
http://aibopet.com, http://aibohack.com


ERS-110, 111


ERS-210[A], 220[A]

Programming AIBO with:

YART, RCodePlus
OpenR SDK



ERS-311[B], 312[B], 31L


ERS7
Home
Movies (all)
PDAs: CLIE ( Panel Zipit )
Lesser Robots: Pleo ( RoboSapien ICybie )
Game Hacks: Nintendo Wii Nintendo DS ( PSP )
Email: aibopet@aibohack.com
[AiboHack] RCodePlus Double Precision Floating Point


RCodePlus Double Precision Floating Point


The floating point routines use one array as a FPU (floating point unit) register bank. The syntax is rather klunky if you write RCodePlus directly. Look at the debug code in the default RCodePlus personality (Mini-ObeyCat) for a simple test program.


Preparing to use floating point

Determine the number of floating point registers you need, and multiply it by 4 (8 bytes per FPU register). Use that number (##) in the following code:
    LOCAL fpu_array 25
    AP_DIM fpu_array ## // ## = number of FPU registers times 4
    SET AP_fpu fpu_array // use this array from now on
All DBL_ operations use indices into this array (that are first multiplied by 8 bytes). So your indices you use start with 0 and go up by 1.


Getting values in and out of FPU registers

To get floating point values in and out of RCODE variables (16 bit signed integers), a simple fixed point representation is used. The int_part is the integer part, and fract_part is the fractional part multiplied by 10000. For positive numbers, you can think of it as a "%d.%04d" format. Negative numbers get tricky (the int_part carries the sign, the fract_part does not).
The complete definition is:
    // float_value = int_part . fract_part
    if (int_part > 0)
    {
        // positive
	    assert(fract_part >= 0 && fract_part < 10000);
        float_value = int_part + fract_part / 10000;
    }
    else if (int_part < 0)
    {
        // negative, fract_part is not signed
	    assert(fract_part >= 0 && fract_part < 10000);
        float_value = int_part - fract_part / 10000;
    }
    else
    {
        // int_part = 0, in this case, fract_part is signed
	    assert(fract_part > -10000 && fract_part < 10000);
        float_value = int_part + fract_part / 10000;
    }

Try to keep values in the FPU registers for as long as you can, and only convert to RCODE variables when you need to.
Setting a FPU register (DBL_SET) comes in two forms, a constant or from another FPU register. Retreiving the current value (int_part, fract_part, perhaps with loss of precision) is done with DBL_GET. You can
	DBL_SET index int_part fract_part // fpu[index] = int_part . fract_part
	DBL_SET index index2  // fpu[index] = fpu

    DBL_GET index variable_for_int_part variable_for_fract_part

    For example:
        DBL_SET 1 10 5 // fpu[0] = 10.5
        DBL_GET 1 a b   // a = 10, b = 5


Binary Operations

The format of the binary operations are all the same. The first index is the destination (an FPU register), followed by the index of the first operand (an FPU register), followed by either one or two numbers. If one number, the second operand is an FPU register. If two numbers, the second operand is an immediate constant value (int_part . fract_part)
    DBL_ADD index0 index1 index2 // fpu[index0] = fpu[index1] + fpu[index2]
    DBL_ADD index0 index1 int_part fract_part // fpu[index0] = fpu[index1] + int_part . fract_part

    For example:
        DBL_ADD 9 9 1 0 // fpu[9] += 1.0
All the binary operators have the same format:

Unary Operations

The format of the unary operations are all the same. The first index is the destination (an FPU register), followed by either one or two numbers. If one number, the operand is an FPU register. If two numbers, it is an immediate constant value (int_part . fract_part)
    DBL_SIN index0 index1 // fpu[index0] = sin ( fpu[index1] )
    DBL_SIN index0 int_part fract_part // fpu[index0] = sin ( int_part . fract_part )

    For example:
        DBL_SIN 7 2 // fpu[7] = sin(fpu[2])
        DBL_EXP 8 1 0 // fpu[8] += e ^ 1 = e
All unary operators have the same format:

All trig is in radians. All logarithms are in base 'e'. Only primary functions are provided. You can create other functions (eg: cos()) or constants (e = exp(1), pi=2*atan(1,0)) by combining them