TaskManager: remove GetStartState() and GetFinishState()
[xcsoar.git] / test / src / TestMacCready.cpp
blobeeeb4b13e0ce526454c7ce0749f574c98cf8eee2
1 /* Copyright_License {
3 XCSoar Glide Computer - http://www.xcsoar.org/
4 Copyright (C) 2000-2013 The XCSoar Project
5 A detailed list of copyright holders can be found in the file "AUTHORS".
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "Geo/SpeedVector.hpp"
24 #include "Engine/GlideSolvers/GlideSettings.hpp"
25 #include "Engine/GlideSolvers/GlidePolar.hpp"
26 #include "Engine/GlideSolvers/GlideState.hpp"
27 #include "Engine/GlideSolvers/GlideResult.hpp"
28 #include "Engine/GlideSolvers/MacCready.hpp"
30 #ifdef FIXED_MATH
31 #define ACCURACY 1000
32 #endif
34 #include "TestUtil.hpp"
36 static GlideSettings glide_settings;
37 static GlidePolar glide_polar(fixed(0));
39 static void
40 Test(const fixed distance, const fixed altitude, const SpeedVector wind)
42 const GeoVector vector(distance, Angle::Zero());
43 const GlideState state(vector,
44 fixed(2000), fixed(2000) + altitude,
45 wind);
46 const GlideResult result =
47 MacCready::Solve(glide_settings, glide_polar, state);
49 const fixed ld_ground = glide_polar.GetLDOverGround(vector.bearing, wind);
51 const fixed mc = glide_polar.GetMC();
52 const fixed v_climb_progress = mc * ld_ground - state.head_wind;
54 const fixed initial_glide_distance = state.altitude_difference * ld_ground;
55 if (initial_glide_distance >= distance ||
56 (!positive(mc) && !positive(v_climb_progress))) {
57 /* reachable by pure glide */
58 ok1(result.validity == GlideResult::Validity::OK);
60 const fixed best_speed =
61 glide_polar.GetBestGlideRatioSpeed(state.head_wind);
62 const fixed best_sink = glide_polar.SinkRate(best_speed);
63 const fixed ld_ground2 = positive(mc)
64 ? ld_ground
65 : (best_speed - state.head_wind) / best_sink;
67 const fixed height_glide = distance / ld_ground2;
68 const fixed height_climb = fixed(0);
69 const fixed altitude_difference = altitude - height_glide;
71 ok1(equals(result.head_wind, wind.norm));
72 ok1(equals(result.vector.distance, distance));
73 ok1(equals(result.height_climb, height_climb));
74 ok1(equals(result.height_glide, height_glide));
75 ok1(equals(result.altitude_difference, altitude_difference));
76 return;
79 if (!positive(v_climb_progress)) {
80 /* excessive wind */
81 ok1(result.validity == GlideResult::Validity::WIND_EXCESSIVE);
82 return;
86 const fixed drifted_distance = (distance - initial_glide_distance)
87 * state.head_wind / v_climb_progress;
89 const fixed drifted_height_climb = (distance - initial_glide_distance)
90 * mc / v_climb_progress;
91 const fixed drifted_height_glide =
92 drifted_height_climb + state.altitude_difference;
94 const fixed height_glide = drifted_height_glide;
95 const fixed altitude_difference = altitude - height_glide;
96 const fixed height_climb = drifted_height_climb;
98 const fixed time_climb = height_climb / mc;
99 const fixed time_glide = height_glide / glide_polar.GetSBestLD();
100 const fixed time_elapsed = time_climb + time_glide;
102 /* more tolerance with strong wind because this unit test doesn't
103 optimise pure glide */
104 const int accuracy = positive(altitude) && positive(wind.norm)
105 ? (wind.norm > fixed(5) ? 5 : 10)
106 : ACCURACY;
108 ok1(result.validity == GlideResult::Validity::OK);
109 ok1(equals(result.head_wind, wind.norm));
110 ok1(equals(result.vector.distance, distance));
111 ok1(equals(result.height_climb, height_climb, accuracy));
112 ok1(equals(result.height_glide, height_glide, accuracy));
113 ok1(equals(result.altitude_difference, altitude_difference, accuracy));
114 ok1(equals(result.time_elapsed, time_elapsed, accuracy));
117 static void
118 TestWind(const SpeedVector &wind)
120 Test(fixed(10000), fixed(-200), wind);
121 Test(fixed(10000), fixed(-100), wind);
122 Test(fixed(10000), fixed(0), wind);
123 Test(fixed(10000), fixed(100), wind);
124 Test(fixed(10000), fixed(200), wind);
126 Test(fixed(1000), fixed(-500), wind);
127 Test(fixed(1000), fixed(-100), wind);
128 Test(fixed(1000), fixed(0), wind);
129 Test(fixed(1000), fixed(100), wind);
130 Test(fixed(1000), fixed(500), wind);
131 Test(fixed(100000), fixed(-1000), wind);
132 Test(fixed(100000), fixed(4000), wind);
135 static void
136 TestAll()
138 TestWind(SpeedVector(Angle::Zero(), fixed(0)));
139 TestWind(SpeedVector(Angle::Zero(), fixed(2)));
140 TestWind(SpeedVector(Angle::Zero(), fixed(5)));
141 TestWind(SpeedVector(Angle::Zero(), fixed(10)));
142 TestWind(SpeedVector(Angle::Zero(), fixed(15)));
143 TestWind(SpeedVector(Angle::Zero(), fixed(30)));
146 int main(int argc, char **argv)
148 plan_tests(2095);
150 glide_settings.SetDefaults();
152 TestAll();
154 glide_polar.SetMC(fixed(0.1));
155 TestAll();
157 glide_polar.SetMC(fixed(1));
158 TestAll();
160 glide_polar.SetMC(fixed(4));
161 TestAll();
163 glide_polar.SetMC(fixed(10));
164 TestAll();
166 return exit_status();