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"
34 #include "TestUtil.hpp"
36 static GlideSettings glide_settings
;
37 static GlidePolar
glide_polar(fixed(0));
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
,
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
)
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
));
79 if (!positive(v_climb_progress
)) {
81 ok1(result
.validity
== GlideResult::Validity::WIND_EXCESSIVE
);
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)
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
));
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
);
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
)
150 glide_settings
.SetDefaults();
154 glide_polar
.SetMC(fixed(0.1));
157 glide_polar
.SetMC(fixed(1));
160 glide_polar
.SetMC(fixed(4));
163 glide_polar
.SetMC(fixed(10));
166 return exit_status();