LdmrsSectorChangeApp.cpp
Go to the documentation of this file.
00001 //
00002 // LdmrsSectorChangeApp.cpp
00003 //
00004 // Demonstrates setting and checking the FlexibleResolution feature of the
00005 // LDMRS. This feature is not available in all firmware versions.
00006 //
00007 // The App starts a thread that, after some time, sets the ResolutionMap of the scanner,
00008 // activates it and later deactivates it.
00009 //
00010 // All changes to the sensor configuration are non-permanent.
00011 //
00012 
00013 #include "LdmrsSectorChangeApp.hpp"
00014 #include "../tools/errorhandler.hpp"    // for printInfoMessage()
00015 #include "../tools/toolbox.hpp"                 // for toString()
00016 #include "../tools/MathToolbox.hpp"
00017 #include "../datatypes/Scan.hpp"
00018 #include "../datatypes/Object.hpp"
00019 #include "../datatypes/Msg.hpp"
00020 #include "../datatypes/Measurement.hpp"
00021 #include "../datatypes/Fields.hpp"
00022 #include "../datatypes/EvalCases.hpp"
00023 #include "../datatypes/EvalCaseResults.hpp"
00024 #include "../devices/LD_MRS.hpp"
00025 
00026 namespace application
00027 {
00028 
00029 //
00030 // Constructor
00031 //
00032 LdmrsSectorChangeApp::LdmrsSectorChangeApp(Manager* manager) :
00033                 m_manager(manager)
00034 {
00035         m_beVerbose = true;
00036 
00037         printInfoMessage("LdmrsSectorChangeApp constructor done.", m_beVerbose);
00038 
00039         // Start the thread that changes the configuration.
00040         if (m_changeThread.isRunning() == false)
00041         {
00042                 m_changeThread.run(this);
00043         }
00044 }
00045 
00046 
00047 // Destructor
00048 // Clean up all dynamic data structures
00049 LdmrsSectorChangeApp::~LdmrsSectorChangeApp()
00050 {
00051         printInfoMessage("LdmrsSectorChangeApp says Goodbye!", m_beVerbose);
00052 }
00053 
00054 //
00055 // Convert the current Sector or ResolutionMap (which is a vector of sectors) to a readable string.
00056 //
00057 std::string sectorToString(const ScannerInfo::ResolutionMap& sector)
00058 {
00059         UINT32 i = 0;
00060         std::ostringstream oss;
00061         oss << std::endl;
00062         for(ScannerInfo::ResolutionMap::const_iterator s = sector.begin(); s != sector.end(); ++s)
00063         {
00064 
00065                 oss  << "Sector (" << i << "): start=" << doubleToString(s->first*rad2deg, 3) << " res=" << doubleToString(s->second*rad2deg,3) << std::endl;
00066                 i++;
00067         }
00068 
00069         return oss.str();
00070 }
00071 
00072 Scan::const_iterator getNextPointInSameLayer(Scan::const_iterator iter, const Scan& scan)
00073 {
00074         Scan::const_iterator ret = iter;
00075         for (++iter /*start with the next point*/ ; iter != scan.end(); ++iter)
00076         {
00077                 if (iter->getLayer() == ret->getLayer())
00078                 {
00079                         ret = iter;
00080                         break;
00081                 }
00082         }
00083         return ret;
00084 
00085 }
00086 
00087 Scan::const_iterator getNextPoint(Scan::const_iterator iter, const Scan& scan)
00088 {
00089         Scan::const_iterator ret = iter;
00090         ++iter;
00091         if (iter != scan.end())
00092         {
00093                 ret = iter;
00094         }
00095         return ret;
00096 
00097 }
00098 
00099 void LdmrsSectorChangeApp::checkResolution(Scan& scan)
00100 {
00101         if (scan.size() < 10)
00102         {
00103                 // do not process on scans with too few scan points
00104                 return;
00105         }
00106 
00107         // We need the scan in scanner coordinate system (sorted)
00108         if ((scan.getFlags() & Scan::FlagVehicleCoordinates) != 0)
00109         {
00110                 // in vehicle coordinate
00111                 printWarning("LdmrsSectorChangeApp::checkResolution: Scan is in vehicle coordinates and thus cannot be processed!");
00112                 return;
00113         }
00114 
00115         // iterate through all scan points and make a diff of the angles
00116         Scan::const_iterator p;
00117         float angleDiff; // compute differences
00118 
00119         ScannerInfo::ResolutionMap sector; // first = start angle, second = resolution
00120 
00121         for (p = scan.begin(); p != scan.end(); ++p)
00122         {
00123                 Scan::const_iterator p2 = getNextPoint(p, scan);
00124                 Scan::const_iterator p3 = getNextPointInSameLayer(p, scan);
00125                 float interlaced = 1.;
00126                 if (fuzzyCompare(p2->getHAngle(), p3->getHAngle()))
00127                 {
00128                         // we are close to the border -> only 2 scan layers left
00129                         interlaced = 0.5;
00130 
00131                 }
00132                 angleDiff = std::fabs(p2->getHAngle() - p->getHAngle()) * interlaced;
00133 
00134                 if (angleDiff > 0)
00135                 {
00136                         if (sector.size() == 0)
00137                         {
00138                                 sector.push_back(std::make_pair(p->getHAngle(), angleDiff));
00139                         }
00140                         else
00141                         {
00142                                 // we detected a new resolution
00143                                 if (fuzzyCompare(float(sector.back().second), angleDiff) == false)
00144                                 {
00145                                         sector.push_back(std::make_pair(p->getHAngle(),angleDiff));
00146                                 }
00147                         }
00148                 }
00149         }
00150 
00151         if (sector != m_lastMeasuredSector)
00152         {
00153                 std::ostringstream oss;
00154                 oss << "Sector:" << sectorToString(sector);
00155                 printInfoMessage(oss.str(), m_beVerbose);
00156                 m_lastMeasuredSector = sector;
00157         }
00158 }
00159 
00160 //
00161 // Receiver for new data from the manager.
00162 //
00163 void LdmrsSectorChangeApp::setData(BasicData& data)
00164 {
00165         // we are just interested in scan data
00166         switch (data.getDatatype())
00167         {
00168                 case Datatype_Scan:
00169                         {
00170                                 Scan* scan = dynamic_cast<Scan*>(&data);
00171 
00172                                 if (scan)
00173                                 {
00174                                         checkResolution(*scan);
00175                                 }
00176                         }
00177                         break;
00178                 default:
00179                         break;
00180         }
00181 }
00182 
00191 INT16 radian2Int (float radAngle)
00192 {
00193         float rad2ticks = float(devices::LuxBase::ANGULAR_TICKS_PER_ROTATION) / (2.f * PI);     // conversion factor from [rad] to [ticks]
00194         radAngle = normalizeRadians(radAngle);                                                                  // shift [pi, 2*pi) to [-pi, 0)
00195         INT16 angleInt = round_to_int<INT16> (radAngle * rad2ticks);
00196         return angleInt;
00197 }
00198 
00199 bool LdmrsSectorChangeApp::readDetailedErrorCode(UINT32* errCode)
00200 {
00201         // read error variable
00202         UINT32 code;
00203 
00204         devices::LDMRS* scanner = dynamic_cast<devices::LDMRS*>(m_manager->getFirstDeviceByType(Sourcetype_LDMRS));
00205         if (scanner)
00206         {
00207                 if(!scanner->getParameter(devices::ParaDetailedError, &code))
00208                 {
00209                         printWarning("NOT ABLE to to read detailed error code");
00210                         return false;
00211                 }
00212                 switch(code)
00213                 {
00214                 case devices::ErrFlexResFreqInvalid:
00215                         printInfoMessage("Detailed Error code: FlexResFreqInvalid", m_beVerbose);
00216                         break;
00217                 case devices::ErrFlexResNumSectorsInvalid:
00218                         printInfoMessage("Detailed Error code: FlexResNumSectorsInvalid", m_beVerbose);
00219                         break;
00220                 case devices::ErrFlexResNumShotsInvalid:
00221                         printInfoMessage("Detailed Error code: FlexResNumShotsInvalid", m_beVerbose);
00222                         break;
00223                 case devices::ErrFlexResResolutionInvalid:
00224                         printInfoMessage("Detailed Error code: FlexResResolutionInvalid", m_beVerbose);
00225                         break;
00226                 case devices::ErrFlexResScannerNotIdle:
00227                         printInfoMessage("Detailed Error code: FlexResScannerNotIdle", m_beVerbose);
00228                         break;
00229                 case devices::ErrFlexResSectorsOverlapping:
00230                         printInfoMessage("Detailed Error code: FlexResSectorsOverlapping", m_beVerbose);
00231                         break;
00232                 case devices::ErrFlexResSizeOneEighthSectorInvalid:
00233                         printInfoMessage("Detailed Error code: FlexResSizeOneEighthSectorInvalid", m_beVerbose);
00234                         break;
00235                 default:
00236                         break;
00237                 }
00238 
00239                 if (errCode != NULL)
00240                 {
00241                         *errCode = code;
00242                 }
00243         }
00244         else
00245         {
00246                 return false;
00247         }
00248 
00249         return true;
00250 }
00251 
00252 bool LdmrsSectorChangeApp::changeFlexResConfiguration(const ScannerInfo::ResolutionMap& configuredRM)
00253 {
00254         if(configuredRM.size() == 0 || configuredRM.size() > 8)
00255         {
00256                 printWarning("Invalid resolution map size.");
00257                 return false;
00258         }
00259 
00260         devices::LDMRS* scanner = dynamic_cast<devices::LDMRS*>(m_manager->getFirstDeviceByType(Sourcetype_LDMRS));
00261         if (scanner)
00262         {
00263                 if (!scanner->setParameter(devices::ParaNumSectors, UINT32(configuredRM.size() ) ) )
00264                 {
00265                         printInfoMessage("LdmrsSectorChangeApp::changeFlexResConfiguration(): set NumSectors not successful", m_beVerbose);
00266                         readDetailedErrorCode();
00267                         return false;
00268                 }
00269 
00270                 for (UINT32 i = 0; i < configuredRM.size(); ++i)
00271                 {
00272                         // set start angle
00273                         if (!scanner->setParameter((devices::MrsParameterId)(0x4001 + i), radian2Int(configuredRM[i].first) ) )
00274                         {
00275                                 printInfoMessage("LdmrsSectorChangeApp::changeFlexResConfiguration(): set start angle not successful: " + doubleToString(configuredRM[i].first, 3) , m_beVerbose);
00276                                 readDetailedErrorCode();
00277                                 return false;
00278                         }
00279                         // set resolution
00280                         if (!scanner->setParameter((devices::MrsParameterId)(0x4009 + i), radian2Int(configuredRM[i].second) ) )
00281                         {
00282                                 printInfoMessage("LdmrsSectorChangeApp::changeFlexResConfiguration(): set resolution not successful: " + doubleToString(configuredRM[i].first, 3) , m_beVerbose);
00283                                 readDetailedErrorCode();
00284                                 return false;
00285                         }
00286                 }
00287         }
00288 
00289         return true;
00290 }
00291 
00292 //
00293 // Set the AngularResolutionType to either Focused, Constant or FlexRes.
00294 //
00295 bool LdmrsSectorChangeApp::changeAngularResolutionType(devices::AngularResolutionType type)
00296 {
00297         devices::LDMRS* scanner = dynamic_cast<devices::LDMRS*>(m_manager->getFirstDeviceByType(Sourcetype_LDMRS));
00298         if (scanner)
00299         {
00300                 if (scanner->setParameter(devices::ParaAngularResolutionType, UINT32(type) ))
00301                 {
00302 //                      printInfoMessage("LdmrsSectorChangeApp::changeThreadFunction(): set NumSectors to 9 not successful", m_beVerbose);
00303                 }
00304                 else
00305                 {
00306 //                      traceNote(VERSION) << "NOT ABLE to change ResType to: type=" << type  << std::endl;
00307                         readDetailedErrorCode();
00308                         return false;
00309                 }
00310         }
00311 
00312         return true;
00313 }
00314 
00315 //
00316 // Thread that does the actual changing of parameters.
00317 //
00318 void LdmrsSectorChangeApp::changeThreadFunction(bool& endThread, UINT16& waitTimeMs)
00319 {
00320         printInfoMessage("LdmrsSectorChangeApp::changeThreadFunction(): started", m_beVerbose);
00321 
00322         devices::LDMRS* ldmrs = dynamic_cast<devices::LDMRS*>(m_manager->getFirstDeviceByType(Sourcetype_LDMRS));
00323 
00324         if (ldmrs)
00325         {
00326                 ldmrs->setScanAngles(50.0 * deg2rad, -60.0 * deg2rad);
00327 
00328                 UINT32 value = 0;
00329                 if (!ldmrs->getParameter(devices::ParaNumSectors, &value))
00330                 {
00331                         // could not read parameter
00332                 }
00333                 else
00334                 {
00335                         printInfoMessage("LdmrsSectorChangeApp::changeThreadFunction(): read parameter NumSectors=" + toString(value), m_beVerbose);
00336                 }
00337 
00338                 if (!ldmrs->setParameter(devices::ParaNumSectors, 9))
00339                 {
00340                         // could not set parameter
00341                         printInfoMessage("LdmrsSectorChangeApp::changeThreadFunction(): set NumSectors to 9 not successful", m_beVerbose);
00342 
00343                         // read detailed error
00344                         UINT32 code;
00345                         readDetailedErrorCode(&code);
00346 
00347                         if (code != devices::ErrFlexResNumSectorsInvalid)
00348                         {
00349                                 printWarning("Received wrong detailed error code.");
00350                         }
00351                 }
00352 
00353                 // sleep some time to receive some scans first
00354                 UINT32 sleepTimeMs = 10000;
00355                 usleep(sleepTimeMs * 1000);
00356 
00357                 ScannerInfo::ResolutionMap configuredRM;
00358                 configuredRM.push_back(std::make_pair(50.f * deg2rad, 1.f * deg2rad));
00359                 configuredRM.push_back(std::make_pair(35.f * deg2rad, .5f * deg2rad));
00360                 configuredRM.push_back(std::make_pair(30.f * deg2rad, .25f * deg2rad));
00361                 configuredRM.push_back(std::make_pair(20.f * deg2rad, .125f * deg2rad));
00362                 configuredRM.push_back(std::make_pair(0.f * deg2rad, .25f * deg2rad));
00363                 configuredRM.push_back(std::make_pair(-20.f * deg2rad, .5f * deg2rad));
00364                 configuredRM.push_back(std::make_pair(-31.f * deg2rad, 1.f * deg2rad));
00365                 configuredRM.push_back(std::make_pair(-40.f * deg2rad, .5f * deg2rad));
00366 
00367                 changeFlexResConfiguration(configuredRM);
00368 
00369                 changeAngularResolutionType(devices::ResolutionTypeFlexRes);
00370 
00371                 usleep(sleepTimeMs * 1000);
00372 
00373                 // change back
00374                 changeAngularResolutionType(devices::ResolutionTypeConstant);
00375         }
00376 
00377         endThread = true;
00378         waitTimeMs = 0;
00379         printInfoMessage("LdmrsSectorChangeApp::changeThreadFunction():  All done, leaving.", m_beVerbose);
00380 }
00381 
00382 }       // namespace application


libsick_ldmrs
Author(s): SICK AG , Martin Günther , Jochen Sprickerhof
autogenerated on Wed Jun 14 2017 04:04:50