diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 66f4e1b..04a24e9 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -17,6 +17,7 @@ ### 后端数据 + - 合力低于显示阈值时,后端不再清空 summary 数组,而是持续写入 `0.0`。 - 压力矩阵在低于显示阈值时仍然清零。 - 前端可以通过 summary 数组是否存在和最新值大小来判断释放状态。 diff --git a/src-tauri/src/commands/serial.rs b/src-tauri/src/commands/serial.rs index e6bebcd..d4b10bb 100644 --- a/src-tauri/src/commands/serial.rs +++ b/src-tauri/src/commands/serial.rs @@ -199,7 +199,7 @@ pub async fn serial_connect( ) .await { - eprintln!("serial task exited with error: {error}"); + log::error!("serial task exited with error: {error}"); } let manager = task_app.state::(); diff --git a/src-tauri/src/serial_core/codecs/test.rs b/src-tauri/src/serial_core/codecs/test.rs index ad4fc60..0a19718 100644 --- a/src-tauri/src/serial_core/codecs/test.rs +++ b/src-tauri/src/serial_core/codecs/test.rs @@ -62,7 +62,6 @@ impl Codec for TestCodec { continue; } let dts = elapsed_millis(session_started_at); - println!("dts_ms: {dts}"); frames.push(TestFrame { header: [0xAA, 0x55], cmd: cmd, @@ -244,11 +243,10 @@ mod tests { fn test_read_csv_basic() -> anyhow::Result<()> { let mut rdr = Reader::from_path("recording_20260329_125238.csv")?; let headers = rdr.headers()?; - println!("headers: {:?}", headers); for result in rdr.records() { let record = result?; - println!("record: {:?}", record); + let _ = record; } Ok(()) diff --git a/src-tauri/src/serial_core/multi_dim_force.rs b/src-tauri/src/serial_core/multi_dim_force.rs index cb6e17f..25ebcaa 100644 --- a/src-tauri/src/serial_core/multi_dim_force.rs +++ b/src-tauri/src/serial_core/multi_dim_force.rs @@ -17,6 +17,7 @@ const POST_STABLE_MS: f32 = 200.0; const POST_STABLE_THRESH: f32 = 0.1; const COP_LPF_ALPHA: f32 = 0.25; const EPSILON: f32 = 1e-8; +const DISPLAY_ANGLE_OFFSET_DEG: f32 = -90.0; #[derive(Debug, Clone, Copy)] pub struct PztSpatialAnalysis { @@ -359,10 +360,7 @@ impl PztProcessor { fn compute_vector_angle(x: f32, y: f32) -> (f32, f32) { let magnitude = (x * x + y * y).sqrt(); - let mut angle = y.atan2(x + EPSILON).to_degrees(); - if angle < 0.0 { - angle += 360.0; - } + let angle = (y.atan2(x + EPSILON).to_degrees() + DISPLAY_ANGLE_OFFSET_DEG).rem_euclid(360.0); (angle, magnitude) } @@ -481,7 +479,7 @@ mod tests { assert!(analysis.contact_active); assert!(analysis.reportable); assert!(analysis.magnitude > 0.0); - assert!(analysis.angle_deg <= 45.0 || analysis.angle_deg >= 315.0); + assert!(analysis.angle_deg >= 225.0 && analysis.angle_deg <= 315.0); } #[test] diff --git a/src-tauri/src/serial_core/serial.rs b/src-tauri/src/serial_core/serial.rs index acaa334..13df981 100644 --- a/src-tauri/src/serial_core/serial.rs +++ b/src-tauri/src/serial_core/serial.rs @@ -358,88 +358,23 @@ fn build_display_values( spatial_force: Option, ) -> Option> { let summary = values.iter().copied().sum::(); - #[cfg(feature = "debug")] - { - let g1 = raw_to_g1(summary as u32); - println!("raw_to_g1 map: {g1}"); - } chart_state.record_spatial_force(spatial_force); - match ad_to_x(summary as f64) { - Some(x) => { - if x <= MIN_DISPLAY_FORCE { - let zero_values = vec![0; values.len()]; - chart_state.record_summary(0.0); - chart_state.record_pressure_matrix(&zero_values); - return Some(vec![0]); - } - - chart_state.record_pressure_matrix(values); - chart_state.record_summary(x as f32); - Some(vec![x.round() as i32]) - } - None => { - chart_state.record_pressure_matrix(values); - chart_state.record_summary(MAX_DISPLAY_FORCE as f32); - Some(vec![MAX_DISPLAY_FORCE.round() as i32]) - } + let x = raw_to_g1(summary as u32).min(MAX_DISPLAY_FORCE); + if x <= MIN_DISPLAY_FORCE { + let zero_values = vec![0; values.len()]; + chart_state.record_summary(0.0); + chart_state.record_pressure_matrix(&zero_values); + return Some(vec![0]); } + + chart_state.record_pressure_matrix(values); + chart_state.record_summary(x as f32); + Some(vec![x.round() as i32]) } const MIN_DISPLAY_FORCE: f64 = 0.1; const MAX_DISPLAY_FORCE: f64 = 25.6; -const QUADRATIC_A: f64 = -375.2; -const QUADRATIC_B: f64 = 25880.0; -const QUADRATIC_C: f64 = 52150.0; - -fn ad_to_x(ad: f64) -> Option { - const CUBIC_LIMIT: f64 = 6.57; - const EPSILON: f64 = 0.000_001; - - let cubic_min = ad_from_cubic_x(0.0); - if ad <= cubic_min { - return Some(0.0); - } - - let cubic_threshold = ad_from_cubic_x(CUBIC_LIMIT); - if ad <= cubic_threshold { - return Some(solve_monotonic_ad(ad, 0.0, CUBIC_LIMIT, ad_from_cubic_x)); - } - - let quadratic_vertex = -QUADRATIC_B / (2.0 * QUADRATIC_A); - let quadratic_max = ad_from_quadratic_x(quadratic_vertex); - if ad - EPSILON > quadratic_max { - return Some(MAX_DISPLAY_FORCE); - } - - Some(solve_monotonic_ad( - ad, - CUBIC_LIMIT, - quadratic_vertex, - ad_from_quadratic_x, - )) -} - -fn solve_monotonic_ad(ad: f64, mut low: f64, mut high: f64, f: fn(f64) -> f64) -> f64 { - for _ in 0..80 { - let mid = (low + high) / 2.0; - if f(mid) < ad { - low = mid; - } else { - high = mid; - } - } - - (low + high) / 2.0 -} - -fn ad_from_cubic_x(x: f64) -> f64 { - -5.732 * x.powi(3) - 131.5 * x.powi(2) + 31980.0 * x + 13490.0 -} - -fn ad_from_quadratic_x(x: f64) -> f64 { - QUADRATIC_A * x.powi(2) + QUADRATIC_B * x + QUADRATIC_C -} #[cfg(feature = "devkit")] fn push_devkit_frame(app: &AppHandle, values: &[i32], dts_ms: u64, resultant_force: f64) { @@ -493,8 +428,6 @@ fn infer_matrix_shape(len: usize) -> (u32, u32) { (best.0 as u32, best.1 as u32) } -#[cfg(feature = "debug")] -#[allow(dead_code)] fn raw_to_g1(raw: u32) -> f64 { const X: [u32; 12] = [ 0, 20829, 102371, 132956, 165568, 182033, 217263, 263098, 283747, 365120, 410556, 477190 diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index fb0bbfe..810d39d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -41,9 +41,7 @@ "template": "nsis/installer.nsi" } }, - "resources": [ - "resources/je-skin-devkit-server.exe" - ] + "resources": [] }, "plugins": { "updater": { diff --git a/src/lib/components/PressureMatrixViewer.svelte b/src/lib/components/PressureMatrixViewer.svelte index 173594b..79d4d76 100644 --- a/src/lib/components/PressureMatrixViewer.svelte +++ b/src/lib/components/PressureMatrixViewer.svelte @@ -677,14 +677,6 @@ {viewerI18n.current} {formatForceStat(stats.current)} -
- {viewerI18n.max} - {formatForceStat(stats.max)} -
-
- {viewerI18n.min} - {formatForceStat(stats.min)} -

