Message.cpp
Go to the documentation of this file.
00001 
00047 #include <unistd.h>
00048 #include <iostream>
00049 #include <string.h>
00050 #include "husky_base/horizon_legacy/crc.h"
00051 #include "husky_base/horizon_legacy/Message.h"
00052 #include "husky_base/horizon_legacy/Message_data.h"
00053 #include "husky_base/horizon_legacy/Number.h"
00054 #include "husky_base/horizon_legacy/Transport.h"
00055 
00056 // Conditions on the below to handle compiling for nonstandard hardware
00057 #ifdef LOGGING_AVAIL
00058 #include "husky_base/horizon_legacy/Logger.h"
00059 #endif
00060 
00061 using namespace std;
00062 
00063 namespace clearpath
00064 {
00065 
00066   MessageException::MessageException(const char *msg, enum errors ex_type)
00067       : Exception(msg), type(ex_type)
00068   {
00069 #ifdef LOGGING_AVAIL
00070         CPR_EXCEPT() << "MessageException "<<type<<": "<< message << endl << flush;
00071 #endif
00072   }
00073 
00074   Message::Message() :
00075       is_sent(false)
00076   {
00077     total_len = HEADER_LENGTH + CRC_LENGTH;
00078     memset(data, 0, MAX_MSG_LENGTH);
00079   }
00080 
00081   Message::Message(void *input, size_t msg_len) :
00082       is_sent(false)
00083   {
00084     total_len = msg_len;
00085     memset(data, 0, MAX_MSG_LENGTH);
00086     memcpy(data, input, msg_len);
00087   }
00088 
00089   Message::Message(const Message &other) :
00090       is_sent(false)
00091   {
00092     total_len = other.total_len;
00093     memset(data, 0, MAX_MSG_LENGTH);
00094     memcpy(data, other.data, total_len);
00095   }
00096 
00097   Message::Message(uint16_t type, uint8_t *payload, size_t payload_len,
00098       uint32_t timestamp, uint8_t flags, uint8_t version) :
00099       is_sent(false)
00100   {
00101     /* Copy in data */
00102     total_len = HEADER_LENGTH + payload_len + CRC_LENGTH;
00103     if (total_len > MAX_MSG_LENGTH)
00104     {
00105       /* If payload is too long, the only recourse we have in constructor
00106        * (other than an abort()) is to truncate silently. */
00107       total_len = MAX_MSG_LENGTH;
00108       payload_len = MAX_MSG_LENGTH - HEADER_LENGTH - CRC_LENGTH;
00109     }
00110     memset(data, 0, MAX_MSG_LENGTH);
00111     memcpy(data + PAYLOAD_OFST, payload, payload_len);
00112 
00113     /* Fill header */
00114     data[SOH_OFST] = SOH;
00115     setLength(total_len - 3);
00116     setType(type);
00117     setTimestamp(timestamp);
00118     setFlags(flags);
00119     setVersion(version);
00120     data[STX_OFST] = STX;
00121 
00122     /* Generate checksum */
00123     uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
00124     utob(data + crcOffset(), 2, checksum);
00125   }
00126 
00127   Message::~Message()
00128   {
00129     // nothing to do, actually.
00130   }
00131 
00132   void Message::send()
00133   {
00134     // We will retry up to 3 times if we receive CRC errors
00135     for (int i = 0; i < 2; ++i)
00136     {
00137       try
00138       {
00139         Transport::instance().send(this);
00140         return;
00141       }
00142       catch (BadAckException *ex)
00143       {
00144         // Any bad ack other than bad checksum needs to
00145         // be thrown on
00146         if (ex->ack_flag != BadAckException::BAD_CHECKSUM)
00147         {
00148           throw ex;
00149         }
00150       }
00151     }
00152 
00153     /* Make the final attempt outside the try, so any exception
00154      * just goes straight through */
00155 #ifdef LOGGING_AVAIL
00156     CPR_WARN() << "Bad checksum twice in a row." << endl;
00157 #endif
00158     Transport::instance().send(this);
00159   }
00160 
00167   size_t Message::getPayload(void *buf, size_t buf_size)
00168   {
00169     // If we don't have enough space in the buffer, don't even try
00170     if (getPayloadLength() > buf_size) { return 0; }
00171 
00172     memcpy(buf, data + PAYLOAD_OFST, getPayloadLength());
00173     return getPayloadLength();
00174   }
00175 
00181   uint8_t *Message::getPayloadPointer(size_t offset)
00182   {
00183     return data + PAYLOAD_OFST + offset;
00184   }
00185 
00186   uint8_t  Message::getLength()
00187   {
00188     return data[LENGTH_OFST];
00189   }
00190 
00191   uint8_t  Message::getLengthComp()
00192   {
00193     return data[LENGTH_COMP_OFST];
00194   }
00195 
00196   uint8_t  Message::getVersion()
00197   {
00198     return data[VERSION_OFST];
00199   }
00200 
00201   uint32_t Message::getTimestamp()
00202   {
00203     return btou(data + TIMESTAMP_OFST, 4);
00204   }
00205 
00206   uint8_t  Message::getFlags()
00207   {
00208     return data[FLAGS_OFST];
00209   }
00210 
00211   uint16_t Message::getType()
00212   {
00213     return btou(data + TYPE_OFST, 2);
00214   }
00215 
00216   uint16_t Message::getChecksum()
00217   {
00218     return btou(data + crcOffset(), 2);
00219   }
00220 
00221   void Message::setLength(uint8_t len)
00222   {
00223     size_t new_total_len = len + 3;
00224     if (new_total_len > MAX_MSG_LENGTH) { return; }
00225     total_len = new_total_len;
00226     data[LENGTH_OFST] = len;
00227     data[LENGTH_COMP_OFST] = ~len;
00228   }
00229 
00230   void Message::setVersion(uint8_t version)
00231   {
00232     data[VERSION_OFST] = version;
00233   }
00234 
00235   void Message::setTimestamp(uint32_t timestamp)
00236   {
00237     utob(data + TIMESTAMP_OFST, 4, timestamp);
00238   }
00239 
00240   void Message::setFlags(uint8_t flags)
00241   {
00242     data[FLAGS_OFST] = flags;
00243   }
00244 
00245   void Message::setType(uint16_t type)
00246   {
00247     utob(data + TYPE_OFST, 2, type);
00248   }
00249 
00256   void Message::setPayloadLength(uint8_t len)
00257   {
00258 
00259     if (((size_t) (len) + HEADER_LENGTH + CRC_LENGTH) > MAX_MSG_LENGTH) { return; }
00260     total_len = len + HEADER_LENGTH + CRC_LENGTH;
00261   }
00262 
00270   void Message::setPayload(void *buf, size_t buf_size)
00271   {
00272     if ((buf_size + HEADER_LENGTH + CRC_LENGTH) > MAX_MSG_LENGTH) { return; }
00273     setPayloadLength(buf_size);
00274     if (buf_size > getPayloadLength()) { return; }
00275     memcpy(data + PAYLOAD_OFST, buf, buf_size);
00276   }
00277 
00284   size_t Message::toBytes(void *buf, size_t buf_size)
00285   {
00286     // If we don't have enough space in the buffer, don't even try
00287     if (total_len > buf_size)
00288     {
00289       return 0;
00290     }
00291     memcpy(buf, data, total_len);
00292     return total_len;
00293   }
00294 
00302   bool Message::isValid(char *whyNot, size_t strLen)
00303   {
00304     // Check SOH 
00305     if (data[SOH_OFST] != SOH)
00306     {
00307       if (whyNot) { strncpy(whyNot, "SOH is not present.", strLen); }
00308       return false;
00309     }
00310     // Check STX
00311     if (data[STX_OFST] != STX)
00312     {
00313       if (whyNot) { strncpy(whyNot, "STX is not present.", strLen); }
00314       return false;
00315     }
00316     // Check length matches complement
00317     if (getLength() != ((~getLengthComp()) & 0xff))
00318     {
00319       if (whyNot) { strncpy(whyNot, "Length does not match complement.", strLen); }
00320       return false;
00321     }
00322     // Check length is correct
00323     if (getLength() != (total_len - 3))
00324     {
00325       if (whyNot) { strncpy(whyNot, "Length is wrong.", strLen); }
00326       return false;
00327     }
00328     // Check the CRC
00329     if (crc16(crcOffset(), CRC_INIT_VAL, this->data) != getChecksum())
00330     {
00331       if (whyNot) { strncpy(whyNot, "CRC is wrong.", strLen); }
00332       return false;
00333     }
00334     return true;
00335   }
00336 
00340   void Message::makeValid()
00341   {
00342     data[SOH_OFST] = SOH;
00343     data[STX_OFST] = STX;
00344     data[LENGTH_OFST] = total_len - 3;
00345     data[LENGTH_COMP_OFST] = ~data[LENGTH_OFST];
00346     uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
00347     utob(data + crcOffset(), 2, checksum);
00348   }
00349 
00350   std::ostream &Message::printMessage(std::ostream &stream)
00351   {
00352     stream << "Message" << endl;
00353     stream << "=======" << endl;
00354     stream << "Length   : " << (int) (getLength()) << endl;
00355     stream << "~Length  : " << (int) (getLengthComp()) << endl;
00356     stream << "Version  : " << (int) (getVersion()) << endl;
00357     stream << "Flags    : " << hex << (int) (getFlags()) << endl;
00358     stream << "Timestamp: " << dec << getTimestamp() << endl;
00359     stream << "Type     : " << hex << (int) (getType()) << endl;
00360     stream << "Checksum : " << hex << (int) (getChecksum()) << endl;
00361     stream << dec;
00362     stream << "Raw      : ";
00363     printRaw(stream);
00364     return stream;
00365   }
00366 
00367   void Message::printRaw(std::ostream &stream)
00368   {
00369     stream << hex << uppercase;
00370     for (unsigned int i = 0; i < total_len; i++)
00371     {
00372       stream << static_cast<short>(data[i]) << " ";
00373     }
00374     stream << dec;
00375     stream << endl;
00376   }
00377 
00385   Message *Message::factory(void *input, size_t msg_len)
00386   {
00387     uint16_t type = btou((char *) input + TYPE_OFST, 2);
00388 
00389     switch (type)
00390     {
00391       case DATA_ACCEL:
00392         return new DataPlatformAcceleration(input, msg_len);
00393 
00394       case DATA_ACCEL_RAW:
00395         return new DataRawAcceleration(input, msg_len);
00396 
00397       case DATA_ACKERMANN_SETPTS:
00398         return new DataAckermannOutput(input, msg_len);
00399 
00400       case DATA_CURRENT_RAW:
00401         return new DataRawCurrent(input, msg_len);
00402 
00403       case DATA_PLATFORM_NAME:
00404         return new DataPlatformName(input, msg_len);
00405 
00406       case DATA_DIFF_CTRL_CONSTS:
00407         return new DataDifferentialControl(input, msg_len);
00408 
00409       case DATA_DIFF_WHEEL_SPEEDS:
00410         return new DataDifferentialSpeed(input, msg_len);
00411 
00412       case DATA_DIFF_WHEEL_SETPTS:
00413         return new DataDifferentialOutput(input, msg_len);
00414 
00415       case DATA_DISTANCE_DATA:
00416         return new DataRangefinders(input, msg_len);
00417 
00418       case DATA_DISTANCE_TIMING:
00419         return new DataRangefinderTimings(input, msg_len);
00420 
00421       case DATA_ECHO:
00422         return new DataEcho(input, msg_len);
00423 
00424       case DATA_ENCODER:
00425         return new DataEncoders(input, msg_len);
00426 
00427       case DATA_ENCODER_RAW:
00428         return new DataEncodersRaw(input, msg_len);
00429 
00430       case DATA_FIRMWARE_INFO:
00431         return new DataFirmwareInfo(input, msg_len);
00432 
00433       case DATA_GYRO_RAW:
00434         return new DataRawGyro(input, msg_len);
00435 
00436       case DATA_MAGNETOMETER:
00437         return new DataPlatformMagnetometer(input, msg_len);
00438 
00439       case DATA_MAGNETOMETER_RAW:
00440         return new DataRawMagnetometer(input, msg_len);
00441 
00442       case DATA_MAX_ACCEL:
00443         return new DataMaxAcceleration(input, msg_len);
00444 
00445       case DATA_MAX_SPEED:
00446         return new DataMaxSpeed(input, msg_len);
00447 
00448       case DATA_ORIENT:
00449         return new DataPlatformOrientation(input, msg_len);
00450 
00451       case DATA_ORIENT_RAW:
00452         return new DataRawOrientation(input, msg_len);
00453 
00454       case DATA_PLATFORM_INFO:
00455         return new DataPlatformInfo(input, msg_len);
00456 
00457       case DATA_POWER_SYSTEM:
00458         return new DataPowerSystem(input, msg_len);
00459 
00460       case DATA_PROC_STATUS:
00461         return new DataProcessorStatus(input, msg_len);
00462 
00463       case DATA_ROT_RATE:
00464         return new DataPlatformRotation(input, msg_len);
00465 
00466       case DATA_SAFETY_SYSTEM:
00467         return new DataSafetySystemStatus(input, msg_len);
00468 
00469       case DATA_SYSTEM_STATUS:
00470         return new DataSystemStatus(input, msg_len);
00471 
00472       case DATA_TEMPERATURE_RAW:
00473         return new DataRawTemperature(input, msg_len);
00474 
00475       case DATA_VELOCITY_SETPT:
00476         return new DataVelocity(input, msg_len);
00477 
00478       case DATA_VOLTAGE_RAW:
00479         return new DataRawVoltage(input, msg_len);
00480 
00481       default:
00482         return new Message(input, msg_len);
00483     } // switch getType()
00484   } // factory()
00485 
00486   Message *Message::popNext()
00487   {
00488     return Transport::instance().popNext();
00489   }
00490 
00491   Message *Message::waitNext(double timeout)
00492   {
00493     return Transport::instance().waitNext(timeout);
00494   }
00495 
00496 }; // namespace clearpath
00497 
00498 std::ostream &operator<<(std::ostream &stream, clearpath::Message &msg)
00499 {
00500   return msg.printMessage(stream);
00501 }
00502 


husky_base
Author(s): Mike Purvis , Paul Bovbel
autogenerated on Sat Jun 8 2019 18:26:01