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
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
00102 total_len = HEADER_LENGTH + payload_len + CRC_LENGTH;
00103 if (total_len > MAX_MSG_LENGTH)
00104 {
00105
00106
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
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
00123 uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
00124 utob(data + crcOffset(), 2, checksum);
00125 }
00126
00127 Message::~Message()
00128 {
00129
00130 }
00131
00132 void Message::send()
00133 {
00134
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
00145
00146 if (ex->ack_flag != BadAckException::BAD_CHECKSUM)
00147 {
00148 throw ex;
00149 }
00150 }
00151 }
00152
00153
00154
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
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
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
00305 if (data[SOH_OFST] != SOH)
00306 {
00307 if (whyNot) { strncpy(whyNot, "SOH is not present.", strLen); }
00308 return false;
00309 }
00310
00311 if (data[STX_OFST] != STX)
00312 {
00313 if (whyNot) { strncpy(whyNot, "STX is not present.", strLen); }
00314 return false;
00315 }
00316
00317 if (getLength() != ((~getLengthComp()) & 0xff))
00318 {
00319 if (whyNot) { strncpy(whyNot, "Length does not match complement.", strLen); }
00320 return false;
00321 }
00322
00323 if (getLength() != (total_len - 3))
00324 {
00325 if (whyNot) { strncpy(whyNot, "Length is wrong.", strLen); }
00326 return false;
00327 }
00328
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 }
00484 }
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 };
00497
00498 std::ostream &operator<<(std::ostream &stream, clearpath::Message &msg)
00499 {
00500 return msg.printMessage(stream);
00501 }
00502