From 7753ce229d17eb4493ec627f91e22209dc64f960 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Sun, 18 Apr 2021 10:45:23 +0100 Subject: [PATCH] Fixed uneven replay of user vs multiplayer aircraft. 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). --- scripts/python/recordreplay.py | 58 ++++++++++++++++++++++++++++++++++ src/AIModel/AIMultiplayer.cxx | 46 ++++++++++++++++++++------- src/Aircraft/replay.cxx | 4 ++- 3 files changed, 96 insertions(+), 12 deletions(-) diff --git a/scripts/python/recordreplay.py b/scripts/python/recordreplay.py index 95e22c4e4..833280e00 100755 --- a/scripts/python/recordreplay.py +++ b/scripts/python/recordreplay.py @@ -492,10 +492,68 @@ def test_motion(fgfs, multiplayer=False): log( f'*** Replay showed uneven speed') errors.append('1') + def show_values(paths): + if isinstance(paths, str): + paths = paths, + log(f'Values in {paths}:') + line2values = dict() + for i, path in enumerate(paths): + line = 0 + for item in fg.fg.ls(path): + if item.name == 'value': + line2values.setdefault(line, []).append(item.value) + line += 1 + for line in sorted(line2values.keys()): + t = '' + for value in line2values[line]: + t += f' {value}' + log(f' {t}') + if multiplayer: examine_values() examine_values('-multiplayer') examine_values('-multiplayer-post') + + if 0: + show_values('/sim/replay/log-raw-speed-multiplayer-post-relative-distance') + show_values('/sim/replay/log-raw-speed-multiplayer-post-relative-bearing') + show_values('/sim/replay/log-raw-speed-multiplayer-post-absolute-distance') + show_values('/sim/replay/log-raw-speed-multiplayer-post-user-absolute-distance') + + def get_values(path): + ''' + Returns /value[] as a list. + ''' + ret = [] + for item in fg.fg.ls(path): + if item.name == 'value': + ret.append(item.value) + return ret + + # Check that distance between user and mp is constant. + # + # The two paths below contain values[] that are the distances of the + # mp and user aircraft from their starting points. Both are moving at + # the same speed in the same direction, so the differences between each + # pair of values should be constant. + # + distances_mp = get_values('/sim/replay/log-raw-speed-multiplayer-post-absolute-distance') + distances_user = get_values('/sim/replay/log-raw-speed-multiplayer-post-user-absolute-distance') + log(f'len(distances_user)={len(distances_user)} len(distances_mp)={len(distances_mp)}') + assert len(distances_user) == len(distances_mp) + assert len(distances_user) > 20 + for i in range(len(distances_user)): + distance_mp = distances_mp[i] + distance_user = distances_user[i] + delta = distance_mp - distance_user + if i == 0: + delta_original = delta + prefix = ' ' + if abs(delta - delta_original) > 0.01: + #log('replay shows varying differences between user and mp aircraft') + errors.append('1') + prefix = '*' + log(f' {prefix} user={distance_user} mp={distance_mp} delta={delta}') else: examine_values() diff --git a/src/AIModel/AIMultiplayer.cxx b/src/AIModel/AIMultiplayer.cxx index 4066df05e..5ad3074c8 100644 --- a/src/AIModel/AIMultiplayer.cxx +++ b/src/AIModel/AIMultiplayer.cxx @@ -286,6 +286,7 @@ void FGAIMultiplayer::update(double dt) if (m_sim_replay_replay_state->getBoolValue()) { tInterp = m_sim_replay_time->getDoubleValue(); + SG_LOG(SG_GENERAL, SG_BULK, "tInterp=" << std::fixed << std::setprecision(6) << tInterp); } else { @@ -660,7 +661,7 @@ void FGAIMultiplayer::update(double dt) // For use with scripts/python/recordreplay.py --test-motion-mp. { SGGeod pos_geod = pos; - if (test_motion) + if (test_motion && !fgGetBool("/sim/replay/replay-state-eof")) { static SGVec3d s_pos_0; static SGVec3d s_pos_prev; @@ -695,17 +696,39 @@ void FGAIMultiplayer::update(double dt) n->setStringValue(buffer); } + SGGeod user_pos_geod = SGGeod::fromDegFt( + fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg"), + fgGetDouble("/position/altitude-ft") + ); + SGVec3d user_pos = SGVec3d::fromGeod(user_pos_geod); + + double user_to_mp_distance = SGGeodesy::distanceM(user_pos_geod, pos_geod); + double user_to_mp_bearing = SGGeodesy::courseDeg(user_pos_geod, pos_geod); + double user_distance0 = length(user_pos - s_pos_0); + + if (1) + { + fgGetNode("/sim/replay/log-raw-speed-multiplayer-post-relative-distance", true /*create*/) + ->addChild("value") + ->setDoubleValue(user_to_mp_distance) + ; + fgGetNode("/sim/replay/log-raw-speed-multiplayer-post-relative-bearing", true /*create*/) + ->addChild("value") + ->setDoubleValue(user_to_mp_bearing) + ; + fgGetNode("/sim/replay/log-raw-speed-multiplayer-post-absolute-distance", true /*create*/) + ->addChild("value") + ->setDoubleValue(distance0) + ; + fgGetNode("/sim/replay/log-raw-speed-multiplayer-post-user-absolute-distance", true /*create*/) + ->addChild("value") + ->setDoubleValue(user_distance0) + ; + } + if (verbose) { - SGGeod user_pos_geod = SGGeod::fromDegFt( - fgGetDouble("/position/longitude-deg"), - fgGetDouble("/position/latitude-deg"), - fgGetDouble("/position/altitude-ft") - ); - - double user_to_mp_bearing = SGGeodesy::courseDeg(user_pos_geod, pos_geod); - double user_to_mp_distance = SGGeodesy::distanceM(user_pos_geod, pos_geod); - int width=16; SG_LOG(SG_GENERAL, SG_ALERT, "Multiplayer-post aircraft callsign=" << _callsign << ":" << std::setprecision(5) @@ -721,7 +744,8 @@ void FGAIMultiplayer::update(double dt) << " t_dt=" << std::setw(width) << t_dt << " dt=" << std::setw(width) << dt << " distance0=" << std::setw(width) << distance0 - << " distance=" << std::setw(width) << distance + << " user_distance0=" << std::setw(width) << user_distance0 + << " speed=" << std::setw(width) << speed << " speed=" << std::setw(width) << speed << " delta_pos_norm=" << std::setw(width) << delta_pos_norm << " calc_type=" << std::setw(width) << calc_type diff --git a/src/Aircraft/replay.cxx b/src/Aircraft/replay.cxx index 51980bb8b..bfa306cf8 100644 --- a/src/Aircraft/replay.cxx +++ b/src/Aircraft/replay.cxx @@ -1009,6 +1009,9 @@ FGReplay::update( double dt ) m_MultiplayMgr->ClearMotion(); } + current_time += dt; + SG_LOG(SG_GENERAL, SG_BULK, "current_time=" << std::fixed << std::setprecision(6) << current_time); + bool IsFinished = replay( current_time ); if (IsFinished) { @@ -1022,7 +1025,6 @@ FGReplay::update( double dt ) } else { - current_time += dt; was_finished_already = false; } replay_time->setDoubleValue(current_time);