1 | // gyrocalibrator.cc
|
---|
2 | // Eric Aubourg CEA/DAPNIA/SPP octobre 1999
|
---|
3 |
|
---|
4 | // assumption : same calibration for all gyros...
|
---|
5 |
|
---|
6 | // Warning, current implementation can only output ONE calibration.
|
---|
7 | // workaround : clone the object for different options.
|
---|
8 |
|
---|
9 |
|
---|
10 | #include "gyrocalibrator.h"
|
---|
11 | #include "archexc.h"
|
---|
12 | #include "archparam.h"
|
---|
13 |
|
---|
14 | #define gyroCal "gyroCal"
|
---|
15 | #define gyroOffset "gyroOffset"
|
---|
16 | #define gyroSpeed "gyroSpeed"
|
---|
17 |
|
---|
18 | GyroCalibrator::GyroCalibrator() {
|
---|
19 | possibleTOIs.insert(TOI(gyroCal, TOI::all, "linearCal", "deg/s/V"));
|
---|
20 | possibleTOIs.insert(TOI(gyroOffset, TOI::all, "linearCal", "deg/s/V"));
|
---|
21 | possibleTOIs.insert(TOI(gyroSpeed, TOI::all , "linearCal", "deg/s"));
|
---|
22 |
|
---|
23 | needAfter = 3600; // about one turn...
|
---|
24 | startSample = -1;
|
---|
25 | lastRotSpeed = -1;
|
---|
26 | lastFence1 = lastFence2 = -1;
|
---|
27 | for (int i=0; i<3; i++) {
|
---|
28 | lastCalib[i] = -99999;
|
---|
29 | lastOffset[i] = 0;
|
---|
30 | }
|
---|
31 | gyroProducer = NULL;
|
---|
32 | }
|
---|
33 |
|
---|
34 | string GyroCalibrator::getName() {
|
---|
35 | return("GyroCalibrator 1.0");
|
---|
36 | }
|
---|
37 |
|
---|
38 |
|
---|
39 | set<TOI> GyroCalibrator::reqTOIFor(TOI const&) {
|
---|
40 | set<TOI> t;
|
---|
41 | t.insert(TOI("rotSpeed", TOI::unspec)); // pull only
|
---|
42 | t.insert(TOI("rotSpeedSample1", TOI::unspec)); // pull only
|
---|
43 | t.insert(TOI("rotSpeedSample2", TOI::unspec)); // pull only
|
---|
44 | t.insert(TOI("gyroV", 0)); // push
|
---|
45 | t.insert(TOI("gyroV", 1)); // push
|
---|
46 | t.insert(TOI("gyroV", 2)); // push
|
---|
47 | return t;
|
---|
48 | }
|
---|
49 |
|
---|
50 | void GyroCalibrator::dataFeed(TOIProducer* , TOI const& toi, long sampleNum, double value) {
|
---|
51 | // if (toi.name != "gyroV" || toi.index != 2) return;
|
---|
52 | if (toi.name != "gyroV" ) return;
|
---|
53 |
|
---|
54 | if (gyro[2].empty()) {
|
---|
55 | startSample = sampleNum;
|
---|
56 | }
|
---|
57 |
|
---|
58 | gyro[toi.index].push_back(value);
|
---|
59 | }
|
---|
60 |
|
---|
61 | void GyroCalibrator::recomputeCalib() {
|
---|
62 | // Integral of gyro signal between the two fences.
|
---|
63 |
|
---|
64 | // can we do it ?
|
---|
65 | for (int i=0; i<3; i++) {
|
---|
66 | lastCalib[i] = -99999;
|
---|
67 | }
|
---|
68 | if (startSample > lastFence1) return;
|
---|
69 | if ((long)gyro[2].size()+startSample < lastFence2) return;
|
---|
70 |
|
---|
71 | double sum[3];
|
---|
72 | for (int i=0; i<3; i++) {
|
---|
73 | sum[i] = 0;
|
---|
74 | }
|
---|
75 | vector<double>::iterator i0 = gyro[0].begin() + (lastFence1-startSample);
|
---|
76 | vector<double>::iterator i1 = gyro[1].begin() + (lastFence1-startSample);
|
---|
77 | vector<double>::iterator i2 = gyro[2].begin() + (lastFence1-startSample);
|
---|
78 | vector<double>::iterator stop2 = gyro[2].begin() + (lastFence2-startSample);
|
---|
79 | for (; i2 != stop2; i0++,i1++,i2++) {
|
---|
80 | sum[0] += *i0;
|
---|
81 | sum[1] += *i1;
|
---|
82 | sum[2] += *i2;
|
---|
83 | }
|
---|
84 |
|
---|
85 | // average of signal
|
---|
86 | sum[0] /= (lastFence2-lastFence1);
|
---|
87 | sum[1] /= (lastFence2-lastFence1);
|
---|
88 | sum[2] /= (lastFence2-lastFence1);
|
---|
89 |
|
---|
90 | lastOffset[0] = sum[0];
|
---|
91 | lastOffset[1] = sum[1];
|
---|
92 | lastOffset[2] = (lastOffset[0] + lastOffset[1])/2.; // We don't have a better estimate...
|
---|
93 |
|
---|
94 | lastCalib[2] = lastRotSpeed / (sum[2] - lastOffset[2]);
|
---|
95 | lastCalib[0] = lastCalib[1] = lastCalib[2]; // We don't have a better estimate...
|
---|
96 | }
|
---|
97 |
|
---|
98 | bool GyroCalibrator::fetchFences(long sampleNum) {
|
---|
99 | map<TOI, TOIProducer*> & m = (*(neededTOIs.begin())).second;
|
---|
100 |
|
---|
101 | long oldf2 = lastFence2;
|
---|
102 | for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
|
---|
103 | TOI const& inToi = (*i).first;
|
---|
104 | TOIProducer* prod = (*i).second;
|
---|
105 | if (inToi.name == "rotSpeed") lastRotSpeed = prod->getValue(sampleNum, inToi);
|
---|
106 | if (inToi.name == "rotSpeedSample1") lastFence1 = prod->getValue(sampleNum, inToi);
|
---|
107 | if (inToi.name == "rotSpeedSample2") lastFence2 = prod->getValue(sampleNum, inToi);
|
---|
108 | if (inToi.name == "gyroV") gyroProducer = prod;
|
---|
109 | }
|
---|
110 |
|
---|
111 | return (oldf2 != lastFence2);
|
---|
112 | }
|
---|
113 |
|
---|
114 |
|
---|
115 | bool GyroCalibrator::canGetValue(long sampleNum, TOI const& ) {
|
---|
116 | // We can get value if sampleNum is between the two fences, or
|
---|
117 | // if a new fence later than sampleNum is now available.
|
---|
118 | // In any case, we must have gyro data up to the highest fence.
|
---|
119 |
|
---|
120 | if (startSample > lastFence1) return false; // will never work...
|
---|
121 | if (sampleNum >= lastFence1 && sampleNum < lastFence2 && (gyro[2].size()+startSample >= lastFence2)) return true;
|
---|
122 | if ((long)gyro[2].size()+startSample < lastFence2) return false; // We have to wait for more gyro data
|
---|
123 | if (fetchFences(sampleNum)) {
|
---|
124 | recomputeCalib(); // do it now to keep a consistent state
|
---|
125 | }
|
---|
126 | if (sampleNum >= lastFence1 && sampleNum < lastFence2) {
|
---|
127 | return true;
|
---|
128 | } else {
|
---|
129 | return false;
|
---|
130 | }
|
---|
131 | }
|
---|
132 |
|
---|
133 | bool GyroCalibrator::canGetValueLater(long sampleNum, TOI const& ) {
|
---|
134 | if (sampleNum >= lastFence1 && sampleNum < lastFence2 && ((long)gyro[2].size()+startSample >= lastFence2)) return false;
|
---|
135 | // because can get now
|
---|
136 | if (sampleNum >= lastFence2) { // check if new fence...
|
---|
137 | if (fetchFences(sampleNum)) {
|
---|
138 | recomputeCalib(); // do it now to keep a consistent state
|
---|
139 | }
|
---|
140 | }
|
---|
141 | if (lastFence1<0 || lastFence2<0) return true;
|
---|
142 | if (sampleNum > lastFence2) return true;
|
---|
143 | return (startSample <= lastFence1 && (long)gyro[2].size()+startSample < lastFence2 && sampleNum > lastFence1);
|
---|
144 | }
|
---|
145 |
|
---|
146 | double GyroCalibrator::getValue(long sampleNum, TOI const& toi) {
|
---|
147 | if (startSample > lastFence1) return -1; // will never work...
|
---|
148 | if ((long)gyro[2].size()+startSample < lastFence2) return -1; // We have to wait for more gyro data
|
---|
149 | if (!(sampleNum >= lastFence1 && sampleNum < lastFence2)) {
|
---|
150 | if (fetchFences(sampleNum)) {
|
---|
151 | if ((long)gyro[2].size()+startSample < lastFence2) return -1; // We have to wait for more gyro data
|
---|
152 | recomputeCalib(); // do it now to keep a consistent state
|
---|
153 | }
|
---|
154 | }
|
---|
155 |
|
---|
156 | if (!(sampleNum >= lastFence1 && sampleNum < lastFence2))
|
---|
157 | return -1;
|
---|
158 |
|
---|
159 | if (lastCalib[0] < 0) recomputeCalib();
|
---|
160 |
|
---|
161 | if (toi.name == gyroCal) return lastCalib[toi.index];
|
---|
162 | if (toi.name == gyroOffset) return lastOffset[toi.index];
|
---|
163 | if (toi.name == gyroSpeed) {
|
---|
164 | TOI toi2 = TOI("gyroV", toi.index); // $CHECK$ maybe should get from reqtoi ?
|
---|
165 | double gv = gyroProducer->getValue(sampleNum, toi2);
|
---|
166 | return (gv-lastOffset[toi.index])*lastCalib[toi.index];
|
---|
167 | }
|
---|
168 | throw ArchExc("Cannot produce "+toi.fullName());
|
---|
169 | }
|
---|
170 |
|
---|
171 |
|
---|
172 | void GyroCalibrator::propagateLowBound(TOI const&, long /*sampleNum*/) {
|
---|
173 | if (startSample < lastFence1) {
|
---|
174 | if (gyro[0].size() > lastFence1 - startSample) {
|
---|
175 | for (int i=0; i<3; i++) {
|
---|
176 | vector<double>::iterator x = gyro[i].begin() + lastFence1 - startSample;
|
---|
177 | gyro[i].erase(gyro[i].begin(), x);
|
---|
178 | }
|
---|
179 | startSample = lastFence1;
|
---|
180 | }
|
---|
181 | }
|
---|
182 | }
|
---|
183 |
|
---|