mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Compare commits
1 Commits
TheButlah-
...
rest-calib
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0155a461da |
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -153,6 +153,12 @@ public class DataFeedBuilder {
|
||||
|
||||
TrackerInfo.addDataSupport(fbb, tracker.getTrackerDataType().getSolarType());
|
||||
|
||||
TrackerInfo
|
||||
.addRestCalibrationStatus(
|
||||
fbb,
|
||||
tracker.getRestCalibrationStatus().getSolarType()
|
||||
);
|
||||
|
||||
return TrackerInfo.endTrackerInfo(fbb);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
Submodule solarxr-protocol updated: df26226d10...4f64cb3a8c
Reference in New Issue
Block a user