Merge branch 'master' into develop

# Conflicts:
#	xpcPlugin/XPlaneConnect/mac.xpl
#	xpcPlugin/xpcPlugin.xcodeproj/project.pbxproj
This commit is contained in:
Chris Teubert
2016-02-29 12:48:30 -08:00
parent 8d5af7e47e
commit cfdd183214
100 changed files with 4224 additions and 1912 deletions

60
Java/src/ViewType.java Normal file
View File

@@ -0,0 +1,60 @@
//NOTICES:
// Copyright <20> 2013-2015 United States Government as represented by the Administrator of the
// National Aeronautics and Space Administration. All Rights Reserved.
//
// DISCLAIMERS
// No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND,
// EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE
// SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT
// SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO
// THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY
// GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE,
// SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE.
// FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY
// SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."
//
// Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES
// GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF
// RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES,
// EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR
// RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD
// HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY
// PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER
// SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
package gov.nasa.xpc;
/**
* Represents a camera view in X-Plane
*
* @author Jason Watkins
* @version 1.1
* @since 2015-05-08
*/
public enum ViewType
{
Forwards(73),
Down(74),
Left(75),
Right(76),
Back(77),
Tower(78),
Runway(79),
Chase(80),
Follow(81),
FollowWithPanel(82),
Spot(83),
FullscreenWithHud(84),
FullscreenNoHud(85);
private final int value;
private ViewType(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}

View File

@@ -331,46 +331,114 @@ public class XPlaneConnect implements AutoCloseable
* @throws IOException If the command cannot be sent.
*/
public void sendDREF(String dref, float[] value) throws IOException
{
sendDREFs(new String[] {dref}, new float[][] {value});
}
/**
* Sends a command to X-Plane that sets the given DREF.
*
* @param drefs The names of the X-Plane datarefs to set.
* @param values A sequence of arrays of floating point values whose structure depends on the drefs specified.
* @throws IOException If the command cannot be sent.
*/
public void sendDREFs(String[] drefs, float[][] values) throws IOException
{
//Preconditions
if(dref == null)
if(drefs == null || drefs.length == 0)
{
throw new IllegalArgumentException("dref must be a valid string.");
throw new IllegalArgumentException(("drefs must be non-empty."));
}
if(value == null || value.length == 0)
if(values == null || values.length != drefs.length)
{
throw new IllegalArgumentException("value must be non-null and should contain at least one value.");
throw new IllegalArgumentException("values must be of the same size as drefs.");
}
//Convert drefs to bytes.
byte[] drefBytes = dref.getBytes(StandardCharsets.UTF_8);
if(drefBytes.length == 0)
{
throw new IllegalArgumentException("DREF is an empty string!");
}
if(drefBytes.length > 255)
{
throw new IllegalArgumentException("dref must be less than 255 bytes in UTF-8. Are you sure this is a valid dref?");
}
ByteBuffer bb = ByteBuffer.allocate(4 * value.length);
bb.order(ByteOrder.LITTLE_ENDIAN);
for(int i = 0; i < value.length; ++i)
{
bb.putFloat(i * 4, value[i]);
}
//Build and send message
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write("DREF".getBytes(StandardCharsets.UTF_8));
os.write(0xFF); //Placeholder for message length
os.write(drefBytes.length);
os.write(drefBytes, 0, drefBytes.length);
os.write(value.length);
os.write(bb.array());
for(int i = 0; i < drefs.length; ++i)
{
String dref = drefs[i];
float[] value = values[i];
if (dref == null)
{
throw new IllegalArgumentException("dref must be a valid string.");
}
if (value == null || value.length == 0)
{
throw new IllegalArgumentException("value must be non-null and should contain at least one value.");
}
//Convert drefs to bytes.
byte[] drefBytes = dref.getBytes(StandardCharsets.UTF_8);
if (drefBytes.length == 0)
{
throw new IllegalArgumentException("DREF is an empty string!");
}
if (drefBytes.length > 255)
{
throw new IllegalArgumentException("dref must be less than 255 bytes in UTF-8. Are you sure this is a valid dref?");
}
ByteBuffer bb = ByteBuffer.allocate(4 * value.length);
bb.order(ByteOrder.LITTLE_ENDIAN);
for (int j = 0; j < value.length; ++j)
{
bb.putFloat(j * 4, value[j]);
}
//Build and send message
os.write(drefBytes.length);
os.write(drefBytes, 0, drefBytes.length);
os.write(value.length);
os.write(bb.array());
}
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.
*
@@ -382,6 +450,7 @@ public class XPlaneConnect implements AutoCloseable
* <li>Throttle [-1, 1]</li>
* <li>Gear (0=up, 1=down)</li>
* <li>Flaps [0, 1]</li>
* <li>Speedbrakes [-0.5, 1.5]</li>
* </ol>
* <p>
* If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To
@@ -406,6 +475,7 @@ public class XPlaneConnect implements AutoCloseable
* <li>Throttle [-1, 1]</li>
* <li>Gear (0=up, 1=down)</li>
* <li>Flaps [0, 1]</li>
* <li>Speedbrakes [-0.5, 1.5]</li>
* </ol>
* <p>
* If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To
@@ -440,7 +510,14 @@ public class XPlaneConnect implements AutoCloseable
{
if(i == 4)
{
bb.put(cur, (byte) values[i]);
if(i >= values.length)
{
bb.put(cur, (byte)-1);
}
else
{
bb.put(cur, (byte)values[i]);
}
cur += 1;
}
else if (i >= values.length)
@@ -465,6 +542,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.
*
@@ -693,6 +808,26 @@ public class XPlaneConnect implements AutoCloseable
sendUDP(os.toByteArray());
}
/**
* Sets the camera view in X-Plane.
*
* @param view The view to use.
* @throws IOException If the command cannot be sent.
*/
public void sendVIEW(ViewType view) throws IOException
{
ByteBuffer bb = ByteBuffer.allocate(4);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(view.getValue());
//Build and send message
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write("VIEW".getBytes(StandardCharsets.UTF_8));
os.write(0xFF); //Placeholder for message length
os.write(bb.array());
sendUDP(os.toByteArray());
}
/**
* Adds, removes, or clears a set of waypoints. If the command is clear, the points are ignored
* and all points are removed.