react-native-cesium 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,10 @@ namespace {
15
15
  // isolation without linking CesiumGeospatial. Matches Ellipsoid::WGS84.
16
16
  inline constexpr double kEarthMeanRadiusM = 6371008.7714150595;
17
17
 
18
+ // Hard ceiling on altitude (metres MSL). Enforced on both the demand and the
19
+ // running estimate so no code path can push the camera above this value.
20
+ inline constexpr double kMaxAltMeters = 100'000.0;
21
+
18
22
  inline double shortAngleDeltaDeg(double from, double to) {
19
23
  return std::fmod(to - from + 540.0, 360.0) - 180.0;
20
24
  }
@@ -105,7 +109,8 @@ void CameraIntegrator::updateAlphaBeta(
105
109
  s.tLastMeas = tz;
106
110
  }
107
111
 
108
- void CameraIntegrator::extrapolate(AlphaBeta& s, TimePoint now, double maxRateAbs) {
112
+ void CameraIntegrator::extrapolate(
113
+ AlphaBeta& s, TimePoint now, double maxRateAbs, double demand) {
109
114
  double dt = std::chrono::duration<double>(now - s.tState).count();
110
115
  if (dt <= 0.0) {
111
116
  s.tState = now;
@@ -121,9 +126,14 @@ void CameraIntegrator::extrapolate(AlphaBeta& s, TimePoint now, double maxRateAb
121
126
  // grace window and the decay τ scale with the EWMA of inter-arrival times
122
127
  // so a 60 Hz worklet bleeds in ~50 ms while a 1 Hz GPS glide is left
123
128
  // alone between fixes.
129
+ //
130
+ // silence and grace are hoisted out of the block so the demand-pull term
131
+ // below can reuse them without a second chrono subtraction.
132
+ double silence = -1.0; // negative sentinel: "no measurement seen yet"
133
+ double grace = 0.0;
124
134
  if (s.tLastMeas.time_since_epoch().count() > 0) {
125
- const double silence = std::chrono::duration<double>(now - s.tLastMeas).count();
126
- const double grace = tunables::kVelocitySilenceGraceFactor * s.meanIntervalSec;
135
+ silence = std::chrono::duration<double>(now - s.tLastMeas).count();
136
+ grace = tunables::kVelocitySilenceGraceFactor * s.meanIntervalSec;
127
137
  if (silence > grace) {
128
138
  const double tau = tunables::kVelocityBleedTauFactor * s.meanIntervalSec;
129
139
  if (tau > 1.0e-6) {
@@ -139,6 +149,16 @@ void CameraIntegrator::extrapolate(AlphaBeta& s, TimePoint now, double maxRateAb
139
149
  }
140
150
  s.value += s.velocity * dt;
141
151
  s.tState = now;
152
+
153
+ // Demand pull — guarantees convergence to the last demanded value for
154
+ // one-shot API calls (e.g. setAltitude from a button tap). Active only
155
+ // when measurements have stopped (silence > grace); continuous gesture or
156
+ // sensor streams always deliver a new update before the grace window
157
+ // expires, so this term is never active for them.
158
+ if (silence > grace && tunables::kDemandPullTauSec > 1.0e-6) {
159
+ s.value += (1.0 - std::exp(-dt / tunables::kDemandPullTauSec))
160
+ * (demand - s.value);
161
+ }
142
162
  }
143
163
 
144
164
  // ── Demand setters ────────────────────────────────────────────────────────
@@ -172,6 +192,7 @@ void CameraIntegrator::setAltitude(double altitudeMeters) {
172
192
  return;
173
193
  }
174
194
 
195
+ altitudeMeters = std::min(altitudeMeters, kMaxAltMeters);
175
196
  updateAlphaBeta(alt_, altitudeMeters, now,
176
197
  tunables::kAlphaAlt, tunables::kBetaAlt, false);
177
198
  demand_.altitude = altitudeMeters;
@@ -285,16 +306,17 @@ CameraParams CameraIntegrator::step() {
285
306
  latLonCapDegSec = glm::degrees(groundCap / kEarthMeanRadiusM);
286
307
  }
287
308
 
288
- extrapolate(lat_, now, latLonCapDegSec);
289
- extrapolate(lon_, now, latLonCapDegSec);
290
- extrapolate(alt_, now, climbCap);
291
- extrapolate(hdg_, now, yawCap);
292
- extrapolate(pitch_, now, pitchCap);
293
- extrapolate(roll_, now, rollCap);
294
- extrapolate(vfov_, now, 0.0); // no velocity term anyway
309
+ extrapolate(lat_, now, latLonCapDegSec, demand_.latitude);
310
+ extrapolate(lon_, now, latLonCapDegSec, demand_.longitude);
311
+ extrapolate(alt_, now, climbCap, demand_.altitude);
312
+ extrapolate(hdg_, now, yawCap, demand_.heading);
313
+ extrapolate(pitch_, now, pitchCap, demand_.pitch);
314
+ extrapolate(roll_, now, rollCap, demand_.roll);
315
+ extrapolate(vfov_, now, 0.0, demand_.verticalFov);
295
316
 
296
317
  hdg_.value = wrap360(hdg_.value);
297
318
  lat_.value = std::clamp(lat_.value, -90.0, 90.0);
319
+ alt_.value = std::min(alt_.value, kMaxAltMeters);
298
320
  // Longitude is allowed to drift over ±180; consumers usually want the raw
299
321
  // continuous value for short-arc maths and the camera transform doesn't
300
322
  // care.
@@ -124,7 +124,7 @@ private:
124
124
  // Advance the running estimate to `now`, clamp velocity to `maxRateAbs`
125
125
  // (per second; 0 = uncapped). For angles, the resulting value is also
126
126
  // normalised to its canonical range by the caller as needed.
127
- static void extrapolate(AlphaBeta& s, TimePoint now, double maxRateAbs);
127
+ static void extrapolate(AlphaBeta& s, TimePoint now, double maxRateAbs, double demand);
128
128
 
129
129
  mutable std::mutex mutex_;
130
130
 
@@ -69,8 +69,8 @@ inline constexpr int32_t kDefaultLoadingDescendantLimit = 20;
69
69
  inline constexpr double kAlphaPos = 0.6; inline constexpr double kBetaPos = 0.05;
70
70
  inline constexpr double kAlphaAlt = 0.6; inline constexpr double kBetaAlt = 0.05;
71
71
  inline constexpr double kAlphaHdg = 0.55; inline constexpr double kBetaHdg = 0.05;
72
- inline constexpr double kAlphaPitch = 0.5; inline constexpr double kBetaPitch = 0.05;
73
- inline constexpr double kAlphaRoll = 0.5; inline constexpr double kBetaRoll = 0.05;
72
+ inline constexpr double kAlphaPitch = 0.75; inline constexpr double kBetaPitch = 0.05;
73
+ inline constexpr double kAlphaRoll = 0.75; inline constexpr double kBetaRoll = 0.05;
74
74
  inline constexpr double kAlphaVfov = 0.4; // no velocity term
75
75
  inline constexpr double kAlphaViewCorr = 0.5; // SLERP toward target
76
76
 
@@ -118,6 +118,13 @@ inline constexpr double kVelocityBleedTauFactor = 2.0;
118
118
  // EWMA blend coefficient for the inter-arrival mean. Higher = faster adapt
119
119
  // to cadence changes (e.g. user switches from gesture to sparse GPS feed).
120
120
  inline constexpr double kIntervalEwmaAlpha = 0.3;
121
+ // Demand-pull time constant (seconds). When measurements have stopped
122
+ // arriving (silence > grace), the actual value is gently pulled toward
123
+ // the last demand at this rate. This guarantees convergence for one-shot
124
+ // API calls (e.g. setAltitude from a button) without affecting continuous
125
+ // sensor or gesture streams — those always deliver a new measurement before
126
+ // the grace window expires, so this term is never active. 0 = disabled.
127
+ inline constexpr double kDemandPullTauSec = 0.8;
121
128
 
122
129
  // Optional outlier rejection (off if 0). When > 0, a single measurement whose
123
130
  // residual against the predicted state exceeds the threshold is dropped (and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-cesium",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Experimental Cesium rendering for React Native via Nitro (iOS/Metal today; Android planned)",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",