Hekateros  3.4.3
RoadNarrows Robotics Robot Arm Project
hekXmlTune.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Hekateros
4 //
5 // Library: libhekateros
6 //
7 // File: hekXmlTune.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-06-03 15:37:18 -0600 (Wed, 03 Jun 2015) $
12  * $Rev: 4012 $
13  *
14  * \brief \h_hek XML tuning class implementation.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  *
18  * \copyright
19  * \h_copy 2014-2017. RoadNarrows LLC.\n
20  * http://www.roadnarrows.com\n
21  * All Rights Reserved
22  */
23 /*
24  * @EulaBegin@
25  *
26  * Unless otherwise stated explicitly, all materials contained are copyrighted
27  * and may not be used without RoadNarrows LLC's written consent,
28  * except as provided in these terms and conditions or in the copyright
29  * notice (documents and software) or other proprietary notice provided with
30  * the relevant materials.
31  *
32  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
33  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
34  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
35  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
36  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
37  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
40  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
42  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
43  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44  *
45  * @EulaEnd@
46  */
47 ////////////////////////////////////////////////////////////////////////////////
48 
49 #include <unistd.h>
50 
51 #include <string>
52 #include <sstream>
53 #include <vector>
54 
55 #include "rnr/rnrconfig.h"
56 #include "rnr/log.h"
57 #include "rnr/appkit/Xml.h"
58 
59 #include "Hekateros/hekateros.h"
60 #include "Hekateros/hekUtils.h"
61 #include "Hekateros/hekTune.h"
62 #include "Hekateros/hekXmlTune.h"
63 
64 using namespace std;
65 using namespace rnr;
66 using namespace hekateros;
67 
68 //------------------------------------------------------------------------------
69 // HekXmlTune Class
70 //------------------------------------------------------------------------------
71 
72 int HekXmlTune::load(HekTunes &tunes,
73  const string &strSearchPath,
74  const string &strXmlFileName,
75  bool bAllInstances)
76 {
77  vector<string> vecPath; // vector of search paths
78  string fqname; // fully qualified file name
79  bool bFoundInstance; // [not] found instance
80  size_t i; // working index
81  int rc; // return code
82 
83  split(strSearchPath, ':', vecPath);
84 
85  bFoundInstance = false;
86  rc = HEK_OK;
87 
88  for(i=0; i<vecPath.size(); ++i)
89  {
90  fqname = vecPath[i] + '/' + strXmlFileName;
91  if( access(fqname.c_str(), F_OK) == 0 )
92  {
93  LOGDIAG3("Loading tune XML file: %s.", fqname.c_str());
94 
95  bFoundInstance = true;
96 
97  if( (rc = Xml::loadFile(fqname)) < 0 )
98  {
99  LOGERROR("Parse of tune parameters from XML file %s failed.",
100  fqname.c_str());
101  rc = -HEK_ECODE_XML;
102  }
103  else
104  {
105  rc = setTunesFromDOM(tunes);
106  }
107 
108  if( rc == HEK_OK )
109  {
110  LOGDIAG2("Tuning parameters from XML file %s loaded.",
111  fqname.c_str());
112  }
113 
114  if( !bAllInstances )
115  {
116  break;
117  }
118  }
119  }
120 
121  if( !bFoundInstance )
122  {
123  LOGDIAG2("Optional XML file %s not found - ignoring.",
124  strXmlFileName.c_str());
125  }
126 
127  return rc;
128 }
129 
130 int HekXmlTune::loadFile(const std::string &strXmlFileName)
131 {
132  int rc;
133 
134  // test existence of optional tuning file
135  if( access(strXmlFileName.c_str(), F_OK) < 0 )
136  {
137  LOGDIAG2("Optional XML file %s does not exist - ignoring.",
138  strXmlFileName.c_str());
139  rc = -HEK_ECODE_XML;
140  }
141 
142  // parse
143  else if( (rc = Xml::loadFile(strXmlFileName)) < 0 )
144  {
145  LOGERROR("Parse of tune parameters from XML file %s failed - ignoring.",
146  strXmlFileName.c_str());
147  rc = -HEK_ECODE_XML;
148  }
149 
150  // success
151  else
152  {
153  rc = HEK_OK;
154  }
155 
156  return rc;
157 }
158 
159 int HekXmlTune::createTemplateFile(const string &strXmlFileName)
160 {
161  FILE *fp; // opened file pointer
162 
163  if( strXmlFileName.empty() )
164  {
165  setErrorMsg("No file name.");
166  LOGERROR("%s", m_bufErrMsg);
167  return -HEK_ECODE_XML;
168  }
169 
170  m_strXmlFileName = strXmlFileName;
171 
172  // open file
173  if( (fp = fopen(m_strXmlFileName.c_str(), "w+")) == NULL )
174  {
175  setErrorMsg("%s: %s(errno=%d).",
176  m_strXmlFileName.c_str(), strerror(errno), errno);
177  LOGERROR("%s", m_bufErrMsg);
178  return -HEK_ECODE_XML;
179  }
180 
181  makeXmlHead();
182  makeXmlTail();
183 
184  //
185  // XML head.
186  //
187  fprintf(fp, " <!-- RoadNarrows Hekateros Tuning Configuration -->\n");
188  fprintf(fp, "%s", m_strXmlHead.c_str());
189 
190  //
191  // Robotic base major element.
192  //
193  fprintf(fp, " <!-- Hekateros tuning -->\n");
194  fprintf(fp, " <%s>\n", m_strMajElemTuning.c_str());
195 
196  fprintf(fp, " <!-- global tunes -->\n");
197  fprintf(fp, " <%s>\n", m_strSecElemGlobal.c_str());
198  fprintf(fp, " <%s>HZ</%s>\n",
199  m_strElemKinHz.c_str(), m_strElemKinHz.c_str());
200  fprintf(fp, " <%s>OFFSET_PCT</%s>\n",
201  m_strElemClearTorqueOff.c_str(), m_strElemClearTorqueOff.c_str());
202  fprintf(fp, " <%s>DERATE_PCT</%s>\n",
203  m_strElemVelDerate.c_str(), m_strElemVelDerate.c_str());
204  fprintf(fp, " <%s>\n", m_strSubSecElemTraj.c_str());
205  fprintf(fp, " <%s>NORM</%s>\n",
206  m_strElemTrajNorm.c_str(), m_strElemTrajNorm.c_str());
207  fprintf(fp, " <%s>E_DEG</%s>\n",
208  m_strElemTrajEpsilon.c_str(), m_strElemTrajEpsilon.c_str());
209  fprintf(fp, " </%s>\n", m_strSubSecElemTraj.c_str());
210  fprintf(fp, " </%s>\n", m_strSecElemGlobal.c_str());
211 
212  fprintf(fp, " <!-- joint tunes -->\n");
213  fprintf(fp, " <%s %s=\"JOINT_NAME\">\n",
214  m_strSecElemJoint.c_str(), m_strAttrJointId.c_str());
215  fprintf(fp, " <%s>POS_TOL_DEG</%s>\n",
216  m_strElemTolPos.c_str(), m_strElemTolPos.c_str());
217  fprintf(fp, " <%s>VEL_TOL_DEG_PER_SEC</%s>\n",
218  m_strElemTolVel.c_str(), m_strElemTolVel.c_str());
219  fprintf(fp, " <%s>OVER_TORQUE_TH_PCT</%s>\n",
220  m_strElemOverTorqueTh.c_str(), m_strElemOverTorqueTh.c_str());
221  fprintf(fp, " <%s>\n", m_strSubSecElemPid.c_str());
222  fprintf(fp, " <%s>FPN</%s>\n",
223  m_strElemPidKp.c_str(), m_strElemPidKp.c_str());
224  fprintf(fp, " <%s>FPN</%s>\n",
225  m_strElemPidKi.c_str(), m_strElemPidKi.c_str());
226  fprintf(fp, " <%s>FPN</%s>\n",
227  m_strElemPidKd.c_str(), m_strElemPidKd.c_str());
228  fprintf(fp, " <%s>FPN</%s>\n",
229  m_strElemPidMaxDeltaV.c_str(), m_strElemPidMaxDeltaV.c_str());
230  fprintf(fp, " </%s>\n", m_strSubSecElemPid.c_str());
231  fprintf(fp, " </%s>\n", m_strSecElemJoint.c_str());
232 
233  fprintf(fp, " </%s>\n\n", m_strMajElemTuning.c_str());
234 
235  //
236  // XML tail
237  //
238  fprintf(fp, "%s", m_strXmlTail.c_str());
239 
240  fclose(fp);
241 
242  LOGDIAG3("Created file %s.", m_strXmlFileName.c_str());
243 
244  return HEK_OK;
245 }
246 
247 int HekXmlTune::setTunesFromDOM(HekTunes &tunes)
248 {
249  TiXmlElement *pElem1, *pElem2; // working xml elements
250  const char *sValue; // working xml element name
251  int rc; // return code
252 
253  // root element
254  if( m_pElemRoot == NULL )
255  {
256  setErrorMsg("Missing DOM and/or <%s> root element missing.",
257  m_strRootElemName.c_str());
258  LOGERROR("%s", m_bufErrMsg);
259  return -HEK_ECODE_XML;
260  }
261 
262  // search for major element
263  for(pElem1 = m_pElemRoot->FirstChildElement(), rc = HEK_OK;
264  (pElem1 != NULL) && (rc == HEK_OK);
265  pElem1 = pElem1->NextSiblingElement())
266  {
267  // element name
268  if( (sValue = pElem1->Value()) == NULL )
269  {
270  continue;
271  }
272 
273  //
274  // Tuning major element. Walk through child elements and convert.
275  //
276  else if( !strcasecmp(sValue, m_strMajElemTuning.c_str()) )
277  {
278  // search for section elements
279  for(pElem2 = pElem1->FirstChildElement();
280  (pElem2 != NULL) && (rc == HEK_OK);
281  pElem2 = pElem2->NextSiblingElement())
282  {
283  // child element name
284  if( (sValue = pElem2->Value()) == NULL )
285  {
286  continue;
287  }
288 
289  // global tuning section
290  else if( !strcasecmp(sValue, m_strSecElemGlobal.c_str()) )
291  {
292  rc = setGlobalTunes(pElem2, tunes);
293  }
294 
295  // joint X tuning section
296  else if( !strcasecmp(sValue, m_strSecElemJoint.c_str()) )
297  {
298  rc = setJointTunes(pElem2, tunes);
299  }
300 
301  // unknown
302  else
303  {
304  warnUnknownElem(sValue);
305  }
306  }
307  }
308  }
309 
310  return HEK_OK;
311 }
312 
313 int HekXmlTune::setDOMFromHekTunes(const HekTunes &tunes)
314 {
315  // TODO
316  return -HEK_ECODE_GEN;
317 }
318 
319 int HekXmlTune::setGlobalTunes(TiXmlElement *pElemSec, HekTunes &tunes)
320 {
321  TiXmlElement *pElem; // working xml element
322  const char *sValue; // working xml element name
323  int rc; // return code
324 
325  //
326  // Walk through child elements and convert.
327  //
328  for(pElem = pElemSec->FirstChildElement(), rc = HEK_OK;
329  (pElem != NULL) && (rc == HEK_OK);
330  pElem = pElem->NextSiblingElement())
331  {
332  // element name
333  if( (sValue = pElem->Value()) == NULL )
334  {
335  continue;
336  }
337 
338  // kinematic hz
339  else if( !strcasecmp(sValue, m_strElemKinHz.c_str()) )
340  {
341  rc = strToDoubleWithMinimum(m_strElemKinHz, elemText(pElem),
342  HekTuneKinHzMin, tunes.m_fKinematicsHz);
343  }
344 
345  // clear over torque condition threshold offset
346  else if( !strcasecmp(sValue, m_strElemClearTorqueOff.c_str()) )
347  {
348  rc = strToDoubleWithinRange(m_strElemClearTorqueOff, elemText(pElem),
349  HekTuneClearTorqueOffsetMin, HekTuneClearTorqueOffsetMax,
350  tunes.m_fClearTorqueOffset);
351 
352  // xml units are percentages - normalize
353  if( rc == HEK_OK )
354  {
355  tunes.m_fClearTorqueOffset /= 100.0;
356  }
357  }
358 
359  // velocity derate
360  else if( !strcasecmp(sValue, m_strElemVelDerate.c_str()) )
361  {
362  rc = strToDoubleWithinRange(m_strElemVelDerate, elemText(pElem),
363  HekTuneVelDerateMin, HekTuneVelDerateMax,
364  tunes.m_fVelDerate);
365 
366  // xml units are percentages - normalize
367  if( rc == HEK_OK )
368  {
369  tunes.m_fVelDerate /= 100.0;
370  }
371  }
372 
373  // trajectory tune parameters
374  else if( !strcasecmp(sValue, m_strSubSecElemTraj.c_str()) )
375  {
376  rc = setGlobalTrajTunes(pElem, tunes);
377  }
378 
379  // unknown
380  else
381  {
382  warnUnknownElem(sValue);
383  }
384  }
385 
386  if( rc == HEK_OK )
387  {
388  LOGDIAG3("%s: Hekateros global tune parameters set.",
389  m_strXmlFileName.c_str());
390  }
391 
392  return rc;
393 }
394 
395 int HekXmlTune::setJointTunes(TiXmlElement *pElemSec, HekTunes &tunes)
396 {
397  string strJointName; // joint name
398  HekTunesJoint tunesJoint; // initialzed with default defaults
399  TiXmlElement *pElem; // working xml element
400  const char *sValue; // working xml element name
401  int rc; // return code
402 
403  strJointName = elemAttr(pElemSec, m_strAttrJointId);
404 
405  if( strJointName.empty() )
406  {
407  setErrorMsg("%s: No %s attribute of <%s> found.",
408  m_strXmlFileName.c_str(),
409  m_strAttrJointId.c_str(),
410  m_strSecElemJoint.c_str());
411  LOGERROR("%s", m_bufErrMsg);
412  return -HEK_ECODE_XML;
413  }
414 
415  // joint tuning entry already present - use as the starting tuning values
416  if( tunes.m_mapJointTunes.find(strJointName) != tunes.m_mapJointTunes.end() )
417  {
418  tunesJoint = tunes.m_mapJointTunes[strJointName];
419  }
420 
421  //
422  // Walk through child elements and convert.
423  //
424  for(pElem = pElemSec->FirstChildElement(), rc = HEK_OK;
425  (pElem != NULL) && (rc == HEK_OK);
426  pElem = pElem->NextSiblingElement())
427  {
428  // element name
429  if( (sValue = pElem->Value()) == NULL )
430  {
431  continue;
432  }
433 
434  // position tolerance
435  else if( !strcasecmp(sValue, m_strElemTolPos.c_str()) )
436  {
437  rc = strToDoubleWithMinimum(m_strElemTolPos, elemText(pElem),
438  HekTuneTolPosMin,
439  tunesJoint.m_fTolPos);
440 
441  // xml units are degrees - convert to radians
442  if( rc == HEK_OK )
443  {
444  tunesJoint.m_fTolPos = degToRad(tunesJoint.m_fTolPos);
445  }
446  }
447 
448  // velocity tolerance
449  else if( !strcasecmp(sValue, m_strElemTolVel.c_str()) )
450  {
451  rc = strToDoubleWithMinimum(m_strElemTolVel, elemText(pElem),
452  HekTuneTolVelMin,
453  tunesJoint.m_fTolVel);
454 
455  // xml units are degrees/second - convert to radians/second
456  if( rc == HEK_OK )
457  {
458  tunesJoint.m_fTolVel = degToRad(tunesJoint.m_fTolVel);
459  }
460  }
461 
462  // over torque threshold
463  else if( !strcasecmp(sValue, m_strElemOverTorqueTh.c_str()) )
464  {
465  rc = strToDoubleWithinRange(m_strElemOverTorqueTh, elemText(pElem),
466  HekTuneOverTorqueThMin, HekTuneOverTorqueThMax,
467  tunesJoint.m_fOverTorqueTh);
468 
469  // xml units are percentages - normalize
470  if( rc == HEK_OK )
471  {
472  tunesJoint.m_fOverTorqueTh /= 100.0;
473  }
474  }
475 
476  // position and velocity PID tune parameters
477  else if( !strcasecmp(sValue, m_strSubSecElemPid.c_str()) )
478  {
479  rc = setJointPidTunes(strJointName, pElem, tunesJoint);
480  }
481 
482  // unknown
483  else
484  {
485  warnUnknownElem(sValue);
486  }
487  }
488 
489  if( rc == HEK_OK )
490  {
491  // add new joint tuning or overwrite existing
492  tunes.m_mapJointTunes[strJointName] = tunesJoint;
493 
494  LOGDIAG3("%s: Hekateros joint %s tune parameters set.",
495  m_strXmlFileName.c_str(), strJointName.c_str());
496  }
497 
498  return rc;
499 }
500 
501 int HekXmlTune::setGlobalTrajTunes(TiXmlElement *pElemSubSec, HekTunes &tunes)
502 {
503  TiXmlElement *pElem; // working xml element
504  const char *sValue; // working xml element name
505  int rc; // return code
506 
507  //
508  // Walk through child elements and convert.
509  //
510  for(pElem = pElemSubSec->FirstChildElement(), rc = HEK_OK;
511  (pElem != NULL) && (rc == HEK_OK);
512  pElem = pElem->NextSiblingElement())
513  {
514  // element name
515  if( (sValue = pElem->Value()) == NULL )
516  {
517  continue;
518  }
519 
520  // norm
521  else if( !strcasecmp(sValue, m_strElemTrajNorm.c_str()) )
522  {
523  strToNorm(m_strElemTrajNorm, elemText(pElem), tunes.m_eTrajNorm);
524  }
525 
526  // epsilon
527  else if( !strcasecmp(sValue, m_strElemTrajEpsilon.c_str()) )
528  {
529  rc = strToDoubleWithMinimum(m_strElemTrajEpsilon, elemText(pElem),
530  HekTuneTrajEpsilonMin, tunes.m_fTrajEpsilon);
531 
532  // xml units are degrees - convert to radians
533  if( rc == HEK_OK )
534  {
535  tunes.m_fTrajEpsilon = degToRad(tunes.m_fTrajEpsilon);
536  }
537  }
538 
539  // unknown
540  else
541  {
542  warnUnknownElem(sValue);
543  }
544  }
545 
546  if( rc == HEK_OK )
547  {
548  LOGDIAG3("%s: Hekateros global trajectory tune parameters set.",
549  m_strXmlFileName.c_str());
550  }
551 
552  return rc;
553 }
554 
555 int HekXmlTune::setJointPidTunes(const string &strJointName,
556  TiXmlElement *pElemSubSec,
557  HekTunesJoint &tunesJoint)
558 {
559  TiXmlElement *pElem; // working xml element
560  const char *sValue; // working xml element name
561  int rc; // return code
562 
563  //
564  // Walk through child elements and convert.
565  //
566  for(pElem = pElemSubSec->FirstChildElement(), rc = HEK_OK;
567  (pElem != NULL) && (rc == HEK_OK);
568  pElem = pElem->NextSiblingElement())
569  {
570  // element name
571  if( (sValue = pElem->Value()) == NULL )
572  {
573  continue;
574  }
575 
576  // Kp
577  else if( !strcasecmp(sValue, m_strElemPidKp.c_str()) )
578  {
579  rc = strToDoubleWithMinimum(m_strElemPidKp, elemText(pElem),
580  HekTunePidKMin, tunesJoint.m_fPidKp);
581  }
582 
583  // Ki
584  else if( !strcasecmp(sValue, m_strElemPidKi.c_str()) )
585  {
586  rc = strToDoubleWithMinimum(m_strElemPidKi, elemText(pElem),
587  HekTunePidKMin, tunesJoint.m_fPidKi);
588  }
589 
590  // Kd
591  else if( !strcasecmp(sValue, m_strElemPidKd.c_str()) )
592  {
593  rc = strToDoubleWithMinimum(m_strElemPidKd, elemText(pElem),
594  HekTunePidKMin, tunesJoint.m_fPidKd);
595  }
596 
597  // max_delta_v
598  else if( !strcasecmp(sValue, m_strElemPidMaxDeltaV.c_str()) )
599  {
600  rc = strToDoubleWithMinimum(m_strElemPidMaxDeltaV, elemText(pElem),
601  HekTunePidDeltaVNoMax,
602  tunesJoint.m_fPidMaxDeltaV);
603 
604  // xml units are degrees - convert to radians
605  if( rc == HEK_OK )
606  {
607  tunesJoint.m_fPidMaxDeltaV = degToRad(tunesJoint.m_fPidMaxDeltaV);
608  }
609  }
610 
611  // unknown
612  else
613  {
614  warnUnknownElem(sValue);
615  }
616  }
617 
618  if( rc == HEK_OK )
619  {
620  LOGDIAG3("%s: Hekateros joint %s PID tune parameters set.",
621  m_strXmlFileName.c_str(), strJointName.c_str());
622  }
623 
624  return rc;
625 }
626 
627 int HekXmlTune::strToDoubleWithMinimum(const string &strElem,
628  const string &strText,
629  const double fMin,
630  double &fVal)
631 {
632  int rc = HEK_OK; // return code
633 
634  if( !strText.empty() )
635  {
636  if( (rc = strToDouble(strText, fVal)) < 0 )
637  {
638  setErrorMsg("%s: Element <%s> text \"%s\" not a FPN.",
639  m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
640  LOGERROR("%s", m_bufErrMsg);
641  rc = -HEK_ECODE_XML;
642  }
643 
644  else if( fVal < fMin )
645  {
646  setErrorMsg("%s: Element <%s> value %lf < than minimum of %lf.",
647  m_strXmlFileName.c_str(), strElem.c_str(), fVal, fMin);
648  LOGWARN("%s", m_bufErrMsg);
649  fVal = fMin;
650  }
651  }
652 
653  return rc;
654 }
655 
656 int HekXmlTune::strToDoubleWithinRange(const string &strElem,
657  const string &strText,
658  const double fMin,
659  const double fMax,
660  double &fVal)
661 {
662  int rc = HEK_OK; // return code
663 
664  if( !strText.empty() )
665  {
666  if( (rc = strToDouble(strText, fVal)) < 0 )
667  {
668  setErrorMsg("%s: Element <%s> text \"%s\" not a FPN.",
669  m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
670  LOGERROR("%s", m_bufErrMsg);
671  rc = -HEK_ECODE_XML;
672  }
673 
674  else if( fVal < fMin )
675  {
676  setErrorMsg("%s: Element <%s> value %lf < than minimum of %lf.",
677  m_strXmlFileName.c_str(), strElem.c_str(), fVal, fMin);
678  LOGWARN("%s", m_bufErrMsg);
679  fVal = fMin;
680  }
681 
682  else if( fVal > fMax )
683  {
684  setErrorMsg("%s: Element <%s> value %lf > than maximum of %lf.",
685  m_strXmlFileName.c_str(), strElem.c_str(), fVal, fMax);
686  LOGWARN("%s", m_bufErrMsg);
687  fVal = fMax;
688  }
689  }
690 
691  return rc;
692 }
693 
694 int HekXmlTune::strToNorm(const string &strElem,
695  const string &strText,
696  HekNorm &eNorm)
697 {
698  if( strText.empty() )
699  {
700  return HEK_OK;
701  }
702  else if( !strcasecmp(strText.c_str(), "L1") )
703  {
704  eNorm = HekNormL1;
705  return HEK_OK;
706  }
707  else if( !strcasecmp(strText.c_str(), "L2") )
708  {
709  eNorm = HekNormL2;
710  return HEK_OK;
711  }
712  else if( !strcasecmp(strText.c_str(), "Linf") )
713  {
714  eNorm = HekNormLinf;
715  return HEK_OK;
716  }
717  else
718  {
719  setErrorMsg("%s: Element <%s> text \"%s\" not a recognized norm.",
720  m_strXmlFileName.c_str(), strElem.c_str(), strText.c_str());
721  LOGERROR("%s", m_bufErrMsg);
722  return -HEK_ECODE_XML;
723  }
724 }
double m_fPidKi
position and velocity PID integral constant
Definition: hekTune.h:373
double m_fPidKp
position and velocity PID proportional const
Definition: hekTune.h:372
double m_fTolVel
velocitiy tolerance (radians/second)
Definition: hekTune.h:371
double m_fVelDerate
velocity derate (fraction)
Definition: hekTune.h:417
Hekateros tuning per joint data class.
Definition: hekTune.h:367
double m_fTrajEpsilon
trajectory epsilon distance (radians)
Definition: hekTune.h:419
Hekateros tuning data class.
Definition: hekTune.h:408
double m_fOverTorqueTh
over torque conditon threshold (fraction)
Definition: hekTune.h:376
double m_fKinematicsHz
kinematic thread rate (hertz)
Definition: hekTune.h:415
double m_fPidKd
position and velocity PID derivative constant
Definition: hekTune.h:374
double m_fPidMaxDeltaV
max output delta v (radians/second)
Definition: hekTune.h:375
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Split string at the delimiter character.
HekNorm m_eTrajNorm
trajectory distanct norm
Definition: hekTune.h:418
Top-level package include file.
double degToRad(double d)
Convert degrees to radians.
Definition: hekUtils.h:125
MapJointTunes m_mapJointTunes
per joint tuning
Definition: hekTune.h:422
Hekateros common utilities.
Hekateros tuning.
double m_fClearTorqueOffset
clear over torque condition offset (frac)
Definition: hekTune.h:416
The <b><i>Hekateros</i></b> namespace encapsulates all <b><i>Hekateros</i></b> related constructs...
Definition: hekateros.h:56
<b><i>Hekateros</i></b> XML tuning class interface.
double m_fTolPos
position tolerance (radians)
Definition: hekTune.h:370