Compare commits

...

1 Commits

Author SHA1 Message Date
gorbit99
0155a461da Add restCalibrationStatus logic to the calibration tutorial 2025-10-01 22:06:43 +02:00
7 changed files with 111 additions and 7 deletions

View File

@@ -971,6 +971,7 @@ onboarding-connect_tracker-next = I connected all my trackers
onboarding-calibration_tutorial = IMU Calibration Tutorial
onboarding-calibration_tutorial-subtitle = This will help reduce tracker drifting!
onboarding-calibration_tutorial-description-v1 = After turning on your trackers, place them on a stable surface for a moment to allow for calibration. Calibration can be performed at any time after the trackers are powered on—this page simply provides a tutorial. To begin, click the "{ onboarding-calibration_tutorial-calibrate }" button, then <b>do not move your trackers!</b>
onboarding-calibration_tutorial-description-no-ready-v1 = After turning on your trackers, place them on a stable surface for a couple seconds to allow for calibration. Calibration can be performed at any time after the trackers are powered on—this page simply provides a tutorial. To begin, put down your trackers, then <b>do not move them!</b>
onboarding-calibration_tutorial-calibrate = I placed my trackers on a table
onboarding-calibration_tutorial-status-waiting = Waiting for you
onboarding-calibration_tutorial-status-calibrating = Calibrating

View File

