From: James Turner Date: Sat, 13 Nov 2010 14:38:35 +0000 (+0000) Subject: Move all MP code in src/MultiPlayer. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=9c983359aa709e47565e094c0fc25700f2a26980;p=flightgear.git Move all MP code in src/MultiPlayer. Allow the subsystem to be (re-)inited at runtime. --- diff --git a/projects/VC90/FlightGear/FlightGear.vcproj b/projects/VC90/FlightGear/FlightGear.vcproj index f7d56ff93..8d70c4028 100644 --- a/projects/VC90/FlightGear/FlightGear.vcproj +++ b/projects/VC90/FlightGear/FlightGear.vcproj @@ -3033,14 +3033,6 @@ RelativePath="..\..\..\src\Network\jsclient.hxx" > - - - - diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx index 6d6be65f5..c45b98f86 100644 --- a/src/Main/fg_io.cxx +++ b/src/Main/fg_io.cxx @@ -65,7 +65,7 @@ #include #include #include -#include + #ifdef FG_HAVE_HLA #include #endif @@ -219,10 +219,23 @@ FGIO::parse_port_config( const string& config ) return NULL; } string dir = tokens[1]; - string rate = tokens[2]; + int rate = atoi(tokens[2].c_str()); string host = tokens[3]; - string port = tokens[4]; - return new FGMultiplay(dir, atoi(rate.c_str()), host, atoi(port.c_str())); + + short port = atoi(tokens[4].c_str()); + + // multiplay used to be handled by an FGProtocol, but no longer. This code + // retains compatability with existing command-line syntax + fgSetInt("/sim/multiplay/tx-rate-hz", rate); + if (dir == "in") { + fgSetInt("/sim/multiplay/rxport", port); + fgSetString("/sim/multiplay/rxhost", host.c_str()); + } else if (dir == "out") { + fgSetInt("/sim/multiplay/txport", port); + fgSetString("/sim/multiplay/txhost", host.c_str()); + } + + return NULL; #ifdef FG_HAVE_HLA } else if ( protocol == "hla" ) { return new FGHLA(tokens); @@ -343,20 +356,20 @@ FGIO::init() // appropriate FGIOChannel structures string_list::iterator i = globals->get_channel_options_list()->begin(); string_list::iterator end = globals->get_channel_options_list()->end(); - for (; i != end; ++i ) - { - p = parse_port_config( *i ); - if ( p != NULL ) { - p->open(); - io_channels.push_back( p ); - if ( !p->is_enabled() ) { - SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." ); - exit(-1); - } - } else { - SG_LOG( SG_IO, SG_INFO, "I/O Channel parse failed." ); - } - } + for (; i != end; ++i ) { + p = parse_port_config( *i ); + if (!p) { + continue; + } + + p->open(); + if ( !p->is_enabled() ) { + SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." ); + delete p; + } + + io_channels.push_back( p ); + } // of channel options iteration } void diff --git a/src/MultiPlayer/multiplaymgr.cxx b/src/MultiPlayer/multiplaymgr.cxx index 9a5413827..a8f862388 100644 --- a/src/MultiPlayer/multiplaymgr.cxx +++ b/src/MultiPlayer/multiplaymgr.cxx @@ -42,9 +42,11 @@ #include #include +#include #include
#include "multiplaymgr.hxx" #include "mpmessages.hxx" +#include using namespace std; @@ -56,11 +58,18 @@ using namespace std; const char sMULTIPLAYMGR_BID[] = "$Id$"; const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID; +struct IdPropertyList { + unsigned id; + const char* name; + simgear::props::Type type; +}; + +static const IdPropertyList* findProperty(unsigned id); + // A static map of protocol property id values to property paths, // This should be extendable dynamically for every specific aircraft ... // For now only that static list -const FGMultiplayMgr::IdPropertyList -FGMultiplayMgr::sIdPropertyList[] = { +static const IdPropertyList sIdPropertyList[] = { {100, "surface-positions/left-aileron-pos-norm", simgear::props::FLOAT}, {101, "surface-positions/right-aileron-pos-norm", simgear::props::FLOAT}, {102, "surface-positions/elevator-pos-norm", simgear::props::FLOAT}, @@ -229,34 +238,33 @@ FGMultiplayMgr::sIdPropertyList[] = { {10319, "sim/multiplay/generic/int[19]", simgear::props::INT} }; -const unsigned -FGMultiplayMgr::numProperties = (sizeof(FGMultiplayMgr::sIdPropertyList) - / sizeof(FGMultiplayMgr::sIdPropertyList[0])); +const unsigned int numProperties = (sizeof(sIdPropertyList) + / sizeof(sIdPropertyList[0])); // Look up a property ID using binary search. namespace { struct ComparePropertyId { - bool operator()(const FGMultiplayMgr::IdPropertyList& lhs, - const FGMultiplayMgr::IdPropertyList& rhs) + bool operator()(const IdPropertyList& lhs, + const IdPropertyList& rhs) { return lhs.id < rhs.id; } - bool operator()(const FGMultiplayMgr::IdPropertyList& lhs, + bool operator()(const IdPropertyList& lhs, unsigned id) { return lhs.id < id; } bool operator()(unsigned id, - const FGMultiplayMgr::IdPropertyList& rhs) + const IdPropertyList& rhs) { return id < rhs.id; } - }; - + }; } -const FGMultiplayMgr::IdPropertyList* FGMultiplayMgr::findProperty(unsigned id) + +const IdPropertyList* findProperty(unsigned id) { std::pair result = std::equal_range(sIdPropertyList, sIdPropertyList + numProperties, id, @@ -276,8 +284,7 @@ namespace const xdr_data_t* xdr = data; while (xdr < end) { unsigned id = XDR_decode_uint32(*xdr); - const FGMultiplayMgr::IdPropertyList* plist - = FGMultiplayMgr::findProperty(id); + const IdPropertyList* plist = findProperty(id); if (plist) { xdr++; @@ -336,6 +343,24 @@ namespace return true; } } + +class MPPropertyListener : public SGPropertyChangeListener +{ +public: + MPPropertyListener(FGMultiplayMgr* mp) : + _multiplay(mp) + { + } + + virtual void childAdded(SGPropertyNode*, SGPropertyNode*) + { + _multiplay->setPropertiesChanged(); + } + +private: + FGMultiplayMgr* _multiplay; +}; + ////////////////////////////////////////////////////////////////////// // // MultiplayMgr constructor @@ -343,9 +368,9 @@ namespace ////////////////////////////////////////////////////////////////////// FGMultiplayMgr::FGMultiplayMgr() { - mSocket = 0; mInitialised = false; mHaveServer = false; + mListener = NULL; } // FGMultiplayMgr::FGMultiplayMgr() ////////////////////////////////////////////////////////////////////// @@ -356,7 +381,7 @@ FGMultiplayMgr::FGMultiplayMgr() ////////////////////////////////////////////////////////////////////// FGMultiplayMgr::~FGMultiplayMgr() { - Close(); + } // FGMultiplayMgr::~FGMultiplayMgr() ////////////////////////////////////////////////////////////////////// @@ -375,22 +400,36 @@ FGMultiplayMgr::init (void) SG_LOG(SG_NETWORK, SG_WARN, "FGMultiplayMgr::init - already initialised"); return; } + + fgSetBool("/sim/multiplay/online", false); + ////////////////////////////////////////////////// // Set members from property values ////////////////////////////////////////////////// short rxPort = fgGetInt("/sim/multiplay/rxport"); string rxAddress = fgGetString("/sim/multiplay/rxhost"); - short txPort = fgGetInt("/sim/multiplay/txport"); + short txPort = fgGetInt("/sim/multiplay/txport", 5000); string txAddress = fgGetString("/sim/multiplay/txhost"); + + int hz = fgGetInt("/sim/multiplay/tx-rate-hz", 10); + if (hz < 1) { + hz = 10; + } + + mDt = 1.0 / hz; + mTimeUntilSend = 0.0; + mCallsign = fgGetString("/sim/multiplay/callsign"); - if (txPort > 0 && !txAddress.empty()) { + if (!txAddress.empty()) { mServer.set(txAddress.c_str(), txPort); if (strncmp (mServer.getHost(), "0.0.0.0", 8) == 0) { mHaveServer = false; - SG_LOG(SG_NETWORK, SG_DEBUG, + SG_LOG(SG_NETWORK, SG_WARN, "FGMultiplayMgr - could not resolve '" << txAddress << "', Multiplayermode disabled"); + return; } else { + SG_LOG(SG_NETWORK, SG_INFO, "have server"); mHaveServer = true; } if (rxPort <= 0) @@ -408,11 +447,10 @@ FGMultiplayMgr::init (void) SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxaddress="<get_props()->addChangeListener(mListener, false); + + fgSetBool("/sim/multiplay/online", true); mInitialised = true; } // FGMultiplayMgr::init() ////////////////////////////////////////////////////////////////////// @@ -435,19 +478,39 @@ FGMultiplayMgr::init (void) // ////////////////////////////////////////////////////////////////////// void -FGMultiplayMgr::Close (void) +FGMultiplayMgr::shutdown (void) { - mMultiPlayerMap.clear(); - - if (mSocket) { + fgSetBool("/sim/multiplay/online", false); + + if (mSocket.get()) { mSocket->close(); - delete mSocket; - mSocket = 0; + mSocket.reset(); + } + + MultiPlayerMap::iterator it = mMultiPlayerMap.begin(), + end = mMultiPlayerMap.end(); + for (; it != end; ++it) { + it->second->setDie(true); } + mMultiPlayerMap.clear(); + + if (mListener) { + globals->get_props()->removeChangeListener(mListener); + delete mListener; + mListener = NULL; + } + mInitialised = false; } // FGMultiplayMgr::Close(void) ////////////////////////////////////////////////////////////////////// +void +FGMultiplayMgr::reinit() +{ + shutdown(); + init(); +} + ////////////////////////////////////////////////////////////////////// // // Description: Sends the position data for the local position. @@ -757,7 +820,7 @@ FGMultiplayMgr::SendTextMessage(const string &MsgText) // ////////////////////////////////////////////////////////////////////// void -FGMultiplayMgr::update(double) +FGMultiplayMgr::update(double dt) { if (!mInitialised) return; @@ -765,6 +828,14 @@ FGMultiplayMgr::update(double) /// Just for expiry long stamp = SGTimeStamp::now().getSeconds(); + ////////////////////////////////////////////////// + // Send if required + ////////////////////////////////////////////////// + mTimeUntilSend -= dt; + if (mTimeUntilSend <= 0.0) { + Send(); + } + ////////////////////////////////////////////////// // Read the receive socket and process any data ////////////////////////////////////////////////// @@ -813,7 +884,7 @@ FGMultiplayMgr::update(double) << "message has invalid protocol number!" ); break; } - if (MsgHdr->MsgLen != bytes) { + if (static_cast(MsgHdr->MsgLen) != bytes) { SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " << "message from " << MsgHdr->Callsign << " has invalid length!"); break; @@ -854,6 +925,140 @@ FGMultiplayMgr::update(double) } // FGMultiplayMgr::ProcessData(void) ////////////////////////////////////////////////////////////////////// +void +FGMultiplayMgr::Send() +{ + using namespace simgear; + + findProperties(); + + // smooth the send rate, by adjusting based on the 'remainder' time, which + // is how -ve mTimeUntilSend is. Watch for large values and ignore them, + // however. + if ((mTimeUntilSend < 0.0) && (fabs(mTimeUntilSend) < mDt)) { + mTimeUntilSend = mDt + mTimeUntilSend; + } else { + mTimeUntilSend = mDt; + } + + double sim_time = globals->get_sim_time_sec(); + static double lastTime = 0.0; + + // SG_LOG(SG_GENERAL, SG_INFO, "actual dt=" << sim_time - lastTime); + lastTime = sim_time; + + FlightProperties ifce; + + // put together a motion info struct, you will get that later + // from FGInterface directly ... + FGExternalMotionData motionInfo; + + // The current simulation time we need to update for, + // note that the simulation time is updated before calling all the + // update methods. Thus it contains the time intervals *end* time. + // The FDM is already run, so the states belong to that time. + motionInfo.time = sim_time; + motionInfo.lag = mDt; + + // These are for now converted from lat/lon/alt and euler angles. + // But this should change in FGInterface ... + double lon = ifce.get_Longitude(); + double lat = ifce.get_Latitude(); + // first the aprioriate structure for the geodetic one + SGGeod geod = SGGeod::fromRadFt(lon, lat, ifce.get_Altitude()); + // Convert to cartesion coordinate + motionInfo.position = SGVec3d::fromGeod(geod); + + // The quaternion rotating from the earth centered frame to the + // horizontal local frame + SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)lon, (float)lat); + // The orientation wrt the horizontal local frame + float heading = ifce.get_Psi(); + float pitch = ifce.get_Theta(); + float roll = ifce.get_Phi(); + SGQuatf hlOr = SGQuatf::fromYawPitchRoll(heading, pitch, roll); + // The orientation of the vehicle wrt the earth centered frame + motionInfo.orientation = qEc2Hl*hlOr; + + if (!globals->get_subsystem("flight")->is_suspended()) { + // velocities + motionInfo.linearVel = SG_FEET_TO_METER*SGVec3f(ifce.get_uBody(), + ifce.get_vBody(), + ifce.get_wBody()); + motionInfo.angularVel = SGVec3f(ifce.get_P_body(), + ifce.get_Q_body(), + ifce.get_R_body()); + + // accels, set that to zero for now. + // Angular accelerations are missing from the interface anyway, + // linear accelerations are screwed up at least for JSBSim. +// motionInfo.linearAccel = SG_FEET_TO_METER*SGVec3f(ifce.get_U_dot_body(), +// ifce.get_V_dot_body(), +// ifce.get_W_dot_body()); + motionInfo.linearAccel = SGVec3f::zeros(); + motionInfo.angularAccel = SGVec3f::zeros(); + } else { + // if the interface is suspendend, prevent the client from + // wild extrapolations + motionInfo.linearVel = SGVec3f::zeros(); + motionInfo.angularVel = SGVec3f::zeros(); + motionInfo.linearAccel = SGVec3f::zeros(); + motionInfo.angularAccel = SGVec3f::zeros(); + } + + // now send the properties + PropertyMap::iterator it; + for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) { + FGPropertyData* pData = new FGPropertyData; + pData->id = it->first; + pData->type = it->second->getType(); + + switch (pData->type) { + case props::INT: + case props::LONG: + case props::BOOL: + pData->int_value = it->second->getIntValue(); + break; + case props::FLOAT: + case props::DOUBLE: + pData->float_value = it->second->getFloatValue(); + break; + case props::STRING: + case props::UNSPECIFIED: + { + // FIXME: We assume unspecified are strings for the moment. + + const char* cstr = it->second->getStringValue(); + int len = strlen(cstr); + + if (len > 0) + { + pData->string_value = new char[len + 1]; + strcpy(pData->string_value, cstr); + } + else + { + // Size 0 - ignore + pData->string_value = 0; + } + + //cout << " Sending property " << pData->id << " " << pData->type << " " << pData->string_value << "\n"; + break; + } + default: + // FIXME Currently default to a float. + //cout << "Unknown type when iterating through props: " << pData->type << "\n"; + pData->float_value = it->second->getFloatValue(); + break; + } + + motionInfo.properties.push_back(pData); + } + + SendMyPosition(motionInfo); +} + + ////////////////////////////////////////////////////////////////////// // // handle a position message @@ -1101,3 +1306,29 @@ FGMultiplayMgr::getMultiplayer(const std::string& callsign) else return 0; } + +void +FGMultiplayMgr::findProperties() +{ + if (!mPropertiesChanged) { + return; + } + + mPropertiesChanged = false; + + for (unsigned i = 0; i < numProperties; ++i) { + const char* name = sIdPropertyList[i].name; + SGPropertyNode* pNode = globals->get_props()->getNode(name); + if (!pNode) { + continue; + } + + int id = sIdPropertyList[i].id; + if (mPropertyMap.find(id) != mPropertyMap.end()) { + continue; // already activated + } + + mPropertyMap[id] = pNode; + SG_LOG(SG_NETWORK, SG_DEBUG, "activating MP property:" << pNode->getPath()); + } +} diff --git a/src/MultiPlayer/multiplaymgr.hxx b/src/MultiPlayer/multiplaymgr.hxx index 8475c0ef1..daae68b57 100644 --- a/src/MultiPlayer/multiplaymgr.hxx +++ b/src/MultiPlayer/multiplaymgr.hxx @@ -31,48 +31,50 @@ #define MULTIPLAYTXMGR_HID "$Id$" -#include "mpmessages.hxx" #include #include #include #include -#include
#include #include -#include - -struct FGExternalMotionInfo; +struct FGExternalMotionData; +class MPPropertyListener; +struct T_MsgHdr; +class FGAIMultiplayer; class FGMultiplayMgr : public SGSubsystem { -public: - - struct IdPropertyList { - unsigned id; - const char* name; - simgear::props::Type type; - }; - static const IdPropertyList sIdPropertyList[]; - static const unsigned numProperties; - - static const IdPropertyList* findProperty(unsigned id); - +public: FGMultiplayMgr(); ~FGMultiplayMgr(); virtual void init(void); virtual void update(double dt); - void Close(void); + virtual void shutdown(void); + virtual void reinit(); + // transmitter - void SendMyPosition(const FGExternalMotionData& motionInfo); + void SendTextMessage(const string &sMsgText); // receiver private: + friend class MPPropertyListener; + + void setPropertiesChanged() + { + mPropertiesChanged = true; + } + + void findProperties(); + + void Send(); + void SendMyPosition(const FGExternalMotionData& motionInfo); + union MsgBuf; FGAIMultiplayer* addMultiplayer(const std::string& callsign, const std::string& modelName); @@ -87,11 +89,22 @@ private: typedef std::map > MultiPlayerMap; MultiPlayerMap mMultiPlayerMap; - simgear::Socket* mSocket; + std::auto_ptr mSocket; simgear::IPAddress mServer; bool mHaveServer; bool mInitialised; std::string mCallsign; + + // Map between the property id's from the multiplayers network packets + // and the property nodes + typedef std::map > PropertyMap; + PropertyMap mPropertyMap; + + bool mPropertiesChanged; + MPPropertyListener* mListener; + + double mDt; // reciprocal of /sim/multiplay/tx-rate-hz + double mTimeUntilSend; }; #endif diff --git a/src/Network/CMakeLists.txt b/src/Network/CMakeLists.txt index 1f42c68c7..3f0e202c2 100644 --- a/src/Network/CMakeLists.txt +++ b/src/Network/CMakeLists.txt @@ -15,7 +15,6 @@ set(SOURCES jpg-httpd.cxx jsclient.cxx lfsglass.cxx - multiplay.cxx native.cxx native_ctrls.cxx native_fdm.cxx diff --git a/src/Network/Makefile.am b/src/Network/Makefile.am index 0935d3ca4..e4ecc3b10 100644 --- a/src/Network/Makefile.am +++ b/src/Network/Makefile.am @@ -9,8 +9,6 @@ else JPEG_SERVER = endif -MPLAYER_AS = multiplay.cxx multiplay.hxx - libNetwork_a_SOURCES = \ protocol.cxx protocol.hxx \ ATC-Main.cxx ATC-Main.hxx \ @@ -33,7 +31,6 @@ libNetwork_a_SOURCES = \ net_ctrls.hxx net_fdm.hxx net_fdm_mini.hxx net_gui.hxx \ nmea.cxx nmea.hxx \ opengc.cxx opengc.hxx opengc_data.hxx \ - $(MPLAYER_AS) \ props.cxx props.hxx \ pve.cxx pve.hxx \ ray.cxx ray.hxx \ diff --git a/src/Network/multiplay.cxx b/src/Network/multiplay.cxx deleted file mode 100644 index ddedccea8..000000000 --- a/src/Network/multiplay.cxx +++ /dev/null @@ -1,319 +0,0 @@ -// multiplay.cxx -- protocol object for multiplay in Flightgear -// -// Written by Diarmuid Tyson, started February 2003. -// diarmuid.tyson@airservicesaustralia.com -// -// With addtions by Vivian Meazza, January 2006 -// -// Copyright (C) 2003 Airservices Australia -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "multiplay.hxx" - -using std::string; - - -// These constants are provided so that the ident command can list file versions. -const char sFG_MULTIPLAY_BID[] = "$Id$"; -const char sFG_MULTIPLAY_HID[] = FG_MULTIPLAY_HID; - -typedef std::set string_set; - -class MPPropertyListener : public SGPropertyChangeListener -{ -public: - MPPropertyListener(FGMultiplay* mp) : - _multiplay(mp) - { - } - - virtual void childAdded(SGPropertyNode*, SGPropertyNode*) - { - _multiplay->setPropertiesChanged(); - } - -private: - FGMultiplay* _multiplay; -}; - -/****************************************************************** -* Name: FGMultiplay -* Description: Constructor. Initialises the protocol and stores -* host and port information. -******************************************************************/ -FGMultiplay::FGMultiplay (const string &dir, const int rate, const string &host, const int port) { - - set_hz(rate); - - set_direction(dir); - - if (get_direction() == SG_IO_IN) { - - fgSetInt("/sim/multiplay/rxport", port); - fgSetString("/sim/multiplay/rxhost", host.c_str()); - - } else if (get_direction() == SG_IO_OUT) { - - fgSetInt("/sim/multiplay/txport", port); - fgSetString("/sim/multiplay/txhost", host.c_str()); - - } - - mPropertiesChanged = true; -} - - -/****************************************************************** -* Name: ~FGMultiplay -* Description: Destructor. -******************************************************************/ -FGMultiplay::~FGMultiplay () { -} - - -/****************************************************************** -* Name: open -* Description: Enables the protocol. -******************************************************************/ -bool FGMultiplay::open() { - - if ( is_enabled() ) { - SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel " - << "is already in use, ignoring" ); - return false; - } - - set_enabled(true); - - mPropertiesChanged = true; - - MPPropertyListener* pl = new MPPropertyListener(this); - globals->get_props()->addChangeListener(pl, false); - return is_enabled(); -} - -void FGMultiplay::findProperties() -{ - if (!mPropertiesChanged) { - return; - } - - mPropertiesChanged = false; - - for (unsigned i = 0; i < FGMultiplayMgr::numProperties; ++i) { - const char* name = FGMultiplayMgr::sIdPropertyList[i].name; - SGPropertyNode* pNode = globals->get_props()->getNode(name); - if (!pNode) { - continue; - } - - int id = FGMultiplayMgr::sIdPropertyList[i].id; - if (mPropertyMap.find(id) != mPropertyMap.end()) { - continue; // already activated - } - - mPropertyMap[id] = pNode; - SG_LOG(SG_NETWORK, SG_INFO, "activating MP property:" << pNode->getPath()); - } - -} - - -/****************************************************************** -* Name: process -* Description: Prompts the multiplayer mgr to either send -* or receive data over the network -******************************************************************/ -bool FGMultiplay::process() { - using namespace simgear; - if (get_direction() == SG_IO_OUT) { - findProperties(); - - // check if we have left initialization phase. That will not provide - // interresting data, also the freeze in simulation time hurts the - // multiplayer clients - double sim_time = globals->get_sim_time_sec(); -// if (sim_time < 20) -// return true; - - FlightProperties ifce; - - // put together a motion info struct, you will get that later - // from FGInterface directly ... - FGExternalMotionData motionInfo; - - // The current simulation time we need to update for, - // note that the simulation time is updated before calling all the - // update methods. Thus it contains the time intervals *end* time. - // The FDM is already run, so the states belong to that time. - motionInfo.time = sim_time; - - // The typical lag will be the reciprocal of the output frequency - double hz = get_hz(); - if (hz != 0) // I guess we can test a double for exact zero in this case - motionInfo.lag = 1/get_hz(); - else - motionInfo.lag = 0.1; //?? - - // These are for now converted from lat/lon/alt and euler angles. - // But this should change in FGInterface ... - double lon = ifce.get_Longitude(); - double lat = ifce.get_Latitude(); - // first the aprioriate structure for the geodetic one - SGGeod geod = SGGeod::fromRadFt(lon, lat, ifce.get_Altitude()); - // Convert to cartesion coordinate - motionInfo.position = SGVec3d::fromGeod(geod); - - // The quaternion rotating from the earth centered frame to the - // horizontal local frame - SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)lon, (float)lat); - // The orientation wrt the horizontal local frame - float heading = ifce.get_Psi(); - float pitch = ifce.get_Theta(); - float roll = ifce.get_Phi(); - SGQuatf hlOr = SGQuatf::fromYawPitchRoll(heading, pitch, roll); - // The orientation of the vehicle wrt the earth centered frame - motionInfo.orientation = qEc2Hl*hlOr; - - if (!globals->get_subsystem("flight")->is_suspended()) { - // velocities - motionInfo.linearVel = SG_FEET_TO_METER*SGVec3f(ifce.get_uBody(), - ifce.get_vBody(), - ifce.get_wBody()); - motionInfo.angularVel = SGVec3f(ifce.get_P_body(), - ifce.get_Q_body(), - ifce.get_R_body()); - - // accels, set that to zero for now. - // Angular accelerations are missing from the interface anyway, - // linear accelerations are screwed up at least for JSBSim. -// motionInfo.linearAccel = SG_FEET_TO_METER*SGVec3f(ifce.get_U_dot_body(), -// ifce.get_V_dot_body(), -// ifce.get_W_dot_body()); - motionInfo.linearAccel = SGVec3f::zeros(); - motionInfo.angularAccel = SGVec3f::zeros(); - } else { - // if the interface is suspendend, prevent the client from - // wild extrapolations - motionInfo.linearVel = SGVec3f::zeros(); - motionInfo.angularVel = SGVec3f::zeros(); - motionInfo.linearAccel = SGVec3f::zeros(); - motionInfo.angularAccel = SGVec3f::zeros(); - } - - // now send the properties - PropertyMap::iterator it; - for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) { - FGPropertyData* pData = new FGPropertyData; - pData->id = it->first; - pData->type = it->second->getType(); - - switch (pData->type) { - case props::INT: - case props::LONG: - case props::BOOL: - pData->int_value = it->second->getIntValue(); - break; - case props::FLOAT: - case props::DOUBLE: - pData->float_value = it->second->getFloatValue(); - break; - case props::STRING: - case props::UNSPECIFIED: - { - // FIXME: We assume unspecified are strings for the moment. - - const char* cstr = it->second->getStringValue(); - int len = strlen(cstr); - - if (len > 0) - { - pData->string_value = new char[len + 1]; - strcpy(pData->string_value, cstr); - } - else - { - // Size 0 - ignore - pData->string_value = 0; - } - - //cout << " Sending property " << pData->id << " " << pData->type << " " << pData->string_value << "\n"; - break; - } - default: - // FIXME Currently default to a float. - //cout << "Unknown type when iterating through props: " << pData->type << "\n"; - pData->float_value = it->second->getFloatValue(); - break; - } - - motionInfo.properties.push_back(pData); - } - - FGMultiplayMgr* mpmgr = (FGMultiplayMgr*) globals->get_subsystem("mp"); - mpmgr->SendMyPosition(motionInfo); - } - - return true; -} - - -/****************************************************************** -* Name: close -* Description: Closes the multiplayer mgrs to stop any further -* network processing -******************************************************************/ -bool FGMultiplay::close() -{ - mPropertyMap.clear(); - - FGMultiplayMgr* mgr = (FGMultiplayMgr*) globals->get_subsystem("mp"); - - if (mgr == 0) { - return false; - } - - if (get_direction() == SG_IO_IN) { - - mgr->Close(); - - } else if (get_direction() == SG_IO_OUT) { - - mgr->Close(); - - } - - return true; -} - diff --git a/src/Network/multiplay.hxx b/src/Network/multiplay.hxx deleted file mode 100644 index f596ea0eb..000000000 --- a/src/Network/multiplay.hxx +++ /dev/null @@ -1,97 +0,0 @@ -// multiplay.hxx -- protocol object for multiplay in Flightgear -// -// Written by Diarmuid Tyson, started February 2003. -// diarmuid.tyson@airservicesaustralia.com -// -// With additions by Vivian Meazza, January 2006 -// -// Copyright (C) 2003 Airservices Australia -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// - -#ifndef _FG_MULTIPLAY_HXX -#define _FG_MULTIPLAY_HXX - -#define FG_MULTIPLAY_HID "$Id$" - -#include - -#include - -#include - -#include
-#include
-#include -#include - -#include "protocol.hxx" - -using std::string; - - -/**************************************************************** -* @version $Id$ -* -* Description: FGMultiplay is an FGProtocol object used as the basic -* interface for the multiplayer code into FlightGears generic IO -* subsystem. It only implements the basic FGProtocol methods: open(), -* process() and close(). It does not use Sim Gear's IO channels, as -* the MultiplayMgrs creates their own sockets through plib. -* -* It will set up it's direction and rate protocol properties when -* created. Subsequent calls to process will prompt the -* MultiplayMgr to either send or receive data over the network. -* -******************************************************************/ - -class FGMultiplay : public FGProtocol { -public: - - /** Constructor */ - FGMultiplay (const string &dir, const int rate, const string &host, const int port); - - /** Destructor. */ - ~FGMultiplay (); - - /** Enables the FGMultiplay object. */ - bool open(); - - /** Tells the multiplayer_mgr to send/receive data. - */ - bool process(); - - /** Closes the multiplayer_mgr. - */ - bool close(); - - void setPropertiesChanged() - { - mPropertiesChanged = true; - } -private: - bool mPropertiesChanged; - - void findProperties(); - - // Map between the property id's from the multiplayers network packets - // and the property nodes - typedef std::map > PropertyMap; - PropertyMap mPropertyMap; -}; - - -#endif // _FG_MULTIPLAY_HXX