react-native-cesium 1.2.3 → 1.2.4
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.
- package/README.md +100 -27
- package/android/CMakeLists.txt +1 -2
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +264 -130
- package/android/src/main/cpp/CesiumBridgeAndroid.h +70 -27
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +68 -44
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +160 -187
- package/cpp/engine/CameraIntegrator.cpp +374 -0
- package/cpp/engine/CameraIntegrator.hpp +146 -0
- package/cpp/engine/EngineTunables.hpp +78 -31
- package/cpp/engine/GlobeCamera.cpp +17 -6
- package/cpp/engine/GlobeCamera.hpp +11 -8
- package/cpp/engine/test/CameraIntegratorTest.cpp +205 -0
- package/cpp/engine/test/build_and_run.sh +27 -0
- package/example/README.md +1 -1
- package/ios/CesiumBridge.h +53 -28
- package/ios/CesiumBridge.mm +172 -86
- package/ios/HybridCesiumView.swift +213 -145
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +77 -13
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +90 -9
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +19 -3
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +20 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +57 -3
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +9 -9
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +82 -9
- package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +25 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +14 -3
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +210 -16
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +19 -3
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +20 -4
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +55 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +5 -0
- package/nitrogen/generated/shared/json/CesiumViewConfig.json +5 -0
- package/package.json +1 -1
- package/src/specs/cesium-view.nitro.ts +93 -14
- package/cpp/engine/CameraSmoother.cpp +0 -68
- package/cpp/engine/CameraSmoother.hpp +0 -28
- package/cpp/engine/CameraTargetState.cpp +0 -205
- package/cpp/engine/CameraTargetState.hpp +0 -126
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "GlobeCamera.hpp"
|
|
4
|
-
|
|
5
|
-
namespace reactnativecesium {
|
|
6
|
-
|
|
7
|
-
// Stateless helper. Given a current camera state and a target camera state,
|
|
8
|
-
// returns the next camera state for a frame of duration `dt` seconds.
|
|
9
|
-
//
|
|
10
|
-
// lat / lon / altitude / heading are snapped directly to the target.
|
|
11
|
-
// CameraTargetState::snapshot() has already linearly interpolated those DoFs
|
|
12
|
-
// to their "current" position based on each DoF's own EWMA inter-arrival
|
|
13
|
-
// interval, so snapping here gives constant-velocity motion between fixes
|
|
14
|
-
// with no ease-in/ease-out. At gesture rates (~60 Hz) the EWMA collapses to
|
|
15
|
-
// ~16 ms so the snap is indistinguishable from the previous behaviour.
|
|
16
|
-
//
|
|
17
|
-
// pitch / roll / viewCorrection use fixed-rate exponential decay
|
|
18
|
-
// `1 - exp(-k * dt)` with k from EngineTunables — appropriate for high-rate
|
|
19
|
-
// attitude sensors where the ease-out feel is desirable.
|
|
20
|
-
// Once a DoF drops below its matching epsilon it is snapped to exact equality.
|
|
21
|
-
class CameraSmoother {
|
|
22
|
-
public:
|
|
23
|
-
static CameraParams step(const CameraParams& current,
|
|
24
|
-
const CameraParams& target,
|
|
25
|
-
double dt);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
} // namespace reactnativecesium
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
#include "CameraTargetState.hpp"
|
|
2
|
-
|
|
3
|
-
#include <algorithm>
|
|
4
|
-
#include <cmath>
|
|
5
|
-
|
|
6
|
-
namespace reactnativecesium {
|
|
7
|
-
|
|
8
|
-
namespace {
|
|
9
|
-
|
|
10
|
-
inline double angleDeltaAbsDeg(double a, double b) {
|
|
11
|
-
return std::abs(std::fmod(b - a + 540.0, 360.0) - 180.0);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
inline double quatDotAbs(const glm::dquat& a, const glm::dquat& b) {
|
|
15
|
-
return std::abs(glm::dot(glm::normalize(a), glm::normalize(b)));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Shortest signed angular delta wrapped to [-180, 180].
|
|
19
|
-
inline double shortAngleDeltaDeg(double from, double to) {
|
|
20
|
-
return std::fmod(to - from + 540.0, 360.0) - 180.0;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Advance an EWMA with a new sample, or seed it on first use.
|
|
24
|
-
inline void updateEwma(double& ewma, bool& active,
|
|
25
|
-
std::chrono::steady_clock::time_point& lastTime,
|
|
26
|
-
const std::chrono::steady_clock::time_point& now,
|
|
27
|
-
double seedSec) {
|
|
28
|
-
if (!active) {
|
|
29
|
-
ewma = seedSec;
|
|
30
|
-
lastTime = now;
|
|
31
|
-
active = true;
|
|
32
|
-
} else {
|
|
33
|
-
const double dt = std::chrono::duration<double>(now - lastTime).count();
|
|
34
|
-
if (dt > 0.0) {
|
|
35
|
-
ewma = ewma + tunables::kEwmaIntervalAlpha * (dt - ewma);
|
|
36
|
-
}
|
|
37
|
-
lastTime = now;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
} // namespace
|
|
42
|
-
|
|
43
|
-
// ── Public writers ────────────────────────────────────────────────────────────
|
|
44
|
-
|
|
45
|
-
void CameraTargetState::setAll(const CameraParams& target) {
|
|
46
|
-
{
|
|
47
|
-
std::lock_guard<std::mutex> g(mutex_);
|
|
48
|
-
target_ = target;
|
|
49
|
-
// Deliberately do NOT touch any interpolation state: setAll is init-only
|
|
50
|
-
// and the first rendered frame must snap to the requested position.
|
|
51
|
-
}
|
|
52
|
-
dirty_.store(true, std::memory_order_release);
|
|
53
|
-
forceRender_.store(true, std::memory_order_release);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
void CameraTargetState::setHpr(double lat, double lon, double alt,
|
|
57
|
-
double heading, double pitch, double roll) {
|
|
58
|
-
{
|
|
59
|
-
std::lock_guard<std::mutex> g(mutex_);
|
|
60
|
-
|
|
61
|
-
const auto now = std::chrono::steady_clock::now();
|
|
62
|
-
|
|
63
|
-
// ── lat / lon ─────────────────────────────────────────────────────────
|
|
64
|
-
const bool posChanged =
|
|
65
|
-
std::abs(lat - target_.latitude) > tunables::kEpsLatLon ||
|
|
66
|
-
std::abs(lon - target_.longitude) > tunables::kEpsLatLon;
|
|
67
|
-
|
|
68
|
-
if (posChanged) {
|
|
69
|
-
if (!hasPosInterp_) {
|
|
70
|
-
// First runtime change: seed "from" = destination for a clean snap,
|
|
71
|
-
// then enable interpolation for subsequent updates.
|
|
72
|
-
posFromLat_ = lat;
|
|
73
|
-
posFromLon_ = lon;
|
|
74
|
-
updateEwma(posEwmaIntervalSec_, hasPosInterp_, posUpdateTime_, now,
|
|
75
|
-
tunables::kSmoothPositionTauMax / tunables::kSmoothPositionAlpha);
|
|
76
|
-
} else {
|
|
77
|
-
posFromLat_ = target_.latitude;
|
|
78
|
-
posFromLon_ = target_.longitude;
|
|
79
|
-
updateEwma(posEwmaIntervalSec_, hasPosInterp_, posUpdateTime_, now,
|
|
80
|
-
tunables::kSmoothPositionTauMax / tunables::kSmoothPositionAlpha);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ── altitude ──────────────────────────────────────────────────────────
|
|
85
|
-
const bool altChanged =
|
|
86
|
-
std::abs(alt - target_.altitude) > tunables::kEpsAltitudeMeters;
|
|
87
|
-
|
|
88
|
-
if (altChanged) {
|
|
89
|
-
if (!hasAltInterp_) {
|
|
90
|
-
altFrom_ = alt;
|
|
91
|
-
updateEwma(altEwmaIntervalSec_, hasAltInterp_, altUpdateTime_, now,
|
|
92
|
-
tunables::kSmoothPositionTauMax / tunables::kSmoothPositionAlpha);
|
|
93
|
-
} else {
|
|
94
|
-
altFrom_ = target_.altitude;
|
|
95
|
-
updateEwma(altEwmaIntervalSec_, hasAltInterp_, altUpdateTime_, now,
|
|
96
|
-
tunables::kSmoothPositionTauMax / tunables::kSmoothPositionAlpha);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ── heading ───────────────────────────────────────────────────────────
|
|
101
|
-
const bool hdgChanged =
|
|
102
|
-
angleDeltaAbsDeg(heading, target_.heading) > tunables::kEpsAngleDeg;
|
|
103
|
-
|
|
104
|
-
if (hdgChanged) {
|
|
105
|
-
if (!hasHdgInterp_) {
|
|
106
|
-
hdgFrom_ = heading;
|
|
107
|
-
updateEwma(hdgEwmaIntervalSec_, hasHdgInterp_, hdgUpdateTime_, now,
|
|
108
|
-
tunables::kSmoothPositionTauMax / tunables::kSmoothPositionAlpha);
|
|
109
|
-
} else {
|
|
110
|
-
hdgFrom_ = target_.heading;
|
|
111
|
-
updateEwma(hdgEwmaIntervalSec_, hasHdgInterp_, hdgUpdateTime_, now,
|
|
112
|
-
tunables::kSmoothPositionTauMax / tunables::kSmoothPositionAlpha);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
target_.latitude = lat;
|
|
117
|
-
target_.longitude = lon;
|
|
118
|
-
target_.altitude = alt;
|
|
119
|
-
target_.heading = heading;
|
|
120
|
-
target_.pitch = pitch;
|
|
121
|
-
target_.roll = roll;
|
|
122
|
-
}
|
|
123
|
-
dirty_.store(true, std::memory_order_release);
|
|
124
|
-
forceRender_.store(true, std::memory_order_release);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
void CameraTargetState::setViewCorrection(const glm::dquat& q) {
|
|
128
|
-
{
|
|
129
|
-
std::lock_guard<std::mutex> g(mutex_);
|
|
130
|
-
target_.viewCorrection = q;
|
|
131
|
-
// Interpolation state is not touched — viewCorrection carries no
|
|
132
|
-
// positional information and must not affect any of the three EWMAs.
|
|
133
|
-
}
|
|
134
|
-
dirty_.store(true, std::memory_order_release);
|
|
135
|
-
forceRender_.store(true, std::memory_order_release);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ── Snapshot (render-thread read) ─────────────────────────────────────────────
|
|
139
|
-
|
|
140
|
-
CameraParams CameraTargetState::snapshot() const {
|
|
141
|
-
const auto now = std::chrono::steady_clock::now();
|
|
142
|
-
std::lock_guard<std::mutex> g(mutex_);
|
|
143
|
-
|
|
144
|
-
CameraParams result = target_;
|
|
145
|
-
|
|
146
|
-
// ── lat / lon ─────────────────────────────────────────────────────────────
|
|
147
|
-
if (hasPosInterp_ && posEwmaIntervalSec_ > 0.0) {
|
|
148
|
-
const double dLat = target_.latitude - posFromLat_;
|
|
149
|
-
const double dLon = shortAngleDeltaDeg(posFromLon_, target_.longitude);
|
|
150
|
-
|
|
151
|
-
const bool snapThrough =
|
|
152
|
-
std::abs(dLat) > tunables::kPosSnapThroughDeg ||
|
|
153
|
-
std::abs(dLon) > tunables::kPosSnapThroughDeg;
|
|
154
|
-
|
|
155
|
-
if (!snapThrough) {
|
|
156
|
-
const double elapsed =
|
|
157
|
-
std::chrono::duration<double>(now - posUpdateTime_).count();
|
|
158
|
-
const double t = std::min(elapsed / posEwmaIntervalSec_, 1.0);
|
|
159
|
-
result.latitude = posFromLat_ + t * dLat;
|
|
160
|
-
result.longitude = posFromLon_ + t * dLon;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// ── altitude ──────────────────────────────────────────────────────────────
|
|
165
|
-
if (hasAltInterp_ && altEwmaIntervalSec_ > 0.0) {
|
|
166
|
-
const double dAlt = target_.altitude - altFrom_;
|
|
167
|
-
|
|
168
|
-
if (std::abs(dAlt) <= tunables::kAltSnapThroughMeters) {
|
|
169
|
-
const double elapsed =
|
|
170
|
-
std::chrono::duration<double>(now - altUpdateTime_).count();
|
|
171
|
-
const double t = std::min(elapsed / altEwmaIntervalSec_, 1.0);
|
|
172
|
-
result.altitude = altFrom_ + t * dAlt;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// ── heading ───────────────────────────────────────────────────────────────
|
|
177
|
-
if (hasHdgInterp_ && hdgEwmaIntervalSec_ > 0.0) {
|
|
178
|
-
const double dHdg = shortAngleDeltaDeg(hdgFrom_, target_.heading);
|
|
179
|
-
|
|
180
|
-
if (std::abs(dHdg) <= tunables::kHdgSnapThroughDeg) {
|
|
181
|
-
const double elapsed =
|
|
182
|
-
std::chrono::duration<double>(now - hdgUpdateTime_).count();
|
|
183
|
-
const double t = std::min(elapsed / hdgEwmaIntervalSec_, 1.0);
|
|
184
|
-
result.heading = hdgFrom_ + t * dHdg;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return result;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// ── Epsilon check (shared) ────────────────────────────────────────────────────
|
|
192
|
-
|
|
193
|
-
bool CameraTargetState::deltaExceedsEpsilon(
|
|
194
|
-
const CameraParams& a, const CameraParams& b) {
|
|
195
|
-
return std::abs(a.latitude - b.latitude) > tunables::kEpsLatLon
|
|
196
|
-
|| std::abs(a.longitude - b.longitude) > tunables::kEpsLatLon
|
|
197
|
-
|| std::abs(a.altitude - b.altitude) > tunables::kEpsAltitudeMeters
|
|
198
|
-
|| angleDeltaAbsDeg(a.heading, b.heading) > tunables::kEpsAngleDeg
|
|
199
|
-
|| angleDeltaAbsDeg(a.pitch, b.pitch) > tunables::kEpsAngleDeg
|
|
200
|
-
|| angleDeltaAbsDeg(a.roll, b.roll) > tunables::kEpsAngleDeg
|
|
201
|
-
|| (1.0 - quatDotAbs(a.viewCorrection, b.viewCorrection))
|
|
202
|
-
> tunables::kEpsQuatDot;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
} // namespace reactnativecesium
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "EngineTunables.hpp"
|
|
4
|
-
#include "GlobeCamera.hpp"
|
|
5
|
-
|
|
6
|
-
#include <atomic>
|
|
7
|
-
#include <chrono>
|
|
8
|
-
#include <mutex>
|
|
9
|
-
|
|
10
|
-
namespace reactnativecesium {
|
|
11
|
-
|
|
12
|
-
// Thread-safe holder for the *demand* camera (what the JS side last asked for).
|
|
13
|
-
//
|
|
14
|
-
// Writers: the React Native JS / worklet thread, via setCamera / setCameraQuaternion.
|
|
15
|
-
// Readers: the dedicated render thread (per frame), via shouldRenderNextFrame /
|
|
16
|
-
// renderFrame.
|
|
17
|
-
//
|
|
18
|
-
// We use a small mutex around `target_` because the writes are uncontended and
|
|
19
|
-
// the read side only happens once per frame; the cost is negligible compared to
|
|
20
|
-
// the cost of *not* synchronising a 56-byte struct that contains a glm::dquat.
|
|
21
|
-
//
|
|
22
|
-
// `dirty_` and `forceRender_` are independent atomic flags so the read side can
|
|
23
|
-
// poll without taking the lock when the camera has not moved.
|
|
24
|
-
//
|
|
25
|
-
// Per-DoF linear interpolation (lat/lon, altitude, heading)
|
|
26
|
-
// ──────────────────────────────────────────────────────────
|
|
27
|
-
// Each of lat/lon, altitude, and heading maintains its own independent EWMA
|
|
28
|
-
// of inter-arrival times and only updates that EWMA when *its own value*
|
|
29
|
-
// actually changes. snapshot() then linearly interpolates each DoF from its
|
|
30
|
-
// previous value to its current target over its own EWMA interval.
|
|
31
|
-
//
|
|
32
|
-
// This means lat/lon, altitude, and heading each self-tune independently:
|
|
33
|
-
// - 60 Hz gesture input → EWMA ~16 ms → interpolation near-instant (snap)
|
|
34
|
-
// - 1 Hz GPS → EWMA ~1 s → constant-velocity glide between fixes
|
|
35
|
-
// - 50 Hz barometer for altitude + 1 Hz GPS for lat/lon → altitude behaves
|
|
36
|
-
// near-instant, lat/lon glides — with no special-casing needed.
|
|
37
|
-
//
|
|
38
|
-
// Special cases in snapshot():
|
|
39
|
-
// - t >= 1: camera has reached the target, returns target_ directly.
|
|
40
|
-
// - Snap-through guard: large jumps bypass interpolation so deliberate
|
|
41
|
-
// teleports remain instant.
|
|
42
|
-
// - First change per DoF: "from" = destination, so lerp(dest, dest, t) = dest
|
|
43
|
-
// for all t — clean snap, no startup glide.
|
|
44
|
-
// - setAll (init-only): never touches any interpolation state.
|
|
45
|
-
//
|
|
46
|
-
// pitch / roll / viewCorrection are NOT interpolated here; CameraSmoother
|
|
47
|
-
// applies fixed-rate exponential curves to them (appropriate for high-rate
|
|
48
|
-
// attitude sensors).
|
|
49
|
-
class CameraTargetState {
|
|
50
|
-
public:
|
|
51
|
-
CameraTargetState() = default;
|
|
52
|
-
|
|
53
|
-
// Replace the entire target. Used only for engine initialisation; does NOT
|
|
54
|
-
// update any interpolation state so the first rendered frame snaps.
|
|
55
|
-
void setAll(const CameraParams& target);
|
|
56
|
-
|
|
57
|
-
// Update lat/lon/alt + heading/pitch/roll, leaving viewCorrection unchanged.
|
|
58
|
-
// Independently tracks cadence for lat/lon, altitude, and heading.
|
|
59
|
-
void setHpr(double lat, double lon, double alt,
|
|
60
|
-
double heading, double pitch, double roll);
|
|
61
|
-
|
|
62
|
-
void setViewCorrection(const glm::dquat& q);
|
|
63
|
-
|
|
64
|
-
// Snapshot the demand target for this render frame. lat/lon, altitude, and
|
|
65
|
-
// heading are linearly interpolated to their "current" position based on
|
|
66
|
-
// each DoF's own EWMA interval. pitch/roll/viewCorrection are returned as-is
|
|
67
|
-
// (CameraSmoother handles their exponential curves).
|
|
68
|
-
CameraParams snapshot() const;
|
|
69
|
-
|
|
70
|
-
// Lightweight, lock-free check used by the render thread to decide whether
|
|
71
|
-
// it should bother taking a full snapshot at all.
|
|
72
|
-
bool isDirty() const noexcept {
|
|
73
|
-
return dirty_.load(std::memory_order_acquire);
|
|
74
|
-
}
|
|
75
|
-
void clearDirty() noexcept {
|
|
76
|
-
dirty_.store(false, std::memory_order_release);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
bool consumeForceRender() noexcept {
|
|
80
|
-
return forceRender_.exchange(false, std::memory_order_acq_rel);
|
|
81
|
-
}
|
|
82
|
-
void requestForceRender() noexcept {
|
|
83
|
-
forceRender_.store(true, std::memory_order_release);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Compares snapshot to "current" (the engine's current camera) and returns
|
|
87
|
-
// true if any DoF differs by more than the matching epsilon. Used to decide
|
|
88
|
-
// whether to render this frame.
|
|
89
|
-
static bool deltaExceedsEpsilon(const CameraParams& a, const CameraParams& b);
|
|
90
|
-
|
|
91
|
-
private:
|
|
92
|
-
mutable std::mutex mutex_;
|
|
93
|
-
CameraParams target_;
|
|
94
|
-
std::atomic<bool> dirty_{false};
|
|
95
|
-
std::atomic<bool> forceRender_{true};
|
|
96
|
-
|
|
97
|
-
// ── Per-DoF linear interpolation state (all protected by mutex_) ─────────
|
|
98
|
-
// Each DoF has: a "from" value, a wall-clock timestamp of the last change,
|
|
99
|
-
// an EWMA of inter-arrival times, and an "active" flag.
|
|
100
|
-
//
|
|
101
|
-
// Pattern per DoF:
|
|
102
|
-
// First change: from = destination (snap), seed EWMA, set active.
|
|
103
|
-
// Subsequent change: from = old target, update EWMA, reset clock.
|
|
104
|
-
// snapshot(): t = clamp(elapsed/ewma, 0, 1); result = from + t*delta.
|
|
105
|
-
|
|
106
|
-
// lat / lon
|
|
107
|
-
double posFromLat_{0.0};
|
|
108
|
-
double posFromLon_{0.0};
|
|
109
|
-
std::chrono::steady_clock::time_point posUpdateTime_{};
|
|
110
|
-
double posEwmaIntervalSec_{0.0};
|
|
111
|
-
bool hasPosInterp_{false};
|
|
112
|
-
|
|
113
|
-
// altitude
|
|
114
|
-
double altFrom_{0.0};
|
|
115
|
-
std::chrono::steady_clock::time_point altUpdateTime_{};
|
|
116
|
-
double altEwmaIntervalSec_{0.0};
|
|
117
|
-
bool hasAltInterp_{false};
|
|
118
|
-
|
|
119
|
-
// heading
|
|
120
|
-
double hdgFrom_{0.0};
|
|
121
|
-
std::chrono::steady_clock::time_point hdgUpdateTime_{};
|
|
122
|
-
double hdgEwmaIntervalSec_{0.0};
|
|
123
|
-
bool hasHdgInterp_{false};
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
} // namespace reactnativecesium
|