Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions DJIOsmoKit/Location/OsmoLocationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
import Observation
import OSLog

/// Manages Core Location updates and pushes GPS data to all connected cameras at 1 Hz.
/// Manages Core Location updates and pushes GPS data to all connected cameras at 10 Hz.
///
/// `OsmoLocationManager` is `@Observable` so SwiftUI views can react to
/// `isActive` and `lastLocation` changes. It is `@MainActor` to match
Expand All @@ -12,7 +12,7 @@ import OSLog
/// Usage:
/// ```swift
/// let locationManager = OsmoLocationManager(cameraManager: .shared)
/// locationManager.start() // begins CL updates + 1 Hz GPS push
/// locationManager.start() // begins CL updates + 10 Hz GPS push
/// locationManager.stop() // stops everything
/// ```
@Observable
Expand All @@ -27,6 +27,9 @@ public final class OsmoLocationManager: NSObject {
/// The most recent location received from Core Location.
public private(set) var lastLocation: CLLocation?

/// Time of the most recent GPS frame pushed to connected cameras.
public private(set) var lastPushAt: Date?

/// Current Core Location authorization status.
public var authorizationStatus: CLAuthorizationStatus {
locationManager.authorizationStatus
Expand Down Expand Up @@ -59,8 +62,8 @@ public final class OsmoLocationManager: NSObject {
locationManager.startUpdatingLocation()
isActive = true

// 1 Hz push timer on the main run loop
pushTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
// 10 Hz push timer on the main run loop
pushTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
Task { @MainActor in
self?.pushGPSToAllCameras()
}
Expand Down Expand Up @@ -90,8 +93,13 @@ public final class OsmoLocationManager: NSObject {
return
}
let targets = manager.enabledConnectedCameras.count
guard targets > 0 else {
OsmoLog.location.debug("GPS push skipped: no connected cameras")
return
}
OsmoLog.location.debug("GPS push → \(targets) camera(s) @ \(String(format: "%.6f", location.coordinate.latitude), privacy: .private),\(String(format: "%.6f", location.coordinate.longitude), privacy: .private)")
manager.pushGPS(location)
lastPushAt = Date()
}
}

Expand Down
13 changes: 10 additions & 3 deletions DJIOsmoKit/Protocol/Commands/GPSPushCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ enum GPSPushCommand {
// DJI protocol requires timestamps in UTC+8 (China Standard Time).
// This matches the reference implementation in dji-sdk/Osmo-GPS-Controller-Demo.
// The camera interprets all GPS timestamps as CST regardless of the user's locale.
cal.timeZone = TimeZone(secondsFromGMT: 8 * 3600)!
cal.timeZone = TimeZone(secondsFromGMT: 0 * 3600)!
let comps = cal.dateComponents(
[.year, .month, .day, .hour, .minute, .second],
from: location.timestamp
Expand Down Expand Up @@ -68,8 +68,15 @@ enum GPSPushCommand {
payload.writeLE(vAcc, at: 32)
payload.writeLE(hAcc, at: 36)
payload.writeLE(sAcc, at: 40)
payload.writeLE(UInt32(0), at: 44) // satellite_number (unavailable from CLLocation)

payload.writeLE(UInt32(8), at: 44) // fake satellite_number; CLLocation does not provide this

OsmoLog.location.debug("""
GPS accuracy:
verticalAccuracy=\(location.verticalAccuracy)m -> vAcc=\(vAcc)mm
horizontalAccuracy=\(location.horizontalAccuracy)m -> hAcc=\(hAcc)mm
speedAccuracy=\(location.speedAccuracy)m/s -> sAcc=\(sAcc)cm/s
""")

return FrameBuilder.build(OutgoingFrame(
cmdType: 0x00, // fire-and-forget, no response expected
seq: seq,
Expand Down