Index: trunk/BNC/src/combination/bnccomb.cpp
===================================================================
--- trunk/BNC/src/combination/bnccomb.cpp	(revision 11099)
+++ trunk/BNC/src/combination/bnccomb.cpp	(revision 11105)
@@ -464,7 +464,12 @@
     }
 
-    // Store the correction
+    // Store the correction; the latest orbit of the previous IOD is kept as
+    // well: the clocks of an epoch may be processed only after the orbits of
+    // the next epoch have arrived, which already refer to a new IOD
     // --------------------
     QMap<t_prn, t_orbCorr>& storage = _orbCorrections[acName];
+    if (storage.contains(orbCorr._prn) && storage[orbCorr._prn]._iod != orbCorr._iod) {
+      _orbCorrectionsPrev[acName][orbCorr._prn] = storage[orbCorr._prn];
+    }
     storage[orbCorr._prn] = orbCorr;
   }
@@ -823,11 +828,14 @@
     else {
       QMap<t_prn, t_orbCorr>& storage = _orbCorrections[acName];
-      if (!storage.contains(clkCorr._prn)  ||
-           storage[clkCorr._prn]._iod != _newCorr->_iod) {
+      QMap<t_prn, t_orbCorr>& prev    = _orbCorrectionsPrev[acName];
+      if (storage.contains(clkCorr._prn) && storage[clkCorr._prn]._iod == _newCorr->_iod) {
+        _newCorr->_orbCorr = storage[clkCorr._prn];
+      }
+      else if (prev.contains(clkCorr._prn) && prev[clkCorr._prn]._iod == _newCorr->_iod) {
+        _newCorr->_orbCorr = prev[clkCorr._prn];
+      }
+      else {
         delete _newCorr; _newCorr = 0;
         continue;
-      }
-      else {
-        _newCorr->_orbCorr = storage[clkCorr._prn];
       }
     }
@@ -955,15 +963,19 @@
         _newCorr->_satYawAngle      = pb._yaw + pb._yawRate * dt;
         _newCorr->_satYawAngleValid = true;
-
-        // _lambdaIF
-        map<t_frequency::type, double> codeCoeff;
-        double channel = double(_newCorr->_eph->slotNum());
-        cmbRefSig::coeff(sys, cmbRefSig::cIF, channel, codeCoeff);
-        map<t_frequency::type, double>::const_iterator it;
-        for (it = codeCoeff.begin(); it != codeCoeff.end(); it++) {
-          t_frequency::type frqType = it->first;
-          double codeCoeff = it->second;
-          _newCorr->_lambdaIF += codeCoeff * t_CST::c / t_CST::freq(frqType, channel);
-        }
+      }
+    }
+
+    // _lambdaIF: ionosphere-free combination of the reference signals'
+    // wavelengths (narrow-lane wavelength), scales the phase wind-up
+    // -------------------------------------------------------------------
+    {
+      map<t_frequency::type, double> codeCoeff;
+      double channel = double(_newCorr->_eph->slotNum());
+      cmbRefSig::coeff(sys, cmbRefSig::cIF, channel, codeCoeff);
+      map<t_frequency::type, double>::const_iterator it;
+      for (it = codeCoeff.begin(); it != codeCoeff.end(); it++) {
+        t_frequency::type frqType = it->first;
+        double codeCoeff = it->second;
+        _newCorr->_lambdaIF += codeCoeff * t_CST::c / t_CST::freq(frqType, channel);
       }
     }
@@ -982,4 +994,15 @@
         delete _newCorr; _newCorr = 0;
         continue;
+      }
+    }
+
+    // Yaw angle of the AC's attitude, for the attitude consistency correction
+    // -----------------------------------------------------------------------
+    if (_antex && !_newCorr->_attYawValid) {
+      for (const cmbAC* ac : _ACs) {
+        if (ac->name == acName) {
+          attitudeYaw(_newCorr, ac);
+          break;
+        }
       }
     }
