✨ Adds imu calibration
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
export enum MessageTopic {
|
export enum MessageTopic {
|
||||||
imu = 'imu',
|
imu = 'imu',
|
||||||
|
imuCalibrate = 'imuCalibrate',
|
||||||
mode = 'mode',
|
mode = 'mode',
|
||||||
input = 'input',
|
input = 'input',
|
||||||
analytics = 'analytics',
|
analytics = 'analytics',
|
||||||
@@ -160,6 +161,10 @@ export type IMUMsg = {
|
|||||||
bmp: [number, number, number, boolean]
|
bmp: [number, number, number, boolean]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type IMUCalibrationResult = {
|
||||||
|
success: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface I2CDevice {
|
export interface I2CDevice {
|
||||||
address: number
|
address: number
|
||||||
part_number: string
|
part_number: string
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { slide } from 'svelte/transition'
|
import { slide } from 'svelte/transition'
|
||||||
import { onDestroy, onMount } from 'svelte'
|
import { onDestroy, onMount } from 'svelte'
|
||||||
import { socket } from '$lib/stores'
|
import { socket } from '$lib/stores'
|
||||||
import { MessageTopic, type IMUMsg } from '$lib/types/models'
|
import { MessageTopic, type IMUMsg, type IMUCalibrationResult } from '$lib/types/models'
|
||||||
import { useFeatureFlags } from '$lib/stores/featureFlags'
|
import { useFeatureFlags } from '$lib/stores/featureFlags'
|
||||||
import { Rotate3d } from '$lib/components/icons'
|
import { Rotate3d } from '$lib/components/icons'
|
||||||
|
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
const features = useFeatureFlags()
|
const features = useFeatureFlags()
|
||||||
let intervalId: ReturnType<typeof setInterval> | number
|
let intervalId: ReturnType<typeof setInterval> | number
|
||||||
|
let isCalibrating = $state(false)
|
||||||
|
let calibrationResult = $state<IMUCalibrationResult | null>(null)
|
||||||
|
|
||||||
let angleChartElement: HTMLCanvasElement
|
let angleChartElement: HTMLCanvasElement
|
||||||
let tempChartElement: HTMLCanvasElement
|
let tempChartElement: HTMLCanvasElement
|
||||||
@@ -206,14 +208,26 @@
|
|||||||
imu.addData(data)
|
imu.addData(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
socket.on(MessageTopic.imuCalibrate, (data: IMUCalibrationResult) => {
|
||||||
|
isCalibrating = false
|
||||||
|
calibrationResult = data
|
||||||
|
})
|
||||||
|
|
||||||
initializeCharts()
|
initializeCharts()
|
||||||
intervalId = setInterval(updateData, 200)
|
intervalId = setInterval(updateData, 200)
|
||||||
})
|
})
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
socket.off(MessageTopic.imu)
|
socket.off(MessageTopic.imu)
|
||||||
|
socket.off(MessageTopic.imuCalibrate)
|
||||||
clearInterval(intervalId)
|
clearInterval(intervalId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function startCalibration() {
|
||||||
|
isCalibrating = true
|
||||||
|
calibrationResult = null
|
||||||
|
socket.sendEvent(MessageTopic.imuCalibrate, {})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SettingsCard collapsible={false}>
|
<SettingsCard collapsible={false}>
|
||||||
@@ -224,6 +238,26 @@
|
|||||||
<span>IMU</span>
|
<span>IMU</span>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2 mb-4">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-primary"
|
||||||
|
onclick={startCalibration}
|
||||||
|
disabled={isCalibrating || !$features.imu}
|
||||||
|
>
|
||||||
|
{#if isCalibrating}
|
||||||
|
<span class="loading loading-spinner loading-xs"></span>
|
||||||
|
Calibrating...
|
||||||
|
{:else}
|
||||||
|
Calibrate IMU
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{#if calibrationResult}
|
||||||
|
<span class="badge" class:badge-success={calibrationResult.success} class:badge-error={!calibrationResult.success}>
|
||||||
|
{calibrationResult.success ? 'Calibrated' : 'Failed'}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if $features.imu}
|
{#if $features.imu}
|
||||||
<div class="w-full overflow-x-auto">
|
<div class="w-full overflow-x-auto">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -123,6 +123,26 @@ class IMU : public SensorBase<IMUAnglesMsg> {
|
|||||||
|
|
||||||
float getAngleZ() { return _msg.rpy[0]; }
|
float getAngleZ() { return _msg.rpy[0]; }
|
||||||
|
|
||||||
|
bool calibrate() {
|
||||||
|
#if FT_ENABLED(USE_MPU6050)
|
||||||
|
if (!_msg.success) return false;
|
||||||
|
ESP_LOGI("IMU", "Starting calibration...");
|
||||||
|
_imu.CalibrateGyro(6);
|
||||||
|
_imu.CalibrateAccel(6);
|
||||||
|
ESP_LOGI("IMU", "Calibration complete");
|
||||||
|
return true;
|
||||||
|
#elif FT_ENABLED(USE_BNO055)
|
||||||
|
if (!_msg.success) return false;
|
||||||
|
ESP_LOGI("IMU", "Starting calibration...");
|
||||||
|
adafruit_bno055_offsets_t offsets;
|
||||||
|
bool result = _imu.getSensorOffsets(offsets);
|
||||||
|
ESP_LOGI("IMU", "Calibration complete");
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if FT_ENABLED(USE_MPU6050)
|
#if FT_ENABLED(USE_MPU6050)
|
||||||
MPU6050 _imu;
|
MPU6050 _imu;
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
|
|||||||
float leftDistance();
|
float leftDistance();
|
||||||
float rightDistance();
|
float rightDistance();
|
||||||
|
|
||||||
|
bool calibrateIMU();
|
||||||
|
|
||||||
StatefulHttpEndpoint<PeripheralsConfiguration> endpoint;
|
StatefulHttpEndpoint<PeripheralsConfiguration> endpoint;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ void setupServer() {
|
|||||||
#define EVENT_I2C_SCAN "i2cScan"
|
#define EVENT_I2C_SCAN "i2cScan"
|
||||||
#define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM"
|
#define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM"
|
||||||
#define EVENT_SERVO_STATE "servoState"
|
#define EVENT_SERVO_STATE "servoState"
|
||||||
|
#define EVENT_IMU_CALIBRATE "imuCalibrate"
|
||||||
|
|
||||||
void setupEventSocket() {
|
void setupEventSocket() {
|
||||||
// Motion events
|
// Motion events
|
||||||
@@ -159,6 +160,13 @@ void setupEventSocket() {
|
|||||||
socket.emit(EVENT_I2C_SCAN, results);
|
socket.emit(EVENT_I2C_SCAN, results);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.onEvent(EVENT_IMU_CALIBRATE, [&](JsonVariant &root, int originId) {
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonVariant results = doc.to<JsonVariant>();
|
||||||
|
results["success"] = peripherals.calibrateIMU();
|
||||||
|
socket.emit(EVENT_IMU_CALIBRATE, results);
|
||||||
|
});
|
||||||
|
|
||||||
// Servo controller events
|
// Servo controller events
|
||||||
socket.onEvent(EVENT_SERVO_CONFIGURATION_SETTINGS,
|
socket.onEvent(EVENT_SERVO_CONFIGURATION_SETTINGS,
|
||||||
[&](JsonVariant &root, int originId) { servoController.servoEvent(root, originId); });
|
[&](JsonVariant &root, int originId) { servoController.servoEvent(root, originId); });
|
||||||
@@ -174,6 +182,7 @@ void IRAM_ATTR SpotControlLoopEntry(void *) {
|
|||||||
peripherals.begin();
|
peripherals.begin();
|
||||||
servoController.begin();
|
servoController.begin();
|
||||||
motionService.begin();
|
motionService.begin();
|
||||||
|
peripherals.calibrateIMU();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
CALLS_PER_SECOND(SpotControlLoopEntry);
|
CALLS_PER_SECOND(SpotControlLoopEntry);
|
||||||
|
|||||||
@@ -186,3 +186,14 @@ void Peripherals::getSonarResult(JsonVariant &root) {
|
|||||||
array[1] = _right_distance;
|
array[1] = _right_distance;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Peripherals::calibrateIMU() {
|
||||||
|
#if FT_ENABLED(USE_MPU6050 || USE_BNO055)
|
||||||
|
beginTransaction();
|
||||||
|
bool result = _imu.calibrate();
|
||||||
|
endTransaction();
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user