Setup a Arc Cos Table

Hi All,

I’ve been working on a AL5B robotic arm. I noticed that there is a bug in the current IDE concerning FACOS in the range 0.61 to 0.68 and 0.92 to 0.94. This forced me to use a table for the acrcos function. Which is faster anyway 8)

The table represents the shape of the function from 0 to 1. The function translates the cos input to the correct table position to get the correct shape-value. This shape value is a multiplier to calculate the correct angle in radials.

The function uses values with 4 decimals. The biggest accuracy error is 0.00308 rad = 0.17 degrees. More then enough for my servos :wink:

Here is a small demo program prints the range to the serial port:

[code] c4DEC con 10000

GetACos bytetable 255,253,252,251,250,248,247,246,244,243,242,241,239,238,237,235,234,233,232,230,229,228,226,|
225,224,223,221,220,219,217,216,215,213,212,211,209,208,207,206,204,203,201,200,199,197,196,|
195,193,192,191,189,188,186,185,184,182,181,179,178,177,175,174,172,171,169,168,166,165,163,|
162,160,159,157,156,154,153,151,149,148,146,145,143,141,140,138,136,135,133,131,129,128,126,|
124,122,120,118,116,115,113,111,109,106,104,102,100,98,96,93,91,89,86,83,81,78,75,73,70,66,63,|
60,56,52,48,44,38,33,26,15,0

;GetSinCos
cos4 var sword ;Input Cosinus of the given Angle, decimals = 4
AngleRad4 var sword ;Output Angle in radials, decimals = 4

Index var sword
Index=-1000
;====================================================================
main:

GoSub GetArcCos[Index*10]

serout s_out, i57600, [sdec index, " ",sdec AngleRad4 , " ", real FACOS(TOFLOAT(Index)/1000.0), 13]

IF Index < 1000 THEN
Index = Index+10
ELSE
Index = -1000
ENDIF

pause 100
goto main
;====================================================================
;[GETARCCOS] Get the sinus and cosinus from the angle +/- multiple circles
;Cos4 - Input Cosinus
;AngleRad4 - Output Angle in AngleRad4
GetArcCos[Cos4]

Cos4 = (Cos4 max c4DEC) min -c4DEC
IF Cos4>=0 THEN
AngleRad4 = GetACos(Cos4/78+1) ;78=table resolution (1/127)
AngleRad4 = AngleRad462 ;62=acos resolution (pi/2/255)
ELSE
AngleRad4 = GetACos(-Cos4/78+1)
AngleRad4 = 31416-AngleRad4
62 ;62=acos resolution (pi/2/255)
ENDIF

return AngleRad4[/code]

Xan

EDIT: Improved function can be found in one of the newer posts. Please read whole topic.

Hi Xan,

Great work with the fixed point FACOS function! Have you tried replacing the FACOS in the Phoenix code (LegIK) yet? Would be great to get rid of that little bug there too. Especially the 0.61 - 0.68 was a bit irritating.

Even better when its faster though! 8)

Great work… not that i understand it. :blush: :wink:

[code] IKA2 = FACOS((TOFLOAT((FemurLengthFemurLength) - (TibiaLengthTibiaLength)) + (IKSWIKSW)) / (TOFLOAT(2Femurlength) * IKSW))

;IKFemurAngle
IKFemurAngle = (TOINT(((IKA1 + IKA2) * 180.0) / 3.141592)*-1)+90

;IKTibiaAngle
IKTibiaAngle = (90-TOINT(((FACOS((TOFLOAT((FemurLength*FemurLength) + (TibiaLength*TibiaLength)) - (IKSW*IKSW)) / TOFLOAT(2*Femurlength*TibiaLength)))*180.0) / 3.141592)) * -1[/code]

IKA1 var float ;Angle between SW line and the ground in rad IKA2 var float ;?

with regards to the IKA2, what is it doing? as its quoted with a :question:

Nope, I didn’t had the time to give it a try but it shouldn’t be to hard in V2.0. I think I’ll try it this week because it made a real difference on the arm. The arm moves really steady now so this also will be a major improvement on the phoenix!

