YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
ControlBoardHelper.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
7#include <yarp/dev/PidEnums.h>
8#include <cstdio> // for printf
9#include <cmath> //fabs
10#include <yarp/os/Log.h>
11#include <yarp/os/LogStream.h>
12#include <map>
13
14using namespace yarp::dev;
15
17{
21 fbk_units = PidFeedbackUnitsEnum::RAW_MACHINE_UNITS;
22 out_units = PidOutputUnitsEnum::RAW_MACHINE_UNITS;
23 }
24};
25
27{
28public:
29 int nj;
30 int *axisMap;
32 bool verbose;
33
35 double *helper_ones;
41 double *bemfToRaws;
42 double *ktauToRaws;
48
53 std::map<PidControlTypeEnum, PidUnits*> pid_units;
54
55 explicit PrivateUnitsHandler(int size) :
56 axisMap(nullptr),
57 invAxisMap(nullptr),
58 verbose(true),
59 position_zeros(nullptr),
60 helper_ones(nullptr),
61 angleToEncoders(nullptr),
62 newtonsToSensors(nullptr),
63 ampereToSensors(nullptr),
64 voltToSensors(nullptr),
65 dutycycleToPWMs(nullptr),
66 bemfToRaws(nullptr),
67 ktauToRaws(nullptr),
68 viscousPosToRaws(nullptr),
69 viscousNegToRaws(nullptr),
70 coulombPosToRaws(nullptr),
71 coulombNegToRaws(nullptr),
72 velocityThresToRaws(nullptr),
73 PosPid_units(nullptr),
74 VelPid_units(nullptr),
75 CurPid_units(nullptr),
76 TrqPid_units(nullptr)
77 {
78 alloc(size);
79 std::fill_n(helper_ones, size, 1.0);
80 std::fill_n(position_zeros, size, 0.0);
81 std::fill_n(angleToEncoders, size, 1.0);
82 std::fill_n(newtonsToSensors, size, 1.0);
83 std::fill_n(ampereToSensors, size, 1.0);
84 std::fill_n(voltToSensors, size, 1.0);
85 std::fill_n(dutycycleToPWMs, size, 1.0);
86 std::fill_n(bemfToRaws, size, 1.0);
87 std::fill_n(ktauToRaws, size, 1.0);
88 std::fill_n(viscousPosToRaws, size, 1.0);
89 std::fill_n(viscousNegToRaws, size, 1.0);
90 std::fill_n(coulombPosToRaws, size, 1.0);
91 std::fill_n(coulombNegToRaws, size, 1.0);
92 std::fill_n(velocityThresToRaws, size, 1.0);
93 }
94
96 {
101 checkAndDestroy<double>(position_zeros);
102 checkAndDestroy<double>(helper_ones);
103 checkAndDestroy<int>(axisMap);
104 checkAndDestroy<int>(invAxisMap);
105 checkAndDestroy<double>(angleToEncoders);
106 checkAndDestroy<double>(newtonsToSensors);
107 checkAndDestroy<double>(ampereToSensors);
108 checkAndDestroy<double>(voltToSensors);
109 checkAndDestroy<double>(dutycycleToPWMs);
110 checkAndDestroy<double>(bemfToRaws);
111 checkAndDestroy<double>(ktauToRaws);
112 checkAndDestroy<double>(viscousPosToRaws);
113 checkAndDestroy<double>(viscousNegToRaws);
114 checkAndDestroy<double>(coulombPosToRaws);
115 checkAndDestroy<double>(coulombNegToRaws);
116 checkAndDestroy<double>(velocityThresToRaws);
117 }
118
119 void alloc(int n)
120 {
121 nj = n;
122 position_zeros = new double[nj];
123 helper_ones = new double[nj];
124 axisMap = new int[nj];
125 invAxisMap = new int[nj];
126 angleToEncoders = new double[nj];
127 newtonsToSensors = new double[nj];
128 ampereToSensors = new double[nj];
129 voltToSensors = new double[nj];
130 dutycycleToPWMs = new double[nj];
131 PosPid_units = new PidUnits[nj];
132 VelPid_units = new PidUnits[nj];
133 TrqPid_units = new PidUnits[nj];
134 CurPid_units = new PidUnits[nj];
135 bemfToRaws = new double[nj];
136 ktauToRaws = new double[nj];
137 viscousPosToRaws = new double[nj];
138 viscousNegToRaws = new double[nj];
139 coulombPosToRaws = new double[nj];
140 coulombNegToRaws = new double[nj];
141 velocityThresToRaws = new double[nj];
142
143 yAssert(position_zeros != nullptr);
144 yAssert(helper_ones != nullptr);
145 yAssert(axisMap != nullptr);
146 yAssert(invAxisMap != nullptr);
147 yAssert(angleToEncoders != nullptr);
148 yAssert(newtonsToSensors != nullptr);
149 yAssert(ampereToSensors != nullptr);
150 yAssert(voltToSensors != nullptr);
151 yAssert(dutycycleToPWMs != nullptr);
152 yAssert(PosPid_units != nullptr);
153 yAssert(VelPid_units != nullptr);
154 yAssert(TrqPid_units != nullptr);
155 yAssert(CurPid_units != nullptr);
156 yAssert(bemfToRaws != nullptr);
157 yAssert(ktauToRaws != nullptr);
158 yAssert(viscousPosToRaws != nullptr);
159 yAssert(viscousNegToRaws != nullptr);
160 yAssert(coulombPosToRaws != nullptr);
161 yAssert(coulombNegToRaws != nullptr);
162 yAssert(velocityThresToRaws != nullptr);
163
168 }
169
171 {
172 alloc(other.nj);
173 memcpy(this->position_zeros, other.position_zeros, sizeof(*other.position_zeros)*nj);
174 memcpy(this->helper_ones, other.helper_ones, sizeof(*other.helper_ones)*nj);
175 memcpy(this->axisMap, other.axisMap, sizeof(*other.axisMap)*nj);
176 memcpy(this->invAxisMap, other.invAxisMap, sizeof(*other.invAxisMap)*nj);
177 memcpy(this->angleToEncoders, other.angleToEncoders, sizeof(*other.angleToEncoders)*nj);
178 memcpy(this->newtonsToSensors, other.newtonsToSensors, sizeof(*other.newtonsToSensors)*nj);
179 memcpy(this->ampereToSensors, other.ampereToSensors, sizeof(*other.ampereToSensors)*nj);
180 memcpy(this->voltToSensors, other.voltToSensors, sizeof(*other.voltToSensors)*nj);
181 memcpy(this->dutycycleToPWMs, other.dutycycleToPWMs, sizeof(*other.dutycycleToPWMs)*nj);
182 memcpy(this->PosPid_units, other.PosPid_units, sizeof(*other.PosPid_units)*nj);
183 memcpy(this->VelPid_units, other.VelPid_units, sizeof(*other.VelPid_units)*nj);
184 memcpy(this->TrqPid_units, other.TrqPid_units, sizeof(*other.TrqPid_units)*nj);
185 memcpy(this->CurPid_units, other.CurPid_units, sizeof(*other.CurPid_units)*nj);
186 memcpy(this->bemfToRaws, other.bemfToRaws, sizeof(*other.bemfToRaws)*nj);
187 memcpy(this->ktauToRaws, other.ktauToRaws, sizeof(*other.ktauToRaws)*nj);
188 memcpy(this->viscousPosToRaws, other.viscousPosToRaws, sizeof(*other.viscousPosToRaws)*nj);
189 memcpy(this->viscousNegToRaws, other.viscousNegToRaws, sizeof(*other.viscousNegToRaws)*nj);
190 memcpy(this->coulombPosToRaws, other.coulombPosToRaws, sizeof(*other.coulombPosToRaws)*nj);
191 memcpy(this->coulombNegToRaws, other.coulombNegToRaws, sizeof(*other.coulombNegToRaws)*nj);
192 memcpy(this->velocityThresToRaws, other.velocityThresToRaws, sizeof(*other.velocityThresToRaws)*nj);
193 }
194};
195
196ControlBoardHelper::ControlBoardHelper(int n, const int *aMap, const double *angToEncs, const double *zs, const double *newtons, const double *amps, const double *volts, const double *dutycycles, const double *kbemf, const double *ktau)
197{
198 yAssert(n>=0); // if number of joints is negative complain!
199 yAssert(aMap!=nullptr); // at least the axisMap is required
200 mPriv = new PrivateUnitsHandler(n);
201
202 memcpy(mPriv->axisMap, aMap, sizeof(int)*n);
203
204 if (zs != nullptr) {
205 memcpy(mPriv->position_zeros, zs, sizeof(double) * n);
206 }
207 if (angToEncs != nullptr) {
208 memcpy(mPriv->angleToEncoders, angToEncs, sizeof(double) * n);
209 }
210 if (newtons != nullptr) {
211 memcpy(mPriv->newtonsToSensors, newtons, sizeof(double) * n);
212 }
213 if (amps != nullptr) {
214 memcpy(mPriv->ampereToSensors, amps, sizeof(double) * n);
215 }
216 if (volts != nullptr) {
217 memcpy(mPriv->voltToSensors, volts, sizeof(double) * n);
218 }
219 if (dutycycles != nullptr) {
220 memcpy(mPriv->dutycycleToPWMs, dutycycles, sizeof(double) * n);
221 }
222 if (kbemf != nullptr) {
223 memcpy(mPriv->bemfToRaws, kbemf, sizeof(double) * n);
224 }
225 if (ktau != nullptr) {
226 memcpy(mPriv->ktauToRaws, ktau, sizeof(double) * n);
227 }
228
229 // invert the axis map
230 memset (mPriv->invAxisMap, 0, sizeof(int) * n);
231 int i;
232 for (i = 0; i < n; i++)
233 {
234 int j;
235 for (j = 0; j < n; j++)
236 {
237 if (mPriv->axisMap[j] == i)
238 {
239 mPriv->invAxisMap[i] = j;
240 break;
241 }
242 }
243 }
244}
245
247{
248 if (mPriv) { delete mPriv; mPriv = nullptr; }
249}
250
255
257{
258 mPriv = new PrivateUnitsHandler(*other.mPriv);
259 return *this;
260}
261
263{
264 if( (id >= mPriv->nj) || (id< 0))
265 {
266 return false;
267 }
268 return true;
269}
270
271
272bool ControlBoardHelper::checkAxesIds(const int n_axes, const int* axesList)
273{
274 if(n_axes > mPriv->nj)
275 {
276 if (mPriv->verbose) {
277 yError("checkAxesIds: num of axes is too big");
278 }
279 return false;
280 }
281 for(int idx = 0; idx<n_axes; idx++)
282 {
283 if( (axesList[idx]<0) || (axesList[idx]>= mPriv->nj) )
284 {
285 if (mPriv->verbose) {
286 yError("checkAxesIds: joint id out of bound");
287 }
288
289 return false;
290 }
291 }
292 return true;
293}
294
296{ return mPriv->axisMap[axis]; }
297
299{ return mPriv->invAxisMap[axis]; }
300
301//map a vector, no conversion
302 void ControlBoardHelper::toUser(const double *hwData, double *user)
303{
304 for (int k = 0; k < mPriv->nj; k++) {
305 user[toUser(k)] = hwData[k];
306 }
307}
308
309//map a vector, no conversion
310void ControlBoardHelper::ControlBoardHelper::toUser(const int *hwData, int *user)
311{
312 for (int k = 0; k < mPriv->nj; k++) {
313 user[toUser(k)] = hwData[k];
314 }
315}
316
317//map a vector, no conversion
318 void ControlBoardHelper::toHw(const double *usr, double *hwData)
319{
320 for (int k = 0; k < mPriv->nj; k++) {
321 hwData[toHw(k)] = usr[k];
322 }
323}
324
325//map a vector, no conversion
326void ControlBoardHelper::toHw(const int *usr, int *hwData)
327{
328 for (int k = 0; k < mPriv->nj; k++) {
329 hwData[toHw(k)] = usr[k];
330 }
331}
332
333void ControlBoardHelper::posA2E(double ang, int j, double &enc, int &k)
334{
335 enc=(ang+ mPriv->position_zeros[j])*mPriv->angleToEncoders[j];
336 k=toHw(j);
337}
338
339double ControlBoardHelper::posA2E(double ang, int j)
340{
341 return (ang+ mPriv->position_zeros[j])*mPriv->angleToEncoders[j];
342}
343
344void ControlBoardHelper::posE2A(double enc, int j, double &ang, int &k)
345{
346 k=toUser(j);
347
348 ang=(enc/ mPriv->angleToEncoders[k])- mPriv->position_zeros[k];
349}
350
351double ControlBoardHelper::posE2A(double enc, int j)
352{
353 int k=toUser(j);
354
355 return (enc/ mPriv->angleToEncoders[k])- mPriv->position_zeros[k];
356}
357
358void ControlBoardHelper::impN2S(double newtons, int j, double &sens, int &k)
359{
360 sens=newtons* mPriv->newtonsToSensors[j]/ mPriv->angleToEncoders[j];
361 k=toHw(j);
362}
363
364double ControlBoardHelper::impN2S(double newtons, int j)
365{
366 return newtons* mPriv->newtonsToSensors[j]/ mPriv->angleToEncoders[j];
367}
368
369void ControlBoardHelper::impN2S(const double *newtons, double *sens)
370{
371 double tmp;
372 int index;
373 for(int j=0;j<mPriv->nj;j++)
374 {
375 impN2S(newtons[j], j, tmp, index);
376 sens[index]=tmp;
377 }
378}
379
380void ControlBoardHelper::trqN2S(double newtons, int j, double &sens, int &k)
381{
382 sens=newtons* mPriv->newtonsToSensors[j];
383 k=toHw(j);
384}
385
386double ControlBoardHelper::trqN2S(double newtons, int j)
387{
388 return newtons* mPriv->newtonsToSensors[j];
389}
390
391//map a vector, convert from newtons to sensors
392void ControlBoardHelper::trqN2S(const double *newtons, double *sens)
393{
394 double tmp;
395 int index;
396 for(int j=0;j<mPriv->nj;j++)
397 {
398 trqN2S(newtons[j], j, tmp, index);
399 sens[index]=tmp;
400 }
401}
402
403//map a vector, convert from sensor to newtons
404void ControlBoardHelper::trqS2N(const double *sens, double *newtons)
405{
406 double tmp;
407 int index;
408 for(int j=0;j<mPriv->nj;j++)
409 {
410 trqS2N(sens[j], j, tmp, index);
411 newtons[index]=tmp;
412 }
413}
414
415void ControlBoardHelper::trqS2N(double sens, int j, double &newton, int &k)
416{
417 k=toUser(j);
418 newton=(sens/ mPriv->newtonsToSensors[k]);
419}
420
421double ControlBoardHelper::trqS2N(double sens, int j)
422{
423 int k=toUser(j);
424 return (sens/ mPriv->newtonsToSensors[k]);
425}
426
427void ControlBoardHelper::impS2N(const double *sens, double *newtons)
428{
429 double tmp;
430 int index;
431 for(int j=0;j<mPriv->nj;j++)
432 {
433 impS2N(sens[j], j, tmp, index);
434 newtons[index]=tmp;
435 }
436}
437
438void ControlBoardHelper::impS2N(double sens, int j, double &newton, int &k)
439{
440 k=toUser(j);
441 newton=(sens/ mPriv->newtonsToSensors[k]* mPriv->angleToEncoders[k]);
442}
443
444double ControlBoardHelper::impS2N(double sens, int j)
445{
446 int k=toUser(j);
447
448 return (sens/ mPriv->newtonsToSensors[k]* mPriv->angleToEncoders[k]);
449}
450
451void ControlBoardHelper::velA2E(double ang, int j, double &enc, int &k)
452{
453 k=toHw(j);
454 enc=ang* mPriv->angleToEncoders[j];
455}
456
457double ControlBoardHelper::velA2E(double ang, int j)
458{
459 return ang* mPriv->angleToEncoders[j];
460}
461
462void ControlBoardHelper::velA2E_abs(double ang, int j, double &enc, int &k)
463{
464 k=toHw(j);
465 enc=ang*fabs(mPriv->angleToEncoders[j]);
466}
467
468void ControlBoardHelper::velE2A(double enc, int j, double &ang, int &k)
469{
470 k=toUser(j);
471 ang=enc/ mPriv->angleToEncoders[k];
472}
473
474void ControlBoardHelper::velE2A_abs(double enc, int j, double &ang, int &k)
475{
476 k=toUser(j);
477 ang=enc/fabs(mPriv->angleToEncoders[k]);
478}
479
480void ControlBoardHelper::accA2E(double ang, int j, double &enc, int &k)
481{
482 velA2E(ang, j, enc, k);
483}
484
485void ControlBoardHelper::accA2E_abs(double ang, int j, double &enc, int &k)
486{
487 velA2E_abs(ang, j, enc, k);
488}
489
490void ControlBoardHelper::accE2A(double enc, int j, double &ang, int &k)
491{
492 velE2A(enc, j, ang, k);
493}
494
495void ControlBoardHelper::accE2A_abs(double enc, int j, double &ang, int &k)
496{
497 velE2A_abs(enc, j, ang, k);
498}
499
500double ControlBoardHelper::velE2A(double enc, int j)
501{
502 int k=toUser(j);
503 return enc/ mPriv->angleToEncoders[k];
504}
505
506double ControlBoardHelper::velE2A_abs(double enc, int j)
507{
508 int k=toUser(j);
509 return enc/fabs(mPriv->angleToEncoders[k]);
510}
511
512
513double ControlBoardHelper::accE2A(double enc, int j)
514{
515 return velE2A(enc, j);
516}
517
518double ControlBoardHelper::accE2A_abs(double enc, int j)
519{
520 return velE2A_abs(enc, j);
521}
522
523//map a vector, convert from angles to encoders
524void ControlBoardHelper::posA2E(const double *ang, double *enc)
525{
526 double tmp;
527 int index;
528 for(int j=0;j<mPriv->nj;j++)
529 {
530 posA2E(ang[j], j, tmp, index);
531 enc[index]=tmp;
532 }
533}
534
535//map a vector, convert from encoders to angles
536void ControlBoardHelper::posE2A(const double *enc, double *ang)
537{
538 double tmp;
539 int index;
540 for(int j=0;j<mPriv->nj;j++)
541 {
542 posE2A(enc[j], j, tmp, index);
543 ang[index]=tmp;
544 }
545}
546
547void ControlBoardHelper::velA2E(const double *ang, double *enc)
548{
549 double tmp;
550 int index;
551 for(int j=0;j<mPriv->nj;j++)
552 {
553 velA2E(ang[j], j, tmp, index);
554 enc[index]=tmp;
555 }
556}
557
558void ControlBoardHelper::velA2E_abs(const double *ang, double *enc)
559{
560 double tmp;
561 int index;
562 for(int j=0;j<mPriv->nj;j++)
563 {
564 velA2E_abs(ang[j], j, tmp, index);
565 enc[index]=tmp;
566 }
567}
568
569void ControlBoardHelper::velE2A(const double *enc, double *ang)
570{
571 double tmp;
572 int index;
573 for(int j=0;j<mPriv->nj;j++)
574 {
575 velE2A(enc[j], j, tmp, index);
576 ang[index]=tmp;
577 }
578}
579
580void ControlBoardHelper::velE2A_abs(const double *enc, double *ang)
581{
582 double tmp;
583 int index;
584 for(int j=0;j<mPriv->nj;j++)
585 {
586 velE2A_abs(enc[j], j, tmp, index);
587 ang[index]=tmp;
588 }
589}
590
591void ControlBoardHelper::accA2E(const double *ang, double *enc)
592{
593 double tmp;
594 int index;
595 for(int j=0;j<mPriv->nj;j++)
596 {
597 accA2E(ang[j], j, tmp, index);
598 enc[index]=tmp;
599 }
600}
601
602void ControlBoardHelper::accA2E_abs(const double *ang, double *enc)
603{
604 double tmp;
605 int index;
606 for(int j=0;j<mPriv->nj;j++)
607 {
608 accA2E_abs(ang[j], j, tmp, index);
609 enc[index]=tmp;
610 }
611}
612
613void ControlBoardHelper::accE2A(const double *enc, double *ang)
614{
615 double tmp;
616 int index;
617 for(int j=0;j<mPriv->nj;j++)
618 {
619 accE2A(enc[j], j, tmp, index);
620 ang[index]=tmp;
621 }
622}
623
624void ControlBoardHelper::accE2A_abs(const double *enc, double *ang)
625{
626 double tmp;
627 int index;
628 for(int j=0;j<mPriv->nj;j++)
629 {
630 accE2A_abs(enc[j], j, tmp, index);
631 ang[index]=tmp;
632 }
633}
634
635//***************** current ******************//
636void ControlBoardHelper::ampereA2S(double ampere, int j, double &sens, int &k)
637{
638 sens=ampere* mPriv->ampereToSensors[j];
639 k=toHw(j);
640}
641
642double ControlBoardHelper::ampereA2S(double ampere, int j)
643{
644 return ampere* mPriv->ampereToSensors[j];
645}
646
647//map a vector, convert from ampere to sensors
648void ControlBoardHelper::ampereA2S(const double *ampere, double *sens)
649{
650 double tmp;
651 int index;
652 for(int j=0;j<mPriv->nj;j++)
653 {
654 ampereA2S(ampere[j], j, tmp, index);
655 sens[index]=tmp;
656 }
657}
658
659//map a vector, convert from sensor to ampere
660void ControlBoardHelper::ampereS2A(const double *sens, double *ampere)
661{
662 double tmp;
663 int index;
664 for(int j=0;j<mPriv->nj;j++)
665 {
666 ampereS2A(sens[j], j, tmp, index);
667 ampere[index]=tmp;
668 }
669}
670
671void ControlBoardHelper::ampereS2A(double sens, int j, double &ampere, int &k)
672{
673 k=toUser(j);
674 ampere=(sens/ mPriv->ampereToSensors[k]);
675}
676
677double ControlBoardHelper::ampereS2A(double sens, int j)
678{
679 int k=toUser(j);
680 return sens/ mPriv->ampereToSensors[k];
681}
682// *******************************************//
683
684//***************** voltage ******************//
685void ControlBoardHelper::voltageV2S(double voltage, int j, double &sens, int &k)
686{
687 sens=voltage* mPriv->voltToSensors[j];
688 k=toHw(j);
689}
690
691double ControlBoardHelper::voltageV2S(double voltage, int j)
692{
693 return voltage* mPriv->voltToSensors[j];
694}
695
696//map a vector, convert from voltage to sensors
697void ControlBoardHelper::voltageV2S(const double *voltage, double *sens)
698{
699 double tmp;
700 int index;
701 for(int j=0;j<mPriv->nj;j++)
702 {
703 voltageV2S(voltage[j], j, tmp, index);
704 sens[index]=tmp;
705 }
706}
707
708//map a vector, convert from sensor to newtons
709void ControlBoardHelper::voltageS2V(const double *sens, double *voltage)
710{
711 double tmp;
712 int index;
713 for(int j=0;j<mPriv->nj;j++)
714 {
715 voltageS2V(sens[j], j, tmp, index);
716 voltage[index]=tmp;
717 }
718}
719
720void ControlBoardHelper::voltageS2V(double sens, int j, double &voltage, int &k)
721{
722 k=toUser(j);
723 voltage=(sens/ mPriv->voltToSensors[k]);
724}
725
726double ControlBoardHelper::voltageS2V(double sens, int j)
727{
728 int k=toUser(j);
729 return (sens/ mPriv->voltToSensors[k]);
730}
731// *******************************************//
732
733//***************** dutycycle ******************//
734void ControlBoardHelper::dutycycle2PWM(double dutycycle, int j, double &pwm, int &k)
735{
736 pwm = dutycycle* mPriv->dutycycleToPWMs[j];
737 k = toHw(j);
738}
739
740double ControlBoardHelper::dutycycle2PWM(double dutycycle, int j)
741{
742 return dutycycle* mPriv->dutycycleToPWMs[j];
743}
744
745void ControlBoardHelper::dutycycle2PWM(const double *dutycycle, double *sens)
746{
747 double tmp;
748 int index;
749 for (int j = 0; j<mPriv->nj; j++)
750 {
751 dutycycle2PWM(dutycycle[j], j, tmp, index);
752 sens[index] = tmp;
753 }
754}
755
756void ControlBoardHelper::PWM2dutycycle(const double *pwm, double *dutycycle)
757{
758 double tmp;
759 int index;
760 for (int j = 0; j<mPriv->nj; j++)
761 {
762 PWM2dutycycle(pwm[j], j, tmp, index);
763 dutycycle[index] = tmp;
764 }
765}
766
767void ControlBoardHelper::PWM2dutycycle(double pwm_raw, int k_raw, double &dutycycle, int &j)
768{
769 j = toUser(k_raw);
770 dutycycle = (pwm_raw / mPriv->dutycycleToPWMs[j]);
771}
772
773double ControlBoardHelper::PWM2dutycycle(double pwm_raw, int k_raw)
774{
775 int j = toUser(k_raw);
776 return (pwm_raw / mPriv->dutycycleToPWMs[j]);
777}
778
779// *******************************************//
780void ControlBoardHelper::bemf_user2raw(double bemf_user, int j, double &bemf_raw, int &k)
781{
782 bemf_raw = bemf_user * mPriv->bemfToRaws[j];
783 k = toHw(j);
784}
785
786void ControlBoardHelper::ktau_user2raw(double ktau_user, int j, double &ktau_raw, int &k)
787{
788 ktau_raw = ktau_user * mPriv->ktauToRaws[j];
789 k = toHw(j);
790}
791
792void ControlBoardHelper::viscousPos_user2raw(double viscousPos_user, int j, double &viscousPos_raw, int &k)
793{
794 viscousPos_raw = viscousPos_user * mPriv->viscousPosToRaws[j];
795 k = toHw(j);
796}
797
798void ControlBoardHelper::viscousNeg_user2raw(double viscousNeg_user, int j, double &viscousNeg_raw, int &k)
799{
800 viscousNeg_raw = viscousNeg_user * mPriv->viscousNegToRaws[j];
801 k = toHw(j);
802}
803
804void ControlBoardHelper::coulombPos_user2raw(double coulombPos_user, int j, double &coulombPos_raw, int &k)
805{
806 coulombPos_raw = coulombPos_user * mPriv->coulombPosToRaws[j];
807 k = toHw(j);
808}
809
810void ControlBoardHelper::coulombNeg_user2raw(double coulombNeg_user, int j, double &coulombNeg_raw, int &k)
811{
812 coulombNeg_raw = coulombNeg_user * mPriv->coulombNegToRaws[j];
813 k = toHw(j);
814}
815
816void ControlBoardHelper::velocityThres_user2raw(double velocityThres_user, int j, double &velocityThres_raw, int &k)
817{
818 velocityThres_raw = velocityThres_user * mPriv->velocityThresToRaws[j];
819 k = toHw(j);
820}
821
822void ControlBoardHelper::bemf_raw2user(double bemf_raw, int k_raw, double &bemf_user, int &j_user)
823{
824 j_user = toUser(k_raw);
825 bemf_user = bemf_raw / mPriv->bemfToRaws[j_user];
826}
827
828void ControlBoardHelper::ktau_raw2user(double ktau_raw, int k_raw, double &ktau_user, int &j_user)
829{
830 j_user = toUser(k_raw);
831 ktau_user = ktau_raw / mPriv->ktauToRaws[j_user];
832}
833
834double ControlBoardHelper::bemf_user2raw(double bemf_user, int j)
835{
836 return bemf_user * mPriv->bemfToRaws[j];
837}
838
839double ControlBoardHelper::ktau_user2raw(double ktau_user, int j)
840{
841 return ktau_user * mPriv->ktauToRaws[j];
842}
843
844double ControlBoardHelper::viscousPos_user2raw(double viscousPos_user, int j)
845{
846 return viscousPos_user * mPriv->viscousPosToRaws[j];
847}
848
849double ControlBoardHelper::viscousNeg_user2raw(double viscousNeg_user, int j)
850{
851 return viscousNeg_user * mPriv->viscousNegToRaws[j];
852}
853
854double ControlBoardHelper::coulombPos_user2raw(double coulombPos_user, int j)
855{
856 return coulombPos_user * mPriv->coulombPosToRaws[j];
857}
858
859double ControlBoardHelper::coulombNeg_user2raw(double coulombNeg_user, int j)
860{
861 return coulombNeg_user * mPriv->coulombNegToRaws[j];
862}
863
864double ControlBoardHelper::velocityThres_user2raw(double velocityThres_user, int j)
865{
866 return velocityThres_user * mPriv->velocityThresToRaws[j];
867}
868
869void ControlBoardHelper::viscousPos_raw2user(double viscousPos_raw, int k_raw, double &viscousPos_user, int &j_user)
870{
871 j_user = toUser(k_raw);
872 viscousPos_user = viscousPos_raw / mPriv->viscousPosToRaws[j_user];
873}
874
875void ControlBoardHelper::viscousNeg_raw2user(double viscousNeg_raw, int k_raw, double &viscousNeg_user, int &j_user)
876{
877 j_user = toUser(k_raw);
878 viscousNeg_user = viscousNeg_raw / mPriv->viscousNegToRaws[j_user];
879}
880
881void ControlBoardHelper::coulombPos_raw2user(double coulombPos_raw, int k_raw, double &coulombPos_user, int &j_user)
882{
883 j_user = toUser(k_raw);
884 coulombPos_user = coulombPos_raw / mPriv->coulombPosToRaws[j_user];
885}
886
887void ControlBoardHelper::coulombNeg_raw2user(double coulombNeg_raw, int k_raw, double &coulombNeg_user, int &j_user)
888{
889 j_user = toUser(k_raw);
890 coulombNeg_user = coulombNeg_raw / mPriv->coulombNegToRaws[j_user];
891}
892
893void ControlBoardHelper::velocityThres_raw2user(double velocityThres_raw, int k_raw, double &velocityThres_user, int &j_user)
894{
895 j_user = toUser(k_raw);
896 velocityThres_user = velocityThres_raw / mPriv->velocityThresToRaws[j_user];
897}
898
899
900// *******************************************//
901
903{ return mPriv->nj; }
904
905// *******************************************//
906
908{
909 double output_conversion_factor;
910 switch (mPriv->pid_units[pidtype][j].out_units)
911 {
912 case PidOutputUnitsEnum::DUTYCYCLE_PWM_PERCENT: output_conversion_factor = mPriv->dutycycleToPWMs[j]; break;
913 case PidOutputUnitsEnum::CURRENT_METRIC: output_conversion_factor = mPriv->ampereToSensors[j]; break;
914 case PidOutputUnitsEnum::POSITION_METRIC: output_conversion_factor = mPriv->angleToEncoders[j]; break;
915 case PidOutputUnitsEnum::VELOCITY_METRIC: output_conversion_factor = mPriv->angleToEncoders[j]; break;
916 case PidOutputUnitsEnum::TORQUE_METRIC: output_conversion_factor = mPriv->newtonsToSensors[j]; break;
918 default: output_conversion_factor = mPriv->helper_ones[j]; break;
919 }
920 return output_conversion_factor;
921}
922
924{
925 double feedback_conversion_factor = 0.0;
926 switch (mPriv->pid_units[pidtype][j].fbk_units)
927 {
929 switch (pidtype)
930 {
931 case yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION: feedback_conversion_factor = mPriv->angleToEncoders[j]; break;
932 case yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_VELOCITY: feedback_conversion_factor = mPriv->angleToEncoders[j]; break;
933 case yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_TORQUE: feedback_conversion_factor = mPriv->newtonsToSensors[j]; break;
934 case yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_CURRENT: feedback_conversion_factor = mPriv->ampereToSensors[j]; break;
935 }
936 break;
938 default: feedback_conversion_factor = mPriv->helper_ones[j]; break;
939 }
940 return (1.0 / feedback_conversion_factor);
941}
942void ControlBoardHelper::convert_pid_to_user(const yarp::dev::PidControlTypeEnum& pidtype, const Pid &in_raw, int j_raw, Pid &out_usr, int &k_usr)
943{
944 ControlBoardHelper* cb_helper = this;
945 k_usr = cb_helper->toUser(j_raw);
946 out_usr = in_raw;
947
948 //feedback is at the denominator, i.e. kp=[PWM/deg]
949 double feedback_conversion_units_user2raw = get_pidfeedback_conversion_factor_user2raw(pidtype, k_usr);
950 out_usr.kp = out_usr.kp / feedback_conversion_units_user2raw;
951 out_usr.ki = out_usr.ki / feedback_conversion_units_user2raw;
952 out_usr.kd = out_usr.kd / feedback_conversion_units_user2raw;
953
954 //output is at the numerator, i.e. kp=[PWM/deg]
955 double output_conversion_units_user2raw = get_pidoutput_conversion_factor_user2raw(pidtype, k_usr);
956 out_usr.kp = out_usr.kp / output_conversion_units_user2raw;
957 out_usr.ki = out_usr.ki / output_conversion_units_user2raw;
958 out_usr.kd = out_usr.kd / output_conversion_units_user2raw;
959 out_usr.max_output = out_usr.max_output / output_conversion_units_user2raw;
960 out_usr.max_int = out_usr.max_int / output_conversion_units_user2raw;
961 out_usr.stiction_up_val = out_usr.stiction_up_val / output_conversion_units_user2raw;
962 out_usr.stiction_down_val = out_usr.stiction_down_val / output_conversion_units_user2raw;
963 out_usr.offset = out_usr.offset / output_conversion_units_user2raw;
964}
965
967{
968 Pid tmp;
969 int tmp_k;
970 convert_pid_to_machine(pidtype, in_usr, j_usr, tmp, tmp_k);
971 return tmp;
972}
973
974void ControlBoardHelper::convert_pid_to_machine(const yarp::dev::PidControlTypeEnum& pidtype, const Pid &in_usr, int j_usr, Pid &out_raw, int &k_raw)
975{
976 ControlBoardHelper* cb_helper = this;
977 k_raw = cb_helper->toHw(j_usr);
978 out_raw = in_usr;
979
980 //feedback is at the denominator, i.e. kp=[PWM/deg]
981 double feedback_conversion_units_user2raw = get_pidfeedback_conversion_factor_user2raw(pidtype, j_usr);
982 out_raw.kp = out_raw.kp * feedback_conversion_units_user2raw;
983 out_raw.ki = out_raw.ki * feedback_conversion_units_user2raw;
984 out_raw.kd = out_raw.kd * feedback_conversion_units_user2raw;
985
986 //output is at the numerator, i.e. kp=[PWM/deg]
987 double output_conversion_units_user2raw = get_pidoutput_conversion_factor_user2raw(pidtype, j_usr);
988 out_raw.kp = out_raw.kp * output_conversion_units_user2raw;
989 out_raw.ki = out_raw.ki * output_conversion_units_user2raw;
990 out_raw.kd = out_raw.kd * output_conversion_units_user2raw;
991 out_raw.max_output = out_raw.max_output * output_conversion_units_user2raw;
992 out_raw.max_int = out_raw.max_int * output_conversion_units_user2raw;
993 out_raw.stiction_up_val = out_raw.stiction_up_val * output_conversion_units_user2raw;
994 out_raw.stiction_down_val = out_raw.stiction_down_val * output_conversion_units_user2raw;
995 out_raw.offset = out_raw.offset * output_conversion_units_user2raw;
996}
997
998void ControlBoardHelper::convert_pidunits_to_machine(const yarp::dev::PidControlTypeEnum& pidtype, double userval, int j, double &machineval, int &k)
999{
1000 ControlBoardHelper* cb_helper = this;
1001 switch (pidtype)
1002 {
1004 //Beware:posA2E employs zeros, not only angleToEncoders
1005 //This is fine if convert_pidunits_to_machine() is called by methods that are aware of this feature, that is intentional.
1006 cb_helper->posA2E(userval, j, machineval, k);
1007 break;
1009 cb_helper->velA2E(userval, j, machineval, k);
1010 break;
1012 cb_helper->trqN2S(userval, j, machineval, k);
1013 break;
1015 cb_helper->ampereA2S(userval, j, machineval, k);
1016 break;
1017 default:
1018 yError() << "convert_units_to_machine: invalid pidtype";
1019 break;
1020 }
1021}
1022
1023void ControlBoardHelper::convert_pidunits_to_machine(const yarp::dev::PidControlTypeEnum& pidtype, const double* userval, double* machineval)
1024{
1025 ControlBoardHelper* cb_helper = this;
1026 switch (pidtype)
1027 {
1029 //Beware:posA2E employs zeros, not only angleToEncoders
1030 //This is fine if convert_pidunits_to_machine() is called by methods that are aware of this feature, that is intentional.
1031 cb_helper->posA2E(userval, machineval);
1032 break;
1034 cb_helper->velA2E(userval, machineval);
1035 break;
1037 cb_helper->trqN2S(userval, machineval);
1038 break;
1040 cb_helper->ampereA2S(userval, machineval);
1041 break;
1042 default:
1043 yError() << "convert_units_to_machine: invalid pidtype";
1044 break;
1045 }
1046}
1047
1048void ControlBoardHelper::convert_pidunits_to_user(const yarp::dev::PidControlTypeEnum& pidtype, const double machineval, double* userval, int k)
1049{
1050 ControlBoardHelper* cb_helper = this;
1051 switch (pidtype)
1052 {
1054 //Beware:posE2A employs zeros, not only angleToEncoders.
1055 //This is fine if convert_pidunits_to_user() is called by methods that are aware of this feature, that is intentional.
1056 *userval = cb_helper->posE2A(machineval, k);
1057 break;
1059 *userval = cb_helper->velE2A(machineval, k);
1060 break;
1062 *userval = cb_helper->trqS2N(machineval, k);
1063 break;
1065 *userval = cb_helper->ampereS2A(machineval, k);
1066 break;
1067 default:
1068 yError() << "convert_units_to_machine: invalid pidtype";
1069 break;
1070 }
1071}
1072
1073void ControlBoardHelper::convert_pidunits_to_user(const yarp::dev::PidControlTypeEnum& pidtype, const double* machineval, double* userval)
1074{
1075 ControlBoardHelper* cb_helper = this;
1076 switch (pidtype)
1077 {
1079 //Beware:posE2A employs zeros, not only angleToEncoders.
1080 //This is fine if convert_pidunits_to_user() is called by methods that are aware of this feature, that is intentional.
1081 cb_helper->posE2A(machineval, userval);
1082 break;
1084 cb_helper->velE2A(machineval, userval);
1085 break;
1087 cb_helper->trqS2N(machineval, userval);
1088 break;
1090 cb_helper->ampereS2A(machineval, userval);
1091 break;
1092 default:
1093 yError() << "convert_units_to_machine: invalid pidtype";
1094 break;
1095 }
1096}
1097
1099{
1100 ControlBoardHelper* cb_helper = this;
1101 int nj = cb_helper->axes();
1102 for (int i = 0; i < nj; i++)
1103 {
1104 mPriv->pid_units[pidtype][i].fbk_units = fbk_conv_units;
1105 mPriv->pid_units[pidtype][i].out_units = out_conv_units;
1106 }
1107}
void checkAndDestroy(T *&p)
#define yError(...)
Definition Log.h:361
#define yAssert(x)
Definition Log.h:388
std::map< PidControlTypeEnum, PidUnits * > pid_units
double get_pidfeedback_conversion_factor_user2raw(const yarp::dev::PidControlTypeEnum &pidtype, int j)
void accE2A(double enc, int j, double &ang, int &k)
void convert_pid_to_user(const yarp::dev::PidControlTypeEnum &pidtype, const Pid &in_raw, int j_raw, Pid &out_usr, int &k_usr)
void viscousNeg_raw2user(double viscousNeg_raw, int k_raw, double &viscousNeg_user, int &j_user)
double viscousNeg_user2raw(double viscousNeg_user, int j)
void ktau_raw2user(double ktau_raw, int k_raw, double &ktau_user, int &j_user)
void trqN2S(double newtons, int j, double &sens, int &k)
void velE2A_abs(double enc, int j, double &ang, int &k)
void convert_pidunits_to_machine(const yarp::dev::PidControlTypeEnum &pidtype, double userval, int j, double &machineval, int &k)
void bemf_raw2user(double bemf_raw, int k_raw, double &bemf_user, int &j_user)
void coulombPos_raw2user(double coulombPos_raw, int k_raw, double &coulombPos_user, int &j_user)
void voltageS2V(const double *sens, double *voltage)
void convert_pid_to_machine(const yarp::dev::PidControlTypeEnum &pidtype, const Pid &in_usr, int j_usr, Pid &out_raw, int &k_raw)
void ampereA2S(double ampere, int j, double &sens, int &k)
void impN2S(double newtons, int j, double &sens, int &k)
double ktau_user2raw(double ktau_user, int j)
double coulombPos_user2raw(double coulombPos_user, int j)
void velE2A(double enc, int j, double &ang, int &k)
double coulombNeg_user2raw(double coulombNeg_user, int j)
double velocityThres_user2raw(double velocityThres_user, int j)
void velocityThres_raw2user(double threshold_raw, int k_raw, double &velocityThres_user, int &j_user)
void velA2E(double ang, int j, double &enc, int &k)
void dutycycle2PWM(double dutycycle, int j, double &pwm, int &k)
void ampereS2A(const double *sens, double *ampere)
double viscousPos_user2raw(double viscousPos_user, int j)
void posE2A(double enc, int j, double &ang, int &k)
void coulombNeg_raw2user(double coulombNeg_raw, int k_raw, double &coulombNeg_user, int &j_user)
void trqS2N(const double *sens, double *newtons)
double get_pidoutput_conversion_factor_user2raw(const yarp::dev::PidControlTypeEnum &pidtype, int j)
void set_pid_conversion_units(const PidControlTypeEnum &pidtype, const PidFeedbackUnitsEnum fbk_conv_units, const PidOutputUnitsEnum out_conv_units)
void voltageV2S(double voltage, int j, double &sens, int &k)
ControlBoardHelper & operator=(const ControlBoardHelper &other)
double bemf_user2raw(double bemf_user, int j)
void accA2E_abs(double ang, int j, double &enc, int &k)
void accA2E(double ang, int j, double &enc, int &k)
void accE2A_abs(double enc, int j, double &ang, int &k)
void velA2E_abs(double ang, int j, double &enc, int &k)
ControlBoardHelper(int n, const int *aMap, const double *angToEncs=nullptr, const double *zs=nullptr, const double *newtons=nullptr, const double *amps=nullptr, const double *volts=nullptr, const double *dutycycles=nullptr, const double *kbemf=nullptr, const double *ktau=nullptr)
void viscousPos_raw2user(double viscousPos_raw, int k_raw, double &viscousPos_user, int &j_user)
void convert_pidunits_to_user(const yarp::dev::PidControlTypeEnum &pidtype, const double machineval, double *userval, int k)
void impS2N(const double *sens, double *newtons)
void PWM2dutycycle(const double *pwm, double *dutycycle)
bool checkAxesIds(const int n_axes, const int *axesList)
void posA2E(double ang, int j, double &enc, int &k)
Contains the parameters for a PID.
double kd
derivative gain
double offset
pwm offset added to the pid output
double stiction_down_val
down stiction offset added to the pid output
double stiction_up_val
up stiction offset added to the pid output
double max_output
max output
double ki
integrative gain
double max_int
saturation threshold for the integrator
double kp
proportional gain
For streams capable of holding different kinds of content, check what they actually have.
PidOutputUnitsEnum
Definition PidEnums.h:31
PidControlTypeEnum
Definition PidEnums.h:15
@ VOCAB_PIDTYPE_TORQUE
Definition PidEnums.h:18
@ VOCAB_PIDTYPE_VELOCITY
Definition PidEnums.h:17
@ VOCAB_PIDTYPE_POSITION
Definition PidEnums.h:16
@ VOCAB_PIDTYPE_CURRENT
Definition PidEnums.h:19
PidFeedbackUnitsEnum
Definition PidEnums.h:25
PidOutputUnitsEnum out_units
PidFeedbackUnitsEnum fbk_units