JSBSim Flight Dynamics Model 1.3.0 (09 Apr 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGWaypoint.cpp
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGWaypoint.cpp
4 Author: Jon S. Berndt
5 Date started: 6/2013
6
7 ------------- Copyright (C) 2013 Jon S. Berndt (jon@jsbsim.org) -------------
8
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 2 of the License, or (at your option) any
12 later version.
13
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17 details.
18
19 You should have received a copy of the GNU Lesser General Public License along
20 with this program; if not, write to the Free Software Foundation, Inc., 59
21 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Further information about the GNU Lesser General Public License can also be
24 found on the world wide web at http://www.gnu.org.
25
26FUNCTIONAL DESCRIPTION
27--------------------------------------------------------------------------------
28
29HISTORY
30--------------------------------------------------------------------------------
31
32%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33COMMENTS, REFERENCES, and NOTES
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37INCLUDES
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40#include "FGWaypoint.h"
41#include "input_output/FGXMLElement.h"
42#include "math/FGLocation.h"
43#include "models/FGFCS.h"
44#include "models/FGInertial.h"
45#include "initialization/FGInitialCondition.h"
46#include "input_output/FGLog.h"
47
48using namespace std;
49
50namespace JSBSim {
51
52/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53CLASS IMPLEMENTATION
54%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55
56//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57
58FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element)
59 : FGFCSComponent(fcs, element)
60{
61 if (Type == "WAYPOINT_HEADING") WaypointType = eHeading;
62 else if (Type == "WAYPOINT_DISTANCE") WaypointType = eDistance;
63
64 target_latitude_unit = 1.0;
65 target_longitude_unit = 1.0;
66 source_latitude_unit = 1.0;
67 source_longitude_unit = 1.0;
68 source = fcs->GetExec()->GetIC()->GetPosition();
69
70 auto PropertyManager = fcs->GetPropertyManager();
71
72 if (element->FindElement("target_latitude") ) {
73 target_latitude = std::make_unique<FGPropertyValue>(element->FindElementValue("target_latitude"),
74 PropertyManager, element);
75 if (element->FindElement("target_latitude")->HasAttribute("unit")) {
76 if (element->FindElement("target_latitude")->GetAttributeValue("unit") == "DEG") {
77 target_latitude_unit = 0.017453293;
78 }
79 }
80 } else {
81 XMLLogException err(element);
82 err << "Target latitude is required for waypoint component: " << Name << "\n";
83 throw err;
84 }
85
86 if (element->FindElement("target_longitude") ) {
87 target_longitude = std::make_unique<FGPropertyValue>(element->FindElementValue("target_longitude"),
88 PropertyManager, element);
89 if (element->FindElement("target_longitude")->HasAttribute("unit")) {
90 if (element->FindElement("target_longitude")->GetAttributeValue("unit") == "DEG") {
91 target_longitude_unit = 0.017453293;
92 }
93 }
94 } else {
95 XMLLogException err(element);
96 err << "Target longitude is required for waypoint component: " << Name << "\n";
97 throw err;
98 }
99
100 if (element->FindElement("source_latitude") ) {
101 source_latitude = std::make_unique<FGPropertyValue>(element->FindElementValue("source_latitude"),
102 PropertyManager, element);
103 if (element->FindElement("source_latitude")->HasAttribute("unit")) {
104 if (element->FindElement("source_latitude")->GetAttributeValue("unit") == "DEG") {
105 source_latitude_unit = 0.017453293;
106 }
107 }
108 } else {
109 XMLLogException err(element);
110 err << "Source latitude is required for waypoint component: " << Name << "\n";
111 throw err;
112 }
113
114 if (element->FindElement("source_longitude") ) {
115 source_longitude = std::make_unique<FGPropertyValue>(element->FindElementValue("source_longitude"),
116 PropertyManager, element);
117 if (element->FindElement("source_longitude")->HasAttribute("unit")) {
118 if (element->FindElement("source_longitude")->GetAttributeValue("unit") == "DEG") {
119 source_longitude_unit = 0.017453293;
120 }
121 }
122 } else {
123 XMLLogException err(element);
124 err << "Source longitude is required for waypoint component: " << Name << "\n";
125 throw err;
126 }
127
128 unit = element->GetAttributeValue("unit");
129 if (WaypointType == eHeading) {
130 if (!unit.empty()) {
131 if (unit == "DEG") eUnit = eDeg;
132 else if (unit == "RAD") eUnit = eRad;
133 else {
134 XMLLogException err(element);
135 err << "Unknown unit " << unit << " in HEADING waypoint component, " << "\n";
136 throw err;
137 }
138 } else {
139 eUnit = eRad; // Default is radians if unspecified
140 }
141 } else {
142 if (!unit.empty()) {
143 if (unit == "FT") eUnit = eFeet;
144 else if (unit == "M") eUnit = eMeters;
145 else {
146 XMLLogException err(element);
147 err << "Unknown unit " << unit << " in DISTANCE waypoint component, "
148 << Name << "\n";
149 throw err;
150 }
151 } else {
152 eUnit = eFeet; // Default is feet if unspecified
153 }
154 }
155
156 bind(element, PropertyManager.get());
157 Debug(0);
158}
159
160//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161
162FGWaypoint::~FGWaypoint()
163{
164 Debug(1);
165}
166
167//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168
169bool FGWaypoint::Run(void )
170{
171 double source_latitude_rad = source_latitude->GetValue() * source_latitude_unit;
172 double source_longitude_rad = source_longitude->GetValue() * source_longitude_unit;
173 double target_latitude_rad = target_latitude->GetValue() * target_latitude_unit;
174 double target_longitude_rad = target_longitude->GetValue() * target_longitude_unit;
175 source.SetPositionGeodetic(source_longitude_rad, source_latitude_rad, 0.0);
176
177 if (fabs(target_latitude_rad) > M_PI/2.0) {
178 LogException err;
179 err << "\nTarget latitude in waypoint \"" << Name
180 << "\" must be less than or equal to 90 degrees.\n"
181 << "(is longitude being mistakenly supplied?)\n\n";
182 throw err;
183 }
184
185 if (fabs(source_latitude_rad) > M_PI/2.0) {
186 LogException err;
187 err << "\nSource latitude in waypoint \"" << Name
188 << "\" must be less than or equal to 90 degrees.\n"
189 << "(is longitude being mistakenly supplied?)\n\n";
190 throw err;
191 }
192
193 if (WaypointType == eHeading) { // Calculate Heading
194
195 double heading_to_waypoint_rad = source.GetHeadingTo(target_longitude_rad,
196 target_latitude_rad);
197
198 if (eUnit == eDeg) Output = heading_to_waypoint_rad * radtodeg;
199 else Output = heading_to_waypoint_rad;
200
201 } else { // Calculate Distance
202
203 double wp_distance = source.GetDistanceTo(target_longitude_rad,
204 target_latitude_rad);
205 if (eUnit == eMeters) Output = FeetToMeters(wp_distance);
206 else Output = wp_distance;
207
208 }
209
210 Clip();
211 SetOutput();
212
213 return true;
214}
215
216//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217// The bitmasked value choices are as follows:
218// unset: In this case (the default) JSBSim would only print
219// out the normally expected messages, essentially echoing
220// the config files as they are read. If the environment
221// variable is not set, debug_lvl is set to 1 internally
222// 0: This requests JSBSim not to output any messages
223// whatsoever.
224// 1: This value explicitly requests the normal JSBSim
225// startup messages
226// 2: This value asks for a message to be printed out when
227// a class is instantiated
228// 4: When this value is set, a message is displayed when a
229// FGModel object executes its Run() method
230// 8: When this value is set, various runtime state variables
231// are printed out periodically
232// 16: When set various parameters are sanity checked and
233// a message is printed out when they go out of bounds
234
235void FGWaypoint::Debug(int from)
236{
237 if (debug_lvl <= 0) return;
238
239 if (debug_lvl & 1) { // Standard console startup message output
240 if (from == 0) { // Constructor
241 }
242 }
243 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
244 FGLogging log(LogLevel::DEBUG);
245 if (from == 0) log << "Instantiated: FGWaypoint\n";
246 if (from == 1) log << "Destroyed: FGWaypoint\n";
247 }
248 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
249 }
250 if (debug_lvl & 8 ) { // Runtime state variables
251 }
252 if (debug_lvl & 16) { // Sanity checking
253 }
254 if (debug_lvl & 64) {
255 if (from == 0) { // Constructor
256 }
257 }
258}
259}
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71