{statsNote}

@@ -773,7 +765,7 @@ .stats-grid { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-template-columns: minmax(0, 1fr); gap: 0.46rem; } diff --git a/src/lib/components/SpatialForcePanel.svelte b/src/lib/components/SpatialForcePanel.svelte index 51162a8..b7b9bf5 100644 --- a/src/lib/components/SpatialForcePanel.svelte +++ b/src/lib/components/SpatialForcePanel.svelte @@ -20,6 +20,7 @@ return delta === -180 ? 180 : delta; } + const displayAngleOffsetDeg = 90; const jumpAngleThresholdDeg = 72; let visualAngleDeg = 0; @@ -95,7 +96,7 @@ spatialForce !== null && Number.isFinite(spatialForce.angleDeg) && (!requireMagnitude || (Number.isFinite(spatialForce.magnitude) && Math.abs(spatialForce.magnitude) >= 0.0001)); - $: angleDeg = hasData ? normalizeAngle(spatialForce?.angleDeg ?? 0) : 0; + $: angleDeg = hasData ? normalizeAngle((spatialForce?.angleDeg ?? 0) + displayAngleOffsetDeg) : 0; $: updateVisualAngle(angleDeg, hasData); @@ -136,10 +137,10 @@ {/if}
- 90 - 0 - 270 - 180 + 0 + 270 + 180 + 90 diff --git a/src/lib/components/SummaryCurve.svelte b/src/lib/components/SummaryCurve.svelte index 68ddee5..b37f61c 100644 --- a/src/lib/components/SummaryCurve.svelte +++ b/src/lib/components/SummaryCurve.svelte @@ -68,18 +68,6 @@ return Math.min(max, Math.max(min, value)); } - function formatValue(value: number | null): string { - if (value === null) { - return "--"; - } - - if (value >= maxDisplayForce) { - return `${maxDisplayForce.toFixed(1)}+`; - } - - return value.toFixed(1); - } - function formatAxisValue(value: number, axis: "x" | "y"): string { if (!Number.isFinite(value)) { return "--"; @@ -373,9 +361,6 @@ $: yAxisTicks = sampleCount > 0 ? buildYAxisTicks(yScaleBounds, yDataBounds) : []; $: xAxisTicks = sampleCount > 0 ? buildXAxisTicks(xScaleBounds) : []; $: drawCanvas(canvasEl, plotPoints, yAxisTicks, xAxisTicks, sampleCount); - $: latestValue = formatValue(summary.latest); - $: minValue = formatValue(summary.min); - $: maxValue = formatValue(summary.max);

RF

-

{summary.label}

-
- - @@ -406,24 +385,6 @@ {/if} - -
-

- - {i18n.now} - {latestValue} -

-

- - {i18n.min} - {minValue} -

-

- - {i18n.max} - {maxValue} -

-