uArm-Developer / UArmForArduino

Arduino uArm Metal Library (uArm Metal only)
http://uarm-developer.github.io/UArmForArduino
82 stars 56 forks source link

The problem with getCalZ(); #1

Closed jaewooklee93 closed 8 years ago

jaewooklee93 commented 8 years ago

You might already notice that the getCalZ() returned wrong results as you wrote in the manual. I guess that is due to the wrong value of theta_3 at calXYZ function.

I simply added an offset(+23) for theta_3 at the first line of calXYZ. Then it returns seemingly more accurate value of Z-coordinate of end-effector.

At uArm_library.cpp

void uArmClass::calXYZ(double theta_1, double theta_2, double theta_3)
{
theta_3+=23;

  g_theta_1=theta_1;
  g_theta_2=theta_2;
  g_theta_3=theta_3;

  g_l3_1 = MATH_L3 * cos(theta_2 / MATH_TRANS);
  g_l4_1 = MATH_L4*cos(theta_3 / MATH_TRANS);
  g_l5 = (MATH_L2 + MATH_L3*cos(theta_2 / MATH_TRANS) + MATH_L4*cos(theta_3 / MATH_TRANS));

  g_cal_x = -cos(abs(theta_1 / MATH_TRANS))*g_l5;
  g_cal_y = -sin(abs(theta_1 / MATH_TRANS))*g_l5;
  g_cal_z = MATH_L1 + MATH_L3*sin(abs(theta_2 / MATH_TRANS)) - MATH_L4*sin(abs(theta_3 / MATH_TRANS));

}

I'm a beginner of uarm, so my point may not be correct, but I hope that this comment may help you solve the problem.

Thank you. Jaewook Lee

songjunyi commented 8 years ago

H, jaewook lee,

This is Joey who wrote this api. Actually the problem of getZ() is caused by the definition of coordinate of end-effector. We define the the coordinate of moveTo(x,y,z) is the point in the middle of two screws in the end of the second link(above the end-effector).

This is because we have different end-effectors such as pump, pen holder or claw. So different end-effector may change the coordinate of Z-axis. So we use an invariant coordinate to calculate the Z-coordinate.

It is not recommended to add a offset to a single servo. Because this angle have a sine relationship with z axis which is z ~ sin(theta_3)*l3 l3 is the length of link 2. So add custom offsets to your Z coordinate (due to the changes of end-effector) will simply solve your problem.

BTW, thanks for you question, we have add this definition(z-axis) in our developer-page.

Thanks very much.

Regards, Joey

jaewooklee93 commented 8 years ago

Thank you for your quick response.

However, I think the problem lies not only on the definition of (x,y,z).

I tried Get XYZ Example in http://developer.ufactory.cc/quickstart/ Just at the calibration posture (servo1,servo2,servo3)=(45,130,20), It displays The current location is -7 , -3 , 21 (at servo1=45 position, x and y should be same, it is another error) default

But when I move the end-effector upward while remaining servo1, servo2 static, or simply (servo1,servo2,servo3)=(45,130,0), it displays The current location is -6 , -2 , 15 2

However, z-coordinate should increase during this motion.

For reference, this is my calibration result.

c
l_address: 60
servo 1
lr.getA():-31.37
lr.getB():0.36
l_address: 66
servo 2
lr.getA():-27.94
lr.getB():0.35
l_address: 72
servo 3
lr.getA():-30.87
lr.getB():0.36
l_address: 78
servo 4
lr.getA():-41.12
lr.getB():0.50
Put uarm in calibration posture (servo 1 to 3: 45, 130, 20 degree respectively), then input 1
Offsets for servo 1 to 3 are -5.60
9.40
-11.95
Save offset done! 
All done!

I think this may be related to the calibration function newly updated in the last week.

Best regards, Jaewook Lee

jaewooklee93 commented 8 years ago

I think I almost figure out the reason of this bug.

The function double uArmClass::readServoOffset(byte servo_num) reads the offset of each servo from EEPROM, and the sign of offset value is stored at kAddrOffset + (servo_num-1)*2. However, the calibration function didn't properly store the sign of offset value.

In uArm_calibration.cpp,

void CalibrationClass::saveOffsetValue(double value, byte servo_num)
{
    int LSBs;
    int MSBs;

    if (value >0)
        LSBs = 1;
    else
        MSBs = 0;

    value *= 10;
    MSBs = (int) value;

    EEPROM.write( uarm.kAddrOffset + (servo_num - 1)*2, abs(LSBs));
    EEPROM.write( uarm.kAddrOffset + (servo_num - 1)*2 +1, abs(MSBs));

}

should be corrected to

    else
        LSBs = 0;
songjunyi commented 8 years ago

Hi, jaewook,

Thanks so much for pointing out this bug. This is a mistake we made and we have fixed this bug.

Because of what you have made, our team decide to give a you a GIFT for fixing this bug. So could you leave your email here OR send a email to our official email-address :info@ufactory.cc. And we will contact you for further delivery process.

Joey

jaewooklee93 commented 8 years ago

You're welcome.

It's truly my pleasure to hear that your team resolves that problem, but it's not a big deal and a joy of problem solving itself is enough for me, so you don't need to give me gift for this :)

Good luck, Jaewook Lee