I took a quick peek at Zenta’s PEP to answer that one :wink:

“This is the angle of the line S>W with respect to the humerus, expressed in radiansâ€

sorry should have updated my post earlier. i already looked into it.

Have you managed to get any vids of the AL5B.

How are you finding the kit?
cheers…
…J

No problem. This reminds me that I need to update my commends in the code. :wink:

The kit is really neat! Very solid. I changed the setup by dropping the SSC and only use a BB2 with BAP. This made one of the servo wires to short so I needed a extra extension wire. I had to get myself some of these (forgot there name again… :frowning:). The tube needs a really tight fit to make it solid and I only had some metric keys.

I’m planning to start a topic on this including some pics and vids. I hope to do it later on this week.

Xan

Did you mean Hex Standoffs? :wink:

Nope, just the tool itself the Hex keys. So simple, jet so hard to remember. The name is totally different in dutch that’s why I keep forgetting it. LOL

The ulna is made from a aluminium tube and got a bolts to connect it to the hub.

Xan

aka Allen Wrench. :wink:

Oh, so it was the tool! :laughing:

aka Unbrako key

Hi Xan,

Just tried a random value, acos(0.4512). I got an error of 0.57 deg. Instead of lookup table, perhaps can add a linear interpolation to refine the lookup. :wink: What do you think?

This is a great sample code. I could never understand what Laurent was doing with his wonderful powerpod code… (I’m very slow when it comes to reading other people’s codes :wink: )

I thought I was the only one experiencing the problem with the FACOS error in that range. I finally got fed up with why my legs had a sudden “jerk” when commanding it to trace a straight line using my IK engine…

After many s_out commands and a table I generated with a spreadsheet (OpenOffice Calc), I noticed that the numbers started to deviate from what it’s actually supposed to be!!!

I finally ended up just limiting the range of FACOS to stay away from that region… But with the table, you can use the full range AND have it scaled to actual integers!!! Not to mention a look up table is super fast (at the cost of memory of course)…

I’ve been meaning to getting rid of all my FCOS and FSIN functions as they are costly, but in the end, the Atom Pro 28 is a miniature little workhorse, I was surprised that it can keep up with the calculations even when I cranked the transit time of the servos to 100msec…

:smiley:

Hi guys,

Sorry I kinda lost track of this post that’s why I didn’t end the previous one… sry for that :wink:

I’ve been experimenting a lot with this method since I’ve got both the Arm and the phoenix running on byte tables for sin/cos, acos and tan2. I found out that the error isn’t as beautiful as I thought it was so you could be right with the found error. The error is (was :wink:) even bigger near cos=1. Interpolation should improve it a bit but it will also cost some time. I haven’t tried it but it sure is word a try.

LOL, Nope you’re one of many who are struggling with the FACOS functions. It took me some time to figure out a good balance between speed, memory and accuracy.

I’ve worked this out in excel. It’s much easier to verify stuff when seeing it on the monitor with a decent graph.

Yepp the byte table cost some memory space but the pro got plenty for our programs. Speed is the thing :imp:

Phoenix V2.0 is at 50ms cycle time at the moment :stuck_out_tongue:

Like I said I found out that the error got much bigger near cos = 1. This is because the function is logarithmic which is giving a pretty vertical line near cos = 1. To solve this I’ve splitted the table up in to 3 parts.
Cos = 0 – 0.9
Cos = 0.9 – 0.99
Cos = 0.99 – 1

Here is the improved function:

