00001
00002
00003
00004
00005
00006
00007 #include "arm/ManusArm.hpp"
00008 #include "arm/MoUT.hpp"
00009
00010 using namespace std;
00011
00012
00013 ManusArm* ManusArm::armInstance = NULL;
00014
00019 void ManusArm::getPosition(float fill[])
00020 {
00021
00022 {
00023 boost::mutex::scoped_lock lock(stateMutex);
00024 for (int i = 0; i < 7; i++)
00025 {
00026 fill[i] = currState.jointPositions[i];
00027
00028 }
00029 }
00030 }
00031
00036 string ManusArm::getCsvState()
00037 {
00038
00039
00040 stringstream sb;
00041 if (currState.isValid)
00042 {
00043 if (currState.cbox == CBOX_4_JOINT)
00044 {
00045
00046 sb << currState.jointPositions[0] * 0.1 << ",";
00047 sb << currState.jointPositions[1] * 0.1 << ",";
00048 sb << currState.jointPositions[2] * 0.1 << ",";
00049 sb << currState.jointPositions[3] * 0.1 << ",";
00050 sb << currState.jointPositions[4] * 0.1 << ",";
00051 sb << currState.jointPositions[5] * 0.1 << ",";
00052 }
00053 else
00054 {
00055
00056 sb << currState.jointPositions[0] * 0.022 << ",";
00057 sb << currState.jointPositions[1] * 0.022 << ",";
00058 sb << currState.jointPositions[2] * 0.022 << ",";
00059
00060 sb << currState.jointPositions[3] * 0.1 << ",";
00061 sb << currState.jointPositions[4] * 0.1 << ",";
00062 sb << currState.jointPositions[5] * 0.1 << ",";
00063 }
00064
00065 sb << currState.jointPositions[6] * 0.1;
00066 }
00067 else
00068 {
00069 sb << "State not valid yet\n";
00070 }
00071 return sb.str();
00072 }
00073
00078 string ManusArm::getPrintState()
00079 {
00080
00081
00082 stringstream sb;
00083 sb << currState.message + "\n";
00084 if (currState.isValid)
00085 {
00086 if (currState.cbox == CBOX_4_JOINT)
00087 {
00088
00089 sb << "Axis 1: " << currState.jointPositions[0] * 0.1 << " degrees \n";
00090 sb << "Axis 2: " << currState.jointPositions[1] * 0.1 << " degrees \n";
00091 sb << "Axis 3: " << currState.jointPositions[2] * 0.1 << " degrees \n";
00092 sb << "Axis 4: " << currState.jointPositions[3] * 0.1 << " degrees \n";
00093 sb << "Axis 5: " << currState.jointPositions[4] * 0.1 << " degrees \n";
00094 sb << "Axis 6: " << currState.jointPositions[5] * 0.1 << " degrees \n";
00095 }
00096 else
00097 {
00098
00099 sb << "X: " << currState.jointPositions[0] * 0.022 << " mm \n";
00100 sb << "Y: " << currState.jointPositions[1] * 0.022 << " mm \n";
00101 sb << "Z: " << currState.jointPositions[2] * 0.022 << " mm \n";
00102
00103 sb << "Yaw: " << currState.jointPositions[3] * 0.1 << " degrees\n";
00104 sb << "Pitch: " << currState.jointPositions[4] * 0.1 << " degrees\n";
00105 sb << "Roll: " << currState.jointPositions[5] * 0.1 << " degrees\n";
00106 }
00107
00108 sb << "Gripper: " << currState.jointPositions[6] * 0.1 << " mm \n";
00109 }
00110 else
00111 {
00112 sb << "State not valid yet\n";
00113 }
00114
00115 return sb.str();
00116 }
00117
00123 void ManusArm::setCbox(int cbox, can_frame* frm)
00124 {
00125 boost::mutex::scoped_lock lock(stateMutex);
00126 currState.cbox = cbox;
00127 frm->can_id = currState.cbox;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00151 void ManusArm::moveCartesian(const CartesianMove& cmd)
00152 {
00153 motionThread = boost::thread(boost::bind(&ManusArm::doCartesianMove, this, cmd));
00154 }
00155
00163 void ManusArm::doCartesianMove(const CartesianMove& cmd)
00164 {
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 const float Kp[CART_MV_ARR_SZ] = { 5, 5, 5, 0.8, 0.7, 0.6, 0.5 };
00175
00176
00177
00178
00179
00180 float pos_err[CART_MV_ARR_SZ];
00181
00182 float prev_pos[CART_MV_ARR_SZ];
00183
00184 float new_speeds[CART_MV_ARR_SZ];
00185
00186 for (int i = 0; i < CART_MV_ARR_SZ; i++)
00187 {
00188 pos_err[i] = 0.0f;
00189 prev_pos[i] = 0.0f;
00190 new_speeds[i] = 0.0f;
00191 }
00192
00193 bool moving = true;
00194
00195 while (moving && !moveComplete)
00196 {
00197
00198 {
00199 boost::mutex::scoped_lock lock(stateMutex);
00200 for (int i = 0; i < CART_MV_ARR_SZ; i++)
00201 prev_pos[i] = currState.jointPositions[i];
00202 }
00203
00204
00205 register float tmp1, tmp2;
00206 for (int i = X; i <= Z; i++)
00207 {
00208 if (i == ROLL)
00209 {
00210 {
00211 tmp1 = (180.0f - cmd.positions[i]) - (180.0f - prev_pos[i]);
00212 }
00213
00214 if (tmp1 >= 0.0f)
00215 if (tmp1 <= 180.0f)
00216 tmp2 = tmp1;
00217 else
00218 tmp2 = tmp1 - 360.0f;
00219 else if (tmp1 > -180.0f)
00220 tmp2 = tmp1;
00221 else
00222 tmp2 = 360.0f + tmp1;
00223
00224 pos_err[i] = tmp2;
00225 }
00226 else
00227 pos_err[i] = cmd.positions[i] - (prev_pos[i]);
00228
00229 float control_input = Kp[i] * pos_err[i];
00230
00231 new_speeds[i] = fabs(control_input) > SPEED_LIMITS[i][cmd.speeds[i]] ?
00232 sign(control_input) * SPEED_LIMITS[i][cmd.speeds[i]] :
00233 control_input;
00234 }
00235 #ifdef DEBUG
00236 cout << "Target Position: ";
00237 for (int ii = 0; ii < CART_MV_ARR_SZ; ii++)
00238 {
00239 cout << cmd.positions[ii] << ", ";
00240 }
00241 cout << endl;
00242
00243 cout << "Position: ";
00244 for (int ii = 0; ii < CART_MV_ARR_SZ; ii++)
00245 {
00246 cout << prev_pos[ii] << ", ";
00247 }
00248 cout << endl;
00249 cout << "Error: ";
00250 for (int ii = 0; ii < CART_MV_ARR_SZ; ii++)
00251 {
00252 cout << pos_err[ii] << ", ";
00253 }
00254 cout << endl;
00255 cout << "New speeds: ";
00256 for (int ii = 0; ii < CART_MV_ARR_SZ; ii++)
00257 {
00258 cout << new_speeds[ii] << ", ";
00259 }
00260 cout << endl << endl;
00261 #endif
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 struct can_frame move;
00274 setCbox(CBOX_1_CARTESIAN, &move);
00275 move.can_dlc = FRM_ARR_SZ;
00276 move.data[LIFT-7] = 0;
00277 move.data[X+1] = new_speeds[X];
00278 move.data[Y+1] = new_speeds[Y];
00279 move.data[Z+1] = new_speeds[Z];
00280 move.data[YAW+1] = 0;
00281 move.data[PITCH+1] = 0;
00282 move.data[ROLL+1] = 0;
00283 move.data[GRIP+1] = 0;
00284
00285 enqueueFrame(move);
00286
00287
00288 boost::this_thread::sleep(boost::posix_time::milliseconds(60));
00289
00290
00291 moving = false;
00292
00293 for (int ii = X; ii <= Z; ii++)
00294 {
00295 if (fabs(pos_err[ii]) > CARTESIAN_SLOP)
00296 {
00297 moving = true;
00298 break;
00299 }
00300 }
00301 }
00302
00303
00304 struct can_frame move;
00305 setCbox(CBOX_1_CARTESIAN, &move);
00306 move.can_dlc = FRM_ARR_SZ;
00307 for (int i = 0; i < FRM_ARR_SZ; i++)
00308 move.data[i] = 0;
00309 enqueueFrame(move);
00310
00311
00312 boost::this_thread::sleep(boost::posix_time::milliseconds(60));
00313
00314 {
00315 boost::mutex::scoped_lock lock(stateMutex);
00316 moveComplete = true;
00317 }
00318 }
00319
00327 void ManusArm::moveConstant(const ConstantMove& cmd)
00328 {
00329 motionThread = boost::thread(boost::bind(&ManusArm::doConstantMove, this, cmd));
00330 }
00331
00339 void ManusArm::doConstantMove(const ConstantMove& cmd)
00340 {
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 struct can_frame move;
00353 setCbox(CBOX_1_CARTESIAN, &move);
00354 move.can_dlc = FRM_ARR_SZ;
00355 move.data[LIFT-7] = cmd.states[LIFT];
00356 for (int i = X; i <= GRIP; i++)
00357 move.data[i+1] = SPEED_LIMITS[i][cmd.speeds[i]] * cmd.states[i];
00358 enqueueFrame(move);
00359
00360
00361 boost::this_thread::sleep(boost::posix_time::milliseconds(60));
00362 }
00363
00367 void ManusArm::setCartesian()
00368 {
00369 struct can_frame frm;
00370
00371 setCbox(CBOX_1_CARTESIAN, &frm);
00372 frm.can_dlc = 8;
00373
00374 for (int ii = 0; ii < frm.can_dlc; ii++)
00375 {
00376 frm.data[ii] = 0;
00377 }
00378 enqueueFrame(frm);
00379 }
00380
00387 void ManusArm::fold()
00388 {
00389 struct can_frame frm;
00390 setCbox(CBOX_6_FOLD, &frm);
00391 frm.can_dlc = 0;
00392
00393 enqueueFrame(frm);
00394 enqueueFrame(frm);
00395 }
00396
00400 void ManusArm::unfold()
00401 {
00402 struct can_frame frm;
00403 setCbox(CBOX_5_UNFOLD, &frm);
00404 frm.can_dlc = 0;
00405
00406
00407 enqueueFrame(frm);
00408 enqueueFrame(frm);
00409 }
00410
00415 void ManusArm::enqueueFrame(can_frame toSend)
00416 {
00417 if (!sendQueue.empty())
00418 {
00419 can_frame prevFrame = *(sendQueue.end() - 1);
00420
00421 if (toSend.can_id == prevFrame.can_id)
00422 {
00423
00424
00425
00426 if (toSend.can_id == CBOX_1_CARTESIAN || toSend.can_id == CBOX_4_JOINT)
00427 {
00428 bool dataMatch = true;
00429 for (int ii = 0; ii < 6; ii++)
00430 {
00431 if (toSend.data[ii] != prevFrame.data[ii])
00432 {
00433 dataMatch = false;
00434 break;
00435 }
00436 }
00437
00438 if (dataMatch)
00439 {
00440 return;
00441 }
00442 }
00443 }
00444 }
00445
00446 sendQueue.insert(sendQueue.begin(), toSend);
00447 }
00448
00452 void ManusArm::pollCanSocket()
00453 {
00454 struct can_frame frame;
00455 while (running)
00456 {
00457
00458 uint bytes_read = recv(canSock, &frame, sizeof(struct can_frame), 0);
00459
00460 if (bytes_read < sizeof(struct can_frame))
00461 {
00462 cerr << "Read: incomplete CAN frame" << endl;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 if (frame.can_id == 0x350)
00474 {
00475
00476 boost::mutex::scoped_lock lock(stateMutex);
00477
00478
00479 currState.jointPositions[0] = ((int8_t) frame.data[2] << 8) + (uint8_t) frame.data[3];
00480 currState.jointPositions[1] = ((int8_t) frame.data[4] << 8) + (uint8_t) frame.data[5];
00481 currState.jointPositions[2] = ((int8_t) frame.data[6] << 8) + (uint8_t) frame.data[7];
00482
00483 currState.message = "STATUS: Updated position(1): " + toString<canid_t> (frame.can_id, hex);
00484
00485
00486 uint8_t status = frame.data[0];
00487 uint8_t mesg = frame.data[1];
00488 switch (status)
00489 {
00490 case STAT_NONE:
00491
00492 break;
00493 case STAT_WARNING:
00494 switch (mesg)
00495 {
00496 case MSG_GRIPPER_STUCK:
00497 currState.message = "WARNING: Gripper is stuck";
00498 break;
00499 case MSG_WRONG_AREA:
00500 currState.message = "WARNING: Wrong area";
00501 break;
00502 case MSG_ARM_FOLDED_STRETCHED:
00503 currState.message = "WARNING: ARM maximum folding or extension reached";
00504 break;
00505 case MSG_BLOCKED_MOTOR:
00506 currState.message = "WARNING: Motor blocked or weight limit exceeded";
00507 break;
00508 case MSG_MAX_ROT:
00509 currState.message = "WARNING: Maximum rotation of base motor";
00510 break;
00511 default:
00512 currState.message = "WARNING: Nonsense message byte: %x\n" + toString<uint8_t> (status, hex);
00513 break;
00514 }
00515 break;
00516 case STAT_GENERAL:
00517 switch (mesg)
00518 {
00519 case MSG_FOLDED:
00520 currState.message = "GENERAL_MESSAGE: ARM folding complete";
00521 break;
00522 case MSG_UNFOLDED:
00523 currState.message = "GENERAL_MESSAGE: ARM unfolding complete";
00524 break;
00525 case MSG_GRIPPER_INIT:
00526 currState.message = "GENERAL_MESSAGE: Gripper ready";
00527 break;
00528 case MSG_ABS_MEASURE:
00529 currState.message = "GENERAL_MESSAGE: Absolute measuring ready";
00530 break;
00531 default:
00532 currState.message = "GENERAL_MESSAGE: Nonsense message byte: %x\n" + toString<uint8_t> (status, hex);
00533 break;
00534 }
00535
00536 break;
00537 case STAT_ERROR:
00538 switch (mesg)
00539 {
00540 case MSG_IO_80C552:
00541 currState.message = "ERROR: CAN I/O processor";
00542 break;
00543 case MSG_ABS_ENCODER:
00544 currState.message = "ERROR: Absolute encoder";
00545 break;
00546 case MSG_MOVE_WITHOUT_INPUT:
00547 currState.message = "ERROR: Move without input";
00548 break;
00549 default:
00550 currState.message = "ERROR: Nonsense message byte: " + toString<uint8_t> (status, hex);
00551 break;
00552 }
00553 break;
00554 default:
00555 currState.message = "STATUS: Nonsense status byte: %x\n" + toString<uint8_t> (status, hex);
00556 break;
00557 }
00558 }
00559 else if (frame.can_id == 0x360)
00560 {
00561
00562 boost::mutex::scoped_lock lock(stateMutex);
00563
00564 currState.jointPositions[3] = ((int8_t) frame.data[0] << 8) + (uint8_t) frame.data[1];
00565 currState.jointPositions[4] = ((int8_t) frame.data[2] << 8) + (uint8_t) frame.data[3];
00566 currState.jointPositions[5] = ((int8_t) frame.data[4] << 8) + (uint8_t) frame.data[5];
00567 currState.jointPositions[6] = ((int8_t) frame.data[6] << 8) + (uint8_t) frame.data[7];
00568 currState.message = "STATUS: Updated position(2): " + toString<canid_t> (frame.can_id, hex);
00569
00570 if (currState.cbox == CBOX_1_CARTESIAN || currState.cbox == CBOX_4_JOINT)
00571 {
00572 currState.isValid = true;
00573 }
00574 }
00575 else if (frame.can_id == 0x37F)
00576 {
00577 boost::mutex::scoped_lock lock(stateMutex);
00578 currState.message = "STATUS: Ready for reply: " + toString<canid_t> (frame.can_id, hex);
00579
00580 if (!sendQueue.empty())
00581 {
00582
00583 can_frame frame = sendQueue.back();
00584 uint bytes_sent = write(canSock, &frame, sizeof(frame));
00585 if (bytes_sent < sizeof(struct can_frame))
00586 {
00587 throw ArmException((char*) "Failed to write CAN frame to arm:" + errno);
00588 }
00589 sendQueue.pop_back();
00590 };
00591 }
00592 else
00593 {
00594 boost::mutex::scoped_lock lock(stateMutex);
00595 currState.message = "WARNING: Nonsense ID value: " + toString<canid_t> (frame.can_id, hex);
00596 }
00597 }
00598 }
00599
00607 ManusArm* ManusArm::instance()
00608 {
00609 if (!armInstance)
00610 {
00611 armInstance = new ManusArm;
00612 }
00613 return armInstance;
00614 }
00615
00621 int ManusArm::init(string interface)
00622 {
00623 moveComplete = false;
00624
00625
00626 canSock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
00627 if (canSock < 0)
00628 {
00629 throw ArmException((char*) "Failed to open socket:" + errno);
00630 }
00631
00632
00633 struct ifreq ifr;
00634 strcpy(ifr.ifr_name, interface.c_str());
00635
00636 if (ioctl(canSock, SIOCGIFINDEX, &ifr) < 0)
00637 {
00638 throw ArmException((char*) "Ioctl failed:" + errno);
00639 }
00640
00641
00642 struct sockaddr_can addr;
00643 addr.can_family = AF_CAN;
00644 addr.can_ifindex = ifr.ifr_ifindex;
00645 if (bind(canSock, (struct sockaddr*) &addr, sizeof(addr)) < 0)
00646 {
00647 throw ArmException((char*) "Bind failed:" + errno);
00648 }
00649
00650
00651
00652
00653 struct can_frame frame;
00654 for (int ii = 0; ii < 4; ii++)
00655 {
00656
00657 setCartesian();
00658
00659
00660 while (1)
00661 {
00662
00663 uint bytes_read = recv(canSock, &frame, sizeof(struct can_frame), 0);
00664
00665 if (bytes_read < sizeof(struct can_frame))
00666 {
00667 cerr << "Read: incomplete CAN frame" << endl;
00668 }
00669
00670 if (frame.can_id == 0x37F)
00671 {
00672 boost::mutex::scoped_lock lock(stateMutex);
00673 currState.message = "STATUS: Ready for reply: " + toString<canid_t> (frame.can_id, hex);
00674
00675 if (!sendQueue.empty())
00676 {
00677
00678 can_frame frame = sendQueue.back();
00679 uint bytes_sent = write(canSock, &frame, sizeof(frame));
00680 if (bytes_sent < sizeof(struct can_frame))
00681 {
00682 throw ArmException((char*) "Failed to write CAN frame to arm:" + errno);
00683 }
00684 sendQueue.pop_back();
00685 }
00686 else
00687 {
00688
00689
00690
00691
00692
00693 break;
00694 }
00695 }
00696 }
00697 }
00698
00699
00700 running = true;
00701 boost::thread doPoll(boost::bind(&ManusArm::pollCanSocket, this));
00702
00703
00704 while (!currState.isValid)
00705 {
00706 sleep(1);
00707
00708
00709
00710
00711
00712
00713 }
00714 cout << "ARM init done" << endl;
00715 return 0;
00716 }
00717
00721 ManusArm::ManusArm()
00722 {
00723
00724 currState.isValid = false;
00725 }
00726
00730 ArmException::ArmException(char* message) throw ()
00731 {
00732 msg = (char*) malloc(strlen(message));
00733 if (msg != NULL)
00734 {
00735 strncpy(msg, message, strlen(message));
00736 }
00737 }
00738
00742 const char* ArmException::what() const throw ()
00743 {
00744 return msg;
00745 }