31#include <simgear/sg_inlines.h>
32#include <simgear/debug/logstream.hxx>
33#include <simgear/props/props_io.hxx>
34#include <simgear/misc/strutils.hxx>
35#include <simgear/structure/exception.hxx>
36#include <simgear/math/SGMath.hxx>
42 m_sampleInterval(5.0),
53 m_enabled =
fgGetNode(
"/sim/history/enabled",
true);
54 m_sampleInterval =
fgGetDouble(
"/sim/history/sample-interval-sec", 1.0);
55 if (m_sampleInterval <= 0.0) {
56 SG_LOG(SG_FLIGHT, SG_INFO,
"invalid flight-history sample interval:" << m_sampleInterval
57 <<
", defaulting to " << m_sampleInterval);
58 m_sampleInterval = 1.0;
62 m_maxMemoryUseBytes =
fgGetInt(
"/sim/history/max-memory-use-bytes", 1024 * 1024 * 4);
63 m_weightOnWheels = NULL;
65 if (
fgGetBool(
"/sim/history/clear-on-takeoff",
true)) {
66 m_weightOnWheels =
fgGetNode(
"/gear/gear[1]/wow", 0,
true);
67 m_lastWoW = m_weightOnWheels->getBoolValue();
72 m_lastCaptureTime =
globals->get_sim_time_sec();
88 if ((dt == 0.0) || !m_enabled->getBoolValue()) {
92 if (m_weightOnWheels) {
94 if (m_lastWoW && !m_weightOnWheels->getBoolValue()) {
95 SG_LOG(SG_FLIGHT, SG_INFO,
"history: detected main-gear takeoff, clearing history");
101 if (!m_buckets.empty()) {
102 SGVec3d lastCaptureCart(SGVec3d::fromGeod(m_buckets.back()->samples[m_validSampleCount - 1].position));
103 double d2 = distSqr(lastCaptureCart,
globals->get_aircraft_position_cart());
109 double elapsed =
globals->get_sim_time_sec() - m_lastCaptureTime;
110 if (elapsed > m_sampleInterval) {
115void FGFlightHistory::allocateNewBucket()
117 SampleBucket* bucket = NULL;
118 if (!m_buckets.empty() && (currentMemoryUseBytes() > m_maxMemoryUseBytes)) {
119 bucket = m_buckets.front();
120 m_buckets.erase(m_buckets.begin());
122 bucket =
new SampleBucket;
125 m_buckets.push_back(bucket);
126 m_validSampleCount = 0;
129void FGFlightHistory::capture()
137 Sample* sample = m_buckets.back()->samples + m_validSampleCount;
139 sample->simTimeMSec =
static_cast<size_t>(m_lastCaptureTime * 1000.0);
142 double heading, pitch, roll;
144 sample->heading =
static_cast<float>(heading);
145 sample->pitch =
static_cast<float>(pitch);
146 sample->roll =
static_cast<float>(roll);
148 ++m_validSampleCount;
154 if (m_buckets.empty()) {
158 for (
auto bucket : m_buckets) {
159 unsigned int count = (bucket == m_buckets.back() ? m_validSampleCount :
SAMPLE_BUCKET_WIDTH);
162 for (
unsigned int index = 0; index < count; ++index) {
165 if( bucket->samples[index].simTimeMSec <= newerThan )
170 SGGeod g = bucket->samples[index].position;
171 result->path.push_back(g);
172 result->last_seen = bucket->samples[index].simTimeMSec;
188 if (m_buckets.empty()) {
192 result.push_back(m_buckets.front()->samples[0].position);
193 SGVec3d lastOutputCart = SGVec3d::fromGeod(result.back());
194 double minLengthSqr = minEdgeLengthM * minEdgeLengthM;
196 for (
auto bucket : m_buckets) {
197 unsigned int count = (bucket == m_buckets.back() ? m_validSampleCount :
SAMPLE_BUCKET_WIDTH);
200 for (
unsigned int index = 0; index < count; ++index) {
201 SGGeod g = bucket->samples[index].position;
202 SGVec3d cart(SGVec3d::fromGeod(g));
203 if (distSqr(cart, lastOutputCart) > minLengthSqr) {
204 lastOutputCart = cart;
215 for (
auto ptr : m_buckets) {
222size_t FGFlightHistory::currentMemoryUseBytes()
const
224 return sizeof(SampleBucket) * m_buckets.size();
SGSubsystemMgr::Registrant< FGFlightHistory > registrantFGFlightHistory
const unsigned int SAMPLE_BUCKET_WIDTH
std::vector< SGGeod > SGGeodVec
SGSharedPtr< PagedPathForHistory > PagedPathForHistory_ptr
SGGeodVec pathForHistory(double minEdgeLengthM=50.0) const
retrieve the path, collapsing segments shorter than the specified minimum length
void update(double dt) override
virtual ~FGFlightHistory()
PagedPathForHistory_ptr pagedPathForHistory(size_t max_entries, size_t newerThan=0) const
void clear()
clear the history
SGGeod get_aircraft_position() const
void get_aircraft_orientation(double &heading, double &pitch, double &roll)
double get_sim_time_sec() const
int fgGetInt(const char *name, int defaultValue)
Get an int value for a property.
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.