| [534] | 1 | // gyrocalibrator.cc | 
|---|
|  | 2 | // Eric Aubourg         CEA/DAPNIA/SPP   octobre 1999 | 
|---|
|  | 3 |  | 
|---|
|  | 4 | // assumption : same calibration for all gyros... | 
|---|
|  | 5 |  | 
|---|
| [555] | 6 | // Warning, current implementation can only output ONE calibration. | 
|---|
|  | 7 | // workaround : clone the object for different options. | 
|---|
| [534] | 8 |  | 
|---|
| [555] | 9 |  | 
|---|
| [534] | 10 | #include "gyrocalibrator.h" | 
|---|
| [555] | 11 | #include "archexc.h" | 
|---|
|  | 12 | #include "archparam.h" | 
|---|
| [534] | 13 |  | 
|---|
|  | 14 | #define gyroCal    "gyroCal" | 
|---|
| [555] | 15 | #define gyroOffset "gyroOffset" | 
|---|
| [534] | 16 | #define gyroSpeed  "gyroSpeed" | 
|---|
|  | 17 |  | 
|---|
|  | 18 | GyroCalibrator::GyroCalibrator() { | 
|---|
| [555] | 19 | possibleTOIs.insert(TOI(gyroCal,      TOI::all,    "linearCal", "deg/s/V")); | 
|---|
|  | 20 | possibleTOIs.insert(TOI(gyroOffset,   TOI::all,    "linearCal", "deg/s/V")); | 
|---|
| [534] | 21 | possibleTOIs.insert(TOI(gyroSpeed,    TOI::all   , "linearCal", "deg/s")); | 
|---|
|  | 22 |  | 
|---|
| [555] | 23 | needAfter = 3600;  // about one turn... | 
|---|
| [534] | 24 | startSample = -1; | 
|---|
| [555] | 25 | lastRotSpeed = -1; | 
|---|
| [534] | 26 | lastFence1 = lastFence2 = -1; | 
|---|
| [555] | 27 | for (int i=0; i<3; i++) { | 
|---|
|  | 28 | lastCalib[i] = -99999; | 
|---|
|  | 29 | lastOffset[i] = 0; | 
|---|
|  | 30 | } | 
|---|
|  | 31 | gyroProducer = NULL; | 
|---|
| [534] | 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 |  | 
|---|
| [555] | 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; | 
|---|
| [534] | 53 |  | 
|---|
| [555] | 54 | if (gyro[2].empty()) { | 
|---|
| [534] | 55 | startSample = sampleNum; | 
|---|
|  | 56 | } | 
|---|
|  | 57 |  | 
|---|
| [555] | 58 | gyro[toi.index].push_back(value); | 
|---|
| [534] | 59 | } | 
|---|
|  | 60 |  | 
|---|
| [555] | 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 | } | 
|---|
| [534] | 97 |  | 
|---|
| [555] | 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); | 
|---|
| [635] | 106 | if (inToi.name == "rotSpeedSample1") lastFence1   = long(prod->getValue(sampleNum, inToi)); | 
|---|
|  | 107 | if (inToi.name == "rotSpeedSample2") lastFence2   = long(prod->getValue(sampleNum, inToi)); | 
|---|
| [555] | 108 | if (inToi.name == "gyroV")           gyroProducer = prod; | 
|---|
|  | 109 | } | 
|---|
|  | 110 |  | 
|---|
|  | 111 | return (oldf2 != lastFence2); | 
|---|
|  | 112 | } | 
|---|
| [534] | 113 |  | 
|---|
| [555] | 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 | } | 
|---|
| [634] | 141 |  | 
|---|
|  | 142 | // Si nos fournisseurs ne peuvent pas, nous non plus... | 
|---|
|  | 143 | map<TOI, TOIProducer*> & m = (*(neededTOIs.begin())).second; | 
|---|
|  | 144 | for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) { | 
|---|
|  | 145 | TOI const& inToi = (*i).first; | 
|---|
|  | 146 | TOIProducer* prod =  (*i).second; | 
|---|
|  | 147 | if (!prod->canGetValue(sampleNum, inToi) && !prod->canGetValueLater(sampleNum, inToi)) return false; | 
|---|
|  | 148 |  | 
|---|
|  | 149 | } | 
|---|
|  | 150 |  | 
|---|
| [555] | 151 | if (lastFence1<0 || lastFence2<0) return true; | 
|---|
|  | 152 | if (sampleNum > lastFence2) return true; | 
|---|
|  | 153 | return (startSample <= lastFence1 && (long)gyro[2].size()+startSample < lastFence2 && sampleNum > lastFence1); | 
|---|
|  | 154 | } | 
|---|
|  | 155 |  | 
|---|
|  | 156 | double GyroCalibrator::getValue(long sampleNum, TOI const& toi) { | 
|---|
|  | 157 | if (startSample > lastFence1) return -1; // will never work... | 
|---|
|  | 158 | if ((long)gyro[2].size()+startSample < lastFence2) return -1; // We have to wait for more gyro data | 
|---|
|  | 159 | if (!(sampleNum >= lastFence1 && sampleNum < lastFence2)) { | 
|---|
|  | 160 | if (fetchFences(sampleNum)) { | 
|---|
|  | 161 | if ((long)gyro[2].size()+startSample < lastFence2) return -1; // We have to wait for more gyro data | 
|---|
|  | 162 | recomputeCalib(); // do it now to keep a consistent state | 
|---|
|  | 163 | } | 
|---|
|  | 164 | } | 
|---|
|  | 165 |  | 
|---|
|  | 166 | if (!(sampleNum >= lastFence1 && sampleNum < lastFence2)) | 
|---|
|  | 167 | return -1; | 
|---|
|  | 168 |  | 
|---|
|  | 169 | if (lastCalib[0] < 0) recomputeCalib(); | 
|---|
|  | 170 |  | 
|---|
|  | 171 | if (toi.name == gyroCal)    return lastCalib[toi.index]; | 
|---|
|  | 172 | if (toi.name == gyroOffset) return lastOffset[toi.index]; | 
|---|
|  | 173 | if (toi.name == gyroSpeed) { | 
|---|
|  | 174 | TOI toi2 = TOI("gyroV", toi.index); // $CHECK$ maybe should get from reqtoi ? | 
|---|
|  | 175 | double gv = gyroProducer->getValue(sampleNum, toi2); | 
|---|
|  | 176 | return (gv-lastOffset[toi.index])*lastCalib[toi.index]; | 
|---|
|  | 177 | } | 
|---|
|  | 178 | throw ArchExc("Cannot produce "+toi.fullName()); | 
|---|
|  | 179 | } | 
|---|
|  | 180 |  | 
|---|
|  | 181 |  | 
|---|
| [634] | 182 | void GyroCalibrator::propagateLowBound(TOI const& toi, long sampleNum) { | 
|---|
| [555] | 183 | if (startSample < lastFence1) { | 
|---|
|  | 184 | if (gyro[0].size() > lastFence1 - startSample) { | 
|---|
|  | 185 | for (int i=0; i<3; i++) { | 
|---|
|  | 186 | vector<double>::iterator x = gyro[i].begin() + lastFence1 - startSample; | 
|---|
|  | 187 | gyro[i].erase(gyro[i].begin(), x); | 
|---|
|  | 188 | } | 
|---|
|  | 189 | startSample = lastFence1; | 
|---|
|  | 190 | } | 
|---|
|  | 191 | } | 
|---|
| [634] | 192 | TOIPullProducer::propagateLowBound(toi, sampleNum); | 
|---|
| [555] | 193 | } | 
|---|
|  | 194 |  | 
|---|