[code]
;====================================================================
c1DEC con 10
c2DEC con 100
c4DEC con 10000
c6DEC con 1000000
;--------------------------------------------------------------------
;[TABLES]
;ArcCosinus Table
;Table build in to 3 part to get higher accuracy near cos = 1.
;The biggest error is near cos = 1 and has a biggest value of 3*0.012098rad = 0.521 deg.
;- Cos 0 to 0.9 is done by steps of 0.0079 rad. (1/127)
;- Cos 0.9 to 0.99 is done by steps of 0.0008 rad (0.1/127)
;- Cos 0.99 to 1 is done by step of 0.0002 rad (0.01/64)
;Since the tables are overlapping the full range of 127+127+64 is not necessary. Total bytes: 277
GetACos bytetable 255,254,252,251,250,249,247,246,245,243,242,241,240,238,237,236,234,233,232,231,229,228,227,225, |
224,223,221,220,219,217,216,215,214,212,211,210,208,207,206,204,203,201,200,199,197,196,195,193, |
192,190,189,188,186,185,183,182,181,179,178,176,175,173,172,170,169,167,166,164,163,161,160,158, |
157,155,154,152,150,149,147,146,144,142,141,139,137,135,134,132,130,128,127,125,123,121,119,117, |
115,113,111,109,107,105,103,101,98,96,94,92,89,87,84,81,79,76,73,73,73,72,72,72,71,71,71,70,70, |
70,70,69,69,69,68,68,68,67,67,67,66,66,66,65,65,65,64,64,64,63,63,63,62,62,62,61,61,61,60,60,59, |
59,59,58,58,58,57,57,57,56,56,55,55,55,54,54,53,53,53,52,52,51,51,51,50,50,49,49,48,48,47,47,47, |
46,46,45,45,44,44,43,43,42,42,41,41,40,40,39,39,38,37,37,36,36,35,34,34,33,33,32,31,31,30,29,28, |
28,27,26,25,24,23,23,23,23,22,22,22,22,21,21,21,21,20,20,20,19,19,19,19,18,18,18,17,17,17,17,16, |
16,16,15,15,15,14,14,13,13,13,12,12,11,11,10,10,9,9,8,7,6,6,5,3,0

;GetSinCos
cos4 var sword ;Input Cosinus of the given Angle, decimals = 4
AngleRad4 var sword ;Output Angle in radials, decimals = 4

Index var sword
Index=-1000
;====================================================================
main:

GoSub GetArcCos[Index*10]

serout s_out, i57600, [sdec index, " ",sdec AngleRad4 , " ", real FACOS(TOFLOAT(Index)/1000.0), 13]

IF Index < 1000 THEN
Index = Index+10
ELSE
Index = -1000
ENDIF

pause 100
goto main
;====================================================================
;[GETARCCOS] Get the sinus and cosinus from the angle +/- multiple circles
;Cos4 - Input Cosinus
;AngleRad4 - Output Angle in AngleRad4
GetArcCos[Cos4]
;Check for negative value
IF (Cos4<0) THEN
Cos4 = -Cos4
NegativeValue = TRUE
ELSE
NegativeValue = FALSE
ENDIF

;Limit Cos4 to his maximal value
Cos4 = (Cos4 max c4DEC)

IF (Cos4>=0 AND Cos4<9000) THEN
AngleRad4 = GetACos(Cos4/79) ;79=table resolution (1/127)
AngleRad4 = AngleRad4*616/c1DEC ;616=acos resolution (pi/2/255)

ELSEIF (Cos4>=9000 AND Cos4<9899)
AngleRad4 = GetACos((Cos4-9000)/8+114) ;8=table resolution (0.1/127), 114 start address 2nd bytetable range
AngleRad4 = AngleRad4*616/c1DEC ;616=acos resolution (pi/2/255)

ELSEIF (Cos4>=9900 AND Cos4<=10000)
AngleRad4 = GetACos((Cos4-9900)/2+227) ;2=table resolution (0.01/64), 227 start address 3rd bytetable range
AngleRad4 = AngleRad4*616/c1DEC ;616=acos resolution (pi/2/255)
ENDIF

;Add negative sign
IF NegativeValue THEN
AngleRad4 = 31416 - AngleRad4
ENDIF

return AngleRad4
;--------------------------------------------------------------------

[/code]** this bytetable and getAcos function are copy passed from the phoenix code. It’s possible that the code doesn’t compile at once.**

This works pretty accurate for the phoenix.

Xan

As always, excellent work Xan!

Thanks for sharing!