Skip to content

Commit

Permalink
Emit proper timestamp when date & time have changed (duration > 1 day)
Browse files Browse the repository at this point in the history
- Update example SQL scripts
- Update minimum / maximum date & times
- More use of "auto"
- Increase maximum replay speed factor to 99999 ("one second per day
timelapses")
  • Loading branch information
till213 committed Jul 10, 2024
1 parent dcc534d commit 5f445a0
Show file tree
Hide file tree
Showing 16 changed files with 109 additions and 95 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
- The maximum simulation rate spinbox now steps in powers of two (1, 2, 4, 8, ..., 128)
* The MSFS simulation rate is always a power of two
* Non-power of two values may still be entered by editing the text
- The maximum custom replay speed factor has been increased from 200 to 99999
* This allows for "timelapse replays" with one second per day (factor of 24 * 60 * 60 = 86400)
- The recording sample rate setting has been removed. Reasoning:
* The aircraft position is now sampled at a fixed 1 Hz (one sample per second) anyway (see above)
* While the aircraft attitude is sampled "as fast as possible" (for each *simulated frame*)...
Expand All @@ -35,11 +37,19 @@
- GPX export: the geoid height (<geoidheight>) can now also optionally be exported
* This may be useful to calculate the ellipsoidial height *h* ([WGS84 reference ellipsoid](https://en.wikipedia.org/wiki/World_Geodetic_System#WGS_84)) as follows: h = H + N = <ele> + <geoidheight>
* Also refer to [Find Ellipsoidal Height from Orthometric Height](https://www.mathworks.com/help/map/ellipsoid-geoid-and-orthometric-height.html)
- The simulation time is now updated in the flight simulator during replay
* According to the recorded simulation start and end times
* Note that the simulation time is not always in sync with real-world time: this is taken into account when interpolating between the simulation start- and end times
* This allows for exact day of time reproductions, useful e.g. for video editing when video-recording (via separate screen capture solutions) the same flight multiple times from different camera angles
- The replay time widget now properly displays replay times longer than a day (for instance one year or longer), by including also the actual start date

## Bug Fixes
- GPX export
* The elevation (<ele>) values are now properly exported as "above mean sea level" (and not "above WGS84 reference ellipsoid" anymore)
* The trackpoint timestamps are properly calculated and exported when exporting the entire flight (and not just the user aircraft); the proper timezone suffix (Z) is appended, too (ISO 8601 format)

## Under the Hood
- Added new [One Year in New York](doc/SQL/Timelapse-One-Year-in-New-York.sql) example SQL ("1 year timelapse")

## 0.17.5
This bug fix release provides an important correction for a regression that would prevent recording (and possibly replay as well), due to wrongly creating an IPv4 network connection instead of a local ("pipe") connection.
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ target_sources(${APP_PROJECT_NAME}
doc/SkyDolly.simvars
doc/LICENSE
doc/SQL/Timelapse-Camera-Pan.sql
doc/SQL/Timelapse-Full-Year.sql
doc/SQL/Timelapse-One-Year-in-New-York.sql
doc/SQL/Flight-Analysis.sql
)

Expand Down
15 changes: 6 additions & 9 deletions doc/SQL/Timelapse-Camera-Pan.sql
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
insert into flight (title, user_aircraft_seq_nr)
values ('LSZH Camera Pan', 1);
-- LSZH Camera Pan
-- ===============

select max(id) from flight;

select * from aircraft_type
order by type;
-- Add a flight with an end date "today + 32 minutes"
insert into flight (title, user_aircraft_seq_nr, end_local_sim_time, end_zulu_sim_time)
values ('LSZH Camera Pan', 1, datetime('now', 'localtime', '+32 minutes'), datetime('now', '+32 minutes'));

-- Add an example aircraft (Asobo XCub)
insert into aircraft (flight_id, seq_nr, type)
values ((select max(id) from flight), 1, 'Asobo XCub');

select * from aircraft
order by id desc;

-- Pan from 47.450681, 8.549628 at 1417.0 + 150 feet altitude (about 50 metres above ground)...
insert into position (aircraft_id, timestamp, latitude, longitude, altitude)
values ((select max(id) from aircraft), 0, 47.450681, 8.549628, 1417.0 + 150);
Expand Down
29 changes: 0 additions & 29 deletions doc/SQL/Timelapse-Full-Year.sql

This file was deleted.

26 changes: 26 additions & 0 deletions doc/SQL/Timelapse-One-Year-in-New-York.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- New York Camera Pan
-- ===================

-- Add a flight with an end date "today + 1 year"
insert into flight (title, user_aircraft_seq_nr, end_local_sim_time, end_zulu_sim_time)
values ('One Year in New York', 1, datetime('now', 'localtime', '+1 year'), datetime('now', '+1 year'));

-- Add an example aircraft (Asobo XCub)
insert into aircraft (flight_id, seq_nr, type)
values ((select max(id) from flight), 1, 'Asobo XCub');

-- Pan from 40.728603, -73.995477 at 1243.55 feet altitude...
insert into position (aircraft_id, timestamp, latitude, longitude, altitude)
values ((select max(id) from aircraft), 0, 40.728603, -73.995477, 1243.55);
-- Attitude: heading 10
insert into attitude (aircraft_id, timestamp, pitch, bank, true_heading, on_ground)
values ((select max(id) from aircraft), 0, 0, 0, 10, 0);

-- ... to 40.746672, -73.986111, within 365 * 24 * 60 * 60 * 1000 [ms] = 1 year
insert into position (aircraft_id, timestamp, latitude, longitude, altitude)
values ((select max(id) from aircraft), 365 * 24 * 60 * 60 * 1000, 40.746672, -73.986111, 1243.55);
-- Attitude: heading 21.5
insert into attitude (aircraft_id, timestamp, pitch, bank, true_heading, on_ground)
values ((select max(id) from aircraft), 365 * 24 * 60 * 60 * 1000, 0, 0, 21.5, 0);

commit;
10 changes: 0 additions & 10 deletions src/PluginManager/include/PluginManager/Connect/SkyConnectIntf.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,16 +354,6 @@ public slots:
*/
void timestampChanged(std::int64_t timestamp, TimeVariableData::Access access);

/*!
* Emitted whenever the simulation time during replay has changed.
*
* \param zuluDateTime
* the simulation zulu date and time
* \param localDateTime
* the simulation local date and time
*/
void simulationTimeChaged(QDateTime zuluDateTime, QDateTime localDateTime);

/*!
* Emitted whenver the connection state has changed.
*
Expand Down
10 changes: 2 additions & 8 deletions src/PluginManager/src/Connect/AbstractSkyConnect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,12 +925,10 @@ bool AbstractSkyConnect::updateSimulationTime() noexcept
const auto realWorldDuation = d->currentFlight.getTotalDurationMSec();
if (realWorldDuation > 0) {
auto startZuluDateTime = d->currentFlight.getFlightCondition().startZuluDateTime;
auto startLocalDateTime = d->currentFlight.getFlightCondition().startLocalDateTime;
if (!(startZuluDateTime.isValid() && startLocalDateTime.isValid())) {
if (!(startZuluDateTime.isValid())) {
// If - for whatever reasons - the flight conditions have not been recorded, fall back
// to the current real-world date and time
startZuluDateTime = QDateTime::currentDateTimeUtc();
startLocalDateTime = QDateTime::currentDateTime();
hasSimulationTime = false;
}
const auto endZuluDateTime = hasSimulationTime ? d->currentFlight.getFlightCondition().endZuluDateTime : startZuluDateTime.addMSecs(realWorldDuation);
Expand All @@ -939,17 +937,13 @@ bool AbstractSkyConnect::updateSimulationTime() noexcept

const auto simulationTime = static_cast<std::int64_t>(std::round(static_cast<double>(d->currentTimestamp) * factor));
const auto currentZuluDateTime = startZuluDateTime.addMSecs(simulationTime);
const auto currentLocalDateTime = startLocalDateTime.addMSecs(simulationTime);

emit simulationTimeChaged(currentZuluDateTime, currentLocalDateTime);
if (sender() == nullptr) {
// Update due to some "seek" operation -> reset timer
d->simulationTimeUpdateTimer.start();
#ifdef DEBUG
} else {
qDebug() << "AbstractSkyConnect::updateSimulationTime: periodic simulation date and time sync: zulu:"
<< currentZuluDateTime.toString() << "local:"
<< currentLocalDateTime.toString();
qDebug() << "AbstractSkyConnect::updateSimulationTime: periodic simulation date and time sync: zulu:" << currentZuluDateTime.toString();
#endif
}
return sendZuluDateTime(currentZuluDateTime);
Expand Down
4 changes: 2 additions & 2 deletions src/Plugins/Connect/PathCreator/src/PathCreatorPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ void PathCreatorPlugin::closeConnection() noexcept

void PathCreatorPlugin::replay() noexcept
{
const std::int64_t timestamp = updateCurrentTimestamp();
const auto timestamp = updateCurrentTimestamp();
if (!sendAircraftData(timestamp, TimeVariableData::Access::Linear, AircraftSelection::All)) {
onEndReached();
}
Expand All @@ -598,7 +598,7 @@ void PathCreatorPlugin::recordData() noexcept
resetElapsedTime(true);
}

const std::int64_t timestamp = updateCurrentTimestamp();
const auto timestamp = updateCurrentTimestamp();
recordPositionData(timestamp);
recordEngineData(timestamp);
recordPrimaryControls(timestamp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ bool FlightRecorderCsvParser::parseRow(const CsvParser::Row &row, FlightData &fl
PositionData positionData;
AttitudeData attitudeData;
bool ok {true};
const std::int64_t timestamp = row.at(d->headers.at(Header::Milliseconds)).toLongLong(&ok) - d->timestampDelta;
const auto timestamp = row.at(d->headers.at(Header::Milliseconds)).toLongLong(&ok) - d->timestampDelta;
if (ok) {
positionData.timestamp = timestamp;
positionData.latitude = row.at(d->headers.at(Header::Latitude)).toDouble(&ok);
Expand Down
2 changes: 1 addition & 1 deletion src/Plugins/Flight/Import/IgcImport/src/IgcParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ bool IgcParser::parseFix(const QByteArray &line) noexcept

if (d->currentDateTimeUtc.isValid()) {

const std::int64_t timestamp = d->header.flightDateTimeUtc.msecsTo(d->currentDateTimeUtc);
const auto timestamp = d->header.flightDateTimeUtc.msecsTo(d->currentDateTimeUtc);

// Latitude
const auto latitudeText = match.capturedView(::BRecordLatitudeDegreesIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void AbstractKmlTrackParser::parseTrack(FlightData &flightData) noexcept
currentDateTimeUtc = QDateTime::fromString(dateTimeText, Qt::ISODate);
}
if (currentDateTimeUtc.isValid()) {
const std::int64_t timestamp = d->firstDateTimeUtc.msecsTo(currentDateTimeUtc);
const auto timestamp = d->firstDateTimeUtc.msecsTo(currentDateTimeUtc);
TrackItem trackItem = std::make_tuple(timestamp, 0.0, 0.0, 0.0);
trackData.push_back(std::move(trackItem));
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/Plugins/Module/Formation/src/FormationPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void FormationPlugin::onStartReplay() noexcept
const Formation::HorizontalDistance horizontalDistance {d->formationWidget->getHorizontalDistance()};
const Formation::VerticalDistance verticalDistance {d->formationWidget->getVerticalDistance()};
const Formation::Bearing relativePosition {d->formationWidget->getRelativePosition()};
const std::int64_t timestamp = fromStart ? 0 : skyConnectManager.getCurrentTimestamp();
const auto timestamp = fromStart ? 0 : skyConnectManager.getCurrentTimestamp();
const InitialPosition initialPosition = d->moduleSettings.isRelativePositionPlacementEnabled() ?
Formation::calculateInitialRelativePositionToUserAircraft(horizontalDistance, verticalDistance, relativePosition, timestamp) :
InitialPosition();
Expand Down
1 change: 1 addition & 0 deletions src/Plugins/Module/Logbook/src/LogbookWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ inline void LogbookWidget::updateRow(const FlightSummary &summary, int row) noex

// Duration
const std::int64_t durationMSec = summary.startSimulationLocalTime.msecsTo(summary.endSimulationLocalTime);
// TODO FIXME Take durations longer than a day into account!
const auto time = QTime::fromMSecsSinceStartOfDay(static_cast<int>(durationMSec));
item = ui->logTableWidget->item(row, LogbookWidgetPrivate::durationColumn);
item->setData(Qt::DisplayRole, d->unit.formatDuration(time));
Expand Down
13 changes: 7 additions & 6 deletions src/UserInterface/src/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ namespace
constexpr int PositionSliderMin {0};
constexpr int PositionSliderMax {1000};
constexpr double ReplaySpeedAbsoluteMin {0.01};
// A replay speed with factor 200 should be fast enough
constexpr double ReplaySpeedAbsoluteMax {200.0};
// A replay speed with factor 99999 should be fast enough (one day has 86400 seconds: this allows
// for a speed-up of one second per day)
constexpr double ReplaySpeedAbsoluteMax {99999.0};
constexpr double ReplaySpeedDecimalPlaces {2};

constexpr int CustomSpeedLineEditMinimumWidth {40};
Expand Down Expand Up @@ -613,7 +614,7 @@ void MainWindow::initModuleSelectorUi() noexcept
auto actionCheckBox = new ActionCheckBox(false, this);
actionCheckBox->setAction(ui->showModulesAction);
actionCheckBox->setFocusPolicy(Qt::NoFocus);
const QString css =
const QString css =
"QCheckBox::indicator:unchecked {"
" image: url(:/img/icons/checkbox-expand-normal.png);"
"}"
Expand Down Expand Up @@ -923,7 +924,7 @@ void MainWindow::updateMinimalUi(bool enable)
ui->moduleVisibilityWidget->setHidden(true);
ui->moduleSelectorWidget->setHidden(true);
ui->showModulesAction->setChecked(false);
ui->showModulesAction->setEnabled(false);
ui->showModulesAction->setEnabled(false);
} else {
const bool moduleSelectorVisible = settings.isModuleSelectorVisible();
ui->moduleVisibilityWidget->setVisible(true);
Expand Down Expand Up @@ -981,7 +982,7 @@ void MainWindow::updateReplaySpeedUi() noexcept
void MainWindow::updateRecordingDuration(std::int64_t timestamp) noexcept
{
ui->timestampEdit->blockSignals(true);
ui->timestampEdit->setMaximumTimestamp(timestamp);
ui->timestampEdit->setEndTimestamp(timestamp);
ui->timestampEdit->setTimestamp(timestamp);
ui->timestampEdit->blockSignals(false);
}
Expand Down Expand Up @@ -1548,7 +1549,7 @@ void MainWindow::updateRecordingDuration() noexcept
const auto &flight = Logbook::getInstance().getCurrentFlight();
const std::int64_t totalDuration = flight.getTotalDurationMSec();
ui->timestampEdit->blockSignals(true);
ui->timestampEdit->setMaximumTimestamp(totalDuration);
ui->timestampEdit->setEndTimestamp(totalDuration);
ui->timestampEdit->blockSignals(false);
}

Expand Down
23 changes: 12 additions & 11 deletions src/Widget/include/Widget/TimestampEdit.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,27 @@ class WIDGET_API TimestampEdit : public QWidget
std::int64_t getTimestamp() const noexcept;

/*!
* Sets the current timestamp.
* Sets the current timestamp to \p timestamp.
*
* \param time
* \param timestamp
* the current timestamp [msec]
*/
void setTimestamp(std::int64_t time) noexcept;
void setTimestamp(std::int64_t timestamp) noexcept;

/*!
* Returns the maximum recorded timestamp.
* Returns the end (maximum recorded) timestamp.
*
* \return the maximum recorded timestamp [msec|
* \return the end timestamp [msec|
*/
std::int64_t getMaximumTimestamp() const noexcept;
std::int64_t getEndTimestamp() const noexcept;

/*!
* Sets the maximum recorded timestamp.
* Sets the end (maximum recorded) timestamp to \p endTimestamp.
*
* \param maximum
* the maximum recorded timestamp [msec]
* \param end
* the end timestamp [msec]
*/
void setMaximumTimestamp(std::int64_t maximum) noexcept;
void setEndTimestamp(std::int64_t endTimestamp) noexcept;

/*!
* Returns whether the minimal user interface is enabled.
Expand Down Expand Up @@ -121,7 +121,8 @@ class WIDGET_API TimestampEdit : public QWidget

void initUi() noexcept;
void frenchConnection() noexcept;
QDateTime convertTimestampToDateTime(std::int64_t timestamp);
void updateTimestamp() noexcept;
inline QDateTime getStartDateTime() const noexcept;

private slots:
void updateUi() noexcept;
Expand Down
Loading

0 comments on commit 5f445a0

Please sign in to comment.