RmpInterface.cpp
Go to the documentation of this file.
00001 /*
00002   COPYRIGHT (c) 2014 SEGWAY Inc.
00003 
00004   Software License Agreement:
00005 
00006   The software supplied herewith by Segway Inc. (the "Company") for its 
00007   RMP Robotic Platforms is intended and supplied to you, the Company's 
00008   customer, for use solely and exclusively with Segway products. The 
00009   software is owned by the Company and/or its supplier, and is protected 
00010   under applicable copyright laws.  All rights are reserved. Any use in 
00011   violation of the foregoing restrictions may subject the user to criminal
00012   sanctions under applicable laws, as well as to civil liability for the 
00013   breach of the terms and conditions of this license. The Company may 
00014   immediately terminate this Agreement upon your use of the software with 
00015   any products that are not Segway products.
00016 
00017   You shall indemnify, defend and hold the Company harmless from any claims, 
00018   demands, liabilities or expenses, including reasonable attorneys fees, incurred 
00019   by the Company as a result of any claim or proceeding against the Company 
00020   arising out of or based upon: 
00021 
00022   (i) The combination, operation or use of the software by you with any hardware, 
00023       products, programs or data not supplied or approved in writing by the Company, 
00024       if such claim or proceeding would have been avoided but for such combination, 
00025       operation or use.
00026 
00027   (ii) The modification of the software by or on behalf of you.
00028 
00029   (iii) Your use of the software.
00030 
00031   THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
00032   WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED
00033   TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00034   PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
00035   IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
00036   CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
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       } // if (result)
00290 
00291       ++attempt;
00292     } // while (...)
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     } // while (...)
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     } // while (...)
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         } // while (...)
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     // w: word
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       // p: fault packing
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           // b: bit
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           } // b
00505         }
00506       } // p
00507     } // w
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       } // default
00632     } // switch (...)
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 } // namespace segway


rmp_base
Author(s):
autogenerated on Wed Aug 26 2015 16:24:39