FlightGear next
autopilotgroup.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: autopilotgroup.cxx
3 * SPDX-FileComment: an even more flexible, generic way to build autopilots
4 * SPDX-FileCopyrightText: Copyright (C) 2010 Torsten Dreyer - Torsten (at) t3r (dot) de
5 * SPDX-FileContributor: Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#ifdef HAVE_CONFIG_H
10# include <config.h>
11#endif
12
13#include "autopilot.hxx"
14#include "autopilotgroup.hxx"
15
16#include <string>
17#include <vector>
18
19#include <simgear/debug/ErrorReportingCallback.hxx>
20#include <simgear/props/props_io.hxx>
21#include <simgear/structure/exception.hxx>
22#include <simgear/structure/subsystem_mgr.hxx>
23
24#include <Main/fg_props.hxx>
26
27using std::vector;
28using simgear::PropertyList;
30
32{
33public:
34 FGXMLAutopilotGroupImplementation(const std::string& nodeName):
36 _nodeName(nodeName)
37 {}
38
39 // Subsystem API.
40 void init() override;
41 InitStatus incrementalInit() override;
42 void reinit() override;
43
44 // Subsystem identification.
45 static const char* staticSubsystemClassId() { return "xml-autopilot-group"; }
46
47 virtual void addAutopilot( const std::string& name,
48 SGPropertyNode_ptr apNode,
49 SGPropertyNode_ptr config );
50 virtual void removeAutopilot( const std::string & name );
51
52private:
53 void initFrom( SGPropertyNode_ptr rootNode, const char * childName );
54 std::string _nodeName;
55};
56
57//------------------------------------------------------------------------------
59 SGPropertyNode_ptr apNode,
60 SGPropertyNode_ptr config )
61{
62 if( has_subsystem(name) )
63 {
64 SG_LOG( SG_AUTOPILOT,
65 SG_ALERT,
66 "NOT adding duplicate " << _nodeName << " name '" << name << "'");
67 return;
68 }
69
70 Autopilot* ap = new Autopilot(apNode, config);
71 ap->set_name( name );
72
73 double updateInterval = config->getDoubleValue("update-interval-secs", 0.0);
74 set_subsystem( name, ap, updateInterval );
75}
76
77//------------------------------------------------------------------------------
79{
80 Autopilot* ap = static_cast<Autopilot*>(get_subsystem(name));
81 if( !ap )
82 {
83 SG_LOG( SG_AUTOPILOT,
84 SG_ALERT,
85 "CAN NOT remove unknown " << _nodeName << " '" << name << "'");
86 return;
87 }
88
89 remove_subsystem(name);
90}
91
92//------------------------------------------------------------------------------
94{
95 SGSubsystemGroup::unbind();
96 clearSubsystems();
97
98 // ensure we bind again, so the SGSubsystemGroup state is correct before
99 // we call init. Since there's no actual group members at this point (we
100 // cleared them just above) this is purely to ensure SGSubsystemGroup::_state
101 // is BIND, so that ::init doesn't assert
102 SGSubsystemGroup::bind();
103 init();
104}
105
106//------------------------------------------------------------------------------
108{
109 init();
110 return INIT_DONE;
111}
112
113//------------------------------------------------------------------------------
115{
116 initFrom(fgGetNode("/sim/systems"), _nodeName.c_str());
117 SGSubsystemGroup::init();
118}
119
120//------------------------------------------------------------------------------
121void FGXMLAutopilotGroupImplementation::initFrom( SGPropertyNode_ptr rootNode,
122 const char* childName )
123{
124 if( !rootNode )
125 return;
126
127 for( auto autopilotNode : rootNode->getChildren(childName) )
128 {
129 SGPropertyNode_ptr pathNode = autopilotNode->getNode("path");
130 if( !pathNode )
131 {
132 SG_LOG
133 (
134 SG_AUTOPILOT,
135 SG_WARN,
136 "No configuration file specified for this " << childName << "!"
137 );
138 continue;
139 }
140
141 std::string apName;
142 SGPropertyNode_ptr nameNode = autopilotNode->getNode( "name" );
143 if( nameNode != NULL ) {
144 apName = nameNode->getStringValue();
145 } else {
146 std::ostringstream buf;
147 buf << "unnamed_autopilot_" << autopilotNode->getIndex();
148 apName = buf.str();
149 }
150
151 {
152 // check for duplicate names
153 std::string name = apName;
154 for( unsigned i = 0; get_subsystem( apName.c_str() ) != NULL; i++ ) {
155 std::ostringstream buf;
156 buf << name << "_" << i;
157 apName = buf.str();
158 }
159 if( apName != name )
160 SG_LOG
161 (
162 SG_AUTOPILOT,
163 SG_DEV_WARN,
164 "Duplicate " << childName << " configuration name " << name
165 << ", renamed to " << apName
166 );
167 }
168
169 addAutopilotFromFile(apName, autopilotNode, pathNode->getStringValue());
170 }
171}
172
174 SGPropertyNode_ptr apNode,
175 const std::string& path )
176{
177 SGPath config = globals->resolve_maybe_aircraft_path(path);
178 if( config.isNull() )
179 {
180 simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::AircraftSystems,
181 std::string{"Autopilot XML not found:"} + path, sg_location{path});
182 SG_LOG(
183 SG_AUTOPILOT,
184 SG_ALERT,
185 "Cannot find property-rule configuration file '" << path << "'.");
186 return;
187 }
188 SG_LOG
189 (
190 SG_AUTOPILOT,
191 SG_INFO,
192 "Reading property-rule configuration from " << config
193 );
194
195 try
196 {
197 SGPropertyNode_ptr configNode = new SGPropertyNode();
198 readProperties(config, configNode);
199
200 SG_LOG(SG_AUTOPILOT, SG_INFO, "adding property-rule subsystem " << name);
201 addAutopilot(name, apNode, configNode);
202 }
203 catch (const sg_exception& e)
204 {
205 SG_LOG
206 (
207 SG_AUTOPILOT,
208 SG_ALERT,
209 "Failed to load property-rule configuration: " << config
210 << ": " << e.getMessage()
211 );
212 simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::AircraftSystems,
213 std::string{"Autopilot XML failed to load:"} + e.getFormattedMessage(), e.getLocation());
214 return;
215 }
216}
217
218//------------------------------------------------------------------------------
220FGXMLAutopilotGroup::createInstance(const std::string& nodeName)
221{
222 return new FGXMLAutopilotGroupImplementation(nodeName);
223}
#define i(x)
virtual void addAutopilot(const std::string &name, SGPropertyNode_ptr apNode, SGPropertyNode_ptr config)
virtual void removeAutopilot(const std::string &name)
FGXMLAutopilotGroupImplementation(const std::string &nodeName)
static const char * staticSubsystemClassId()
InitStatus incrementalInit() override
Model an autopilot system by implementing a SGSubsystemGroup.
static FGXMLAutopilotGroup * createInstance(const std::string &nodeName)
void addAutopilotFromFile(const std::string &name, SGPropertyNode_ptr apNode, const std::string &path)
virtual void addAutopilot(const std::string &name, SGPropertyNode_ptr apNode, SGPropertyNode_ptr config)=0
A SGSubsystemGroup implementation to serve as a collection of Components.
Definition autopilot.hxx:38
void set_name(const std::string &name)
Definition autopilot.hxx:55
const char * name
FGGlobals * globals
Definition globals.cxx:142
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27