xp12camera
Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/xp12camera.git
lockon
Commit 1bf77dfaeadf64a27e227c2ba4f2f8daf5165d17 by SM <seb.michalk@gmail.com> on 2025-06-25 20:30:36 +0200
diff --git a/FLIR_LockOn.cpp b/FLIR_LockOn.cpp
index 0925a61..47a393e 100644
--- a/FLIR_LockOn.cpp
+++ b/FLIR_LockOn.cpp
@@ -2,11 +2,12 @@
* FLIR_LockOn.cpp
*
* Real-world lock-on system for FLIR camera
- * Implements proper target acquisition and tracking like military systems
+ * Implements proper world-space target tracking using X-Plane's coordinate system
*/
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
@@ -14,13 +15,14 @@
#include "XPLMDataAccess.h"
#include "XPLMUtilities.h"
+#include "XPLMGraphics.h"
#include "FLIR_LockOn.h"
-// Lock-on state
+// Lock-on state - using OpenGL local coordinates for precision
static int gLockOnActive = 0;
-static float gTargetBearing = 0.0f; // Absolute bearing to target (degrees)
-static float gTargetElevation = 0.0f; // Elevation angle to target (degrees)
-static float gTargetRange = 0.0f; // Range to target (meters)
+static double gTargetX = 0.0; // Target X in OpenGL coordinates (East)
+static double gTargetY = 0.0; // Target Y in OpenGL coordinates (Up)
+static double gTargetZ = 0.0; // Target Z in OpenGL coordinates (South)
static float gLockAcquisitionTime = 0.0f; // Time when lock was acquired
// Aircraft position datarefs
@@ -51,63 +53,95 @@ void SetArbitraryLockPoint(float currentPan, float currentTilt, float distance)
return;
}
- // Get current aircraft position and heading
+ // Get current aircraft position in OpenGL coordinates
+ double planeX = XPLMGetDataf(gPlaneX);
+ double planeY = XPLMGetDataf(gPlaneY);
+ double planeZ = XPLMGetDataf(gPlaneZ);
float planeHeading = XPLMGetDataf(gPlaneHeading);
- // Calculate absolute target bearing and elevation
- // Real-world systems store bearing/elevation relative to magnetic north
- gTargetBearing = planeHeading + currentPan;
- gTargetElevation = currentTilt;
- gTargetRange = distance;
- gLockAcquisitionTime = XPLMGetDataf(XPLMFindDataRef("sim/time/total_running_time_sec"));
+ // Calculate camera position (belly-mounted, slightly forward)
+ float headingRad = planeHeading * M_PI / 180.0f;
+ double cameraX = planeX + 3.0 * sin(headingRad); // 3m forward
+ double cameraY = planeY - 5.0; // 5m below
+ double cameraZ = planeZ + 3.0 * cos(headingRad); // Note: Z+ is south
+
+ // Calculate absolute camera direction
+ float absoluteHeading = planeHeading + currentPan;
+ float headingRadAbs = absoluteHeading * M_PI / 180.0f;
+ float pitchRad = currentTilt * M_PI / 180.0f;
- // Normalize bearing to 0-360 degrees
- while (gTargetBearing >= 360.0f) gTargetBearing -= 360.0f;
- while (gTargetBearing < 0.0f) gTargetBearing += 360.0f;
+ // Calculate target point in OpenGL coordinates
+ // X-Plane: X=East, Y=Up, Z=South, camera starts facing -Z (north)
+ double horizontalDistance = distance * cos(pitchRad);
+ gTargetX = cameraX + horizontalDistance * sin(headingRadAbs); // East component
+ gTargetY = cameraY + distance * sin(pitchRad); // Altitude component
+ gTargetZ = cameraZ - horizontalDistance * cos(headingRadAbs); // South component (note minus for north)
+ gLockAcquisitionTime = XPLMGetDataf(XPLMFindDataRef("sim/time/total_running_time_sec"));
gLockOnActive = 1;
char msg[256];
- sprintf(msg, "FLIR Lock-On: Target acquired - Bearing %.1f°, Elevation %.1f°, Range %.0fm\n",
- gTargetBearing, gTargetElevation, gTargetRange);
+ sprintf(msg, "FLIR Lock-On: Target acquired at OpenGL coords (%.1f, %.1f, %.1f)\n",
+ gTargetX, gTargetY, gTargetZ);
XPLMDebugString(msg);
}
void UpdateCameraToLockPoint(float* outPan, float* outTilt)
{
- if (!gLockOnActive || !gPlaneHeading) {
+ if (!gLockOnActive || !gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading) {
return;
}
- // Get current aircraft heading
- float currentHeading = XPLMGetDataf(gPlaneHeading);
+ // Get current aircraft position and heading
+ double planeX = XPLMGetDataf(gPlaneX);
+ double planeY = XPLMGetDataf(gPlaneY);
+ double planeZ = XPLMGetDataf(gPlaneZ);
+ float planeHeading = XPLMGetDataf(gPlaneHeading);
+
+ // Calculate current camera position (same as in SetArbitraryLockPoint)
+ float headingRad = planeHeading * M_PI / 180.0f;
+ double cameraX = planeX + 3.0 * sin(headingRad); // 3m forward
+ double cameraY = planeY - 5.0; // 5m below
+ double cameraZ = planeZ + 3.0 * cos(headingRad); // Note: Z+ is south
- // Calculate required camera pan to maintain lock on target bearing
- // Pan = Target Bearing - Aircraft Heading
- *outPan = gTargetBearing - currentHeading;
+ // Calculate vector from camera to target
+ double dx = gTargetX - cameraX; // East component
+ double dy = gTargetY - cameraY; // Up component
+ double dz = gTargetZ - cameraZ; // South component
- // Normalize pan angle to -180 to +180 degrees for natural camera movement
+ // Calculate distance to target
+ double horizontalDist = sqrt(dx * dx + dz * dz);
+ double totalDist = sqrt(dx * dx + dy * dy + dz * dz);
+
+ if (totalDist < 1.0) {
+ // Target too close, maintain current angles
+ return;
+ }
+
+ // Convert vector to spherical coordinates
+ // X-Plane: Camera faces -Z initially (north), X=East, Z=South
+ float targetHeading = atan2(dx, -dz) * 180.0f / M_PI; // Note: -dz for north=0°
+ float targetPitch = atan2(dy, horizontalDist) * 180.0f / M_PI;
+
+ // Convert absolute heading to relative camera pan
+ *outPan = targetHeading - planeHeading;
+ *outTilt = targetPitch;
+
+ // Normalize pan angle to -180 to +180 degrees
while (*outPan > 180.0f) *outPan -= 360.0f;
while (*outPan < -180.0f) *outPan += 360.0f;
- // Elevation stays constant (target doesn't move up/down)
- *outTilt = gTargetElevation;
-
- // Clamp to camera physical limits
+ // Clamp to camera physical limits
if (*outPan > 180.0f) *outPan = 180.0f;
if (*outPan < -180.0f) *outPan = -180.0f;
if (*outTilt > 45.0f) *outTilt = 45.0f;
if (*outTilt < -90.0f) *outTilt = -90.0f;
- // Optional: Add slight tracking drift for realism
- float currentTime = XPLMGetDataf(XPLMFindDataRef("sim/time/total_running_time_sec"));
- float lockDuration = currentTime - gLockAcquisitionTime;
-
- // Small drift after 30 seconds (realistic for long-range tracking)
- if (lockDuration > 30.0f) {
- float drift = (lockDuration - 30.0f) * 0.01f; // 0.01 degrees per second
- *outPan += drift * sin(currentTime * 0.1f); // Small oscillation
- }
+ // Debug output for testing
+ char debugMsg[256];
+ sprintf(debugMsg, "FLIR Track: Dist=%.1fm, TargetHdg=%.1f°, Pan=%.1f°, Pitch=%.1f°\n",
+ totalDist, targetHeading, *outPan, *outTilt);
+ XPLMDebugString(debugMsg);
}
void DisableLockOn()
@@ -129,7 +163,28 @@ void GetLockOnStatus(char* statusBuffer, int bufferSize)
return;
}
- snprintf(statusBuffer, bufferSize, "LOCK: BRG %.0f° EL %.0f° RNG %.0fm",
- gTargetBearing, gTargetElevation, gTargetRange);
+ // Calculate current distance to target
+ if (gPlaneX && gPlaneY && gPlaneZ) {
+ double planeX = XPLMGetDataf(gPlaneX);
+ double planeY = XPLMGetDataf(gPlaneY);
+ double planeZ = XPLMGetDataf(gPlaneZ);
+
+ // Calculate camera position
+ float planeHeading = XPLMGetDataf(gPlaneHeading);
+ float headingRad = planeHeading * M_PI / 180.0f;
+ double cameraX = planeX + 3.0 * sin(headingRad);
+ double cameraY = planeY - 5.0;
+ double cameraZ = planeZ + 3.0 * cos(headingRad);
+
+ // Calculate distance to target
+ double dx = gTargetX - cameraX;
+ double dy = gTargetY - cameraY;
+ double dz = gTargetZ - cameraZ;
+ double distance = sqrt(dx * dx + dy * dy + dz * dz);
+
+ snprintf(statusBuffer, bufferSize, "LOCK: ON RNG %.0fm", distance);
+ } else {
+ strncpy(statusBuffer, "LOCK: ON", bufferSize - 1);
+ }
statusBuffer[bufferSize - 1] = '\0';
}
\ No newline at end of file
diff --git a/FLIR_LockOn.o b/FLIR_LockOn.o
index 2f5e853..985c44c 100644
Binary files a/FLIR_LockOn.o and b/FLIR_LockOn.o differ
diff --git a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl
index b120c1e..074e29f 100755
Binary files a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl and b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl differ