ManusArm.cpp
Go to the documentation of this file.
00001 /*
00002  * ManusArm.cpp
00003  * Copyright 2013 University of Massachusetts Lowell
00004  * Authors: Abraham Shultz, Jonathan Hasenzahl
00005  */
00006 
00007 #include "arm/ManusArm.hpp"
00008 #include "arm/MoUT.hpp"
00009 
00010 using namespace std;
00011 
00012 /* Pointer to the existing instance */
00013 ManusArm* ManusArm::armInstance = NULL;
00014 
00019 void ManusArm::getPosition(float fill[])
00020 {
00021         //get current position
00022         {
00023                 boost::mutex::scoped_lock lock(stateMutex);
00024                 for (int i = 0; i < 7; i++)
00025                 {
00026                         fill[i] = currState.jointPositions[i];
00027                         //cout << "currState.jointPositions[" << i << "] = " << currState.jointPositions[i] << endl;
00028                 }
00029         }
00030 }
00031 
00036 string ManusArm::getCsvState()
00037 {
00038         //Probably shouldn't lock here, as it only reads, and is used for debugging
00039         //boost::mutex::scoped_lock lock(stateMutex);
00040         stringstream sb;
00041         if (currState.isValid)
00042         {
00043                 if (currState.cbox == CBOX_4_JOINT)
00044                 {
00045                         //Units are tenths of a degree
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                         //Units are 0.022mm
00056                         sb << currState.jointPositions[0] * 0.022 << ",";
00057                         sb << currState.jointPositions[1] * 0.022 << ",";
00058                         sb << currState.jointPositions[2] * 0.022 << ",";
00059                         //Units are tenths of a degree
00060                         sb << currState.jointPositions[3] * 0.1 << ",";
00061                         sb << currState.jointPositions[4] * 0.1 << ",";
00062                         sb << currState.jointPositions[5] * 0.1 << ",";
00063                 }
00064                 //Units are tenths of a millimeter
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         //Should not lock here, only reads, useful for debugging as arm moves
00081         //boost::mutex::scoped_lock lock(stateMutex);
00082         stringstream sb;
00083         sb << currState.message + "\n";
00084         if (currState.isValid)
00085         {
00086                 if (currState.cbox == CBOX_4_JOINT)
00087                 {
00088                         //Units are tenths of a degree
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                         //Units are 0.022mm
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                         //Units are tenths of a degree
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                 //Units are tenths of a millimeter
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 /* Units are as follows
00131  * X, Y, Z are 0.022 mm every 20 ms, (1.1mm/sec) with a possible delay of 60ms on the first motion
00132  * So to move at 1 cm / second, you need to request a speed of 9 (9.9mm/sec) or 10 (11mm/sec),
00133  * depending on whether you want to be too fast or too slow. The valid range is 0-127.
00134  *
00135  * Roll, pitch, and yaw all refer to the gripper, and are in 0.1 degree per increments.
00136  * The valid range is 0-10 (0-1 degree/20msec)
00137  *
00138  * Gripper is opening and closing rates in units of 0.1mm/20msec.
00139  * The valid range is 0 to 15
00140  *
00141  *  We don't have a lift unit. The valid values are -1 (up), 0 (off), and 1 (down)
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         // A lot of the logic here is from can_comm.cpp's function pd_control()
00166         // Generally speaking, it works by:
00167         // 1. Calculating the difference between the current position and the desired position (the error)
00168         // 2. Multiplying the error by a speed constant
00169         // 3. Checking that the speeds are within limits
00170         // 4. Sending the speeds to the arm
00171         // Steps 1 and 2 ensure that the arm slows as it approaches the desired position
00172 
00173         // Speed constants for arm
00174         const float Kp[CART_MV_ARR_SZ] = { 5, 5, 5, 0.8, 0.7, 0.6, 0.5 };
00175 
00176         // Which speed limits to use. 4 is full, kate's work used 2 when approaching user
00177 
00178 
00179         // Error in position
00180         float pos_err[CART_MV_ARR_SZ];
00181         // Previous position
00182         float prev_pos[CART_MV_ARR_SZ];
00183         // New speeds
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                 // Get current position
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                 // Calculate the error and speeds
00205                 register float tmp1, tmp2;
00206                 for (int i = X; i <= Z; i++) // Currently only calculates for X, Y, Z
00207                 {
00208                         if (i == ROLL) // roll -180 ~ 180 : linear scaling
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                 // The struct can_frame uses a different order for axes of movement:
00264                 //              lift:   0 (LIFT-7)
00265                 //              x:      1 (X+1)
00266                 //              y:              2 (Y+1)
00267                 //              z:              3 (Z+1)
00268                 //              yaw:    4 (YAW+1)
00269                 //              pitch:  5 (PITCH+1)
00270                 //              roll:   6 (ROLL+1)
00271                 //              grip:   7 (GRIP+1)
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; // Lift unit is not used in Cartesian moves
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; // Yaw movement not yet implemented
00281                 move.data[PITCH+1] = 0; // Pitch movement not yet implemented
00282                 move.data[ROLL+1] = 0; // Roll movement not yet implemented
00283                 move.data[GRIP+1] = 0; // Grip movement not yet implemented
00284 
00285                 enqueueFrame(move);
00286 
00287                 // Wait 60 msec
00288                 boost::this_thread::sleep(boost::posix_time::milliseconds(60));
00289 
00290                 // Assume we are done
00291                 moving = false;
00292 
00293                 for (int ii = X; ii <= Z; ii++) // Currently only calculates for X, Y, Z
00294                 {
00295                         if (fabs(pos_err[ii]) > CARTESIAN_SLOP)
00296                         {
00297                                 moving = true;
00298                                 break;
00299                         }
00300                 }
00301         }
00302 
00303         //Stop the arm, otherwise it continues with whatever speeds it had when the move was done
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         // Wait 60 msec
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         // The struct can_frame uses a different order for axes of movement:
00342         //              lift:   0 (LIFT-7)
00343         //              x:      1 (X+1)
00344         //              y:              2 (Y+1)
00345         //              z:              3 (Z+1)
00346         //              yaw:    4 (YAW+1)
00347         //              pitch:  5 (PITCH+1)
00348         //              roll:   6 (ROLL+1)
00349         //              grip:   7 (GRIP+1)
00350 
00351     // Enqueue the movement frame
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         // Wait 60 msec
00361         boost::this_thread::sleep(boost::posix_time::milliseconds(60));
00362 }
00363 
00367 void ManusArm::setCartesian()
00368 {
00369         struct can_frame frm;
00370         //Transition to Cartesian mode
00371         setCbox(CBOX_1_CARTESIAN, &frm);
00372         frm.can_dlc = 8;
00373         //Zero all motion rates
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         //Send twice to trigger folding
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         //Should I zero the data here?
00406         //send twice to trigger unfolding
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                 //Check if this message and the last message queued are the same type
00421                 if (toSend.can_id == prevFrame.can_id)
00422                 {
00423                         /* If it is a motion packet, check if the data is the same. Otherwise,
00424                          * it is a fold out/fold in packet, and so can be repeated
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                                 //All the data were the same, don't resend the packet
00438                                 if (dataMatch)
00439                                 {
00440                                         return;
00441                                 }
00442                         }
00443                 }
00444         }
00445         //None of the previous checks blocked the packet, add it to the queue
00446         sendQueue.insert(sendQueue.begin(), toSend);
00447 }
00448 
00452 void ManusArm::pollCanSocket()
00453 {
00454         struct can_frame frame;
00455         while (running)
00456         {
00457                 /* Read a message back from the CAN bus */
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                 //              printf("ID: %x \n", frame.can_id);
00466                 //              printf("Length: %i \n", frame.can_dlc);
00467                 //              for (int ii = 0; ii < frame.can_dlc; ii++)
00468                 //              {
00469                 //                      printf("Data %x\n", frame.data[ii]);
00470                 //              }
00471 
00472                 //TODO copy the data out into a data structure in the ARM class
00473                 if (frame.can_id == 0x350)
00474                 { //Status bytes (2 bytes) and axis 1-3 (6 bytes)
00475                         //Lock to modify state
00476                         boost::mutex::scoped_lock lock(stateMutex);
00477 
00478                         //Update joint positions
00479                         currState.jointPositions[0] = ((int8_t) frame.data[2] << 8) + (uint8_t) frame.data[3]; //X
00480                         currState.jointPositions[1] = ((int8_t) frame.data[4] << 8) + (uint8_t) frame.data[5]; //Y
00481                         currState.jointPositions[2] = ((int8_t) frame.data[6] << 8) + (uint8_t) frame.data[7]; //Z
00482 
00483                         currState.message = "STATUS: Updated position(1): " + toString<canid_t> (frame.can_id, hex);
00484 
00485                         //Deal with status bytes
00486                         uint8_t status = frame.data[0];
00487                         uint8_t mesg = frame.data[1];
00488                         switch (status)
00489                         {
00490                         case STAT_NONE:
00491                                 //Do Nothing
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                                 //cout << currState.message << endl;
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                 { //Axis 4-7 (8 bytes)
00561                         //Lock to update state
00562                         boost::mutex::scoped_lock lock(stateMutex);
00563                         //Update joint positions
00564                         currState.jointPositions[3] = ((int8_t) frame.data[0] << 8) + (uint8_t) frame.data[1]; //Yaw
00565                         currState.jointPositions[4] = ((int8_t) frame.data[2] << 8) + (uint8_t) frame.data[3]; //Pitch
00566                         currState.jointPositions[5] = ((int8_t) frame.data[4] << 8) + (uint8_t) frame.data[5]; //Roll
00567                         currState.jointPositions[6] = ((int8_t) frame.data[6] << 8) + (uint8_t) frame.data[7]; //Gripper
00568                         currState.message = "STATUS: Updated position(2): " + toString<canid_t> (frame.can_id, hex);
00569                         //The state has been updated and is now valid
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                 { //Go to send reply
00577                         boost::mutex::scoped_lock lock(stateMutex);
00578                         currState.message = "STATUS: Ready for reply: " + toString<canid_t> (frame.can_id, hex);
00579                         //if there is a reply ready, send it
00580                         if (!sendQueue.empty())
00581                         {
00582                                 //filled from front, sent from back
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         /* Create the socket */
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         /* Locate the interface you wish to use */
00633         struct ifreq ifr;
00634         strcpy(ifr.ifr_name, interface.c_str());
00635         /* ifr.ifr_ifindex gets filled with that device's index */
00636         if (ioctl(canSock, SIOCGIFINDEX, &ifr) < 0)
00637         {
00638                 throw ArmException((char*) "Ioctl failed:" + errno);
00639         }
00640 
00641         /* Select that CAN interface, and bind the socket to it. */
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         /* Send a message three times, wasting time
00651          *  to get valid position data.
00652          */
00653         struct can_frame frame;
00654         for (int ii = 0; ii < 4; ii++)
00655         {
00656                 //Set the mode to cartesian
00657                 setCartesian();
00658 
00659                 //Send the mode setting CAN message
00660                 while (1)
00661                 {
00662                         /* Read a message back from the CAN bus */
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                         { //Go to send reply
00672                                 boost::mutex::scoped_lock lock(stateMutex);
00673                                 currState.message = "STATUS: Ready for reply: " + toString<canid_t> (frame.can_id, hex);
00674                                 //if there is a reply ready, send it
00675                                 if (!sendQueue.empty())
00676                                 {
00677                                         //filled from front, sent from back
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                                         /* We have sent the message and received the 0x37F reply after it,
00689                                          * which means we are now in cartesian mode and tthe position data
00690                                          * will mean something. Otherwise, the position data is not well-defined,
00691                                          * and causes problems.
00692                                          */
00693                                         break;
00694                                 }
00695                         }
00696                 }
00697         }
00698 
00699         //Start the main CAN communication loop
00700         running = true;
00701         boost::thread doPoll(boost::bind(&ManusArm::pollCanSocket, this));
00702 
00703         //Wait for the main loop to update the state
00704         while (!currState.isValid)
00705         {
00706                 sleep(1);
00707                 //wait 120 msec
00708                 //              timespec delay;
00709                 //              timespec remaining;
00710                 //              delay.tv_sec = 0;
00711                 //              delay.tv_nsec = 120000000;
00712                 //              nanosleep(&delay, &remaining);
00713         }
00714         cout << "ARM init done" << endl;
00715         return 0;
00716 }
00717 
00721 ManusArm::ManusArm()
00722 {
00723         //Not valid until the polling thread updates the state
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 }


arm
Author(s): Jonathan Hasenzahl
autogenerated on Sun Jan 5 2014 11:12:32