Skip to content

Commit

Permalink
Merge pull request #9 from ericjohnson97/feature/jsbsim_support
Browse files Browse the repository at this point in the history
JSBsim Support
  • Loading branch information
ericjohnson97 authored Jun 10, 2024
2 parents e734b56 + 1b84c69 commit ec04020
Show file tree
Hide file tree
Showing 16 changed files with 805 additions and 58 deletions.
43 changes: 39 additions & 4 deletions Assets/Scenes/ImageGenerator.unity
Original file line number Diff line number Diff line change
Expand Up @@ -10973,7 +10973,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
georeference: {fileID: 1628688806}
droneController: {fileID: 0}
isDynamicCameraSpawned: 0
droneTemplate: {fileID: 200453354}
mavlinkMessageProcessor: {fileID: 110319845}
currentOriginECEF:
Expand Down Expand Up @@ -11015,6 +11015,7 @@ MonoBehaviour:
tileURL:
mavlink2RestURL:
vehicles: []
worldController: {fileID: 110319846}
--- !u!114 &110319849
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -11115,6 +11116,8 @@ GameObject:
m_Component:
- component: {fileID: 200453355}
- component: {fileID: 200453357}
- component: {fileID: 200453358}
- component: {fileID: 200453359}
m_Layer: 0
m_Name: drone
m_TagString: Untagged
Expand Down Expand Up @@ -11149,7 +11152,7 @@ MonoBehaviour:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 200453354}
m_Enabled: 1
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 74d8ba08a3a6db2479ae04677a87515b, type: 3}
m_Name:
Expand All @@ -11161,6 +11164,38 @@ MonoBehaviour:
latLonAlt: {x: 0, y: 0, z: 0}
alpha: 0.98
positionAlpha: 0.99
--- !u!114 &200453358
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 200453354}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d860125edf05d204db373663b8bb979e, type: 3}
m_Name:
m_EditorClassIdentifier:
georeference: {fileID: 0}
jsbUDPReceiver: {fileID: 0}
drone: {fileID: 0}
systemId: 1
latLonAlt: {x: 0, y: 0, z: 0}
alpha: 0.98
positionAlpha: 0.98
--- !u!114 &200453359
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 200453354}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45d4fc40122054c4b9d035bf9999e32f, type: 3}
m_Name:
m_EditorClassIdentifier:
port: 12345
--- !u!1001 &254928480
PrefabInstance:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -12225,7 +12260,7 @@ Light:
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_Intensity: 0.8
m_Intensity: 0.5
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
Expand Down Expand Up @@ -13210,7 +13245,7 @@ Camera:
width: 1
height: 1
near clip plane: 0.5
far clip plane: 1000000
far clip plane: 30000
field of view: 60
orthographic: 0
orthographic size: 5
Expand Down
43 changes: 42 additions & 1 deletion Assets/Scripts/ConfigLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public class Config
[System.Serializable]
public class VehicleConfig
{
public bool jsbsim = false;
public string type = "NONE";
public int port = 12345;
public int id;
public CameraConfig[] cameras;
}
Expand All @@ -35,6 +38,8 @@ public class ConfigLoader : MonoBehaviour

public Config config;

public WorldController worldController;

private void Start()
{
LoadConfig();
Expand All @@ -57,10 +62,46 @@ private void LoadConfig()
}
}


// {
// "tileURL": "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCLQrJ7iJvSyCcs5MCQwINWxLrtu9tlnfA",
// "mavlink2RestURL" : "wss://sim.intelligentquads.com/60e8797ec8e541c2b50b191c4fda7d9c",
// "vehicles" : [
// {
// "jsbsim" : false
// "id" : 1,
// "cameras" : [
// {
// "id": 1,
// "position" : [3, 0, 0],
// "orientation" : [0, 0, 0],
// "vFOV" : 26,
// "streamingEnabled" : "false",
// "encoding" : "H264Nvidia",
// "destination" : "udp://127.0.0.1:5600"
// }
// ]
// }
// ]

