How to invert cosine on BAP?

Here’s more details to my project. I’m building an arm that will need to be able to position itself based on input from a distance sensor mounted at the base of the arm. I’m trying to use the Law of Cosines to find the shoulderangle since the distance input, arm, and forearm make a triangle. Here is my equation that has been tried and works on a calculator.

cos shoulderangle = (distance*distance) + (arm*arm) - (forearm*forearm)/2(distance*arm)

The only problem now is putting the equation into my code which is where my problem is. The question comes down to. How do I invert a cosine in Basic Atom Pro? as in

shoulderangle = Invert COS (number the rest of equation comes to)

Here is the actual code I’m working on.

[code]shoulderangle = ((cm_distancecm_distance)+(armarm)-(forearmforearm))/(2cm_distance*arm)

shoulderangle = facos shoulderangle[/code]

Thankyou VERY much for any help provided. This problem has been a real headache for me lately.

Go to an arc cosine table lookup. Take a look at the hexapod code Phoenix, etc. for a “Law of Cosines” solution. Probably look for acos or GetACos.

Alan KM6VV

If you want to use FACOS then you need to supply those commands with radians, not degrees. Also floating point is a lot slower than using alookup but the lookup is less precise. So it comes down to your requirements.

To convert from degrees to radians you need to multiply by PI and divide by 180. You should define PI as a floating point constant to atleast 6 decimal places. Assuming you go the FP route.

Thankyou very much, both of you. I will do some testing and post my results.
Oh, and exactly how accurate is floating point or lookup? + or - how many milimeters or so.

I changed my code to convert degrees to radians when I use the FACOS command.

[code]pi fcon 3.1415926535
stepsperdegree fcon 166.6

distance = 150
;---------------------------------------------------------------------------------------------------------------------
main

shoulderangle = ((distancedistance)+(armarm)-(forearmforearm))/(2distance*arm)

shoulderangle = toint((tofloat shoulderangle) * pi)
shoulderangle = shoulderangle/180

shoulderangle = toint (facos(tofloat shoulderangle))

shoulderangle = shoulderangle * 180
shoulderangle = toint ((tofloat shoulderangle) / pi)

elbowangle = (shoulderangle*distance)/forearm

shoulderangle = shoulderangle - 90;offset zero centers to natural angles of shoulder and elbow
elbowangle = elbowangle - 90

shoulderangle = toint ((tofloat shoulderangle) * stepsperdegree);convert so hservo can use this
elbowangle = toint ((tofloat elbowangle) * stepsperdegree)

gosub servo_driver

shoulderangle = toint ((tofloat shoulderangle) / stepsperdegree)
elbowangle = toint ((tofloat elbowangle) / stepsperdegree)

shoulderangle = shoulderangle + 90
elbowangle = elbowangle + 90[/code]

The results from the arm are “OK” as in the arm doesn’t crash into itself and goes to more predictable positions than previously. The shoulder angle is still much different than what I get from using a calculator.

Check that steps per degree is correct. Send servo commands to rotate teh servo back and for 90 degrees(eg 90 * 166) and see if the servo actualy moves 90 degrees. Adjust stepsperdegree until it does move exactly 90 degrees.

It could also mean something is wrong in the math. With 32bit FP you only have so much precision so you have to be very carefull. It’s been a couple years since I did IK routines for one of Jims arms so I’m not exactly fresh on the math. I plan on doing IK routines for one of Jims arms again using an ARC32 in a couple days. Once I’m done I’ll post my code. I expect I’ll be using fixed point math though for speed reasons.

I checked the servos and found that my shoulder servo lags downward 10 - 15 degrees. So does anyone out there know some sort of gravity compensate formula or something of the sorts. Such as the one from RIOS possibly?

P.S
I haven’t tried load balancing springs yet. I expect they will probably make a very substantial difference.

I put a load balancing spring on the arm and it made all the difference so I won’t need a gravity compensate equation or anything like that. However, I’ve still been having many errors with the arm so I’ve decided to modify the rover arm phoenix code to control my arm. I have a few questions though. Are the x and y coordinates measured in milimeters? Is the constant “Base Length” measured from the shoulder axis to the ground? If my x coordinates are 150, will 150 milimeters measure from the shoulder axis to the wrist axis, or will they measure from the shoulder axis to the gripper tip? Same so with the y coordinates as well. And finnally, how much accuracy should I expect from this code.