52 #include "rnr/rnrconfig.h" 54 #include "rnr/appkit/Xml.h" 72 const string &strSearchPath,
73 const string &strXmlFileName,
76 vector<string> vecPath;
82 split(strSearchPath,
':', vecPath);
84 bFoundInstance =
false;
87 for(i=0; i<vecPath.size(); ++i)
89 fqname = vecPath[i] +
'/' + strXmlFileName;
90 if( access(fqname.c_str(), F_OK) == 0 )
92 LOGDIAG3(
"Loading tune XML file: %s.", fqname.c_str());
94 bFoundInstance =
true;
96 if( (rc = Xml::loadFile(fqname)) < 0 )
98 LOGERROR(
"Parse of tune parameters from XML file %s failed.",
104 rc = setTunesFromDOM(tunes);
109 LOGDIAG2(
"Loaded tuning parameters from XML file %s.", fqname.c_str());
119 if( !bFoundInstance )
121 LOGDIAG2(
"Optional XML file %s not found - ignoring.",
122 strXmlFileName.c_str());
128 int LaeXmlTune::loadFile(
const std::string &strXmlFileName)
133 if( access(strXmlFileName.c_str(), F_OK) < 0 )
135 LOGDIAG2(
"Optional XML file %s does not exist - ignoring.",
136 strXmlFileName.c_str());
141 else if( (rc = Xml::loadFile(strXmlFileName)) < 0 )
143 LOGERROR(
"Parse of tune parameters from XML file %s failed - ignoring.",
144 strXmlFileName.c_str());
157 int LaeXmlTune::loadFile(
LaeTunes &tunes,
const std::string &strXmlFileName)
161 if( (rc = loadFile(strXmlFileName)) == LAE_OK )
163 rc = setTunesFromDOM(tunes);
166 return rc < 0? -LAE_ECODE_XML: LAE_OK;
169 int LaeXmlTune::createTemplateFile(
const string &strXmlFileName)
173 if( strXmlFileName.empty() )
175 setErrorMsg(
"No file name.");
176 LOGERROR(
"%s", m_bufErrMsg);
177 return -LAE_ECODE_XML;
180 m_strXmlFileName = strXmlFileName;
183 if( (fp = fopen(m_strXmlFileName.c_str(),
"w+")) == NULL )
185 setErrorMsg(
"%s: %s(errno=%d).",
186 m_strXmlFileName.c_str(), strerror(errno), errno);
187 LOGERROR(
"%s", m_bufErrMsg);
188 return -LAE_ECODE_XML;
197 fprintf(fp,
" <!-- RoadNarrows Laelaps Tuning Configuration -->\n");
198 fprintf(fp,
"%s", m_strXmlHead.c_str());
203 fprintf(fp,
" <!-- Laelaps tuning -->\n");
204 fprintf(fp,
" <%s>\n", m_strMajElemTuning.c_str());
206 fprintf(fp,
" <!-- TUNING ELEMENTS HERE -->\n");
208 fprintf(fp,
" </%s>\n\n", m_strMajElemTuning.c_str());
213 fprintf(fp,
"%s", m_strXmlTail.c_str());
217 LOGDIAG3(
"Created file %s.", m_strXmlFileName.c_str());
224 TiXmlElement *pElem1, *pElem2;
229 if( m_pElemRoot == NULL )
231 setErrorMsg(
"Missing DOM and/or <%s> root element missing.",
232 m_strRootElemName.c_str());
233 LOGERROR(
"%s", m_bufErrMsg);
234 return -LAE_ECODE_XML;
238 for(pElem1 = m_pElemRoot->FirstChildElement(), rc = LAE_OK;
239 (pElem1 != NULL) && (rc == LAE_OK);
240 pElem1 = pElem1->NextSiblingElement())
243 if( (sValue = pElem1->Value()) == NULL )
253 else if( !strcasecmp(sValue, m_strMajElemTuning.c_str()) )
256 for(pElem2 = pElem1->FirstChildElement();
257 (pElem2 != NULL) && (rc == LAE_OK);
258 pElem2 = pElem2->NextSiblingElement())
261 if( (sValue = pElem2->Value()) == NULL )
267 else if( !strcasecmp(sValue, m_strSecElemGlobal.c_str()) )
269 rc = setGlobalTunes(pElem2, tunes);
273 else if( !strcasecmp(sValue, m_strSecElemBattery.c_str()) )
275 rc = setBatteryTunes(pElem2, tunes);
279 else if( !strcasecmp(sValue, m_strSecElemPowertrains.c_str()) )
281 rc = setPowertrainTunes(pElem2, tunes);
285 else if( !strcasecmp(sValue, m_strSecElemRangeSensor.c_str()) )
287 rc = setRangeSensorTunes(pElem2, tunes);
293 warnUnknownElem(sValue);
302 int LaeXmlTune::setDOMFromTunes(
const LaeTunes &tunes)
305 return -LAE_ECODE_GEN;
313 int LaeXmlTune::setGlobalTunes(TiXmlElement *pElemSec,
LaeTunes &tunes)
316 string strSubSecElemThreads(
"threads");
317 string strSubSecElemTraj(
"trajectory");
318 string strElemVelDerate(
"velocity_derate");
319 string strElemWdTimeout(
"watchdog_timeout");
328 for(pElem = pElemSec->FirstChildElement(), rc = LAE_OK;
329 (pElem != NULL) && (rc == LAE_OK);
330 pElem = pElem->NextSiblingElement())
333 if( (sValue = pElem->Value()) == NULL )
339 else if( !strcasecmp(sValue, strSubSecElemThreads.c_str()) )
341 rc = setGlobalThreadTunes(pElem, tunes);
345 else if( !strcasecmp(sValue, strElemVelDerate.c_str()) )
347 rc = strToDoubleWithinRange(strElemVelDerate, elemText(pElem),
348 LaeTuneVelDerateMin, LaeTuneVelDerateMax,
359 else if( !strcasecmp(sValue, strSubSecElemTraj.c_str()) )
361 rc = setGlobalTrajTunes(pElem, tunes);
365 else if( !strcasecmp(sValue, strElemWdTimeout.c_str()) )
367 rc = strToDoubleWithinRange(strElemWdTimeout, elemText(pElem),
368 LaeTuneWdTimeoutMin, LaeTuneWdTimeoutMax,
380 warnUnknownElem(sValue);
386 LOGDIAG3(
"%s: Laelaps global tune parameters set.",
387 m_strXmlFileName.c_str());
393 int LaeXmlTune::setGlobalThreadTunes(TiXmlElement *pElemSubSec,
LaeTunes &tunes)
396 string strElemImuHz(
"imu_hz");
397 string strElemKinHz(
"kinematics_hz");
398 string strElemRangeHz(
"range_hz");
407 for(pElem = pElemSubSec->FirstChildElement(), rc = LAE_OK;
408 (pElem != NULL) && (rc == LAE_OK);
409 pElem = pElem->NextSiblingElement())
412 if( (sValue = pElem->Value()) == NULL )
418 else if( !strcasecmp(sValue, strElemImuHz.c_str()) )
420 rc = strToDoubleWithMinimum(strElemImuHz, elemText(pElem),
421 LaeTuneThreadHzMin, tunes.
m_fImuHz);
425 else if( !strcasecmp(sValue, strElemKinHz.c_str()) )
427 rc = strToDoubleWithMinimum(strElemKinHz, elemText(pElem),
432 else if( !strcasecmp(sValue, strElemRangeHz.c_str()) )
434 rc = strToDoubleWithMinimum(strElemRangeHz, elemText(pElem),
441 warnUnknownElem(sValue);
447 LOGDIAG3(
"%s: Laelaps global thread tune parameters set.",
448 m_strXmlFileName.c_str());
454 int LaeXmlTune::setGlobalTrajTunes(TiXmlElement *pElemSubSec,
LaeTunes &tunes)
457 string strElemTrajNorm(
"norm");
458 string strElemTrajEpsilon(
"epsilon");
467 for(pElem = pElemSubSec->FirstChildElement(), rc = LAE_OK;
468 (pElem != NULL) && (rc == LAE_OK);
469 pElem = pElem->NextSiblingElement())
472 if( (sValue = pElem->Value()) == NULL )
478 else if( !strcasecmp(sValue, strElemTrajNorm.c_str()) )
480 strToNorm(strElemTrajNorm, elemText(pElem), tunes.
m_eTrajNorm);
484 else if( !strcasecmp(sValue, strElemTrajEpsilon.c_str()) )
486 rc = strToDoubleWithMinimum(strElemTrajEpsilon, elemText(pElem),
499 warnUnknownElem(sValue);
505 LOGDIAG3(
"%s: Laelaps global trajectory tune parameters set.",
506 m_strXmlFileName.c_str());
517 int LaeXmlTune::setBatteryTunes(TiXmlElement *pElemSec,
LaeTunes &tunes)
520 string strElemType(
"type");
521 string strElemChem(
"chemistry");
522 string strElemCap(
"capacity");
523 string strElemCells(
"cells");
524 string strElemMax(
"max");
525 string strElemNominal(
"nominal");
526 string strElemMin(
"min");
538 for(pElem = pElemSec->FirstChildElement(), rc = LAE_OK;
539 (pElem != NULL) && (rc == LAE_OK);
540 pElem = pElem->NextSiblingElement())
543 if( (sValue = pElem->Value()) == NULL )
549 else if( !strcasecmp(sValue, strElemType.c_str()) )
556 else if( !strcasecmp(sValue, strElemChem.c_str()) )
563 else if( !strcasecmp(sValue, strElemCap.c_str()) )
565 str = elemText(pElem);
568 if( (rc = strToDouble(str, fVal)) < 0 )
570 setErrorMsg(
"%s: Element <%s> text \"%s\" not an number.",
571 m_strXmlFileName.c_str(), strElemCap.c_str(),
573 LOGERROR(
"%s", m_bufErrMsg);
576 else if( fVal != LaeTuneBattCapAh )
578 setErrorMsg(
"%s: Element <%s> value is fixed at %.1lfAh.",
579 m_strXmlFileName.c_str(), strElemCap.c_str(), LaeTuneBattCapAh);
580 LOGWARN(
"%s", m_bufErrMsg);
586 else if( !strcasecmp(sValue, strElemCells.c_str()) )
588 str = elemText(pElem);
591 if( (rc = strToInt(str, iVal)) < 0 )
593 setErrorMsg(
"%s: Element <%s> text \"%s\" not an number.",
594 m_strXmlFileName.c_str(), strElemCells.c_str(),
596 LOGERROR(
"%s", m_bufErrMsg);
599 else if( iVal != LaeTuneBattCells )
601 setErrorMsg(
"%s: Element <%s> value is fixed at %d cells.",
602 m_strXmlFileName.c_str(), strElemCells.c_str(),
604 LOGWARN(
"%s", m_bufErrMsg);
610 else if( !strcasecmp(sValue, strElemNominal.c_str()) )
612 str = elemText(pElem);
615 if( (rc = strToDouble(str, fVal)) < 0 )
617 setErrorMsg(
"%s: Element <%s> text \"%s\" not an number.",
618 m_strXmlFileName.c_str(), strElemNominal.c_str(),
620 LOGERROR(
"%s", m_bufErrMsg);
623 else if( fVal != LaeTuneBattNominalV )
625 setErrorMsg(
"%s: Element <%s> value is fixed at %.1lfV.",
626 m_strXmlFileName.c_str(), strElemNominal.c_str(),
627 LaeTuneBattNominalV);
628 LOGERROR(
"%s", m_bufErrMsg);
629 return -LAE_ECODE_XML;
635 else if( !strcasecmp(sValue, strElemMax.c_str()) )
637 rc = strToDoubleWithinRange(strElemMax, elemText(pElem),
638 LaeTuneBattNominalV, LaeTuneBattMaxVMax,
643 else if( !strcasecmp(sValue, strElemMin.c_str()) )
645 rc = strToDoubleWithinRange(strElemMin, elemText(pElem),
646 LaeTuneBattMinVMin, LaeTuneBattNominalV,
652 warnUnknownElem(sValue);
658 LOGDIAG3(
"%s: Laelaps battery tune parameters set.",
659 m_strXmlFileName.c_str());
670 int LaeXmlTune::setPowertrainTunes(TiXmlElement *pElemSec,
LaeTunes &tunes)
673 string strAttrLoc(
"location");
674 string strSubSecElemVelPid(
"velocity_pid");
675 string strSubSecElemTires(
"tires");
684 strLoc = elemAttr(pElemSec, strAttrLoc);
688 setErrorMsg(
"%s: No %s attribute of <%s> found.",
689 m_strXmlFileName.c_str(),
691 m_strSecElemPowertrains.c_str());
692 LOGERROR(
"%s", m_bufErrMsg);
693 return -LAE_ECODE_XML;
696 for(i = 0, bFound =
false; i < LaeNumMotorCtlrs; ++i)
698 if( !strcasecmp(strLoc.c_str(), LaeDesc::KeyMotorCtlr[i]) )
707 setErrorMsg(
"%s: Bad %s=\"%s\" attribute value of <%s> found.",
708 m_strXmlFileName.c_str(),
711 m_strSecElemPowertrains.c_str());
712 LOGERROR(
"%s", m_bufErrMsg);
713 return -LAE_ECODE_XML;
725 for(pElem = pElemSec->FirstChildElement(), rc = LAE_OK;
726 (pElem != NULL) && (rc == LAE_OK);
727 pElem = pElem->NextSiblingElement())
730 if( (sValue = pElem->Value()) == NULL )
736 else if( !strcasecmp(sValue, strSubSecElemVelPid.c_str()) )
738 rc = setPowertrainVelPidTunes(strLoc, pElem, tunes);
742 else if( !strcasecmp(sValue, strSubSecElemTires.c_str()) )
744 rc = setPowertrainTireTunes(strLoc, pElem, tunes);
750 warnUnknownElem(sValue);
756 LOGDIAG3(
"%s: Laelaps %s powertrain tune parameters set.",
757 m_strXmlFileName.c_str(), strLoc.c_str());
763 int LaeXmlTune::setPowertrainVelPidTunes(
const string &strLoc,
764 TiXmlElement *pElemSubSec,
768 string strElemVelPidKp(
"Kp");
769 string strElemVelPidKi(
"Ki");
770 string strElemVelPidKd(
"Kd");
780 tunesPowertrain = tunes.
m_mapPtp[strLoc];
784 LOGERROR(
"Bug: Cannot find \%s\" powertrain tuning parameters.",
786 return -LAE_ECODE_INTERNAL;
792 for(pElem = pElemSubSec->FirstChildElement(), rc = LAE_OK;
793 (pElem != NULL) && (rc == LAE_OK);
794 pElem = pElem->NextSiblingElement())
797 if( (sValue = pElem->Value()) == NULL )
803 else if( !strcasecmp(sValue, strElemVelPidKp.c_str()) )
805 rc = strToDoubleWithMinimum(strElemVelPidKp, elemText(pElem),
811 else if( !strcasecmp(sValue, strElemVelPidKi.c_str()) )
813 rc = strToDoubleWithMinimum(strElemVelPidKi, elemText(pElem),
819 else if( !strcasecmp(sValue, strElemVelPidKd.c_str()) )
821 rc = strToDoubleWithMinimum(strElemVelPidKd, elemText(pElem),
829 warnUnknownElem(sValue);
836 tunes.
m_mapPtp[strLoc] = tunesPowertrain;
838 LOGDIAG3(
"%s: Laelaps %s powertrain velocity PID tune parameters set.",
839 m_strXmlFileName.c_str(), strLoc.c_str());
845 int LaeXmlTune::setPowertrainTireTunes(
const string &strLoc,
846 TiXmlElement *pElemSubSec,
850 string strElemTireRadius(
"radius");
851 string strElemTireWidth(
"width");
861 tunesPowertrain = tunes.
m_mapPtp[strLoc];
865 LOGERROR(
"Bug: Cannot find \%s\" powertrain tuning parameters.",
867 return -LAE_ECODE_INTERNAL;
873 for(pElem = pElemSubSec->FirstChildElement(), rc = LAE_OK;
874 (pElem != NULL) && (rc == LAE_OK);
875 pElem = pElem->NextSiblingElement())
878 if( (sValue = pElem->Value()) == NULL )
884 else if( !strcasecmp(sValue, strElemTireRadius.c_str()) )
886 rc = strToDoubleWithMinimum(strElemTireRadius, elemText(pElem),
892 else if( !strcasecmp(sValue, strElemTireWidth.c_str()) )
894 rc = strToDoubleWithMinimum(strElemTireWidth, elemText(pElem),
902 warnUnknownElem(sValue);
909 tunes.
m_mapPtp[strLoc] = tunesPowertrain;
911 LOGDIAG3(
"%s: Laelaps %s powertrain tire dimension tune parameters set.",
912 m_strXmlFileName.c_str(), strLoc.c_str());
923 int LaeXmlTune::setRangeSensorTunes(TiXmlElement *pElemSec,
LaeTunes &tunes)
926 string strAttrType(
"type");
927 string strAttrLoc(
"location");
932 strType = elemAttr(pElemSec, strAttrType);
933 strLoc = elemAttr(pElemSec, strAttrLoc);
935 if( strType.empty() )
937 setErrorMsg(
"%s: No %s attribute of <%s> found.",
938 m_strXmlFileName.c_str(),
940 m_strSecElemRangeSensor.c_str());
941 LOGERROR(
"%s", m_bufErrMsg);
942 return -LAE_ECODE_XML;
945 else if( strcasecmp(strType.c_str(),
"vl6180") )
947 setErrorMsg(
"%s: Bad %s=\"%s\" attribute value of <%s> found.",
948 m_strXmlFileName.c_str(),
951 m_strSecElemRangeSensor.c_str());
952 LOGERROR(
"%s", m_bufErrMsg);
953 return -LAE_ECODE_XML;
958 return setVL6180Tunes(pElemSec, strType, strLoc, tunes);
962 int LaeXmlTune::setVL6180Tunes(TiXmlElement *pElemSec,
968 string strAttrLoc(
"location");
969 string strElemTofOffset(
"tof_offset");
970 string strElemTofCrossTalk(
"tof_crosstalk");
971 string strElemAlsGain(
"als_gain");
972 string strElemAlsIntPeriod(
"als_int_period");
973 string strValFactory(
"factory");
985 setErrorMsg(
"%s: No %s attribute of <%s> found.",
986 m_strXmlFileName.c_str(),
988 m_strSecElemRangeSensor.c_str());
989 LOGERROR(
"%s", m_bufErrMsg);
990 return -LAE_ECODE_XML;
993 for(i = 0, bFound =
false; i < ToFSensorMaxNumOf; ++i)
995 if( !strcasecmp(strLoc.c_str(), LaeDesc::KeyRangeSensorMax[i]) )
1004 setErrorMsg(
"%s: Bad %s=\"%s\" attribute value of <%s> found.",
1005 m_strXmlFileName.c_str(),
1008 m_strSecElemRangeSensor.c_str());
1009 LOGERROR(
"%s", m_bufErrMsg);
1010 return -LAE_ECODE_XML;
1026 for(pElem = pElemSec->FirstChildElement(), rc = LAE_OK;
1027 (pElem != NULL) && (rc == LAE_OK);
1028 pElem = pElem->NextSiblingElement())
1031 if( (sValue = pElem->Value()) == NULL )
1037 else if( !strcasecmp(sValue, strElemTofOffset.c_str()) )
1039 strText = elemText(pElem);
1040 if( !strcasecmp(strText.c_str(), strValFactory.c_str()) )
1046 rc = strToIntWithinRange(strElemTofOffset, strText,
1047 LaeTuneVL6180TofOffsetMin, LaeTuneVL6180TofOffsetMax,
1053 else if( !strcasecmp(sValue, strElemTofCrossTalk.c_str()) )
1055 strText = elemText(pElem);
1056 if( !strcasecmp(strText.c_str(), strValFactory.c_str()) )
1062 rc = strToIntWithinRange(strElemTofCrossTalk, strText,
1063 LaeTuneVL6180TofXTalkMin, LaeTuneVL6180TofXTalkMax,
1069 else if( !strcasecmp(sValue, strElemAlsGain.c_str()) )
1071 strText = elemText(pElem);
1072 if( !strcasecmp(strText.c_str(), strValFactory.c_str()) )
1074 tunesSensor.
m_fAlsGain = LaeTuneVL6180AlsGainDft;
1078 rc = strToDoubleWithinRange(strElemAlsGain, strText,
1079 LaeTuneVL6180AlsGainMin, LaeTuneVL6180AlsGainMax,
1085 else if( !strcasecmp(sValue, strElemAlsIntPeriod.c_str()) )
1087 strText = elemText(pElem);
1088 if( !strcasecmp(strText.c_str(), strValFactory.c_str()) )
1094 rc = strToIntWithinRange(strElemAlsIntPeriod, strText,
1095 LaeTuneVL6180AlsIntPeriodMin, LaeTuneVL6180AlsIntPeriodMax,
1103 warnUnknownElem(sValue);
1110 LOGDIAG3(
"%s: Laelaps %s VL6180 tune parameters set.",
1111 m_strXmlFileName.c_str(), strLoc.c_str());
1117 int LaeXmlTune::strToDoubleWithMinimum(
const string &strElem,
1118 const string &strText,
1124 if( !strText.empty() )
1126 if( (rc = strToDouble(strText, fVal)) < 0 )
1128 setErrorMsg(
"%s: Element <%s> text \"%s\" not a FPN.",
1129 m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
1130 LOGERROR(
"%s", m_bufErrMsg);
1131 rc = -LAE_ECODE_XML;
1134 else if( fVal < fMin )
1136 setErrorMsg(
"%s: Element <%s> value %lf < than minimum of %lf.",
1137 m_strXmlFileName.c_str(), strElem.c_str(), fVal, fMin);
1138 LOGWARN(
"%s", m_bufErrMsg);
1145 int LaeXmlTune::strToDoubleWithinRange(
const string &strElem,
1146 const string &strText,
1153 if( !strText.empty() )
1155 if( (rc = strToDouble(strText, fVal)) < 0 )
1157 setErrorMsg(
"%s: Element <%s> text \"%s\" not a FPN.",
1158 m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
1159 LOGERROR(
"%s", m_bufErrMsg);
1160 rc = -LAE_ECODE_XML;
1163 else if( fVal < fMin )
1165 setErrorMsg(
"%s: Element <%s> value %lf < than minimum of %lf.",
1166 m_strXmlFileName.c_str(), strElem.c_str(), fVal, fMin);
1167 LOGWARN(
"%s", m_bufErrMsg);
1171 else if( fVal > fMax )
1173 setErrorMsg(
"%s: Element <%s> value %lf > than maximum of %lf.",
1174 m_strXmlFileName.c_str(), strElem.c_str(), fVal, fMax);
1175 LOGWARN(
"%s", m_bufErrMsg);
1183 int LaeXmlTune::strToIntWithinRange(
const string &strElem,
1184 const string &strText,
1191 if( !strText.empty() )
1193 if( (rc = strToInt(strText, nVal)) < 0 )
1195 setErrorMsg(
"%s: Element <%s> text \"%s\" Not a Number.",
1196 m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
1197 LOGERROR(
"%s", m_bufErrMsg);
1198 rc = -LAE_ECODE_XML;
1201 else if( nVal < nMin )
1203 setErrorMsg(
"%s: Element <%s> value %d < than minimum of %d.",
1204 m_strXmlFileName.c_str(), strElem.c_str(), nVal, nMin);
1205 LOGWARN(
"%s", m_bufErrMsg);
1209 else if( nVal > nMax )
1211 setErrorMsg(
"%s: Element <%s> value %d > than maximum of %d.",
1212 m_strXmlFileName.c_str(), strElem.c_str(), nVal, nMax);
1213 LOGWARN(
"%s", m_bufErrMsg);
1221 int LaeXmlTune::strToNorm(
const string &strElem,
1222 const string &strText,
1225 if( strText.empty() )
1229 else if( !strcasecmp(strText.c_str(),
"L1") )
1234 else if( !strcasecmp(strText.c_str(),
"L2") )
1239 else if( !strcasecmp(strText.c_str(),
"Linf") )
1241 eNorm = LaeNormLinf;
1246 setErrorMsg(
"%s: Element <%s> text \"%s\" not a recognized norm.",
1247 m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
1248 LOGERROR(
"%s", m_bufErrMsg);
1249 return -LAE_ECODE_XML;
double m_fMinV
minimum operation voltage
double m_fImuHz
kinematic thread rate (hertz)
double m_fKinematicsHz
kinematic thread rate (hertz)
Laelaps tuning data class.
double degToRad(double d)
Convert degrees to radians.
LaeTunesMapVL6180 m_mapVL6180
range sensors tuning
double m_fVelPidKd
motor velocity PID derivative constant
int m_nTofOffset
ToF part-to-part offset.
double m_fVelPidKp
motor velocity PID proportional const
int m_nAlsIntPeriod
ALS integration period.
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Split string at the delimiter character.
double m_fTireRadius
tire radius (meters)
<b><i>Laelaps</i></b> XML tuning class interface.
LaeNorm m_eTrajNorm
trajectory distanct norm
The <b><i>Laelaps</i></b> namespace encapsulates all <b><i>Laelaps</i></b> related constructs...
Laelaps robotic base mobile platform description class interface.
double m_fWatchDogTimeout
watchdog timeout (seconds)
Laelaps common utilities.
LaeTunesMapPtp m_mapPtp
powertrain pair tuning
int m_nTofCrossTalk
ToF cross-talk compensation.
double m_fVelPidKi
motor velocity PID integral constant
double m_fTrajEpsilon
trajectory epsilon distance (radians)
double m_fMaxV
maximum operating voltage
double m_fTireWidth
tire width (meters)
double m_fVelDerate
velocity derate (fraction)
Laelaps motors, encoder, and controllers hardware abstraction interfaces.
double m_fRangeHz
kinematic thread rate (hertz)
Laelaps powertrain tuning data class.
Laelaps powertrain tuning data class.
LaeTunesBattery m_battery
battery tuning
double m_fAlsGain
ALS analog gain.
Top-level package include file.