| [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 | 
 | 
|---|