Error executing a mathematical expresion

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
Arthurmed
Posts: 4
Joined: Thu Aug 07, 2014 9:20 am

Error executing a mathematical expresion

Post by Arthurmed » Tue Aug 26, 2014 4:27 pm

Hi there,

Currently I am programming a class to communicate with an accelerometer(ADXL345) through I2C bus. The bus works nice and I can communicate with this device without difficulties. However, when I try to calculate the Euler angles using the atan2 function, it returns me a wrong result. For example:

Code: Select all

>>> math.atan2(0.0108, math.sqrt(0.0288 ** 2 + 0.846 ** 2))
0.0
However, If a execute the same expresion in a terminal on my PC using python3, it return me a valid result:

Code: Select all

>>> math.atan2(0.0108, math.sqrt(0.0288 ** 2 + 0.846 ** 2))
0.012757874448614656
Any idea about what is going on?

Thanks in advance,

Arthurmed.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Error executing a mathematical expresion

Post by dhylands » Wed Aug 27, 2014 1:52 am

Yeah - there are still some unimplemented functionality:
See: https://github.com/micropython/micropyt ... ath.c#L117

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Error executing a mathematical expresion

Post by pythoncoder » Wed Aug 27, 2014 5:51 am

Computing arctangents efficiently is a common requirement in embedded systems. The following article might provide some guidance.
http://www.embedded.com/design/other/42 ... roximation

Regards, Pete
Peter Hinch
Index to my micropython libraries.

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: Error executing a mathematical expresion

Post by fma » Wed Aug 27, 2014 6:04 am

BTW, other math functions has been imported from the musl lib; why the reminding ones are not?
Frédéric

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Error executing a mathematical expresion

Post by dhylands » Wed Aug 27, 2014 6:22 am

I think that somebody just has to do it, verify that the licenses are compatible, write some tests....

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Error executing a mathematical expresion

Post by pythoncoder » Wed Aug 27, 2014 9:23 am

I don't know if the full implementations might be a little on the large size - not to mention slow. OTOH there's a lot to be said for full cPython compatibility. In embedded applications it's common to use approximate, fast functions for trig where errors are determined by sensors rather than maths. Out of curiosity I tested the methods outlined in the article I cited.

Code: Select all

import math # for test only
PI = 3.141592653
def approxatan2(q, i): # q is imaginary part
    K = 0.28125
    if (q < 0 and i < 0 and -q <= -i):
        q, i = i + q, i - q
        return -3*PI/4 - i*q/(q*q + K*i*i)
    if (q >=0 and i >= 0 and q <= i) or (q <= 0 and i >= 0 and -q <= i): # 1st or 8th octant
        return i*q/(i*i + K*q*q)
    if (q >=0 and i >= 0 and q >= i) or (q >= 0 and i <= 0 and q >= -i): # 2nd or 3rd
        return PI/2 - i*q/(q*q + K*i*i)
    if (q >= 0 and i <= 0 and q <= -i) or (q <= 0 and i <= 0 and -q <= -i): # 4th or 5th
        return PI + i*q/(i*i + K*q*q)
    return -PI/2 - i*q/(q*q + K*i*i)

# Method described in Rafc's comment adapted for two argument arctan (full 2*PI range)
def atan_approx(x):
    b = 0.596227
    return (PI/2)*(b*x + x*x)/(1 + 2*b*x + x*x)

def atan2_approx(q, i):
    if i > 0:           # In quadrants 1,2,7,8
        x = q/i
        if x >= 0:
            return atan_approx(x)
        return -atan_approx(-x)
    else:
        i, q = -i, -q   # rotate by PI to put in q 1,2,7,8
        x = q/i
        if x >= 0:
            return atan_approx(x) - PI 
        return -atan_approx(-x) + PI

def test():
    for func in (approxatan2, atan2_approx):
        maxerror = 0.0
        for i in (1.0, -1.0):
            q = -40
            while q < 40:
                theirs, mine = math.atan2(q,i), func(q,i)
                error = theirs -mine
                maxerror = max(maxerror, abs(error))
                if abs(error) > 0.1:
                    print("i = {:7.4f} q = {:7.4f}".format(i,q))
                    print("math {:7.4f} mine {:7.4f} error {:7.4f}".format(theirs, mine, error))
                q += 0.01
        print("Max error (radians): {:7.4f} degs: {:7.4f}".format(maxerror, maxerror*180/PI))
For obvious reasons the test only works in cPython.
Results as expected:
>>> atan.test()
Max error (radians): 0.0049 degs: 0.2813
Max error (radians): 0.0028 degs: 0.1620

As for the two algorithms, you pays yer money and you makes yer choice ;)

Regards, Pete
Peter Hinch
Index to my micropython libraries.

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: Error executing a mathematical expresion

Post by blmorris » Wed Aug 27, 2014 3:49 pm

Over on Github, @pfalcon posted an RFC a little while ago on the best way to proceed with filling in the remaining math functions: https://github.com/micropython/micropython/issues/748
The question is whether to proceed as things have been done, manually copying license-appropriate code from musl or newlib into stmhal/math.c, or whether the math functions should instead be implemented by creating a new top-level directory, libm/, and populating that directly with math function files from musl and/or newlib.

I have an interest in seeing full the full set of math functions implemented eventually, but no informed opinion on the best way to accomplish this.

If I ever get around to creating my motorized star-tracking telescope mount - not in the next few months, anyway - I would probably be willing to trade off quite a bit of execution speed for a bit more precision, but for many other applications the speed-accuracy tradeoff certainly goes the other way.

-Bryan

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Error executing a mathematical expresion

Post by pythoncoder » Thu Aug 28, 2014 6:24 am

You are quite right, Bryan - the issue of astronomical calculations had occurred to me as one where accuracy is paramount. Yet in other embedded applications speed can be vital: I've seen systems which resorted to lookup tables. On balance my vote (if I had one) would be for providing cPython standard functions if code size constraints permit. Anyone needing faster options could code their own C library. There's little point in implementing the "fast" algorithms in Python if my quick benchmarks on a PC are anything to go by: math.atan2 proved four times quicker than the two alternatives, doubtless because it's coded in C.

The native code emitters could change this balance, but until we have math.atan2 on Micropython we've no means of knowing.

Regards, Pete
Peter Hinch
Index to my micropython libraries.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Error executing a mathematical expresion

Post by dhylands » Thu Aug 28, 2014 7:23 am

Keep in mind that micropython only knows about 32-bit floats
CPython is working with a 64-bit double.

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: Error executing a mathematical expresion

Post by blmorris » Fri Aug 29, 2014 3:31 pm

dhylands wrote:Keep in mind that micropython only knows about 32-bit floats
CPython is working with a 64-bit double.
Thanks Dave, that is an important point that I hadn't considered. Somehow I imagined that a set of double-precision floating point operations could be built up from single precision floats, but never thought about how that might work; after all, you can't simply concatenate floats like you can with integers to increase your precision.

I suppose that given sufficient processing time, it is still possible to achieve any arbitrary level of precision using long or multi-precision integers and emulated floating point routines.

At any rate, this could all be overkill, and I am still a very long way from implementing any high-precision astronomical calculations - my motorized telescope mount is still in the paper sketch / wishful thinking stage. If it ever does go anywhere, I will post about it here ;)

Post Reply