diff --git a/C/src/xplaneConnect.c b/C/src/xplaneConnect.c
index e4e633e..9969a57 100755
--- a/C/src/xplaneConnect.c
+++ b/C/src/xplaneConnect.c
@@ -521,6 +521,38 @@ int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char
/*****************************************************************************/
/**** POSI functions ****/
/*****************************************************************************/
+int getPOSI(XPCSocket sock, float values[7], char ac)
+{
+ // Setup send command
+ unsigned char buffer[6] = "GETP";
+ buffer[5] = ac;
+
+ // Send command
+ if (sendUDP(sock, buffer, 6) < 0)
+ {
+ printError("getPOSI", "Failed to send command.");
+ return -1;
+ }
+
+ // Get response
+ unsigned char readBuffer[34];
+ int readResult = readUDP(sock, readBuffer, 34);
+ if (readResult < 0)
+ {
+ printError("getPOSI", "Failed to read response.");
+ return -2;
+ }
+ if (readResult != 34)
+ {
+ printError("getPOSI", "Unexpected response length.");
+ return -3;
+ }
+
+ // Copy response into values
+ memcpy(values, readBuffer + 6, 7 * sizeof(float));
+ return 0;
+}
+
int sendPOSI(XPCSocket sock, float values[], int size, char ac)
{
// Validate input
@@ -565,6 +597,41 @@ int sendPOSI(XPCSocket sock, float values[], int size, char ac)
/*****************************************************************************/
/**** CTRL functions ****/
/*****************************************************************************/
+int getCTRL(XPCSocket sock, float values[7], char ac)
+{
+ // Setup send command
+ unsigned char buffer[6] = "GETC";
+ buffer[5] = ac;
+
+ // Send command
+ if (sendUDP(sock, buffer, 6) < 0)
+ {
+ printError("getCTRL", "Failed to send command.");
+ return -1;
+ }
+
+ // Get response
+ unsigned char readBuffer[31];
+ int readResult = readUDP(sock, readBuffer, 31);
+ if (readResult < 0)
+ {
+ printError("getCTRL", "Failed to read response.");
+ return -2;
+ }
+ if (readResult != 31)
+ {
+ printError("getCTRL", "Unexpected response length.");
+ return -3;
+ }
+
+ // Copy response into values
+ memcpy(values, readBuffer + 5, 4 * sizeof(float));
+ values[4] = readBuffer[21];
+ values[5] = *((float*)(readBuffer + 22));
+ values[6] = *((float*)(readBuffer + 27));
+ return 0;
+}
+
int sendCTRL(XPCSocket sock, float values[], int size, char ac)
{
// Validate input
diff --git a/C/src/xplaneConnect.h b/C/src/xplaneConnect.h
index 3827a68..161178a 100644
--- a/C/src/xplaneConnect.h
+++ b/C/src/xplaneConnect.h
@@ -196,6 +196,14 @@ int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char
// Position
+/// Gets the position and orientation of the specified aircraft.
+///
+/// \param sock The socket used to send the command and receive the response.
+/// \param values An array to store the position information returned by the
+/// plugin. The format of values is [Lat, Lon, Alt, Pitch, Roll, Yaw, Gear]
+/// \returns 0 if successful, otherwise a negative value.
+int getPOSI(XPCSocket sock, float values[7], char ac);
+
/// Sets the position and orientation of the specified aircraft.
///
/// \param sock The socket to use to send the command.
@@ -209,6 +217,16 @@ int sendPOSI(XPCSocket sock, float values[], int size, char ac);
// Controls
+/// Gets the control surface information for the specified aircraft.
+///
+/// \param sock The socket used to send the command and receive the response.
+/// \param values An array to store the position information returned by the
+/// plugin. The format of values is [Elevator, Aileron, Rudder,
+/// Throttle, Gear, Flaps, Speed Brakes]
+/// \param ac The aircraft to set the control surfaces of. 0 is the main/player aircraft.
+/// \returns 0 if successful, otherwise a negative value.
+int getCTRL(XPCSocket sock, float values[7], char ac);
+
/// Sets the control surfaces of the specified aircraft.
///
/// \param sock The socket to use to send the command.
diff --git a/Java/src/XPlaneConnect.java b/Java/src/XPlaneConnect.java
index ba545d5..ad3307e 100644
--- a/Java/src/XPlaneConnect.java
+++ b/Java/src/XPlaneConnect.java
@@ -398,6 +398,47 @@ public class XPlaneConnect implements AutoCloseable
sendUDP(os.toByteArray());
}
+ /**
+ * Gets the control surface information for the specified airplane.
+ *
+ * @param ac The aircraft to get control surface information for.
+ * @return An array containing control surface data in the same format as {@code sendCTRL}.
+ * @throws IOException If the command cannot be sent or a response cannot be read.
+ */
+ public float[] getCTRL(int ac) throws IOException
+ {
+ // Send request
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ os.write("GETC".getBytes(StandardCharsets.UTF_8));
+ os.write(0xFF); //Placeholder for message length
+ os.write(ac);
+ sendUDP(os.toByteArray());
+
+ // Read response
+ byte[] data = readUDP();
+ if(data.length == 0)
+ {
+ throw new IOException("No response received.");
+ }
+ if(data.length < 31)
+ {
+ throw new IOException("Response too short");
+ }
+
+ // Parse response
+ float[] result = new float[7];
+ ByteBuffer bb = ByteBuffer.wrap(data);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ result[0] = bb.getFloat(5);
+ result[1] = bb.getFloat(9);
+ result[2] = bb.getFloat(13);
+ result[3] = bb.getFloat(17);
+ result[4] = bb.get(21);
+ result[5] = bb.getFloat(22);
+ result[6] = bb.getFloat(27);
+ return result;
+ }
+
/**
* Sends command to X-Plane setting control surfaces on the player ac.
*
@@ -409,6 +450,7 @@ public class XPlaneConnect implements AutoCloseable
*
Throttle [-1, 1]
* Gear (0=up, 1=down)
* Flaps [0, 1]
+ * Speedbrakes [-0.5, 1.5]
*
*
* If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To
@@ -433,6 +475,7 @@ public class XPlaneConnect implements AutoCloseable
*
Throttle [-1, 1]
* Gear (0=up, 1=down)
* Flaps [0, 1]
+ * Speedbrakes [-0.5, 1.5]
*
*
* If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To
@@ -492,6 +535,44 @@ public class XPlaneConnect implements AutoCloseable
sendUDP(os.toByteArray());
}
+ /**
+ * Gets position information for the specified airplane.
+ *
+ * @param ac The aircraft to get position information for.
+ * @return An array containing control surface data in the same format as {@code sendPOSI}.
+ * @throws IOException If the command cannot be sent or a response cannot be read.
+ */
+ public float[] getPOSI(int ac) throws IOException
+ {
+ // Send request
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ os.write("GETP".getBytes(StandardCharsets.UTF_8));
+ os.write(0xFF); //Placeholder for message length
+ os.write(ac);
+ sendUDP(os.toByteArray());
+
+ // Read response
+ byte[] data = readUDP();
+ if(data.length == 0)
+ {
+ throw new IOException("No response received.");
+ }
+ if(data.length < 34)
+ {
+ throw new IOException("Response too short");
+ }
+
+ // Parse response
+ float[] result = new float[7];
+ ByteBuffer bb = ByteBuffer.wrap(data);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ for(int i = 0; i < 7; ++i)
+ {
+ result[i] = bb.getFloat(6 + 4 * i);
+ }
+ return result;
+ }
+
/**
* Sets the position of the player ac.
*
diff --git a/MATLAB/+XPlaneConnect/XPlaneConnect.jar b/MATLAB/+XPlaneConnect/XPlaneConnect.jar
index c779711..eba5283 100644
Binary files a/MATLAB/+XPlaneConnect/XPlaneConnect.jar and b/MATLAB/+XPlaneConnect/XPlaneConnect.jar differ
diff --git a/MATLAB/+XPlaneConnect/getCTRL.m b/MATLAB/+XPlaneConnect/getCTRL.m
new file mode 100644
index 0000000..820afca
--- /dev/null
+++ b/MATLAB/+XPlaneConnect/getCTRL.m
@@ -0,0 +1,29 @@
+function ctrl = getCTRL(ac, socket)
+% getCTRL Gets control surface information for the specified aircraft
+%
+% Inputs
+% ac: The aircraft number to get control surface data for.
+% Outputs
+% posi: An array of values matching the the format used by sendCTRL
+
+
+import XPlaneConnect.*
+
+%% Get client
+global clients;
+if ~exist('socket', 'var')
+ assert(isequal(length(clients) < 2, 1), '[getCTRL] ERROR: Multiple clients open. You must specify which client to use.');
+ if isempty(clients)
+ socket = openUDP();
+ else
+ socket = clients(1);
+ end
+end
+
+%% Validate input
+ac = int32(ac);
+
+%% Send command
+ctrl = socket.getCTRL(ac);
+
+end
\ No newline at end of file
diff --git a/MATLAB/+XPlaneConnect/getPOSI.m b/MATLAB/+XPlaneConnect/getPOSI.m
new file mode 100644
index 0000000..35b8d5a
--- /dev/null
+++ b/MATLAB/+XPlaneConnect/getPOSI.m
@@ -0,0 +1,29 @@
+function posi = getPOSI(ac, socket)
+% getPOSI Gets position information for the specified aircraft
+%
+% Inputs
+% ac: The aircraft number to get position data for.
+% Outputs
+% posi: An array of values matching the the format used by sendPOSI
+
+
+import XPlaneConnect.*
+
+%% Get client
+global clients;
+if ~exist('socket', 'var')
+ assert(isequal(length(clients) < 2, 1), '[getPOSI] ERROR: Multiple clients open. You must specify which client to use.');
+ if isempty(clients)
+ socket = openUDP();
+ else
+ socket = clients(1);
+ end
+end
+
+%% Validate input
+ac = int32(ac);
+
+%% Send command
+posi = socket.getPOSI(ac);
+
+end
\ No newline at end of file
diff --git a/Python/src/xpc.py b/Python/src/xpc.py
index c19bbdb..e2b5c5e 100644
--- a/Python/src/xpc.py
+++ b/Python/src/xpc.py
@@ -143,7 +143,29 @@ class XPlaneConnect(object):
buffer += struct.pack("= 0)
+ {
+ result = getCTRL(sock, actual, ac);
+ }
+ closeUDP(sock);
+ if (result < 0)
+ {
+ return -1;
+ }
+
+ // Test values
+ for (int i = 0; i < 7; ++i)
+ {
+ if (fabs(expected[i] - actual[i]) > 1e-4)
+ {
+ return -10 - i;
+ }
+ }
+ return 0;
+}
+
int basicCTRLTest(char** drefs, int ac)
{
// Set control surfaces to known state.
@@ -146,4 +173,16 @@ int testCTRL_Speedbrakes()
}
return 0;
}
+
+int testGETC()
+{
+ float CTRL[7] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F, -1.5F };
+ return doGETCTest(CTRL, 0, CTRL);
+}
+
+int testGETC_NonPlayer()
+{
+ float CTRL[7] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F, -1.5F };
+ return doGETCTest(CTRL, 2, CTRL);
+}
#endif
\ No newline at end of file
diff --git a/TestScripts/C Tests/PosiTests.h b/TestScripts/C Tests/PosiTests.h
index d8b5673..a46ca61 100644
--- a/TestScripts/C Tests/PosiTests.h
+++ b/TestScripts/C Tests/PosiTests.h
@@ -40,6 +40,33 @@ int doPOSITest(char* drefs[7], float values[], int size, int ac, float expected[
return compareArray(expected, actual, 7);
}
+int doGETPTest(float values[7], int ac, float expected[7])
+{
+ // Execute Test
+ float actual[7];
+ XPCSocket sock = openUDP(IP);
+ int result = sendPOSI(sock, values, 7, ac);
+ if (result >= 0)
+ {
+ result = getPOSI(sock, actual, ac);
+ }
+ closeUDP(sock);
+ if (result < 0)
+ {
+ return -1;
+ }
+
+ // Test values
+ for (int i = 0; i < 7; ++i)
+ {
+ if (fabs(expected[i] - actual[i]) > 1e-4)
+ {
+ return -10 - i;
+ }
+ }
+ return 0;
+}
+
int basicPOSITest(char** drefs, int ac)
{
// Set psoition and initial orientation
@@ -116,6 +143,16 @@ int testPOSI_NonPlayer()
return basicPOSITest(drefs, 1);
}
+int testGetPOSI_Player()
+{
+ float POSI[7] = { 37.524F, -122.06899F, 2500, 0, 0, 0, 1 };
+ doGETPTest(POSI, 0, POSI);
+}
+int testGetPOSI_NonPlayer()
+{
+ float POSI[7] = { 37.624F, -122.06899F, 1500, 0, 0, 0, 1 };
+ doGETPTest(POSI, 3, POSI);
+}
#endif
\ No newline at end of file
diff --git a/TestScripts/C Tests/main.c b/TestScripts/C Tests/main.c
index 0f5cdd9..26428eb 100644
--- a/TestScripts/C Tests/main.c
+++ b/TestScripts/C Tests/main.c
@@ -40,9 +40,13 @@ int main(int argc, const char * argv[])
runTest(testCTRL_Player, "CTRL (player)");
runTest(testCTRL_NonPlayer, "CTRL (non-player)");
runTest(testCTRL_Speedbrakes, "CTRL (speedbrakes)");
+ runTest(testGETC, "GETC (player)");
+ runTest(testGETC_NonPlayer, "GETC (Non-player)");
// POSI
runTest(testPOSI_Player, "POSI (player)");
runTest(testPOSI_NonPlayer, "POSI (non-player)");
+ runTest(testGetPOSI_Player, "GETP (player)");
+ runTest(testGetPOSI_NonPlayer, "GETP (non-player)");
// Data
runTest(testDATA, "DATA");
// Text
diff --git a/TestScripts/Java Tests/XPlaneConnectTest.java b/TestScripts/Java Tests/XPlaneConnectTest.java
index fc7c76e..2e94bb5 100644
--- a/TestScripts/Java Tests/XPlaneConnectTest.java
+++ b/TestScripts/Java Tests/XPlaneConnectTest.java
@@ -698,4 +698,31 @@ public class XPlaneConnectTest
}
}
+
+ @Test
+ public void testGetPOSI() throws IOException
+ {
+ float[] values = { 37.524F, -122.06899F, 2500.0F, 45.0F, -45.0F, 15.0F, 1.0F };
+ try(XPlaneConnect xpc = new XPlaneConnect())
+ {
+ xpc.pauseSim(true);
+ xpc.sendPOSI(values);
+ float[] actual = xpc.getPOSI(0);
+
+ assertArrayEquals(values, actual, 1e-4F);
+ }
+ }
+
+ @Test
+ public void testGetCTRL() throws IOException
+ {
+ float[] values = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F, -1.5F };
+ try(XPlaneConnect xpc = new XPlaneConnect())
+ {
+ xpc.sendCTRL(values);
+ float[] actual = xpc.getCTRL(0);
+
+ assertArrayEquals(values, actual, 1e-4F);
+ }
+ }
}
\ No newline at end of file
diff --git a/TestScripts/MATLAB Tests/getCTRLTest.m b/TestScripts/MATLAB Tests/getCTRLTest.m
new file mode 100644
index 0000000..3dc74f8
--- /dev/null
+++ b/TestScripts/MATLAB Tests/getCTRLTest.m
@@ -0,0 +1,15 @@
+function getCTRLTest()
+%GETCTRLTEST Summary of this function goes here
+% Detailed explanation goes here
+addpath('../../MATLAB')
+import XPlaneConnect.*
+
+values = [10.0, 5.0, -5.0, 0.8, 1.0, 0.5, -1.5];
+sendCTRL(values, 0);
+actual = getCTRL(0);
+
+assert(isequal(length(actual), length(values)));
+for i = 1:length(actual)
+ assert(abs(actual(i) - values(i)) <1e-4)
+end
+end
diff --git a/TestScripts/MATLAB Tests/getPOSITest.m b/TestScripts/MATLAB Tests/getPOSITest.m
new file mode 100644
index 0000000..c80b79a
--- /dev/null
+++ b/TestScripts/MATLAB Tests/getPOSITest.m
@@ -0,0 +1,17 @@
+function getPOSITest()
+%GETCTRLTEST Summary of this function goes here
+% Detailed explanation goes here
+addpath('../../MATLAB')
+import XPlaneConnect.*
+
+values = [ 37.524, -122.06899, 2500, 45, -45, 15, 1 ];
+pauseSim(1);
+sendPOSI(values, 0);
+actual = getPOSI(0);
+pauseSim(0);
+
+assert(isequal(length(actual), length(values)));
+for i = 1:length(actual)
+ assert(abs(actual(i) - values(i)) <1e-4)
+end
+end
diff --git a/TestScripts/MATLAB Tests/CTRLTest.m b/TestScripts/MATLAB Tests/sendCTRLTest.m
similarity index 98%
rename from TestScripts/MATLAB Tests/CTRLTest.m
rename to TestScripts/MATLAB Tests/sendCTRLTest.m
index 7b8a9bc..0569917 100644
--- a/TestScripts/MATLAB Tests/CTRLTest.m
+++ b/TestScripts/MATLAB Tests/sendCTRLTest.m
@@ -1,4 +1,4 @@
-function CTRLTest( )
+function sendCTRLTest( )
%CTRLTest Summary of this function goes here
% Detailed explanation goes here
%% Test player aircraft
diff --git a/TestScripts/MATLAB Tests/POSITest.m b/TestScripts/MATLAB Tests/sendPOSITest.m
similarity index 96%
rename from TestScripts/MATLAB Tests/POSITest.m
rename to TestScripts/MATLAB Tests/sendPOSITest.m
index 16b6c8d..42a6e15 100644
--- a/TestScripts/MATLAB Tests/POSITest.m
+++ b/TestScripts/MATLAB Tests/sendPOSITest.m
@@ -1,4 +1,4 @@
-function POSITest( )
+function sendPOSITest( )
%POSITest Summary of this function goes here
% Detailed explanation goes here
addpath('../../MATLAB')
diff --git a/TestScripts/MATLAB Tests/tests.m b/TestScripts/MATLAB Tests/tests.m
index 13e0be4..2ef6d5f 100644
--- a/TestScripts/MATLAB Tests/tests.m
+++ b/TestScripts/MATLAB Tests/tests.m
@@ -18,8 +18,10 @@ theTests = {{@openCloseTest, 'Open/Close Test', 0},...
{@getDREFsTest,'Request DREF Test', 0},...
{@sendDREFTest,'Send DREF Test', 0},...
{@DATATest,'DATA Test', 0},...
- {@CTRLTest,'CTRL Test', 0},...
- {@POSITest,'POSI Test', 0},...
+ {@sendCTRLTest,'sendCTRL Test', 0},...
+ {@getCTRLTest,'getCTRL Test', 0},...
+ {@sendPOSITest,'sendPOSI Test', 0},...
+ {@getPOSITest,'getPOSI Test', 0},...
{@sendWYPTTest,'WYPT Test', 0},...
{@sendVIEWTest,'VIEW Test', 0},...
{@pauseTest,'Pause Test', 0},...
diff --git a/TestScripts/Python Tests/Tests.py b/TestScripts/Python Tests/Tests.py
index 2cdc825..8a88d32 100644
--- a/TestScripts/Python Tests/Tests.py
+++ b/TestScripts/Python Tests/Tests.py
@@ -202,6 +202,29 @@ class XPCTests(unittest.TestCase):
expected = 0.0
do_test()
+ def test_getCTRL(self):
+ values = None
+ ac = 0
+ expected = None
+ def do_test():
+ with xpc.XPlaneConnect() as client:
+ # Execute
+ client.sendCTRL(values, ac)
+ result = client.getCTRL(ac)
+
+ # Test
+ self.assertEqual(len(result), len(expected))
+ for a, e in zip(result, expected):
+ self.assertAlmostEqual(a, e, 4)
+
+ values = [0.0, 0.0, 0.0, 0.8, 1.0, 0.5, -1.5]
+ expected = values
+ ac = 0
+ do_test()
+
+ ac = 3
+ do_test()
+
def test_sendCTRL(self):
# Setup
@@ -270,6 +293,31 @@ class XPCTests(unittest.TestCase):
ctrl[6] = 0.0
do_test()
+ def test_getPOSI(self):
+ values = None
+ ac = 0
+ expected = None
+ def do_test():
+ with xpc.XPlaneConnect() as client:
+ # Execute
+ client.pauseSim(True)
+ client.sendPOSI(values, ac)
+ result = client.getPOSI(ac)
+ client.pauseSim(False)
+
+ # Test
+ self.assertEqual(len(result), len(expected))
+ for a, e in zip(result, expected):
+ self.assertAlmostEqual(a, e, 4)
+
+ values = [ 37.524, -122.06899, 2500, 45, -45, 15, 1 ]
+ expected = values
+ ac = 0
+ do_test()
+
+ ac = 3
+ do_test()
+
def test_sendPOSI(self):
# Setup
drefs = ["sim/flightmodel/position/latitude",\
diff --git a/xpcPlugin/DataManager.cpp b/xpcPlugin/DataManager.cpp
index 42048e5..eccb8c2 100644
--- a/xpcPlugin/DataManager.cpp
+++ b/xpcPlugin/DataManager.cpp
@@ -169,8 +169,8 @@ namespace XPC
sprintf(multi, "sim/multiplayer/position/plane%i_gear_deploy", i);
mdrefs[i][DREF_GearDeploy] = XPLMFindDataRef(multi);
sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio", i);
- mdrefs[i][DREF_FlapSetting] = XPLMFindDataRef(multi); // Can't set the actual flap setting on npc aircraft
mdrefs[i][DREF_FlapActual] = XPLMFindDataRef(multi);
+ mdrefs[i][DREF_FlapSetting] = mdrefs[i][DREF_FlapActual]; // Can't set the actual flap setting on npc aircraft
sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio2", i);
mdrefs[i][DREF_FlapActual2] = XPLMFindDataRef(multi);
sprintf(multi, "sim/multiplayer/position/plane%i_spoiler_ratio", i);
@@ -183,6 +183,7 @@ namespace XPC
mdrefs[i][DREF_Sweep] = XPLMFindDataRef(multi);
sprintf(multi, "sim/multiplayer/position/plane%i_throttle", i);
mdrefs[i][DREF_ThrottleActual] = XPLMFindDataRef(multi);
+ mdrefs[i][DREF_ThrottleSet] = mdrefs[i][DREF_ThrottleActual]; // No throttle set for multiplayer planes.
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_pitch", i);
mdrefs[i][DREF_YokePitch] = XPLMFindDataRef(multi);
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_roll", i);
@@ -729,13 +730,13 @@ namespace XPC
// http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf
float q[4];
float halfRad = 0.00872664625997F;
- orient[2] = halfRad * orient[2];
- orient[0] = halfRad * orient[0];
- orient[1] = halfRad * orient[1];
- q[0] = cos(orient[2]) * cos(orient[0]) * cos(orient[1]) + sin(orient[2]) * sin(orient[0]) * sin(orient[1]);
- q[1] = cos(orient[2]) * cos(orient[0]) * sin(orient[1]) - sin(orient[2]) * sin(orient[0]) * cos(orient[1]);
- q[2] = cos(orient[2]) * sin(orient[0]) * cos(orient[1]) + sin(orient[2]) * cos(orient[0]) * sin(orient[1]);
- q[3] = sin(orient[2]) * cos(orient[0]) * cos(orient[1]) - cos(orient[2]) * sin(orient[0]) * sin(orient[1]);
+ float theta = halfRad * orient[0];
+ float phi = halfRad * orient[1];
+ float psi = halfRad * orient[2];
+ q[0] = cos(phi) * cos(theta) * cos(psi) + sin(phi) * sin(theta) * sin(psi);
+ q[1] = sin(phi) * cos(theta) * cos(psi) - cos(phi) * sin(theta) * sin(psi);
+ q[2] = cos(phi) * sin(theta) * cos(psi) + sin(phi) * cos(theta) * sin(psi);
+ q[3] = cos(phi) * cos(theta) * sin(psi) - sin(phi) * sin(theta) * cos(psi);
// If the sim is un-paused, this will overwrite the pitch/roll/yaw
// values set above.
diff --git a/xpcPlugin/MessageHandlers.cpp b/xpcPlugin/MessageHandlers.cpp
index d72b8a8..d94be09 100644
--- a/xpcPlugin/MessageHandlers.cpp
+++ b/xpcPlugin/MessageHandlers.cpp
@@ -55,6 +55,8 @@ namespace XPC
handlers.insert(std::make_pair("TEXT", MessageHandlers::HandleText));
handlers.insert(std::make_pair("WYPT", MessageHandlers::HandleWypt));
handlers.insert(std::make_pair("VIEW", MessageHandlers::HandleView));
+ handlers.insert(std::make_pair("GETC", MessageHandlers::HandleGetC));
+ handlers.insert(std::make_pair("GETP", MessageHandlers::HandleGetP));
// X-Plane data messages
handlers.insert(std::make_pair("DSEL", MessageHandlers::HandleXPlaneData));
handlers.insert(std::make_pair("USEL", MessageHandlers::HandleXPlaneData));
@@ -425,6 +427,43 @@ namespace XPC
}
}
+ void MessageHandlers::HandleGetC(const Message& msg)
+ {
+ const unsigned char* buffer = msg.GetBuffer();
+ std::size_t size = msg.GetSize();
+ if (size != 6)
+ {
+ Log::FormatLine(LOG_ERROR, "GCTL", "Unexpected message length: %u", size);
+ return;
+ }
+ unsigned char aircraft = buffer[5];
+ // TODO(jason-watkins): Get proper printf specifier for unsigned char
+ Log::FormatLine(LOG_TRACE, "GCTL", "Getting control information for aircraft %u", aircraft);
+
+ float throttle[8];
+ unsigned char response[31] = "CTRL";
+ *((float*)(response + 5)) = DataManager::GetFloat(DREF_Elevator, aircraft);
+ *((float*)(response + 9)) = DataManager::GetFloat(DREF_Aileron, aircraft);
+ *((float*)(response + 13)) = DataManager::GetFloat(DREF_Rudder, aircraft);
+ DataManager::GetFloatArray(DREF_ThrottleSet, throttle, 8, aircraft);
+ *((float*)(response + 17)) = throttle[0];
+ if (aircraft == 0)
+ {
+ response[21] = (char)DataManager::GetInt(DREF_GearHandle, aircraft);
+ }
+ else
+ {
+ float mpGear[10];
+ DataManager::GetFloatArray(DREF_GearDeploy, mpGear, 10, aircraft);
+ response[21] = mpGear[0] > 0.5 ? 1 : 0;
+ }
+ *((float*)(response + 22)) = DataManager::GetFloat(DREF_FlapSetting, aircraft);
+ response[26] = aircraft;
+ *((float*)(response + 27)) = DataManager::GetFloat(DREF_SpeedBrakeSet, aircraft);
+
+ sock->SendTo(response, 31, &connection.addr);
+ }
+
void MessageHandlers::HandleGetD(const Message& msg)
{
const unsigned char* buffer = msg.GetBuffer();
@@ -471,6 +510,34 @@ namespace XPC
sock->SendTo(response, cur, &connection.addr);
}
+ void MessageHandlers::HandleGetP(const Message& msg)
+ {
+ const unsigned char* buffer = msg.GetBuffer();
+ std::size_t size = msg.GetSize();
+ if (size != 6)
+ {
+ Log::FormatLine(LOG_ERROR, "GPOS", "Unexpected message length: %u", size);
+ return;
+ }
+ unsigned char aircraft = buffer[5];
+ Log::FormatLine(LOG_TRACE, "GPOS", "Getting position information for aircraft %u", aircraft);
+
+ unsigned char response[34] = "POSI";
+ response[5] = (char)DataManager::GetInt(DREF_GearHandle, aircraft);
+ *((float*)(response + 6)) = (float)DataManager::GetDouble(DREF_Latitude, aircraft);
+ *((float*)(response + 10)) = (float)DataManager::GetDouble(DREF_Longitude, aircraft);
+ *((float*)(response + 14)) = (float)DataManager::GetDouble(DREF_Elevation, aircraft);
+ *((float*)(response + 18)) = DataManager::GetFloat(DREF_Pitch, aircraft);
+ *((float*)(response + 22)) = DataManager::GetFloat(DREF_Roll, aircraft);
+ *((float*)(response + 26)) = DataManager::GetFloat(DREF_HeadingTrue, aircraft);
+
+ float gear[10];
+ DataManager::GetFloatArray(DREF_GearDeploy, gear, 10, aircraft);
+ *((float*)(response + 30)) = gear[0];
+
+ sock->SendTo(response, 34, &connection.addr);
+ }
+
void MessageHandlers::HandlePosi(const Message& msg)
{
// Update log
diff --git a/xpcPlugin/MessageHandlers.h b/xpcPlugin/MessageHandlers.h
index 13742ee..d7f317d 100644
--- a/xpcPlugin/MessageHandlers.h
+++ b/xpcPlugin/MessageHandlers.h
@@ -43,7 +43,9 @@ namespace XPC
static void HandleCtrl(const Message& msg);
static void HandleData(const Message& msg);
static void HandleDref(const Message& msg);
+ static void HandleGetC(const Message& msg);
static void HandleGetD(const Message& msg);
+ static void HandleGetP(const Message& msg);
static void HandlePosi(const Message& msg);
static void HandleSimu(const Message& msg);
static void HandleText(const Message& msg);
diff --git a/xpcPlugin/UDPSocket.cpp b/xpcPlugin/UDPSocket.cpp
index 349f127..210cc56 100644
--- a/xpcPlugin/UDPSocket.cpp
+++ b/xpcPlugin/UDPSocket.cpp
@@ -135,7 +135,7 @@ namespace XPC
}
else
{
- Log::FormatLine(LOG_INFO, tag, "Send failed. (remote: %s)", GetHost(remote).c_str());
+ Log::FormatLine(LOG_INFO, tag, "Send succeeded. (remote: %s)", GetHost(remote).c_str());
}
}