// }
private void ApplySettings(Config config)
{
// Apply settings to tileset and mavlinkWS as before.
tileset.url = config.tileURL;
mavlinkWS.Connect(config.mavlink2RestURL);

for (int i = 0; i < config.vehicles.Length; i++)
{
VehicleConfig vehicleConfig = config.vehicles[i];
if (vehicleConfig.jsbsim)
{
Debug.Log("JSBSim vehicle detected. config: " + JsonUtility.ToJson(vehicleConfig, true));
worldController.SpawnDrone(vehicleConfig.id, vehicleConfig.type, vehicleConfig.port);
}



}
}
}
}
28 changes: 28 additions & 0 deletions Assets/Scripts/DroneController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class DroneController : MonoBehaviour
public MavlinkMessageProcessor mavlinkMessageProcessor;
public GameObject drone;

private bool dynamicCameraController = false;

public int systemId = 1;
public Vector3 latLonAlt = new Vector3(0, 0, 0);

Expand All @@ -18,6 +20,26 @@ public class DroneController : MonoBehaviour

private Quaternion lastOrientation = Quaternion.identity;

private double3 currentOriginECEF = new double3(0, 0, 0);

public void setAsDynamicCameraController()
{
dynamicCameraController = true;
}

private void updateWorldOriginIfNeeded(double newLongitude, double newLatitude, double newAltitude)
{
double3 newPositionECEF = CesiumForUnity.CesiumWgs84Ellipsoid.LongitudeLatitudeHeightToEarthCenteredEarthFixed(new double3(newLongitude, newLatitude, newAltitude));
double distance = math.distance(currentOriginECEF, newPositionECEF);

if (distance > 100000)
{
georeference.SetOriginLongitudeLatitudeHeight(newLongitude, newLatitude, newAltitude);
currentOriginECEF = newPositionECEF;
Debug.Log("World origin updated to drone's current location.");
}
}

private void updatellaPos()
{
latLonAlt.x = mavlinkMessageProcessor.globalPositionIntArray[systemId].message.lat / 1e7f;
Expand Down Expand Up @@ -140,6 +162,12 @@ private void FixedUpdate()

// Store the last known orientation
lastOrientation = drone.transform.rotation;

if (dynamicCameraController)
{
// Update the georeference's origin if the drone has moved significantly
updateWorldOriginIfNeeded(latLonAlt.y, latLonAlt.x, latLonAlt.z);
}
}

}
8 changes: 8 additions & 0 deletions Assets/Scripts/JSBSim.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

171 changes: 171 additions & 0 deletions Assets/Scripts/JSBSim/JSBSimDroneController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System;
using UnityEngine;
using Unity.Mathematics;

