Re-creating the route-path every update is wasteful, just cache it
until the roue changes. Since we already have similar logic for
the property-tree waypoint mirror, just piggy-back off that.
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.
Try to catch NaN SGGeod position before we pass them to the intersect
visitor, so we don’t fill the console/logs with error messages: we
catch NaNs in other places.