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