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
FGAngles.cpp
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGAngles.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--------------------------------------------------------------------------------
31Created: 6/2013 Jon S. Berndt
32
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34COMMENTS, REFERENCES, and NOTES
35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36
37 The Included Angle to Heading algorithm is used to find the smallest included
38 angle (the angle less than or equal to 180 degrees) to a specified heading
39 from the current heading. The sense of the rotation to get to that angle is
40 also calculated (positive 1 for a clockwise rotation, negative 1 for counter-
41 clockwise).
42
43 The angle to the heading is calculated as follows:
44
45 Given an angle phi:
46
47 V = cos(phi)i + sin(phi)j (this is a unit vector)
48
49 The dot product for two, 2D vectors is written:
50
51 V1*V2 = |V1||V2|cos(phi)
52
53 Since the magnitude of a unit vector is 1, we can write the equation as
54 follows:
55
56 V1*V2 = cos(phi)
57
58 or,
59
60 phi = acos(V1*V2)
61
62 or,
63
64 phi = acos[ cos(phi1)cos(phi2) + sin(phi1)sin(phi2) ]
65
66%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67INCLUDES
68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
69
70#include "FGAngles.h"
71#include "models/FGFCS.h"
72#include "input_output/FGXMLElement.h"
73#include "input_output/FGLog.h"
74
75using namespace std;
76
77namespace JSBSim {
78
79/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80CLASS IMPLEMENTATION
81%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
82
83//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
85FGAngles::FGAngles(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
86{
87 source_angle = 0.0;
88 target_angle = 0.0;
89 source_angle_unit = 1.0;
90 target_angle_unit = 1.0;
91 output_unit = 1.0;
92
93 auto PropertyManager = fcs->GetPropertyManager();
94
95 if (element->FindElement("target_angle") ) {
96 target_angle_pNode = PropertyManager->GetNode(element->FindElementValue("target_angle"));
97 if (element->FindElement("target_angle")->HasAttribute("unit")) {
98 if (element->FindElement("target_angle")->GetAttributeValue("unit") == "DEG") {
99 target_angle_unit = 0.017453293;
100 }
101 }
102 } else {
103 XMLLogException err(element);
104 err << "Target angle is required for Angles component: " << Name << "\n";
105 throw err;
106 }
107
108 if (element->FindElement("source_angle") ) {
109 source_angle_pNode = PropertyManager->GetNode(element->FindElementValue("source_angle"));
110 if (element->FindElement("source_angle")->HasAttribute("unit")) {
111 if (element->FindElement("source_angle")->GetAttributeValue("unit") == "DEG") {
112 source_angle_unit = 0.017453293;
113 }
114 }
115 } else {
116 XMLLogException err(element);
117 err << "Source angle is required for Angles component: " << Name << "\n";
118 throw err;
119 }
120
121 unit = element->GetAttributeValue("unit");
122 if (!unit.empty()) {
123 if (unit == "DEG") output_unit = 180.0/M_PI;
124 else if (unit == "RAD") output_unit = 1.0;
125 else {
126 XMLLogException err(element);
127 err << "Unknown unit " << unit << " in angle component, " << Name << "\n";
128 throw err;
129 }
130 } else {
131 output_unit = 1.0; // Default is radians (1.0) if unspecified
132 }
133
134 bind(element, PropertyManager.get());
135 Debug(0);
136}
137
138//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139
140FGAngles::~FGAngles()
141{
142 Debug(1);
143}
144
145//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146
147bool FGAngles::Run(void )
148{
149 source_angle = source_angle_pNode->getDoubleValue() * source_angle_unit;
150 target_angle = target_angle_pNode->getDoubleValue() * target_angle_unit;
151
152 double x1 = cos(source_angle);
153 double y1 = sin(source_angle);
154 double x2 = cos(target_angle);
155 double y2 = sin(target_angle);
156
157 double x1x2_y1y2 = max(-1.0, min(x1*x2 + y1*y2, 1.0));
158 double angle_to_heading_rad = acos(x1x2_y1y2);
159 double x1y2 = x1*y2;
160 double x2y1 = x2*y1;
161
162 if (x1y2 >= x2y1) Output = angle_to_heading_rad * output_unit;
163 else Output = -angle_to_heading_rad * output_unit;
164
165 Clip();
166 SetOutput();
167
168 return true;
169}
170
171//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172// The bitmasked value choices are as follows:
173// unset: In this case (the default) JSBSim would only print
174// out the normally expected messages, essentially echoing
175// the config files as they are read. If the environment
176// variable is not set, debug_lvl is set to 1 internally
177// 0: This requests JSBSim not to output any messages
178// whatsoever.
179// 1: This value explicitly requests the normal JSBSim
180// startup messages
181// 2: This value asks for a message to be printed out when
182// a class is instantiated
183// 4: When this value is set, a message is displayed when a
184// FGModel object executes its Run() method
185// 8: When this value is set, various runtime state variables
186// are printed out periodically
187// 16: When set various parameters are sanity checked and
188// a message is printed out when they go out of bounds
189
190void FGAngles::Debug(int from)
191{
192 if (debug_lvl <= 0) return;
193
194 if (debug_lvl & 1) { // Standard console startup message output
195 if (from == 0) { // Constructor
196 }
197 }
198 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
199 FGLogging log(LogLevel::DEBUG);
200 if (from == 0) log << "Instantiated: FGAngles\n";
201 if (from == 1) log << "Destroyed: FGAngles\n";
202 }
203 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
204 }
205 if (debug_lvl & 8 ) { // Runtime state variables
206 }
207 if (debug_lvl & 16) { // Sanity checking
208 }
209 if (debug_lvl & 64) {
210 if (from == 0) { // Constructor
211 }
212 }
213}
214}
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71