public class JSBSimDroneController : MonoBehaviour
{
public CesiumForUnity.CesiumGeoreference georeference;

private bool dynamicCameraController = false;
public JSBUDPReceiver jsbUDPReceiver;
public GameObject drone;

public int systemId = 1;
public Vector3 latLonAlt = new Vector3(0, 0, 0);

public float alpha = 0.98f;
public float positionAlpha = 0.98f;
private string aircraftType = "NONE";
private Vector3 nedPos = new Vector3(0, 0, 0);

private Quaternion lastOrientation = Quaternion.identity;

private double3 currentOriginECEF = new double3(0, 0, 0);


public void setUpJSBReceiver(JSBUDPReceiver rec, int connectionPort)
{
jsbUDPReceiver = rec;
jsbUDPReceiver.port = connectionPort;
jsbUDPReceiver.SetupConnection();

}

public void setAsDynamicCameraController()
{
dynamicCameraController = true;
}

private void updateWorldOriginIfNeeded(double newLongitude, double newLatitude, double newAltitude)
{
double3 newPositionECEF = CesiumForUnity.CesiumWgs84Ellipsoid.LongitudeLatitudeHeightToEarthCenteredEarthFixed(new double3(newLongitude, newLatitude, newAltitude));
double distance = math.distance(currentOriginECEF, newPositionECEF);

if (distance > 100000)
{
georeference.SetOriginLongitudeLatitudeHeight(newLongitude, newLatitude, newAltitude);
currentOriginECEF = newPositionECEF;
Debug.Log("World origin updated to drone's current location.");
}
}

public Vector3 ConvertGeoToUnityCoordinates(double longitude, double latitude, double altitude)
{
// Step 1: Convert to ECEF
double3 longitudeLatitudeHeight = new double3(longitude, latitude, altitude);
double3 ecef = CesiumForUnity.CesiumWgs84Ellipsoid.LongitudeLatitudeHeightToEarthCenteredEarthFixed(longitudeLatitudeHeight);

// subtrace

// Step 2: Transform ECEF to Unity coordinates
double3 unityCoords = georeference.TransformEarthCenteredEarthFixedPositionToUnity(ecef);

// Return as Vector3 for Unity
return new Vector3((float)unityCoords.x, (float)unityCoords.y, (float)unityCoords.z);
}
private void calculateNedPos()
{
nedPos = ConvertGeoToUnityCoordinates(latLonAlt.y, latLonAlt.x, latLonAlt.z);
}

// TODO: make the dynamic loading of the aircraft mesh better
public void UpdateAircraftType(string type)
{

// Show the right mesh
Transform planeTransform = drone.transform.Find("plane");
Transform copterTransform = drone.transform.Find("copter");

if (planeTransform == null || copterTransform == null)
{
Debug.LogError("One of the required GameObjects (plane or copter) is missing in the children of " + drone.name);
return;
}

if (type == "MAV_TYPE_FIXED_WING")
{
planeTransform.gameObject.SetActive(true);
copterTransform.gameObject.SetActive(false);
}
else if (type == "MAV_TYPE_QUADROTOR")
{
copterTransform.gameObject.SetActive(true);
planeTransform.gameObject.SetActive(false);
}
}


private void FixedUpdate()
{
// Retrieve the FGNetFDM packet
FGNetFDM aircraftState = jsbUDPReceiver.AircraftState;

UpdatePosition(aircraftState);
UpdateOrientation(aircraftState);

if (dynamicCameraController)
{
// Update the georeference's origin if the drone has moved significantly
updateWorldOriginIfNeeded(aircraftState.longitude * Mathf.Rad2Deg, aircraftState.latitude * Mathf.Rad2Deg, aircraftState.altitude);
}
}

private void UpdatePosition(FGNetFDM aircraftState)
{
// Convert velocities from m/s to Unity units per second and integrate to get position
Vector3 velocityChange = new Vector3(
aircraftState.v_east,
-aircraftState.v_down,
aircraftState.v_north
) * Time.fixedDeltaTime;

Vector3 integratedPosition = drone.transform.position + velocityChange;

// Update NED position
Vector3 nedPoslla = new Vector3(
(float)aircraftState.longitude * Mathf.Rad2Deg,
(float)aircraftState.latitude * Mathf.Rad2Deg,
(float)aircraftState.altitude
);

nedPos = ConvertGeoToUnityCoordinates(nedPoslla.x, nedPoslla.y, nedPoslla.z);

// Apply the complementary filter for position
Vector3 filteredPosition = Vector3.Lerp(integratedPosition, nedPos, 1 - positionAlpha);

// Update the GameObject's position
drone.transform.position = filteredPosition;
}

private void UpdateOrientation(FGNetFDM aircraftState)
{
// Convert angular velocities from rad/s to degrees/s
float rollDegreesPerSecond = aircraftState.phidot * Mathf.Rad2Deg;
float pitchDegreesPerSecond = aircraftState.thetadot * Mathf.Rad2Deg;
float yawDegreesPerSecond = aircraftState.psidot * Mathf.Rad2Deg;

// Calculate change in orientation based on angular velocity
Quaternion gyroDeltaRotation = Quaternion.Euler(
-pitchDegreesPerSecond * Time.fixedDeltaTime,
yawDegreesPerSecond * Time.fixedDeltaTime,
-rollDegreesPerSecond * Time.fixedDeltaTime
);

// Apply the gyro-based orientation change to the last known orientation
Quaternion gyroBasedOrientation = lastOrientation * gyroDeltaRotation;

// Convert the estimated orientation from Euler angles to a Quaternion
Quaternion sensorBasedOrientation = Quaternion.Euler(
-aircraftState.theta * Mathf.Rad2Deg,
aircraftState.psi * Mathf.Rad2Deg,
-aircraftState.phi * Mathf.Rad2Deg
);

// Apply the complementary filter
drone.transform.rotation = Quaternion.Slerp(gyroBasedOrientation, sensorBasedOrientation, 1 - alpha);

// Store the last known orientation
lastOrientation = drone.transform.rotation;
}

}
Loading

0 comments on commit ec04020

Please sign in to comment.