/home/fwph/code/wurde/modules/rFlexBase/RFlex.cpp

Go to the documentation of this file.
00001 #include <RFlex.H>
00002 #include <cassert>
00003 #include <cstring>
00004 #include <cmath>
00005 #include <iostream>
00006 #include <unistd.h>
00007 #include <sys/select.h>
00008 #include <netinet/in.h>
00009 
00010 #include <wds-debug.h>
00011 
00012 
00013 // Magic numbers to convert rFlex units to real units
00014 static const double B21_MAGIC_DISTANCE = 101230.0;
00015 static const double B21_MAGIC_ANGLE = 35343.888;
00016 static const double B21_MAGIC_TORQUE = 35000.0;
00017 
00018 static const double ATRVJR_MAGIC_DISTANCE = 90810.0;
00019 static const double ATRVJR_MAGIC_ANGLE = 37000.0;
00020 static const double ATRVJR_MAGIC_TORQUE = 35000.0;
00021 
00022 // Protocol information
00023 static const int PROTOCOL_SIZE = 9;
00024 static const int PACKET_CRC_START = 2;
00025 static const int PACKET_CRC_OFFSET = 4;
00026 
00027 // Escape codes used in the data packets
00028 static const unsigned char NUL = 0;
00029 static const unsigned char SOH = 1;
00030 static const unsigned char STX = 2;
00031 static const unsigned char ETX = 3;
00032 static const unsigned char ESC = 27;
00033 
00034 // Packet data identifiers
00035 static const unsigned int SYSTEM_PORT = 1;
00036 static const unsigned int MOTOR_PORT = 2;
00037 static const unsigned int JOYSTICK_PORT = 3;
00038 static const unsigned int SONAR_PORT = 4;
00039 static const unsigned int DIGITAL_IO_PORT = 5;
00040 static const unsigned int IR_PORT = 6;
00041 
00042 // Packet data slots
00043 static const int PACKET_PORT_BYTE = 2;
00044 static const int PACKET_ID_BYTE = 3;
00045 static const int PACKET_OPCODE_BYTE = 4;
00046 static const int PACKET_SIZE_BYTE = 5;
00047 static const int PACKET_DATA_START_BYTE = 6;
00048 
00049 
00050 // Packet data opcodes
00051 static const int SYSTEM_LCD_DUMP = 0;
00052 static const int SYSTEM_STATUS = 1;
00053 
00054 static const int MOTOR_AXIS_GET_SYSTEM = 0;
00055 static const int MOTOR_AXIS_GET_MODEL = 1;
00056 static const int MOTOR_AXIS_GET_TARGET = 2;
00057 static const int MOTOR_AXIS_SET_LIMITS = 3;
00058 static const int MOTOR_AXIS_GET_LIMITS = 4;
00059 static const int MOTOR_AXIS_SET_POS_LIMITS = 5;
00060 static const int MOTOR_AXIS_GET_POS_LIMITS = 6;
00061 static const int MOTOR_AXIS_SET_DIR = 7;
00062 static const int MOTOR_AXIS_SET_POS = 8;
00063 static const int MOTOR_AXIS_GET_MODE = 9;
00064 static const int MOTOR_SET_DEFAULTS = 10;
00065 static const int MOTOR_BRAKE_SET = 11;
00066 static const int MOTOR_BRAKE_RELEASE = 12;
00067 static const int MOTOR_SYSTEM_REPORT = 33;
00068 static const int MOTOR_SYSTEM_REPORT_REQUEST = 34;
00069 static const int MOTOR_GET_NAXES = 65;
00070 static const int MOTOR_SET_GEARING = 66;
00071 static const int MOTOR_GET_GEARING = 67;
00072 static const int MOTOR_MOTOR_SET_MODE = 68;
00073 static const int MOTOR_MOTOR_GET_MODE = 69;
00074 static const int MOTOR_MOTOR_SET_PARMS = 70;
00075 static const int MOTOR_MOTOR_GET_PARMS = 71;
00076 static const int MOTOR_MOTOR_SET_LIMITS = 72;
00077 static const int MOTOR_MOTOR_GET_LIMITS = 73;
00078 static const int MOTOR_MOTOR_GET_DATA = 74;
00079 static const int MOTOR_AXIS_SET_PARMS = 75;
00080 static const int MOTOR_AXIS_GET_PARMS = 76;
00081 static const int MOTOR_AXIS_SET_PWM_LIMIT = 77;
00082 static const int MOTOR_AXIS_GET_PWM_LIMIT = 78;
00083 static const int MOTOR_AXIS_SET_PWM = 79;
00084 static const int MOTOR_AXIS_GET_PWM = 80;
00085 
00086 static const int JOYSTICK_GET_STATE = 0;
00087 
00088 static const int SONAR_RUN = 0;
00089 static const int SONAR_GET_UPDATE = 1;
00090 static const int SONAR_REPORT = 2;
00091 
00092 static const unsigned char SONAR_OFF = 0;
00093 static const unsigned char SONAR_REPORT_ON_REQUEST = 1;
00094 static const unsigned char SONAR_CONTINUOUS_REPORT = 2;
00095 
00096 static const int DIGITAL_IO_REPORT_REQUEST = 0;
00097 static const int DIGITAL_IO_REPORT = 1;
00098 static const int DIGITAL_IO_GET_UPDATE = 2;
00099 static const int DIGITAL_IO_UPDATE = 3;
00100 static const int DIGITAL_IO_SET = 4;
00101 
00102 static const int IR_RUN = 0;
00103 static const int IR_REPORT = 1;
00104 
00105 
00106 using namespace std;
00107 
00108 //======================================================================
00109 // RFlex
00110 //======================================================================
00111 
00112 RFlex::RFlex(const std::string &filename, const std::string &robotType) :m_port(filename, 115200), m_found(false), m_offset(0), m_translate_command(0.0), m_rotate_command(0.0) {
00113         // Set the initial values of the holding variables
00114         m_x = 0.0;
00115         m_y = 0.0;
00116         m_theta = 0;
00117         m_last_distance = 0;
00118         m_last_angdistance = 0;
00119         m_last_distance_set =false;
00120         m_last_angdistance_set = false;
00121         m_trans_velocity = 0.0;
00122         m_rot_velocity = 0.0;
00123         
00124         bzero(m_sonars,MAX_SONAR*sizeof(double));
00125         if(robotType=="B21r"){
00126                m_type=RFLEX_B21R;
00127                m_magicDistance=B21_MAGIC_DISTANCE;
00128                m_magicAngle=B21_MAGIC_ANGLE;
00129                m_magicTorque=B21_MAGIC_TORQUE;
00130                m_numSonar=0; // not doing B21 sonar yet
00131         }else if(robotType=="ATRVJr"){
00132                m_type=RFLEX_ATRVJR;
00133                m_magicDistance=ATRVJR_MAGIC_DISTANCE;
00134                m_magicAngle=ATRVJR_MAGIC_ANGLE;
00135                m_magicTorque=ATRVJR_MAGIC_TORQUE;
00136                m_numSonar=17;
00137         }else{
00138                cerr << "Unknown robot type!" << endl;
00139                exit(1);
00140         }
00141         
00142         // Initialize the mutexes
00143         pthread_mutex_init(&m_write_mutex, NULL);
00144         pthread_mutex_init(&m_motor_mutex, NULL);
00145         pthread_mutex_init(&m_command_mutex, NULL);
00146 
00147         // Start the read and periodic threads
00148         pthread_create(&m_read_thread, NULL, RFlex::rFlexReadThread, this);
00149         pthread_create(&m_periodic_thread, NULL, RFlex::rFlexPeriodicThread, this);
00150 
00151         // Get some initial values
00152         systemUpdate();
00153         odometryOn();
00154 }
00155 
00156 
00157 
00158 RFlex::~RFlex() {
00159         // Stop the systems
00160         motorSetTranslateVelocity(0.0);
00161         motorSetRotateVelocity(0.0);
00162         odometryOff();
00163         digitalIOOff();
00164         sonarOff();
00165 
00166         // Get rid of the mutexes
00167         pthread_mutex_destroy(&m_write_mutex);
00168         pthread_mutex_destroy(&m_motor_mutex);
00169 
00170         // Need to clean up the threads here
00171 }
00172 
00173 
00174 bool RFlex::systemUpdate() {
00175         pthread_mutex_lock(&m_write_mutex);
00176         const bool retval = sendCommand(SYSTEM_PORT, 0, SYSTEM_STATUS, 0);
00177         pthread_mutex_unlock(&m_write_mutex);
00178 
00179         return retval;
00180 }
00181 
00182 
00183 #warning Need to check this
00184 bool RFlex::systemLCDDump() {
00185         pthread_mutex_lock(&m_write_mutex);
00186         const bool retval = sendCommand(SYSTEM_PORT, 0, SYSTEM_LCD_DUMP, 5);
00187         pthread_mutex_unlock(&m_write_mutex);
00188 
00189         return retval;
00190 }
00191 
00192 
00193 bool RFlex::motionSetDefaults() {
00194         pthread_mutex_lock(&m_write_mutex);
00195         pthread_mutex_unlock(&m_write_mutex);
00196 
00197 #warning Need to implement this
00198         return false;
00199 }
00200 
00201 
00202 #warning No effect
00203 bool RFlex::setBrake() {
00204         pthread_mutex_lock(&m_write_mutex);
00205         const bool retval = sendCommand(MOTOR_PORT, 0, MOTOR_BRAKE_SET, 0);
00206         pthread_mutex_unlock(&m_write_mutex);
00207 
00208         return retval;
00209 }
00210 
00211 
00212 #warning No effect
00213 bool RFlex::releaseBrake() {
00214         pthread_mutex_lock(&m_write_mutex);
00215         const bool retval = sendCommand(MOTOR_PORT, 0, MOTOR_BRAKE_RELEASE, 0);
00216         pthread_mutex_unlock(&m_write_mutex);
00217 
00218         return retval;
00219 }
00220 
00221 
00222 void RFlex::motorSetTranslateVelocity(const double velocity) {
00223         pthread_mutex_lock(&m_command_mutex);
00224         m_translate_command = velocity;
00225         pthread_mutex_unlock(&m_command_mutex);
00226 }
00227 
00228 
00229 void RFlex::motorSetRotateVelocity(const double velocity) {
00230         pthread_mutex_lock(&m_command_mutex);
00231         m_rotate_command = velocity;
00232         pthread_mutex_unlock(&m_command_mutex);
00233 }
00234 
00235 
00236 void RFlex::motorSetVelocity(const double translate, const double rotate) {
00237         pthread_mutex_lock(&m_command_mutex);
00238         m_translate_command = translate;
00239         m_rotate_command = rotate;
00240         pthread_mutex_unlock(&m_command_mutex);
00241 }
00242 
00243 
00244 bool RFlex::odometryOn(const int period) {
00245         pthread_mutex_lock(&m_write_mutex);
00246         insertLong(period, 0);  // Period in ms
00247         insertLong(3, 4);       // Mask
00248 
00249         const bool retval = sendCommand(MOTOR_PORT, 0, MOTOR_SYSTEM_REPORT_REQUEST, 8);
00250         pthread_mutex_unlock(&m_write_mutex);
00251 
00252         return retval;
00253 }
00254 
00255 
00256 bool RFlex::odometryOff() {
00257         pthread_mutex_lock(&m_write_mutex);
00258         insertLong(0, 0);    // Period in ms
00259         insertLong(3, 4);    // Mask
00260 
00261         const bool retval = sendCommand(MOTOR_PORT, 0, MOTOR_SYSTEM_REPORT_REQUEST, 8);
00262         pthread_mutex_unlock(&m_write_mutex);
00263 
00264         return retval;
00265 }
00266 
00267 
00268 bool RFlex::digitalIOOn(const int period) {
00269         pthread_mutex_lock(&m_write_mutex);
00270         insertLong(period, 0);    // period in ms
00271 
00272         const bool retval = sendCommand(DIGITAL_IO_PORT, 0, DIGITAL_IO_REPORT_REQUEST, 4);
00273         pthread_mutex_unlock(&m_write_mutex);
00274 
00275         return retval;
00276 }
00277 
00278 
00279 bool RFlex::digitalIOOff() {
00280         pthread_mutex_lock(&m_write_mutex);
00281         insertLong(0, 0);    // period in ms
00282 
00283         const bool retval = sendCommand(DIGITAL_IO_PORT, 0, DIGITAL_IO_REPORT_REQUEST, 4);
00284         pthread_mutex_unlock(&m_write_mutex);
00285 
00286         return retval;
00287 }
00288 
00289 
00290 bool RFlex::joystickReport() {
00291         pthread_mutex_lock(&m_write_mutex);
00292         const bool retval = sendCommand(JOYSTICK_PORT, 0, JOYSTICK_GET_STATE, 0);
00293         pthread_mutex_unlock(&m_write_mutex);
00294 
00295         return retval;
00296 }
00297 
00298 
00299 bool RFlex::sonarOn() {
00300         pthread_mutex_lock(&m_write_mutex);
00301         insertLong(30000, 0);    // Echo delay
00302         insertLong(0, 4);        // Ping delay
00303         insertLong(0, 8);        // Set delay
00304         insertChar(SONAR_CONTINUOUS_REPORT, 12);   // Reporting mode
00305 
00306         const bool retval = sendCommand(SONAR_PORT, 4, SONAR_RUN, 13);
00307         pthread_mutex_unlock(&m_write_mutex);
00308 
00309         return retval;
00310 }
00311 
00312 
00313 bool RFlex::sonarOff() {
00314         pthread_mutex_lock(&m_write_mutex);
00315 
00316         memset(m_write_buffer + PACKET_DATA_START_BYTE, 0, 13);
00317 
00318         const bool retval = sendCommand(SONAR_PORT, 4, SONAR_RUN, 13);
00319         pthread_mutex_unlock(&m_write_mutex);
00320 
00321         return retval;
00322 }
00323 
00324 
00325 bool RFlex::motorSendTranslateVelocity(const double velocity) {
00326        const unsigned long vel =static_cast<unsigned long>(fabs(velocity) * m_magicDistance);
00327        const unsigned long acceleration = static_cast<unsigned long>(1.0 * m_magicDistance);
00328        const unsigned long torque = static_cast<unsigned long>(1.0 * m_magicTorque);
00329        
00330        pthread_mutex_lock(&m_write_mutex);
00331        insertChar(0, 0);             // Translation
00332        insertLong(vel, 1);           // Velocity
00333        insertLong(acceleration, 5);  // Acceleration
00334        insertLong(torque, 9);        // Torque
00335        insertChar((velocity < 0)?(0):(1), 13);  // Direction
00336        
00337        const bool retval = sendCommand(MOTOR_PORT, 0, MOTOR_AXIS_SET_DIR, 14);
00338        pthread_mutex_unlock(&m_write_mutex);
00339        
00340        return retval;
00341 }
00342 
00343 
00344 bool RFlex::motorSendRotateVelocity(const double velocity) {
00345        const unsigned long vel =static_cast<unsigned long>(fabs(velocity) * m_magicAngle);
00346        const unsigned long acceleration = static_cast<unsigned long>(1.0 * m_magicDistance);
00347        const unsigned long torque = static_cast<unsigned long>(1.0 * m_magicTorque);
00348 
00349         pthread_mutex_lock(&m_write_mutex);
00350         insertChar(1, 0);             // Rotation
00351         insertLong(vel, 1);           // Velocity
00352         insertLong(acceleration, 5);  // Acceleration
00353         insertLong(torque, 9);        // Torque
00354         insertChar((velocity < 0)?(0):(1), 13);  // Direction
00355 
00356         const bool retval = sendCommand(MOTOR_PORT, 0, MOTOR_AXIS_SET_DIR, 14);
00357         pthread_mutex_unlock(&m_write_mutex);
00358 
00359         return retval;
00360 }
00361 
00362 
00363 bool RFlex::sendCommand(const unsigned char port, const unsigned char id, const unsigned char opcode, const int length) {
00364         assert(length + PROTOCOL_SIZE <= s_buffer_size);
00365 
00366         // Header
00367         m_write_buffer[0] = ESC;
00368         m_write_buffer[1] = STX;
00369         m_write_buffer[PACKET_PORT_BYTE] = port;
00370         m_write_buffer[PACKET_ID_BYTE] = id;
00371         m_write_buffer[PACKET_OPCODE_BYTE] = opcode;
00372         m_write_buffer[PACKET_SIZE_BYTE] = static_cast<unsigned char>(length);
00373 
00374         // Footer
00375         m_write_buffer[length + PACKET_DATA_START_BYTE] = computeCRC(m_write_buffer + PACKET_CRC_START, length + PACKET_CRC_OFFSET);
00376         m_write_buffer[length + PACKET_DATA_START_BYTE + 1] = ESC;
00377         m_write_buffer[length + PACKET_DATA_START_BYTE + 2] = ETX;
00378 
00379 
00380         return writePacket(length + 9);
00381 }
00382 
00383 
00384 bool RFlex::writePacket(const int length) const {
00385         if (m_port.fail())
00386                 return false;
00387 
00388         int bytes_written = 0;
00389 
00390         while (bytes_written < length) {
00391                 int n = write(m_port, m_write_buffer + bytes_written, length - bytes_written);
00392                 if (n < 0)
00393                         return false;
00394                 else
00395                         bytes_written += n;
00396 
00397                 // Put in a short wait to let the rFlex controller catch up
00398                 usleep(1000);
00399         }
00400 
00401         return true;
00402 }
00403 
00404 
00405 void RFlex::readPacket() {
00406         // If there's no packet ready, just return
00407         const int read_size = readData();
00408         if (read_size == 0)
00409                 return;
00410 
00411         // Check to make sure that the packet is the correct size
00412         const int data_size = read_size - PROTOCOL_SIZE;
00413         if (m_read_buffer[PACKET_SIZE_BYTE] != data_size) {
00414                //debug("Error in packet size.  Expected %i, got %i\n", data_size, static_cast<int>(m_read_buffer[PACKET_SIZE_BYTE]));
00415                 for(int i = 0; i < s_buffer_size; ++i) {
00416                        //                       debug("%2x ", static_cast<int>(m_read_buffer[i]));
00417                        //                       if (((i + 1) % 10) == 0)
00418                                //                               debug("\n");
00419                 }
00420         }
00421 
00422         // Calculate the packet CRC and verify that it matches
00423         if (computeCRC(m_read_buffer + PACKET_CRC_START, data_size + PACKET_CRC_OFFSET) != m_read_buffer[data_size + PACKET_DATA_START_BYTE]) {
00424                //               debug("CRC error: Expected %i, got %i\n", static_cast<int>(m_read_buffer[read_size - PROTOCOL_SIZE + PACKET_DATA_START_BYTE]), static_cast<int>(computeCRC(m_read_buffer + PACKET_CRC_START, data_size + PACKET_CRC_OFFSET)));
00425 
00426                 for(int i = 0; i < s_buffer_size; ++i) {
00427                        //                       debug("%2x ", static_cast<int>(m_read_buffer[i]));
00428                        //       if (((i + 1) % 10) == 0)
00429                        //       debug("\n");
00430                 }
00431 
00432                 // Eat everything up to the end of the packet
00433                 unsigned char tdata = 0;
00434                 while (tdata != ETX)
00435                         while (read(m_port, &tdata, 1) != 1);
00436 
00437                 return;
00438         }
00439 
00440         // If we get ti here, we have a good packet.  Parse the packet, and process the contents
00441         switch (m_read_buffer[PACKET_PORT_BYTE]) {
00442         case SYSTEM_PORT:
00443                //               debug("System report\n");
00444                 parseSystemReport();
00445                 break;
00446         case MOTOR_PORT:
00447                //debug("Motor report\n");
00448                 parseMotorReport();
00449                 break;
00450         case JOYSTICK_PORT:
00451                //debug("Joystick report\n");
00452                 parseJoystickReport();
00453                 break;
00454         case SONAR_PORT:
00455                //       debug("Sonar report\n");
00456                 parseSonarReport();
00457                 break;
00458         case DIGITAL_IO_PORT:
00459                //debug("Digital IO report\n");
00460                 parseDigitalIOReport();
00461                 break;
00462         case IR_PORT:
00463                //debug("IR report\n");
00464                 parseIRReport();
00465                 break;
00466         default:
00467                //debug("Unknown packet type: %02x\n", static_cast<int>(m_read_buffer[PACKET_PORT_BYTE]));
00468                 break;
00469         }
00470 }
00471 
00472 
00473 int RFlex::readData() {
00474         // Read one byte of of the packet.  No need to check for errors, since this will be called repeatedly.
00475         if (read(m_port, m_read_buffer + m_offset, 1) != 1)
00476                 return 0;
00477 
00478         // Have we started a packet yet?
00479         if (!m_found) {
00480                 // If the first character isn't an ESC, the packet is invalid.  Reset the offset and return.  This
00481                 // will eat badly-formed packets.
00482                 if (m_read_buffer[0] != ESC) {
00483                         m_offset = 0;
00484                         return 0;
00485                 }
00486                 if (m_offset == 0) {
00487                         m_offset = 1;
00488                         return 0;
00489                 }
00490 
00491                 // We have to wait for a STX to show up before it's a valid packet.  If we see an ESC, then we just
00492                 // keep looking for an STX.  If we see something else, give up and start looking for a new packet.
00493                 if (m_read_buffer[1] == STX) {
00494                         m_found = true;
00495                         m_offset = 2;
00496                         return 0;
00497                 } else if (m_read_buffer[1] == ESC) {
00498                         m_offset = 1;
00499                         return 0;
00500                 } else {
00501                         m_offset = 0;
00502                         return 0;
00503                 }
00504         } else {
00505                 // If the previous character was an ESC,
00506                 if (m_read_buffer[m_offset - 1] == ESC) {
00507                         switch (m_read_buffer[m_offset]) {
00508                         case NUL:  // Skip over NULs
00509                                 read(m_port, m_read_buffer + m_offset, 1);  // Should we be checking the return code here?
00510                                 ++m_offset;
00511                                 return 0;
00512                         case SOH:  // Ignore SOHs by deleting them
00513                                 --m_offset;
00514                                 return 0;
00515                         case ETX: // ETX ends the packet, so return the length
00516                                 const int retval = m_offset + 1;
00517                                 m_found = false;
00518                                 m_offset = 0;
00519                                 return retval;
00520                         };
00521                 } else {
00522                         // Just increment the counter
00523                         ++m_offset;
00524                         assert(m_offset < s_buffer_size);
00525 
00526                         return 0;
00527                 }
00528         }
00529 
00530         // Should never get here
00531         return 0;
00532 }
00533 
00534 
00535 void RFlex::parseSystemReport() {
00536         assert(m_read_buffer[PACKET_PORT_BYTE] == SYSTEM_PORT);
00537 
00538         const int TIMESTAMP_OFFSET = 6;
00539         const int BATTERY_OFFSET = 10;
00540         const int BRAKE_OFFSET = 14;
00541 
00542         const int ROW_OFFSET = 10;
00543         const int MESSAGE_LENGTH_OFFSET = 11;
00544         const int MESSAGE_BODY_OFFSET = 12;
00545 
00546         const long timestamp = convertLong(TIMESTAMP_OFFSET);
00547 
00548         switch (m_read_buffer[PACKET_OPCODE_BYTE]) {
00549         case SYSTEM_LCD_DUMP: {
00550                 const int row = static_cast<int>(convertChar(ROW_OFFSET));
00551                 const int length = static_cast<int>(convertChar(MESSAGE_LENGTH_OFFSET));
00552 
00553 #ifndef NDEBUG
00554                 //debug("  row: %i\n  message (%i): ", row, length);
00555                 for(int i = 0; i < length; ++i)
00556                        //               debug("%c", m_read_buffer[MESSAGE_BODY_OFFSET + i]);
00557                        //               debug("\n");
00558 #endif
00559                 break;
00560         }
00561         case SYSTEM_STATUS:
00562                 m_battery_voltage = static_cast<float>(convertLong(BATTERY_OFFSET)) / 100.0;
00563                 //              debug("  battery voltage: %f\n  brake: %s\n", m_battery_voltage, ((m_brake)?("on"):("off")));
00564                 break;
00565         default:
00566                //               debug("Unknown system opcode: %02x\n", m_read_buffer[PACKET_OPCODE_BYTE]);
00567                 break;
00568         }
00569 }
00570 
00571 
00572 #warning Not complete yet
00573 void RFlex::parseMotorReport() {
00574         assert(m_read_buffer[PACKET_PORT_BYTE] == MOTOR_PORT);
00575 
00576         // We're not looking at offset 6, which is rv in the old code.  What is it?
00577         const int TIMESTAMP_OFFSET = 10;
00578         const int AXIS_OFFSET = 14;
00579         const int POSITION_OFFSET = 15;
00580         const int VELOCITY_OFFSET = 19;
00581         const int ACCELERATION_OFFSET = 23;
00582         const int TORQUE_OFFSET = 27;
00583 
00584         const int TRANSLATION_AXIS = 0;
00585         const int ROTATION_AXIS = 1;
00586 
00587         switch (m_read_buffer[PACKET_OPCODE_BYTE]) {
00588         case MOTOR_SYSTEM_REPORT: {
00589                 const long timestamp = convertLong(TIMESTAMP_OFFSET);
00590                 const long distance = static_cast<long>(convertLong(POSITION_OFFSET));
00591 
00592                 switch (m_read_buffer[AXIS_OFFSET]) {
00593                 case TRANSLATION_AXIS:
00594                         pthread_mutex_lock(&m_motor_mutex);
00595                         if(!m_last_distance_set){
00596                                m_last_distance=distance;
00597                                m_last_distance_set=true;
00598                         }
00599                         m_x += static_cast<double>(distance - m_last_distance) / m_magicDistance * cos(m_theta);
00600                         m_y += static_cast<double>(distance - m_last_distance) / m_magicDistance * sin(m_theta);
00601 
00602                         m_trans_velocity = static_cast<double>(convertLong(VELOCITY_OFFSET)) / m_magicDistance;
00603                         m_trans_acceleration = static_cast<double>(convertLong(ACCELERATION_OFFSET)) / m_magicDistance;
00604 #warning Should the torque be using MAGIC_TORQUE?
00605                         m_trans_torque = static_cast<double>(convertLong(TORQUE_OFFSET)) / m_magicDistance;
00606                         m_last_distance = distance;
00607                         pthread_mutex_unlock(&m_motor_mutex);
00608 
00609                         break;
00610                 case ROTATION_AXIS:
00611                         pthread_mutex_lock(&m_motor_mutex);
00612                         if(!m_last_angdistance_set){
00613                                m_last_angdistance=distance;
00614                                m_last_angdistance_set=true;
00615                         }
00616                         //                      m_theta = fmod(static_cast<double>(distance) / m_magicAngle, 2.0 * M_PI) - M_PI;
00617                         m_theta += static_cast<double>(distance-m_last_angdistance) / m_magicAngle;
00618 
00619                         m_rot_velocity = static_cast<double>(convertLong(VELOCITY_OFFSET)) / m_magicAngle;
00620                         m_rot_acceleration = static_cast<double>(convertLong(ACCELERATION_OFFSET)) / m_magicAngle;
00621 #warning Should the torque be using MAGIC_TORQUE?
00622                         m_rot_torque = static_cast<double>(convertLong(TORQUE_OFFSET)) / m_magicAngle;
00623                         m_last_angdistance=distance;
00624                         pthread_mutex_unlock(&m_motor_mutex);
00625                         break;
00626                 default:
00627                        //debug("Unknown motor axis: %02x\n", m_read_buffer[AXIS_OFFSET]);
00628                         break;
00629                 };
00630                 break;
00631         }
00632         case MOTOR_AXIS_SET_DIR:
00633                 // Return value from a write
00634 #warning Should we keep a total of requests and acks, to make sure that theyre more-or-less balanced?
00635                 break;
00636         default:
00637                //       debug("Unknown motor opcode: %02x\n", m_read_buffer[PACKET_OPCODE_BYTE]);
00638                 break;
00639         }
00640 }
00641 
00642 
00643 #warning Not complete yet
00644 void RFlex::parseJoystickReport() {
00645         assert(m_read_buffer[PACKET_PORT_BYTE] == JOYSTICK_PORT);
00646 
00647         const int TIMESTAMP_OFFSET = 6;
00648         const int X_OFFSET = 10;
00649         const int Y_OFFSET = 14;
00650         const int BUTTON_OFFSET = 18;
00651 
00652         switch (m_read_buffer[PACKET_OPCODE_BYTE]) {
00653         case JOYSTICK_GET_STATE: {
00654                 const long timestamp = convertLong(TIMESTAMP_OFFSET);
00655                 const long x = convertLong(X_OFFSET);
00656                 const long y = convertLong(Y_OFFSET);
00657                 const unsigned char buttons = convertChar(BUTTON_OFFSET);
00658 
00659                 //debug("  position: (%li, %li)\n  buttons: %02x\n", x, y, buttons);
00660 
00661 #warning Need to update stored values
00662                 break;
00663                 }
00664         default:
00665                //               debug("Unknown joystick opcode: %02x\n", m_read_buffer[PACKET_OPCODE_BYTE]);
00666                 break;
00667         }
00668 }
00669 
00670 
00671 #warning Not complete yet
00672 void RFlex::parseSonarReport() {
00673 #warning Need to implement this
00674         assert(m_read_buffer[PACKET_PORT_BYTE] == SONAR_PORT);
00675 
00676         const int DATA_LENGTH_OFFSET = 5;
00677         const int VALUE_OFFSET = 6;
00678         const int TIMESTAMP_OFFSET = 10;
00679         const int DATA_OFFSET = 14;
00680 
00681         switch (m_read_buffer[PACKET_OPCODE_BYTE]) {
00682         case SONAR_REPORT: 
00683                const unsigned char data_length = convertChar(DATA_LENGTH_OFFSET);
00684                const long value = convertLong(VALUE_OFFSET);
00685                const long timestamp = convertLong(TIMESTAMP_OFFSET);
00686                
00687                for(int i = 0; i < (data_length - 8) / 3; ++i) {
00688                       const int sonar_id = convertChar(DATA_OFFSET + (3 * i));
00689                       const int sonar_value = convertShort(DATA_OFFSET + (3 * i) + 1);
00690                       if (sonar_value < 500){
00691                              //not the prettiest way to do this
00692                              if(m_type==RFLEX_ATRVJR){
00693                                     switch(sonar_id){
00694                                     case 0x22:
00695                                            m_sonars[0]=sonar_value;
00696                                            break;
00697                                     case 0x23:
00698                                            m_sonars[1]=sonar_value;
00699                                            break;
00700                                     case 0x24:
00701                                            m_sonars[2]=sonar_value;
00702                                            break;
00703                                     case 0x25:
00704                                            m_sonars[3]=sonar_value;
00705                                            break;
00706                                     case 0x14:
00707                                            m_sonars[4]=sonar_value;
00708                                            break;
00709                                     case 0x13:
00710                                            m_sonars[5]=sonar_value;
00711                                            break;
00712                                     case 0x12:
00713                                            m_sonars[6]=sonar_value;
00714                                            break;
00715                                     case 0x11:
00716                                            m_sonars[7]=sonar_value;
00717                                            break;
00718                                     case 0x10:
00719                                            m_sonars[8]=sonar_value;
00720                                            break;
00721                                     case 0x05:
00722                                            m_sonars[9]=sonar_value;
00723                                            break;
00724                                     case 0x04:
00725                                            m_sonars[10]=sonar_value;
00726                                            break;
00727                                     case 0x03:
00728                                            m_sonars[11]=sonar_value;
00729                                            break;
00730                                     case 0x02:
00731                                            m_sonars[12]=sonar_value;
00732                                            break;
00733                                     case 0x01:
00734                                            m_sonars[13]=sonar_value;
00735                                            break;
00736                                     case 0x00:
00737                                            m_sonars[14]=sonar_value;
00738                                            break;
00739                                     case 0x20:
00740                                            m_sonars[15]=sonar_value;
00741                                            break;
00742                                     case 0x21:
00743                                            m_sonars[16]=sonar_value;
00744                                            break;
00745                                     }
00746                              }
00747                       }
00748                              cerr << "Sonar " << sonar_id << " value: " << sonar_value << endl;
00749                       //                               debug("Sonar %02x: %i\n", sonar_id, sonar_value);
00750                }
00751                
00752                break;
00753                
00754                //       default:
00755                //break;
00756                //               debug("Unknown sonar report opcode\n");
00757         }
00758 }
00759 
00760 
00761 #warning Not complete yet
00762 void RFlex::parseDigitalIOReport() {
00763 #warning Need to implement this
00764         assert(m_read_buffer[PACKET_PORT_BYTE] == DIGITAL_IO_PORT);
00765 }
00766 
00767 
00768 #warning Not complete yet
00769 void RFlex::parseIRReport() {
00770 #warning Need to implement this
00771         assert(m_read_buffer[PACKET_PORT_BYTE] == IR_PORT);
00772 }
00773 
00774 
00775 unsigned char RFlex::convertChar(const int offset) const {
00776         assert((offset >= 0) && (offset < s_buffer_size - 1));
00777 
00778         unsigned char n;
00779         memcpy(&n, m_read_buffer + offset, sizeof(unsigned char));
00780         return n;
00781 }
00782 
00783 
00784 unsigned short RFlex::convertShort(const int offset) const {
00785         assert((offset >= 0) && (offset < s_buffer_size - 2));
00786 
00787   unsigned short n;
00788   memcpy(&n, m_read_buffer + offset, sizeof(unsigned short));
00789   return htons(n);
00790 }
00791 
00792 
00793 unsigned long RFlex::convertLong(const int offset) const {
00794         assert((offset >= 0) && (offset < s_buffer_size - 4));
00795 
00796   unsigned long n;
00797   memcpy(&n, m_read_buffer + offset, sizeof(unsigned long));
00798   return htonl(n);
00799 }
00800 
00801 
00802 void RFlex::insertChar(const unsigned char value, const int offset) {
00803         assert(sizeof(unsigned char) == 1);
00804         assert((offset >= 0) && (offset < s_buffer_size - PACKET_DATA_START_BYTE - 1));
00805 
00806         memcpy(m_write_buffer + PACKET_DATA_START_BYTE + offset, &value, sizeof(unsigned char));
00807 }
00808 
00809 
00810 void RFlex::insertLong(const long value, const int offset) {
00811         assert(sizeof(unsigned long) == 4);
00812         assert((offset >= 0) && (offset < s_buffer_size - PACKET_DATA_START_BYTE - 4));
00813 
00814         unsigned long v = htonl(value);
00815         memcpy(m_write_buffer + PACKET_DATA_START_BYTE + offset, &v, sizeof(unsigned long));
00816 }
00817 
00818 
00819 unsigned char RFlex::computeCRC(const unsigned char *buffer, const int n) {
00820         assert(buffer != NULL);
00821   assert(n > 0);
00822 
00823         int crc =buffer[0];
00824         for(int i = 1; i < n; ++i)
00825                 crc ^= buffer[i];
00826 
00827         return crc;
00828 }
00829 
00830 
00831 void *RFlex::rFlexReadThread(void *ptr) {
00832         RFlex *rflex = static_cast<RFlex *>(ptr);
00833 
00834         while (true) {
00835                 // Set up the read set to include the serial port
00836                 fd_set read_set;
00837                 FD_ZERO(&read_set);
00838                 FD_SET(rflex->m_port, &read_set);
00839 
00840                 // Is there any new data to be read from the rFlex?
00841                 if (select(rflex->m_port + 1, &read_set, NULL, NULL, NULL) < 0) {
00842                        //debug("Error in select\n");
00843                 } else if (FD_ISSET(rflex->m_port, &read_set)) {
00844                         rflex->readPacket();
00845                 }
00846         }
00847 }
00848 
00849 
00850 void *RFlex::rFlexPeriodicThread(void *ptr) {
00851         RFlex *rflex = static_cast<RFlex *>(ptr);
00852 
00853         int counter = 0;
00854         while (true) {
00855                 // 100 Hz
00856 
00857                 // 20 Hz
00858                 if ((counter % 5) == 0) {
00859                 }
00860 
00861                 // 10 Hz
00862                 if ((counter % 10) == 0) {
00863                         // This limits our control frequency to 10Hz.  If we want immediate control, then we need to
00864                         // add an active send to the velocity-setting commands.
00865                         pthread_mutex_lock(&(rflex->m_command_mutex));
00866                         rflex->motorSendTranslateVelocity(rflex->m_translate_command);
00867                         rflex->motorSendRotateVelocity(rflex->m_rotate_command);
00868                         pthread_mutex_unlock(&(rflex->m_command_mutex));
00869 
00870                         rflex->systemUpdate();
00871                         //rflex->joystickReport();
00872                 }
00873 
00874                 // 5 Hz
00875                 if ((counter % 20) == 0) {
00876                 }
00877 
00878                 // 1 Hz
00879                 if (counter == 0) {
00880                 }
00881 
00882                 // Maximum control frequency is 100 Hz
00883                 usleep(10000);
00884 
00885                 counter = (counter + 1) % 100;
00886         }
00887 }
00888 

Generated on Thu Feb 1 15:31:52 2007 for WURDE by  doxygen 1.5.1