@@ -14,6 +14,7 @@ import { Vector3 } from 'three';
import { useTimeout } from '@/hooks/timeout';
import { useAtomValue } from 'jotai';
import { connectedIMUTrackersAtom } from '@/store/app-store';
import { RestCalibrationStatus } from 'solarxr-protocol';
export enum CalibrationStatus {
SUCCESS,
@@ -40,9 +41,25 @@ export function CalibrationTutorialPage() {
const connectedIMUTrackers = useAtomValue(connectedIMUTrackersAtom);
const restCalibrationTrackers =
useRestCalibrationTrackers(connectedIMUTrackers);
const useRestCalibrationFlag = useMemo(
() =>
restCalibrationTrackers.length > 0 &&
restCalibrationTrackers.every(
(tracker) =>
tracker.tracker.info?.restCalibrationStatus !==
RestCalibrationStatus.NOT_SUPPORTED
),
[restCalibrationTrackers]
);
const [rested, setRested] = useState(false);
const lastValueMap = useRef(new Map<number, Vector3[]>());
useEffect(() => {
if (useRestCalibrationFlag) {
return;
}
const accelLength = restCalibrationTrackers.every((x) => {
if (
x.tracker.trackerId?.trackerNum === undefined ||
@@ -71,6 +88,29 @@ export function CalibrationTutorialPage() {
}, [restCalibrationTrackers]);
useEffect(() => {
if (!useRestCalibrationFlag) {
return;
}
if (
restCalibrationTrackers.some(
(tracker) =>
tracker.tracker.info?.restCalibrationStatus !==
RestCalibrationStatus.CALIBRATED
)
) {
return;
}
setCalibrationStatus(CalibrationStatus.SUCCESS);
abortCountdown();
}, [restCalibrationTrackers]);
useEffect(() => {
if (useRestCalibrationFlag) {
return;
}
if (calibrationStatus === CalibrationStatus.CALIBRATING && !rested) {
setCalibrationStatus(CalibrationStatus.ERROR);
abortCountdown();
@@ -129,7 +169,11 @@ export function CalibrationTutorialPage() {
</Typography>
</div>
<Localized
id="onboarding-calibration_tutorial-description-v1"
id={
useRestCalibrationFlag
? 'onboarding-calibration_tutorial-description-no-ready-v1'
: 'onboarding-calibration_tutorial-description-v1'
}
elems={{ b: <b></b> }}
>
<Typography>Description on calibration of IMU</Typography>
@@ -177,7 +221,9 @@ export function CalibrationTutorialPage() {
disabled={isCounting || !rested}
className={classNames(
'xs:ml-auto',
CalibrationStatus.SUCCESS === calibrationStatus && 'hidden'
(CalibrationStatus.SUCCESS === calibrationStatus ||
useRestCalibrationFlag) &&
'hidden'
)}
>
{l10n.getString('onboarding-calibration_tutorial-calibrate')}
@@ -187,8 +233,14 @@ export function CalibrationTutorialPage() {
to="/onboarding/assign-tutorial"
className={classNames(
'xs:ml-auto',
CalibrationStatus.SUCCESS !== calibrationStatus && 'hidden'
CalibrationStatus.SUCCESS !== calibrationStatus &&
!useRestCalibrationFlag &&
'hidden'
)}
disabled={
useRestCalibrationFlag &&
calibrationStatus !== CalibrationStatus.SUCCESS
}
>
{l10n.getString('onboarding-continue')}
</Button>

View File

@@ -153,6 +153,12 @@ public class DataFeedBuilder {
TrackerInfo.addDataSupport(fbb, tracker.getTrackerDataType().getSolarType());
TrackerInfo
.addRestCalibrationStatus(
fbb,
tracker.getRestCalibrationStatus().getSolarType()
);
return TrackerInfo.endTrackerInfo(fbb);
}

View File

@@ -6,6 +6,7 @@ import dev.slimevr.tracking.processor.stayaligned.trackers.StayAlignedTrackerSta
import dev.slimevr.tracking.trackers.TrackerPosition.Companion.getByDesignation
import dev.slimevr.tracking.trackers.udp.IMUType
import dev.slimevr.tracking.trackers.udp.MagnetometerStatus
import dev.slimevr.tracking.trackers.udp.RestCalibrationStatus
import dev.slimevr.tracking.trackers.udp.TrackerDataType
import dev.slimevr.util.InterpolationHandler
import io.eiren.util.BufferedTimer
@@ -84,6 +85,7 @@ class Tracker @JvmOverloads constructor(
*/
val trackRotDirection: Boolean = true,
magStatus: MagnetometerStatus = MagnetometerStatus.NOT_SUPPORTED,
restCalibrationStatus: RestCalibrationStatus = RestCalibrationStatus.NOT_SUPPORTED,
/**
* Rotation by default.
* NOT the same as hasRotation (other data types emulate rotation)
@@ -107,6 +109,8 @@ class Tracker @JvmOverloads constructor(
var customName: String? = null
var magStatus: MagnetometerStatus = magStatus
private set
var restCalibrationStatus: RestCalibrationStatus = restCalibrationStatus
private set
/**
* If the tracker has gotten disconnected after it was initialized first time
@@ -474,6 +478,10 @@ class Tracker @JvmOverloads constructor(
}
}
internal fun setRestCalibrationPrivate(status: RestCalibrationStatus) {
restCalibrationStatus = status
}
/**
* Gets the magnetic field vector, in mGauss.
*/

View File

@@ -153,6 +153,30 @@ enum class MagnetometerStatus {
}
}
enum class RestCalibrationStatus {
NOT_SUPPORTED,
NOT_CALIBRATED,
CALIBRATED,
;
fun getSolarType(): Int = this.ordinal
companion object {
private val byId = entries.associateBy { it.ordinal.toUByte() }
@JvmStatic
fun getById(id: UByte): RestCalibrationStatus? = byId[id]
@JvmStatic
fun fromBoolean(value: Boolean?): RestCalibrationStatus =
when (value) {
null -> NOT_SUPPORTED
true -> CALIBRATED
false -> NOT_CALIBRATED
}
}
}
@JvmInline
value class SensorConfig(val v: UShort) {
val magStatus

View File

@@ -174,7 +174,16 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
// Set up new sensor for older firmware.
// Firmware after 7 should send sensor status packet and sensor
// will be created when it's received
setUpSensor(connection, 0, handshake.imuType, 1, MagnetometerStatus.NOT_SUPPORTED, null, TrackerDataType.ROTATION)
setUpSensor(
connection,
0,
handshake.imuType,
1,
MagnetometerStatus.NOT_SUPPORTED,
RestCalibrationStatus.NOT_SUPPORTED,
null,
TrackerDataType.ROTATION,
)
}
connection
}
@@ -186,7 +195,7 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
}
private val mainScope = CoroutineScope(SupervisorJob())
private fun setUpSensor(connection: UDPDevice, trackerId: Int, sensorType: IMUType, sensorStatus: Int, magStatus: MagnetometerStatus, trackerPosition: TrackerPosition?, trackerDataType: TrackerDataType) {
private fun setUpSensor(connection: UDPDevice, trackerId: Int, sensorType: IMUType, sensorStatus: Int, magStatus: MagnetometerStatus, restCalibrationStatus: RestCalibrationStatus, trackerPosition: TrackerPosition?, trackerDataType: TrackerDataType) {
LogManager.info("[TrackerServer] Sensor $trackerId for ${connection.name} status: $sensorStatus")
var imuTracker = connection.getTracker(trackerId)
if (imuTracker == null) {
@@ -214,6 +223,7 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
needsMounting = true,
usesTimeout = true,
magStatus = magStatus,
restCalibrationStatus = restCalibrationStatus,
trackerDataType = trackerDataType,
)
connection.trackers[trackerId] = imuTracker
@@ -223,7 +233,6 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
val status = UDPPacket15SensorInfo.getStatus(sensorStatus)
if (status != null) imuTracker.status = status
if (magStatus == MagnetometerStatus.NOT_SUPPORTED) return
if (magStatus == MagnetometerStatus.ENABLED &&
(!VRServer.instance.configManager.vrConfig.server.useMagnetometerOnAllTrackers || imuTracker.config.shouldHaveMagEnabled == false)
) {
@@ -241,6 +250,8 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
}
}
}
imuTracker.setRestCalibrationPrivate(restCalibrationStatus)
}
private data class ConfigStateWaiter(
@@ -475,12 +486,14 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
is UDPPacket15SensorInfo -> {
if (connection == null) return
val magStatus = packet.sensorConfig?.magStatus ?: MagnetometerStatus.NOT_SUPPORTED
val restCalibrationStatus = RestCalibrationStatus.fromBoolean(packet.hasCompletedRestCalibration)
setUpSensor(
connection,
packet.sensorId,
packet.sensorType,
packet.sensorStatus,
magStatus,
restCalibrationStatus,
packet.trackerPosition,
packet.trackerDataType,
)