@@ -1432,5 +1455,6 @@
   double Mjd = corr->_time.mjd() + corr->_time.daysec() / 86400.0;
   ColumnVector dx(3); dx = 0.0;
-  if (_antex->satCoMcorrection(corr->_prn, Mjd, xc.Rows(1,3), vv, dx, attMode, extYaw, AC->name) != success) {
+  if (_antex->satCoMcorrection(corr->_prn, Mjd, xc.Rows(1,3), vv, dx, attMode, extYaw, AC->name,
+                               &corr->_attYaw) != success) {
     if (_antex->warnNoSatEntry(corr->_prn, corr->_time)) {
       emit newMessage("bncComb: no satellite antenna entry valid at " +
@@ -1441,4 +1465,5 @@
     return failure;
   }
+  corr->_attYawValid = true;
   // X = X_brdc - RSW(xr): X_CoM = X_APC - dx  =>  xr_CoM = xr_APC + RSW(dx)
   ColumnVector dRAO(3);
@@ -1446,4 +1471,31 @@
   corr->_orbCorr._xr += dRAO;
   return success;
+}
+
+// Yaw angle of the attitude an AC uses (SSR yaw or attitude model)
+////////////////////////////////////////////////////////////////////////////
+// Only needed if the orbit is not converted from APC to CoM, which already
+// provides the yaw angle. Separate model state per AC (key AC + ":att").
+////////////////////////////////////////////////////////////////////////////
+void bncComb::attitudeYaw(cmbCorr* corr, const cmbAC* AC) {
+  if (AC->attitudeSource == "SSR" && corr->_satYawAngleValid) {
+    corr->_attYaw      = corr->_satYawAngle;
+    corr->_attYawValid = true;
+    return;
+  }
+  corr->_eph->setOrbCorr(&corr->_orbCorr);
+  corr->_eph->setClkCorr(&corr->_clkCorr);
+  ColumnVector xc(6), vv(3);
+  if (corr->_eph->getCrd(corr->_time, xc, vv, true) != success) {
+    return;
+  }
+  bncAntex::e_attMode attMode = (AC->attitudeSource == "Nominal") ? bncAntex::ATT_NOMINAL
+                                                                  : bncAntex::ATT_COMPUTED;
+  double Mjd = corr->_time.mjd() + corr->_time.daysec() / 86400.0;
+  ColumnVector dx(3); dx = 0.0;
+  if (_antex->satCoMcorrection(corr->_prn, Mjd, xc.Rows(1,3), vv, dx, attMode, 0.0,
+                               AC->name + ":att", &corr->_attYaw) == success) {
+    corr->_attYawValid = true;
+  }
 }
 
@@ -1828,7 +1880,13 @@
     double dC_orb = DotProduct((corr->_satPos - masterCorr[prn]->_satPos), corr->_satPos);
     dC_orb /= masterCorr[prn]->_satPos.NormFrobenius();
-    double dC_att = (corr->_satYawAngle - masterCorr[prn]->_satYawAngle) / (2 * M_PI);
-    dC_att *= corr->_lambdaIF;
-    double dC_apriori_corr = dC_orb;// + dC_att; can be added if useful values are provided by the ACs
+    // Attitude: a yaw difference dpsi changes the phase wind-up of the
+    // ionosphere-free combination by lambda_IF * dpsi / 2pi, which is
+    // absorbed by the AC's clock (zero if both use the same attitude model)
+    double dC_att = 0.0;
+    if (corr->_attYawValid && masterCorr[prn]->_attYawValid) {
+      double dPsi = remainder(corr->_attYaw - masterCorr[prn]->_attYaw, 2.0 * M_PI);
+      dC_att = corr->_lambdaIF * dPsi / (2.0 * M_PI);
+    }
+    double dC_apriori_corr = dC_orb + dC_att;
 
     // Clock referred to the ionosphere-free combination of the reference
