Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <RmpInterface.h>
00040
00041 #include <stdexcept>
00042 #include <iostream>
00043 #include <thread>
00044 #include <chrono>
00045
00046 #include <RmpMessage.h>
00047 #include <RmpType.h>
00048 #include <RmpHelper.h>
00049 #include <RmpUdp.h>
00050 #include <RmpUsb.h>
00051 #include <RmpConfigurationCommand.h>
00052 #include <RmpLogger.h>
00053
00054 namespace segway
00055 {
00056 static const size_t MAX_TRIAL_NBR = 7;
00057
00058 RmpInterface::RmpInterface()
00059 : m_IsFeedbackBitmapSet(false)
00060 {
00061 Logger::SetMinLogLevel(INFO);
00062 Logger::AddLogFile(std::string("rmp_interface.log"));
00063 Logger::AddOutputStream(std::cout);
00064 }
00065
00066 RmpInterface::~RmpInterface()
00067 {
00068 ShutDown();
00069 }
00070
00071 void RmpInterface::Initialize(const std::string& rIpAddress, uint16_t portNumber)
00072 {
00073 if (m_pTransport != nullptr)
00074 {
00075 throw std::logic_error(std::string("Rmp already initialized."));
00076 }
00077
00078 m_pTransport = RmpTransport::Ptr(new RmpUdp(rIpAddress, portNumber));
00079
00080 Initialize();
00081 }
00082
00083 void RmpInterface::Initialize(const std::string& rDevicePort)
00084 {
00085 if (m_pTransport != nullptr)
00086 {
00087 throw std::logic_error(std::string("Rmp already initialized."));
00088 }
00089
00090 m_pTransport = RmpTransport::Ptr(new RmpUsb(rDevicePort));
00091
00092 Initialize();
00093 }
00094
00095 void RmpInterface::ShutDown()
00096 {
00097 if (m_pTransport != nullptr)
00098 {
00099 ChangeOperationalMode(STANDBY_REQUEST);
00100 m_pTransport.reset();
00101 }
00102 }
00103
00104 template<typename T>
00105 bool RmpInterface::SetConfiguration(const RmpConfigurationCommand<T>& rConfigurationCommand, T value)
00106 {
00107 throw std::logic_error(std::string("Method not implemented for this template."));
00108
00109 return false;
00110 }
00111
00112 template<>
00113 bool RmpInterface::SetConfiguration(const RmpConfigurationCommand<uint32_t>& rConfigurationCommand, uint32_t value)
00114 {
00115 if ((value < rConfigurationCommand.m_Min) && (value > rConfigurationCommand.m_Max))
00116 {
00117 SEGWAY_LOG(ERROR, "Try to set configuration with invalid value: " << value << " should be between " << rConfigurationCommand.m_Min << " and " << rConfigurationCommand.m_Max);
00118
00119 return false;
00120 }
00121
00122 if (m_pTransport == nullptr)
00123 {
00124 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00125 }
00126
00127 return SetConfiguration(static_cast<uint16_t>(rConfigurationCommand.m_CommandId), rConfigurationCommand.m_FeedbackType, value);
00128 }
00129
00130 template<>
00131 bool RmpInterface::SetConfiguration(const RmpConfigurationCommand<float>& rConfigurationCommand, float value)
00132 {
00133 if ((value < rConfigurationCommand.m_Min) && (value > rConfigurationCommand.m_Max))
00134 {
00135 SEGWAY_LOG(ERROR, "Try to set configuration with invalid value: " << value << " should be between " << rConfigurationCommand.m_Min << " and " << rConfigurationCommand.m_Max);
00136
00137 return false;
00138 }
00139
00140 if (m_pTransport == nullptr)
00141 {
00142 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00143 }
00144
00145 return SetConfiguration(static_cast<uint16_t>(rConfigurationCommand.m_CommandId), rConfigurationCommand.m_FeedbackType, ConvertFloatToUint32(value));
00146 }
00147
00148 bool RmpInterface::Update(bool forceUpdate)
00149 {
00150 if (m_pTransport == nullptr)
00151 {
00152 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00153 }
00154
00155 if (!m_IsFeedbackBitmapSet)
00156 {
00157 SEGWAY_LOG(ERROR, "Unable to update. Bitmap is not set.");
00158
00159 return false;
00160 }
00161
00162 bool result = false;
00163 size_t expectedUserFeedbackSize = GetFeedbackEntryCount() * sizeof(uint32_t);
00164 uint32_t attempt = 0;
00165 Bytes bytes;
00166
00167 while (!result && (attempt < MAX_TRIAL_NBR))
00168 {
00169 result = m_pTransport->Receive(bytes, expectedUserFeedbackSize);
00170
00171 if (!result && forceUpdate)
00172 {
00173 SetConfiguration(RmpConfigurationCommandSet::NONE, static_cast<uint32_t>(0));
00174 }
00175
00176 ++attempt;
00177 }
00178
00179 if (result)
00180 {
00181 UpdateUserDefinedFeedback(bytes);
00182 }
00183
00184 return result;
00185 }
00186
00187 template<typename T>
00188 T RmpInterface::GetUserDefinedFeedback(UserDefinedFeedbackType type)
00189 {
00190 throw std::runtime_error(std::string("Method not implemented for this template."));
00191
00192 return static_cast<T>(0);
00193 }
00194
00195 template<>
00196 uint32_t RmpInterface::GetUserDefinedFeedback(UserDefinedFeedbackType type)
00197 {
00198 if (!m_IsFeedbackBitmapSet)
00199 {
00200 throw std::logic_error(std::string("Unable to retrieve user defined feedback. Bitmap is not set."));
00201 }
00202
00203 size_t feedbackType = type / MAX_ENTRIES_PER_FEEDBACK;
00204 size_t entry = type % MAX_ENTRIES_PER_FEEDBACK;
00205
00206 uint32_t mask = 1 << entry;
00207
00208 if (!(m_FeedbackBitmap[feedbackType] & mask))
00209 {
00210 std::stringstream stringStream;
00211 stringStream << "Unable to retrieve user defined feedback. Feedback is not set for type: " << type;
00212 throw std::runtime_error(stringStream.str());
00213 }
00214
00215 return m_UserDefinedFeedback[feedbackType][entry];
00216 }
00217
00218 template<>
00219 float RmpInterface::GetUserDefinedFeedback(UserDefinedFeedbackType type)
00220 {
00221 return ConvertUint32ToFloat(GetUserDefinedFeedback<uint32_t>(type));
00222 }
00223
00224 bool RmpInterface::ResetIntegrators(uint32_t bitmap)
00225 {
00226 if (bitmap > RESET_ALL_POSITION_DATA)
00227 {
00228 throw std::logic_error(std::string("Invalid reset integrator bitmap."));
00229 }
00230
00231 if (m_pTransport == nullptr)
00232 {
00233 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00234 }
00235
00236 bool result = false;
00237 size_t attempt = 0;
00238
00239 while (!result && (attempt < MAX_TRIAL_NBR))
00240 {
00241 result = SendConfigurationCommand(CONFIG_CMD_ID_RESET_INTEGRATORS, bitmap);
00242
00243 if (result)
00244 {
00245 result = Update(true);
00246
00247 if (result)
00248 {
00249 if (bitmap & RESET_LINEAR_POSITION)
00250 {
00251 if (GetUserDefinedFeedback<float>(LINEAR_POS_M) != 0)
00252 {
00253 result = false;
00254 }
00255 }
00256
00257 if (bitmap & RESET_RIGHT_FRONT_POSITION)
00258 {
00259 if (GetUserDefinedFeedback<float>(RIGHT_FRONT_POS_M) != 0)
00260 {
00261 result = false;
00262 }
00263 }
00264
00265 if (bitmap & RESET_LEFT_FRONT_POSITION)
00266 {
00267 if (GetUserDefinedFeedback<float>(LEFT_FRONT_POS_M) != 0)
00268 {
00269 result = false;
00270 }
00271 }
00272
00273 if (bitmap & RESET_RIGHT_REAR_POSITION)
00274 {
00275 if (GetUserDefinedFeedback<float>(RIGHT_REAR_POS_M) != 0)
00276 {
00277 result = false;
00278 }
00279 }
00280
00281 if (bitmap & RESET_LEFT_REAR_POSITION)
00282 {
00283 if (GetUserDefinedFeedback<float>(LEFT_REAR_POS_M) != 0)
00284 {
00285 result = false;
00286 }
00287 }
00288 }
00289 }
00290
00291 ++attempt;
00292 }
00293
00294 return result;
00295 }
00296
00297 bool RmpInterface::ResetParamsToDefault()
00298 {
00299 if (m_pTransport == nullptr)
00300 {
00301 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00302 }
00303
00304 bool result = false;
00305 size_t attempt = 0;
00306
00307 while (!result && (attempt < MAX_TRIAL_NBR))
00308 {
00309 result = SendConfigurationCommand(static_cast<uint16_t>(CONFIG_CMD_ID_RESET_PARAMS_TO_DEFAULT), 0);
00310
00311 if (result)
00312 {
00313 result = Update(true);
00314 }
00315
00316 ++attempt;
00317 }
00318
00319 if (result)
00320 {
00321 InitializeFeedbackBitmaps();
00322 }
00323
00324 return result;
00325 }
00326
00327 bool RmpInterface::SetUserDefinedFeedbackBitmap(UserDefinedFeedbackBitmapType bitmapType, const uint32_t bitmap)
00328 {
00329 if (m_pTransport == nullptr)
00330 {
00331 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00332 }
00333
00334 RmpConfigurationCommandId configurationCommandId;
00335 bool isValid = false;
00336
00337 switch (bitmapType)
00338 {
00339 case USER_DEFINED_FEEDBACK_BITMAP_1:
00340 {
00341 configurationCommandId = CONFIG_CMD_ID_SET_USER_FB_1_BITMAP;
00342 isValid = IsValidFeedbackBitmap(RmpConfigurationCommandSet::SET_USER_FB_1_BITMAP, bitmap);
00343
00344 break;
00345 }
00346 case USER_DEFINED_FEEDBACK_BITMAP_2:
00347 {
00348 configurationCommandId = CONFIG_CMD_ID_SET_USER_FB_2_BITMAP;
00349 isValid = IsValidFeedbackBitmap(RmpConfigurationCommandSet::SET_USER_FB_2_BITMAP, bitmap);
00350
00351 break;
00352 }
00353 case USER_DEFINED_FEEDBACK_BITMAP_3:
00354 {
00355 configurationCommandId = CONFIG_CMD_ID_SET_USER_FB_3_BITMAP;
00356 isValid = IsValidFeedbackBitmap(RmpConfigurationCommandSet::SET_USER_FB_3_BITMAP, bitmap);
00357
00358 break;
00359 }
00360 case USER_DEFINED_FEEDBACK_BITMAP_4:
00361 {
00362 configurationCommandId = CONFIG_CMD_ID_SET_USER_FB_4_BITMAP;
00363 isValid = IsValidFeedbackBitmap(RmpConfigurationCommandSet::SET_USER_FB_4_BITMAP, bitmap);
00364
00365 break;
00366 }
00367 default:
00368 {
00369 throw std::logic_error(std::string("Invalid feedback bitmap type."));
00370 }
00371 }
00372
00373 if (!isValid)
00374 {
00375 throw std::logic_error(std::string("Invalid feedback bitmap."));
00376 }
00377
00378 bool result = false;
00379 size_t attempt = 0;
00380
00381 while (!result && (attempt < MAX_TRIAL_NBR))
00382 {
00383 result = SendConfigurationCommand(static_cast<uint32_t>(configurationCommandId), bitmap);
00384
00385 if (result)
00386 {
00387 result = Update(true);
00388 }
00389
00390 ++attempt;
00391 }
00392
00393 if (result)
00394 {
00395 InitializeFeedbackBitmaps();
00396
00397 if (bitmap != m_FeedbackBitmap[bitmapType])
00398 {
00399 result = false;
00400 }
00401 }
00402
00403 return result;
00404 }
00405
00406 bool RmpInterface::ChangeOperationalMode(RmpOperationalModeRequest modeRequest)
00407 {
00408 if (m_pTransport == nullptr)
00409 {
00410 throw std::runtime_error(std::string("Initialize communication before calling any methods."));
00411 }
00412
00413 switch (modeRequest)
00414 {
00415 case POWERDOWN_REQUEST:
00416 case DTZ_REQUEST:
00417 {
00418 bool result = false;
00419 size_t attempt = 0;
00420
00421 while (!result && (attempt < MAX_TRIAL_NBR))
00422 {
00423 result = SendConfigurationCommand(static_cast<uint16_t>(CONFIG_CMD_ID_SET_OPERATIONAL_MODE), modeRequest);
00424
00425 ++attempt;
00426 }
00427
00428 return result;
00429 }
00430 case DISABLE_REQUEST:
00431 case STANDBY_REQUEST:
00432 case TRACTOR_REQUEST:
00433 {
00434 bool result = false;
00435 size_t attempt = 0;
00436
00437 while (!result && (attempt < MAX_TRIAL_NBR))
00438 {
00439 result = SendConfigurationCommand(static_cast<uint16_t>(CONFIG_CMD_ID_SET_OPERATIONAL_MODE), modeRequest);
00440
00441 if (result)
00442 {
00443 result = Update(true);
00444
00445 if (result)
00446 {
00447 uint32_t currentMode = GetUserDefinedFeedback<uint32_t>(OPERATIONAL_STATE);
00448
00449 result = false;
00450
00451 if ( ((modeRequest == TRACTOR_REQUEST) && (currentMode == TRACTOR_MODE)) ||
00452 ((modeRequest == STANDBY_REQUEST) && (currentMode == STANDBY_MODE)) ||
00453 ((modeRequest == DISABLE_REQUEST) && (currentMode == DISABLE_POWER)) )
00454 {
00455 result = true;
00456 }
00457 }
00458 }
00459
00460 ++attempt;
00461 }
00462
00463 return result;
00464 }
00465 default:
00466 {
00467 throw std::logic_error(std::string("Invalid mode request type."));
00468 }
00469 }
00470
00471 return false;
00472 }
00473
00474 void RmpInterface::GetFaultStatusDescription(FaultStatusDescription& rDescription)
00475 {
00476 rDescription.clear();
00477
00478 const FeedbackTypeList& rFeedbackTypeList = RmpFault::GetFaultFeedbackEntryList();
00479
00480 for (size_t w = 0; w < rFeedbackTypeList.size(); ++w)
00481 {
00482 UserDefinedFeedbackType feedbackType = rFeedbackTypeList[w];
00483 uint32_t faultWord = GetUserDefinedFeedback<uint32_t>(feedbackType);
00484 const FaultPackingList& rFaultPackingList = RmpFault::GetFaultPackingList(feedbackType);
00485
00486
00487 for (size_t p = 0; p < rFaultPackingList.size(); ++p)
00488 {
00489 const FaultPacking& rFaultPacking = rFaultPackingList[p];
00490
00491 if ((faultWord & rFaultPacking.GetMask()) != NO_FAULT)
00492 {
00493 const FaultDecodeList& rFaultDecodeList = RmpFault::GetFaultDecodeList(rFaultPacking.GetGroup());
00494
00495
00496 for (size_t b = 0; b < rFaultDecodeList.size(); ++b)
00497 {
00498 uint32_t testBit = 1 << (b + rFaultPacking.GetShift());
00499
00500 if (testBit & faultWord)
00501 {
00502 rDescription.push_back(rFaultDecodeList[b]);
00503 }
00504 }
00505 }
00506 }
00507 }
00508 }
00509
00510 void RmpInterface::Initialize()
00511 {
00512 InitializeFeedbackBitmaps();
00513
00514 bool result = ChangeOperationalMode(TRACTOR_REQUEST);
00515 if (!result)
00516 {
00517 throw std::runtime_error(std::string("Fail to set the rmp in tractor mode."));
00518 }
00519 }
00520
00521 void RmpInterface::InitializeFeedbackBitmaps()
00522 {
00523 bool result = false;
00524 size_t attempt = 0;
00525 Bytes bytes;
00526
00527 while (!result && (attempt < MAX_TRIAL_NBR))
00528 {
00529 result = SendConfigurationCommand(static_cast<uint16_t>(CONFIG_CMD_ID_FORCE_CONFIG_FEEDBACK_BITMAPS), 1);
00530
00531 if (result)
00532 {
00533 result = m_pTransport->Receive(bytes, NVM_CONFIG_PARAM_SIZE);
00534 }
00535
00536 ++attempt;
00537 }
00538
00539 if (result)
00540 {
00541 m_IsFeedbackBitmapSet = true;
00542 }
00543 else
00544 {
00545 throw std::runtime_error(std::string("Unable to initialize feedback bitmap"));
00546 }
00547
00548 for (size_t i = 0; i < FEEDBACK_TYPE_NBR; ++i)
00549 {
00550 m_FeedbackBitmap[i] = ConvertBytesToUint32(&bytes[(FORCE_CONFIG_FEEDBACK_1_IDX + i) * sizeof(uint32_t)], sizeof(uint32_t));
00551
00552 SEGWAY_LOG(INFO, "Initialize feedback " << i << " with bitmap: " << std::hex << m_FeedbackBitmap[i]);
00553 }
00554
00555 result = false;
00556 size_t expectedUserFeedbackSize = GetFeedbackEntryCount() * sizeof(uint32_t);
00557 attempt = 0;
00558
00559 while (!result && (attempt < MAX_TRIAL_NBR))
00560 {
00561 result = SendConfigurationCommand(static_cast<uint16_t>(CONFIG_CMD_ID_FORCE_CONFIG_FEEDBACK_BITMAPS), 0);
00562
00563 if (result)
00564 {
00565 result = m_pTransport->Receive(bytes, expectedUserFeedbackSize);
00566 }
00567
00568 ++attempt;
00569 }
00570
00571 if (result)
00572 {
00573 UpdateUserDefinedFeedback(bytes);
00574 }
00575 else
00576 {
00577 throw std::runtime_error(std::string("Unable to stop force config feedback command."));
00578 }
00579 }
00580
00581 bool RmpInterface::SetConfiguration(uint16_t commandId, UserDefinedFeedbackType feedbackType, uint32_t value)
00582 {
00583 switch (feedbackType)
00584 {
00585 case NO_FEEDBACK:
00586 {
00587 bool result = false;
00588 size_t attempt = 0;
00589
00590 while (!result && (attempt < MAX_TRIAL_NBR))
00591 {
00592 result = SendConfigurationCommand(commandId, value);
00593
00594 ++attempt;
00595 }
00596
00597 return result;
00598 }
00599 case INVALID_FEEDBACK:
00600 {
00601 throw std::runtime_error(std::string("Invalid use of configuration command, please use dedicated method."));
00602 }
00603 default:
00604 {
00605 bool result = false;
00606 size_t attempt = 0;
00607
00608 while (!result && (attempt < MAX_TRIAL_NBR))
00609 {
00610 result = SendConfigurationCommand(commandId, value);
00611
00612 if (result)
00613 {
00614 result = Update(true);
00615
00616 if (result)
00617 {
00618 uint32_t feedback = GetUserDefinedFeedback<uint32_t>(feedbackType);
00619
00620 if (feedback != value)
00621 {
00622 result = false;
00623 }
00624 }
00625 }
00626
00627 ++attempt;
00628 }
00629
00630 return result;
00631 }
00632 }
00633
00634 return false;
00635 }
00636
00637 bool RmpInterface::SendConfigurationCommand(uint16_t commandId, uint32_t value)
00638 {
00639 return m_pTransport->Send(CONFIGURATION_CMD, commandId, value);
00640 }
00641
00642
00643 size_t RmpInterface::GetFeedbackEntryCount()
00644 {
00645 size_t count = 0;
00646
00647 for (size_t f = 0; f < FEEDBACK_TYPE_NBR; ++f)
00648 {
00649 for (size_t b = 0; b < MAX_ENTRIES_PER_FEEDBACK; ++b)
00650 {
00651 uint32_t mask = 1 << b;
00652 if (m_FeedbackBitmap[f] & mask)
00653 {
00654 ++count;
00655 }
00656 }
00657 }
00658
00659 return count;
00660 }
00661
00662 void RmpInterface::UpdateUserDefinedFeedback(const Bytes& rBytes)
00663 {
00664 size_t idx = 0;
00665
00666 for (size_t f = 0; f < FEEDBACK_TYPE_NBR; ++f)
00667 {
00668 for (size_t b = 0; b < MAX_ENTRIES_PER_FEEDBACK; ++b)
00669 {
00670 uint32_t mask = 1 << b;
00671 if (m_FeedbackBitmap[f] & mask)
00672 {
00673 assert(idx * sizeof(uint32_t) < rBytes.size());
00674
00675 m_UserDefinedFeedback[f][b] = ConvertBytesToUint32(&(rBytes[idx * sizeof(uint32_t)]), sizeof(uint32_t));
00676 ++idx;
00677 }
00678 }
00679 }
00680 }
00681
00682 bool RmpInterface::IsValidFeedbackBitmap(const RmpConfigurationCommand<uint32_t>& rConfigurationCommand, const uint32_t bitmap)
00683 {
00684 if ((bitmap >= rConfigurationCommand.m_Min) && (bitmap <= rConfigurationCommand.m_Max))
00685 {
00686 return true;
00687 }
00688
00689 return false;
00690 }
00691 }