FlightGear next
AIWakeGroup.cxx
Go to the documentation of this file.
1// AIWakeGroup.hxx -- Group of AI wake meshes for the computation of the induced
2// wake.
3//
4// Written by Bertrand Coconnier, started April 2017.
5//
6// Copyright (C) 2017 Bertrand Coconnier - bcoconni@users.sf.net
7//
8// This program is free software; you can redistribute it and/or modify it under
9// the terms of the GNU General Public License as published by the Free Software
10// Foundation; either version 2 of the License, or (at your option) any later
11// version.
12//
13// This program is distributed in the hope that it will be useful, but WITHOUT
14// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16// details.
17//
18// You should have received a copy of the GNU General Public License along with
19// this program; if not, write to the Free Software Foundation, Inc., 51
20// Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21//
22// $Id$
23
24#include <cmath>
25#include <vector>
26#include <simgear/structure/SGSharedPtr.hxx>
27#include <simgear/math/SGVec3.hxx>
28#include <simgear/math/SGGeod.hxx>
29#include <simgear/math/SGGeoc.hxx>
30#include <simgear/math/SGQuat.hxx>
31#include "Main/globals.hxx"
35
37{
38 SGPropertyNode* _props = globals->get_props();
39 _density_slugft = _props->getNode("environment/density-slugft3", true);
40}
41
43{
44 int id = ai->getID();
45 PerformanceData* perfData = ai->getPerformance();
46
47 if (_aiWakeData.find(id) == _aiWakeData.end()) {
48 double span = perfData->wingSpan();
49 double chord = perfData->wingChord();
50 _aiWakeData[id] = AIWakeData(new WakeMesh(span, chord,
51 std::string("AI:") + ai->_getName()));
52
53 SG_LOG(SG_FLIGHT, SG_DEV_ALERT,
54 "Created mesh for " << ai->_getName() << " ID: #" << id);
55 }
56
57 AIWakeData& data = _aiWakeData[id];
58 data.visited = true;
59
60 data.position = ai->getCartPos() * SG_METER_TO_FEET;
61 SGGeoc geoc = SGGeoc::fromCart(data.position);
62 SGQuatd Te2l = SGQuatd::fromLonLatRad(geoc.getLongitudeRad(),
63 geoc.getLatitudeRad());
64 data.Te2b = Te2l * SGQuatd::fromYawPitchRollDeg(ai->_getHeading(),
65 ai->getPitch(), 0.0);
66
67 double hVel = ai->getSpeed()*SG_KT_TO_FPS;
68 double vVel = ai->getVerticalSpeedFPM()/60;
69 double gamma = atan2(vVel, hVel);
70 double vel = sqrt(hVel*hVel + vVel*vVel);
71 double weight = perfData->weight();
72 _aiWakeData[id].mesh->computeAoA(vel, _density_slugft->getDoubleValue(),
73 weight*cos(gamma));
74}
75
76SGVec3d AIWakeGroup::getInducedVelocityAt(const SGVec3d& pt) const
77{
78 SGVec3d vi(0.,0.,0.);
79 for (auto item : _aiWakeData) {
80 AIWakeData& data = item.second;
81 if (!data.visited) continue;
82
83 SGVec3d at = data.Te2b.transform(pt - data.position);
84 vi += data.Te2b.backTransform(data.mesh->getInducedVelocityAt(at));
85 }
86 return vi;
87}
88
90{
91 for (auto it=_aiWakeData.begin(); it != _aiWakeData.end(); ++it) {
92 if (!(*it).second.visited) {
93 SG_LOG(SG_FLIGHT, SG_DEV_ALERT, "Deleted mesh for aircraft #"
94 << (*it).first);
95 _aiWakeData.erase(it);
96 break; // erase has invalidated the iterator, other dead meshes (if
97 // any) will be erased at the next time steps.
98 }
99 }
100
101 for (auto &item : _aiWakeData) item.second.visited = false;
102}
AIWakeGroup(void)
void gc(void)
void AddAI(FGAIAircraft *ai)
SGVec3d getInducedVelocityAt(const SGVec3d &pt) const
double getVerticalSpeedFPM() const
PerformanceData * getPerformance()
double getSpeed() const
double getPitch() const
SGVec3d getCartPos() const
Definition AIBase.cxx:899
int getID() const
Definition AIBase.cxx:1092
double _getHeading() const
Definition AIBase.cxx:1112
const char * _getName() const
Definition AIBase.cxx:1136
Data storage for aircraft performance data.
double weight() const
double wingSpan() const
double wingChord() const
FGGlobals * globals
Definition globals.cxx:142