Set telnet_hz to 100 to reduce delay when making a recording - this avoids
problem where telnet round-trip time could result in recording being 1-2s
longer than we expected, leading to test failures.
New properies so recordreplay can know extent of current in-memory normal
recording:
sim/replay/record-normal-begin
sim/replay/record-normal-end
This is required since scripts/python/recordreplay.py improved checking of
recording length when replaying.
scripts/python/recordreplay.py
src/Aircraft/replay.cxx
src/Aircraft/replay.hxx
src/Aircraft/replay.*:
If /sim/replay/record-continuous-compression is true, we compress each
frame's data as a separate raw zlib stream.
Requires latest simgear's simgear/io/iostreams/zlibstream.cxx for
decompression with ZLibCompressionFormat::ZLIB_RAW. Haven't figured out how
to extend simgear's code to provide a compressing ostream so for now we
have our own local compression code.
We open popup and set sim/replay/replay-error=true if we fail to read
compressed data.
scripts/python/recordreplay.py:
Added test of compressed continuous recordings.
docs-mini/README-recordings.md:
Added information about compressed format.
Also fixed uneven MP carrier motion.
If /ai/models/carrier[]/ai-latch is true (e.g. by MPCarrier.nas), we
set /position/* and /orientation/* in C++ every frame instead of in
nasal. For external multiplayer carriers the values are copied from
/ai/models/multiplayer[]/*, so the AI carrier follows the corresponding MP
carrier exactly. For this to be useful, multiplayer motion needs be smooth,
e.g. with /sim/time/simple-time/enabled=true.
scripts/python/recordreplay.py
Added --carrier test - checks that multiplayer carrier moves with even
speed.
src/AIModel/AIBase.hxx
Added speed_fps, to be kept up to date and tied to velocities/uBody-fps
when we are a carrier. Previously this was set from Nasal which doesn't
do what is required when all updates happen in C++.
src/AIModel/AICarrier.cxx
src/AIModel/AICarrier.hxx
If is-user-craft is true, we directly update /position/* every frame.
If ai-latch is true, we don't call TurnToLaunch(), TurnToRecover(),
ReturnToBox(), TurnToBase() etc, because our position and orientation is
determined only by multiplayer packets.
src/AIModel/AIMultiplayer.cxx
src/AIModel/AIMultiplayer.hxx
If an mp craft is a carrier, MP packets define velocities/speed-kts but
set ecLinearVel to all-zeros. So we now copy across to ensure that the
extrapolation algorithm has a velocity to work with. Previously the zero
velocity caused very uneven motion.
If ai-latch is true we set AI craft's position+velocities directly from
the equivalent (extrapolated or interpolated) MP position, every frame. We
also set AI craft's orientation. And we copy MP's uBody-fps to AI's
velocities/speed-kts which ensures that friction works between carrier deck
and aircraft undercarriage.
Added logging of raw speeds implied by multiplayer packets, activated by
/sim/log-multiplayer-callsign; used by scripts/python/recordreplay.py's
--carrier test.
src/AIModel/AIShip.cxx
Tie velocities/uBody-fps to new speed_fps member and set speed_fps in
update() along with members that are tied to properties.
Replaced code that calculated new position using heading and speed:
Previously the new position after dt was calculated using
ft_per_deg_lat, ft_per_deg_lon, speed_north_deg_sec and
speed_east_deg_sec. But this was moving slightly faster than the
specified speed.
This was leading to incremental errors when a different Flightgear
instance extrapolated the multiplayer position from the information in
multiplayer packets, because the specified velocity was too small, so
we jumped forwards when extrapolation moved to a new packet.
The fix is to use a Quaternion-based calculation to calculate movement
in the direction specified by (heading, pitch, roll), as done by other
code such as the view code.
src/Main/fg_init.cxx
Moved FGAIManager to just before FGMultiplayMgr so we send latest info in
mp packets.
src/MultiPlayer/multiplaymgr.cxx
Fixed minimum transmit rate calculation - if transmit rate is less than 1,
default to 1, not 10.
src/Network/props.cxx
Use more precision when sending double-precision values e.g. to telnet
client. Otherwise for example UTC times don't have sufficient resolution.
src/Viewer/viewmgr.cxx
Generate internal logs of multiplayer position and speed (after
interpolation/extrapolation) if /sim/log-multiplayer-callsign is set. Used
by scripts/python/recordreplay.py's --carrier test.
FGReplay was using time t, AIMultiplayer was using t+dt. The fix is to make
FGReplay also use t+dt.
scripts/python/recordreplay.py
Make --test-motion-mp test for this problem - we check that user and mp
aircraft are a constant distance apart when replaying.
src/AIModel/AIMultiplayer.cxx
Create properties showing distance moved since start by user and mp
aircraft, which can then be tested by recordreplay.py.
src/Aircraft/replay.cxx
Increment current_time by dt before calling replay(current_time), to
ensure that replay() sees the time as is later used by AIMultiplayer (via
/sim/replay/time).
test_motion() now sets /sim/time/simple-time/enabled=true.
Also show any description items - these are generate by related changes to
src/AIModel/AIMultiplayer.cxx.
This is in addition to mp speed in mp packets. Looks like this final mp speed
is very uneven.
Have changed the test slightly to move both UFOs at the same speed so replaying
e.g. with Helicopter View shows them incorrectly moving relative to each other.
Setting sim/replay/log-raw-speed logs raw speed to
/sim/replay/log-raw-speed-values/value[].
'scripts/python/recordreplay.py --test-motion' uses this to test for a bug
where the user aircraft simtime and signals information don't quite match in
continuous recordings.
Recording of extra properties is only supported in Continuous recordings.
Modified Continuous recording format to allow future forwards
compatibility. See docs-mini/README-recordings.md for details. This breaks
compatibility with previously-generated Continuous recordings, but this only
affects next.
To reduce overhead we record all extra property values in the first frame and
then later frames contain only extra property changes. When replaying, if the
user jumps backwards we replay all extra property changes since the start of
the recording. Similarly if the user jumps forwards, we replay any intervening
extra property changes.
Recording extra properties:
This is enabled by:
/sim/replay/record-extra-properties
The extra properties that are recorded are identified by the property
paths in the values of /sim/replay/record-extra-properties-paths/path[]
properties. We record the entire tree for each specified path.
Recording of main window position size:
We have specific support for record and replay of main window position/size.
This is enabled by:
/sim/replay/record-main-window
Recording of main window view:
We have specific support for recording the view type and direction/zoom
settings.
This is enabled by:
/sim/replay/record-main-view
We record the /sim/current-view/ property tree, excluding some subtrees
that continuously vary but are not required for replaying of the view.
When replaying, we allow separate control of what extra property changes are
replayed, with:
/sim/replay/replay-extra-property-changes
/sim/replay/replay-extra-property-removal
/sim/replay/replay-main-window-position
/sim/replay/replay-main-window-size
/sim/replay/replay-main-view
We work around some problems caused by the use of tied properties when
replaying changes to view-number.
Window position issue:
When replaying window position and size changes, things get a little tricky
because osgViewer::GraphicsWindow::setWindowRectangle() takes a position
for the entire window, but osgGA::GUIEventAdapter::RESIZE events contain
the position of the interior of the window; for example the y values will
differ by the height of the window's titlebar. This can cause windows to
move progressively further down each time they are positioned or resized.
There doesn't seem to be a way of finding the size of a window's
furniture directly. So instead this commit adds a new method
osgGA::GUIEventAdapter::setWindowRectangleInteriorWithCorrection() which
wraps osgViewer::GraphicsWindow::setWindowRectangle(). We listen for the
following osgGA::GUIEventAdapter::RESIZE event and calculate corrections
for x and y position that are used for subsequent calls.
docs-mini/README-recordings.md:
Updated to document new Continuous format.
scripts/python/recordreplay.py:
New script to test various aspects of record/replay.
Other:
We now create convenience softlink to most recent continuous recording, using
SGPath::makeLink(). Note that SGPath::makeLink() currently does nothing on
Windows.
Changed format of Continuous recordings to contain a single property tree
in header. This is much simpler than having separate Config and Meta trees.