1 // multiplay.cxx -- protocol object for multiplay in Flightgear
3 // Written by Diarmuid Tyson, started February 2003.
4 // diarmuid.tyson@airservicesaustralia.com
6 // With addtions by Vivian Meazza, January 2006
8 // Copyright (C) 2003 Airservices Australia
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <simgear/compiler.h>
37 #include <simgear/debug/logstream.hxx>
38 #include <simgear/scene/model/placement.hxx>
39 #include <simgear/scene/model/placementtrans.hxx>
41 #include <Scenery/scenery.hxx>
43 #include "multiplay.hxx"
48 // These constants are provided so that the ident command can list file versions.
49 const char sFG_MULTIPLAY_BID[] = "$Id$";
50 const char sFG_MULTIPLAY_HID[] = FG_MULTIPLAY_HID;
53 /******************************************************************
55 * Description: Constructor. Initialises the protocol and stores
56 * host and port information.
57 ******************************************************************/
58 FGMultiplay::FGMultiplay (const string &dir, const int rate, const string &host, const int port) {
61 last_speedN = last_speedE = last_speedD = 0;
62 calcaccN = calcaccE = calcaccD = 0;
67 if (get_direction() == SG_IO_IN) {
69 fgSetInt("/sim/multiplay/rxport", port);
70 fgSetString("/sim/multiplay/rxhost", host.c_str());
72 } else if (get_direction() == SG_IO_OUT) {
74 fgSetInt("/sim/multiplay/txport", port);
75 fgSetString("/sim/multiplay/txhost", host.c_str());
79 lat_n = fgGetNode("/position/latitude-deg", true);
80 lon_n = fgGetNode("/position/longitude-deg", true);
81 alt_n = fgGetNode("/position/altitude-ft", true);
82 heading_n = fgGetNode("/orientation/heading-deg", true);
83 roll_n = fgGetNode("/orientation/roll-deg", true);
84 pitch_n = fgGetNode("/orientation/pitch-deg", true);
85 speedN_n = fgGetNode("/velocities/speed-north-fps", true);
86 speedE_n = fgGetNode("/velocities/speed-east-fps", true);
87 speedD_n = fgGetNode("/velocities/speed-down-fps", true);
88 left_aileron_n = fgGetNode("/surface-positions/left-aileron-pos-norm", true);
89 right_aileron_n = fgGetNode("/surface-positions/right-aileron-pos-norm", true);
90 elevator_n = fgGetNode("/surface-positions/elevator-pos-norm", true);
91 rudder_n = fgGetNode("/surface-positions/rudder-pos-norm", true);
92 /*rpms_n[0] = fgGetNode("/engines/engine/rpm", true);
93 rpms_n[1] = fgGetNode("/engines/engine[1]/rpm", true);
94 rpms_n[2] = fgGetNode("/engines/engine[2]/rpm", true);
95 rpms_n[3] = fgGetNode("/engines/engine[3]/rpm", true);
96 rpms_n[4] = fgGetNode("/engines/engine[4]/rpm", true);
97 rpms_n[5] = fgGetNode("/engines/engine[5]/rpm", true);*/
98 rateH_n = fgGetNode("/orientation/yaw-rate-degps", true);
99 rateR_n = fgGetNode("/orientation/roll-rate-degps", true);
100 rateP_n = fgGetNode("/orientation/pitch-rate-degps", true);
102 SGPropertyNode_ptr n = fgGetNode("/controls/flight/slats",true);
103 _node_cache *c = new _node_cache( n->getDoubleValue(), n );
104 props["controls/flight/slats"] = c;
106 n = fgGetNode("/controls/flight/speedbrake", true);
107 c = new _node_cache( n->getDoubleValue(), n );
108 props["controls/flight/speedbrake"] = c;
110 n = fgGetNode("/controls/flight/spoilers", true);
111 c = new _node_cache( n->getDoubleValue(), n );
112 props["controls/flight/spoilers"] = c;
114 n = fgGetNode("/controls/gear/gear-down", true);
115 c = new _node_cache( n->getDoubleValue(), n );
116 props["controls/gear/gear-down"] = c;
118 n = fgGetNode("/controls/lighting/nav-lights", true);
119 c = new _node_cache( n->getDoubleValue(), n );
120 props["controls/lighting/nav-lights"] = c;
122 n = fgGetNode("/surface-positions/flap-pos-norm", true);
123 c = new _node_cache( n->getDoubleValue(), n );
124 props["surface-positions/flap-pos-norm"] = c;
126 n = fgGetNode("/surface-positions/speedbrake-pos-norm", true);
127 c = new _node_cache( n->getDoubleValue(), n );
128 props["surface-positions/speedbrake-pos-norm"] = c;
130 for (int i = 0; i < 6; i++)
132 char *s = new char[32];
134 snprintf(s, 32, "engines/engine[%i]/n1", i);
135 n = fgGetNode(s, true);
136 c = new _node_cache( n->getDoubleValue(), n );
139 snprintf(s, 32, "engines/engine[%i]/n2", i);
140 n = fgGetNode(s, true);
141 c = new _node_cache( n->getDoubleValue(), n );
144 snprintf(s, 32, "engines/engine[%i]/rpm", i);
145 n = fgGetNode(s, true);
146 c = new _node_cache( n->getDoubleValue(), n );
152 for (int j = 0; j < 5; j++)
154 char *s = new char[32];
156 snprintf(s, 32, "gear/gear[%i]/compression-norm", j);
157 n = fgGetNode(s, true);
158 c = new _node_cache( n->getDoubleValue(), n );
161 snprintf(s, 32, "gear/gear[%i]/position-norm", j);
162 n = fgGetNode(s, true);
163 c = new _node_cache( n->getDoubleValue(), n );
166 snprintf(s, 32, "gear/gear[%i]/rollspeed-ms", j);
167 n = fgGetNode(s, true);
168 c = new _node_cache( n->getDoubleValue(), n );
174 n = fgGetNode("gear/tailhook/position-norm", true);
175 c = new _node_cache( n->getDoubleValue(), n );
176 props["gear/tailhook/position-norm"] = c;
180 /******************************************************************
182 * Description: Destructor.
183 ******************************************************************/
184 FGMultiplay::~FGMultiplay () {
189 /******************************************************************
191 * Description: Enables the protocol.
192 ******************************************************************/
193 bool FGMultiplay::open() {
195 if ( is_enabled() ) {
196 SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
197 << "is already in use, ignoring" );
207 /******************************************************************
209 * Description: Prompts the multiplayer mgr to either send
210 * or receive data over the network
211 ******************************************************************/
212 bool FGMultiplay::process() {
214 if (get_direction() == SG_IO_IN) {
216 globals->get_multiplayer_mgr()->ProcessData();
218 } else if (get_direction() == SG_IO_OUT) {
220 double accN, accE, accD;
221 string fdm = fgGetString("/sim/flight-model");
224 calcAcc(speedN_n->getDoubleValue(),
225 speedE_n->getDoubleValue(),
226 speedD_n->getDoubleValue());
231 SG_LOG(SG_GENERAL, SG_DEBUG," not doing acc calc" << fdm);
232 accN = fgGetDouble("/accelerations/ned/north-accel-fps_sec");
233 accE = fgGetDouble("/accelerations/ned/east-accel-fps_sec");
234 accD = fgGetDouble("/accelerations/ned/down-accel-fps_sec");
237 globals->get_multiplayer_mgr()->SendMyPosition(
238 lat_n->getDoubleValue(),
239 lon_n->getDoubleValue(),
240 alt_n->getDoubleValue(),
241 heading_n->getDoubleValue(),
242 roll_n->getDoubleValue(),
243 pitch_n->getDoubleValue(),
244 speedN_n->getDoubleValue(),
245 speedE_n->getDoubleValue(),
246 speedD_n->getDoubleValue(),
247 left_aileron_n->getDoubleValue(),
248 right_aileron_n->getDoubleValue(),
249 elevator_n->getDoubleValue(),
250 rudder_n->getDoubleValue(),
251 rateH_n->getDoubleValue(),
252 rateR_n->getDoubleValue(),
253 rateP_n->getDoubleValue(),
257 for (propit = props.begin(); propit != props.end(); propit++)
259 double val = propit->second->val;
260 double curr_val = propit->second->node->getDoubleValue();
261 if (curr_val < val * 0.99 || curr_val > val * 1.01 )
263 SGPropertyNode::Type type = propit->second->node->getType();
264 propit->second->val = val = curr_val;
265 globals->get_multiplayer_mgr()->SendPropMessage(propit->first, type, val);
266 //cout << "Prop " << propit->first <<" type " << type << " val " << val << endl;
268 // cout << "no change" << endl;
272 // send all properties when necessary
273 // FGMultiplayMgr::getSendAllProps();
274 bool send_all = globals->get_multiplayer_mgr()->getSendAllProps();
275 //cout << "send_all in " << send;
277 SG_LOG( SG_NETWORK, SG_ALERT,
278 "FGMultiplay::sending ALL property messages" );
279 for (propit = props.begin(); propit != props.end(); propit++) {
280 SGPropertyNode::Type type = propit->second->node->getType();
281 double val = propit->second->val;
282 globals->get_multiplayer_mgr()->SendPropMessage(propit->first, type, val);
285 globals->get_multiplayer_mgr()->setSendAllProps(send_all);
287 //cout << " send_all out " << s << endl;
294 /******************************************************************
296 * Description: Closes the multiplayer mgrs to stop any further
298 ******************************************************************/
299 bool FGMultiplay::close() {
301 if (get_direction() == SG_IO_IN) {
303 globals->get_multiplayer_mgr()->Close();
305 } else if (get_direction() == SG_IO_OUT) {
307 // globals->get_multiplayer_mgr()->Close();
314 /******************************************************************
316 * Description: Calculate accelerations given speedN, speedE, speedD
317 ******************************************************************/
318 void FGMultiplay::calcAcc(double speedN, double speedE, double speedD)
320 double time, dt; //secs
321 /*double accN, accE, accD; */ //fps2
325 time = fgGetDouble("/sim/time/elapsed-sec");
329 SG_LOG(SG_GENERAL, SG_DEBUG," doing acc calc"
330 <<"time: "<< time << " last " << last_time << " dt " << dt );
332 //calculate the accelerations
333 calcaccN = (speedN - last_speedN)/dt;
334 calcaccE = (speedE - last_speedE)/dt;
335 calcaccD = (speedD - last_speedD)/dt;
338 /*fgSetDouble("/accelerations/ned/north-accel-fps_sec",accN);
339 fgSetDouble("/accelerations/ned/east-accel-fps_sec",accE);
340 fgSetDouble("/accelerations/ned/down-accel-fps_sec",accN);*/
344 last_speedN = speedN;
345 last_speedE = speedE;
346 last_speedD = speedD;