更新202606222
This commit is contained in:
@@ -533,11 +533,21 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
|||||||
|
|
||||||
var pressure = ConvertAdc(pressureRaw, pressureZero, pressureCoefficient);
|
var pressure = ConvertAdc(pressureRaw, pressureZero, pressureCoefficient);
|
||||||
|
|
||||||
// Keep each settings row paired with the same ADC channel used by the legacy zero-capture button.
|
var namedFriction1 = ConvertAdc(friction1Raw, frictionZero1, frictionCoefficient1);
|
||||||
var friction1 = ConvertAdc(friction1Raw, frictionZero1, frictionCoefficient1);
|
var namedFriction2 = ConvertAdc(friction2Raw, frictionZero2, frictionCoefficient2);
|
||||||
var friction2 = ConvertAdc(friction2Raw, frictionZero2, frictionCoefficient2);
|
var namedFriction = (namedFriction1 + namedFriction2) * -1.0;
|
||||||
var friction = (friction1 + friction2) * -1.0;
|
|
||||||
return AdcConversionResult.Valid(pressure, friction1, friction2, friction);
|
var legacyFriction1 = ConvertAdc(friction2Raw, frictionZero1, frictionCoefficient2);
|
||||||
|
var legacyFriction2 = ConvertAdc(friction1Raw, frictionZero2, frictionCoefficient1);
|
||||||
|
var legacyFriction = (legacyFriction1 + legacyFriction2) * -1.0;
|
||||||
|
return AdcConversionResult.Valid(
|
||||||
|
pressure,
|
||||||
|
namedFriction1,
|
||||||
|
namedFriction2,
|
||||||
|
namedFriction,
|
||||||
|
legacyFriction1,
|
||||||
|
legacyFriction2,
|
||||||
|
legacyFriction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidateAdcSettings(
|
private bool ValidateAdcSettings(
|
||||||
@@ -606,14 +616,18 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
|||||||
if (conversion.IsValid)
|
if (conversion.IsValid)
|
||||||
{
|
{
|
||||||
Log.Debug(
|
Log.Debug(
|
||||||
"ADC 采样:RawPressure={RawPressure}, RawFriction1={RawFriction1}, RawFriction2={RawFriction2}, Pressure={Pressure:F3} N, Friction1={Friction1:F3} N, Friction2={Friction2:F3} N, Friction={Friction:F3} N, Coefficients=[P:{PressureCoefficient}, F1:{FrictionCoefficient1}, F2:{FrictionCoefficient2}], Zeros=[P:{PressureZero}, F1:{FrictionZero1}, F2:{FrictionZero2}]",
|
"ADC 采样:RawPressure={RawPressure}, RawFriction1={RawFriction1}, RawFriction2={RawFriction2}, Pressure={Pressure:F3} N, FrictionMode=LegacyCross, FinalFriction={Friction:F3} N, LegacyFriction1={LegacyFriction1:F3} N, LegacyFriction2={LegacyFriction2:F3} N, NamedFriction1={NamedFriction1:F3} N, NamedFriction2={NamedFriction2:F3} N, NamedFriction={NamedFriction:F3} N, FrictionDelta={FrictionDelta:F3} N, Coefficients=[P:{PressureCoefficient}, F1:{FrictionCoefficient1}, F2:{FrictionCoefficient2}], Zeros=[P:{PressureZero}, F1:{FrictionZero1}, F2:{FrictionZero2}]",
|
||||||
pressureRaw,
|
pressureRaw,
|
||||||
friction1Raw,
|
friction1Raw,
|
||||||
friction2Raw,
|
friction2Raw,
|
||||||
conversion.Pressure,
|
conversion.Pressure,
|
||||||
conversion.Friction1,
|
|
||||||
conversion.Friction2,
|
|
||||||
conversion.Friction,
|
conversion.Friction,
|
||||||
|
conversion.LegacyFriction1,
|
||||||
|
conversion.LegacyFriction2,
|
||||||
|
conversion.NamedFriction1,
|
||||||
|
conversion.NamedFriction2,
|
||||||
|
conversion.NamedFriction,
|
||||||
|
conversion.Friction - conversion.NamedFriction,
|
||||||
settings.NormalPressureCoefficient,
|
settings.NormalPressureCoefficient,
|
||||||
settings.FrictionCoefficient1,
|
settings.FrictionCoefficient1,
|
||||||
settings.FrictionCoefficient2,
|
settings.FrictionCoefficient2,
|
||||||
@@ -734,16 +748,35 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
|||||||
private readonly record struct AdcConversionResult(
|
private readonly record struct AdcConversionResult(
|
||||||
bool IsValid,
|
bool IsValid,
|
||||||
double Pressure,
|
double Pressure,
|
||||||
double Friction1,
|
double NamedFriction1,
|
||||||
double Friction2,
|
double NamedFriction2,
|
||||||
|
double NamedFriction,
|
||||||
|
double LegacyFriction1,
|
||||||
|
double LegacyFriction2,
|
||||||
double Friction,
|
double Friction,
|
||||||
string Error)
|
string Error)
|
||||||
{
|
{
|
||||||
public static AdcConversionResult Valid(double pressure, double friction1, double friction2, double friction) =>
|
public static AdcConversionResult Valid(
|
||||||
new(true, pressure, friction1, friction2, friction, string.Empty);
|
double pressure,
|
||||||
|
double namedFriction1,
|
||||||
|
double namedFriction2,
|
||||||
|
double namedFriction,
|
||||||
|
double legacyFriction1,
|
||||||
|
double legacyFriction2,
|
||||||
|
double friction) =>
|
||||||
|
new(
|
||||||
|
true,
|
||||||
|
pressure,
|
||||||
|
namedFriction1,
|
||||||
|
namedFriction2,
|
||||||
|
namedFriction,
|
||||||
|
legacyFriction1,
|
||||||
|
legacyFriction2,
|
||||||
|
friction,
|
||||||
|
string.Empty);
|
||||||
|
|
||||||
public static AdcConversionResult Invalid(string error) =>
|
public static AdcConversionResult Invalid(string error) =>
|
||||||
new(false, 0, 0, 0, 0, error);
|
new(false, 0, 0, 0, 0, 0, 0, 0, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,13 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
private const double MinimumAnalysisLoadRatio = 0.8;
|
private const double MinimumAnalysisLoadRatio = 0.8;
|
||||||
// 预触发缓冲:滑动检测前持续缓存的力/位移历史长度,用于回溯真实滑动起点(保证第一个摩擦力峰值被采到)。
|
// 预触发缓冲:滑动检测前持续缓存的力/位移历史长度,用于回溯真实滑动起点(保证第一个摩擦力峰值被采到)。
|
||||||
private const double PreTriggerWindowSeconds = 0.5;
|
private const double PreTriggerWindowSeconds = 0.5;
|
||||||
// 滑动检测:载荷达标后,水平摩擦力较静置接触基线上升超过该值即判定已进入滑动。
|
// 滑动检测:载荷达标后只接受明显陡升,避免低幅慢漂移提前把曲线 0 点定错。
|
||||||
private const double SlidingFrictionTriggerRiseN = 5.0;
|
private const double SlidingFrictionTriggerRiseN = 35.0;
|
||||||
// 回溯滑动起点:从检测点向前回溯,直到摩擦力回到基线附近(该裕度内)即认定为 onset(t=0)。
|
private const double SlidingFrictionTriggerLookbackSeconds = 0.12;
|
||||||
private const double SlidingOnsetFrictionMarginN = 2.0;
|
private const double SlidingFrictionTriggerSlopeN = 25.0;
|
||||||
|
private const double SlidingDisplacementFrictionRiseN = 20.0;
|
||||||
|
// 回溯滑动起点:在触发前短窗口内找摩擦最低点,贴近标准曲线中首峰前的真实滑动起点。
|
||||||
|
private const double SlidingOnsetSearchBackSeconds = 0.12;
|
||||||
// 曲线/分析窗口:滑动开始后只保留该时长,剔除加载段与滑动后回程,对应标准曲线图的有效区间。
|
// 曲线/分析窗口:滑动开始后只保留该时长,剔除加载段与滑动后回程,对应标准曲线图的有效区间。
|
||||||
private const double CurveEndSeconds = 1.0;
|
private const double CurveEndSeconds = 1.0;
|
||||||
private const int StaticPeakDropConfirmationPointCount = 3;
|
private const int StaticPeakDropConfirmationPointCount = 3;
|
||||||
@@ -900,26 +903,67 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var frictionRose = samplePoint.HorizontalFrictionN - slidingBaselineFrictionN >= SlidingFrictionTriggerRiseN;
|
var frictionRiseFromBaseline = samplePoint.HorizontalFrictionN - slidingBaselineFrictionN;
|
||||||
|
var lookbackPoint = FindLookbackPoint(samplePoint.TimeSeconds - SlidingFrictionTriggerLookbackSeconds);
|
||||||
|
var frictionRiseFromLookback = lookbackPoint is null
|
||||||
|
? 0
|
||||||
|
: samplePoint.HorizontalFrictionN - lookbackPoint.HorizontalFrictionN;
|
||||||
|
var frictionRose = frictionRiseFromBaseline >= SlidingFrictionTriggerRiseN
|
||||||
|
&& frictionRiseFromLookback >= SlidingFrictionTriggerSlopeN;
|
||||||
var displacementMoved = Math.Abs(samplePoint.DisplacementMm - runStartDisplacementMm) >= SlidingStartDisplacementThresholdMm;
|
var displacementMoved = Math.Abs(samplePoint.DisplacementMm - runStartDisplacementMm) >= SlidingStartDisplacementThresholdMm;
|
||||||
if (frictionRose || displacementMoved)
|
var displacementWithFriction = displacementMoved
|
||||||
|
&& frictionRiseFromBaseline >= SlidingDisplacementFrictionRiseN;
|
||||||
|
if (frictionRose || displacementWithFriction)
|
||||||
{
|
{
|
||||||
MarkSlidingStartFromBuffer(frictionRose ? "FrictionRise" : "DisplacementMove");
|
MarkSlidingStartFromBuffer(frictionRose ? "FrictionSharpRise" : "DisplacementWithFrictionRise");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displacementMoved)
|
||||||
|
{
|
||||||
|
Log.Debug(
|
||||||
|
"滑动起点候选未触发:TestNumber={TestNumber}, Reason=DisplacementWithoutFrictionRise, DisplacementDelta={DisplacementDelta:F3}mm, FrictionRiseFromBaseline={FrictionRiseFromBaseline:F3}N, FrictionRiseFromLookback={FrictionRiseFromLookback:F3}N, BaselineFriction={BaselineFriction:F3}N, CurrentFriction={CurrentFriction:F3}N",
|
||||||
|
TestNumber,
|
||||||
|
Math.Abs(samplePoint.DisplacementMm - runStartDisplacementMm),
|
||||||
|
frictionRiseFromBaseline,
|
||||||
|
frictionRiseFromLookback,
|
||||||
|
slidingBaselineFrictionN,
|
||||||
|
samplePoint.HorizontalFrictionN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回溯预触发缓冲到摩擦力刚离开基线的那一刻设为 t=0,并把该时刻起的缓冲点补进曲线,保证第一个峰值被采到。
|
private SlipDataPoint? FindLookbackPoint(double targetTime)
|
||||||
private void MarkSlidingStartFromBuffer(string trigger)
|
|
||||||
{
|
{
|
||||||
var onsetIndex = preTriggerBuffer.Count - 1;
|
for (var index = preTriggerBuffer.Count - 1; index >= 0; index--)
|
||||||
while (onsetIndex > 0
|
|
||||||
&& preTriggerBuffer[onsetIndex - 1].HorizontalFrictionN > slidingBaselineFrictionN + SlidingOnsetFrictionMarginN)
|
|
||||||
{
|
{
|
||||||
onsetIndex--;
|
if (preTriggerBuffer[index].TimeSeconds <= targetTime)
|
||||||
|
{
|
||||||
|
return preTriggerBuffer[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return preTriggerBuffer.Count > 0 ? preTriggerBuffer[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回溯预触发缓冲到摩擦力陡升前的低点设为 t=0,并把该时刻起的缓冲点补进曲线,保证第一个峰值被采到。
|
||||||
|
private void MarkSlidingStartFromBuffer(string trigger)
|
||||||
|
{
|
||||||
|
var triggerPoint = preTriggerBuffer[^1];
|
||||||
|
var earliestOnsetTime = triggerPoint.TimeSeconds - SlidingOnsetSearchBackSeconds;
|
||||||
|
var onsetIndex = preTriggerBuffer.Count - 1;
|
||||||
|
for (var index = preTriggerBuffer.Count - 1; index >= 0; index--)
|
||||||
|
{
|
||||||
|
if (preTriggerBuffer[index].TimeSeconds < earliestOnsetTime)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preTriggerBuffer[index].HorizontalFrictionN <= preTriggerBuffer[onsetIndex].HorizontalFrictionN)
|
||||||
|
{
|
||||||
|
onsetIndex = index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多回退一个点(≈基线水平)作为 t=0,使曲线起点的摩擦力接近基线、随后升至首峰,与标准曲线一致。
|
|
||||||
onsetIndex = Math.Max(0, onsetIndex - 1);
|
|
||||||
var onset = preTriggerBuffer[onsetIndex];
|
var onset = preTriggerBuffer[onsetIndex];
|
||||||
slidingStartTimeSeconds = onset.TimeSeconds;
|
slidingStartTimeSeconds = onset.TimeSeconds;
|
||||||
slidingStartDisplacementMm = onset.DisplacementMm;
|
slidingStartDisplacementMm = onset.DisplacementMm;
|
||||||
@@ -940,12 +984,17 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
|
|
||||||
CurrentStatus = "已检测到有效滑动开始:曲线从 0.000 s 开始记录";
|
CurrentStatus = "已检测到有效滑动开始:曲线从 0.000 s 开始记录";
|
||||||
Log.Information(
|
Log.Information(
|
||||||
"检测到有效滑动开始并建立曲线零点:TestNumber={TestNumber}, Trigger={Trigger}, SlidingStartTime={SlidingStartTime:F3}s, BaselineFriction={BaselineFriction:F3}N, OnsetDisplacement={OnsetDisplacement:F3}mm, FlushedPointCount={FlushedPointCount}",
|
"检测到有效滑动开始并建立曲线零点:TestNumber={TestNumber}, Trigger={Trigger}, SlidingStartTime={SlidingStartTime:F3}s, TriggerTime={TriggerTime:F3}s, BaselineFriction={BaselineFriction:F3}N, OnsetFriction={OnsetFriction:F3}N, TriggerFriction={TriggerFriction:F3}N, FrictionRise={FrictionRise:F3}N, OnsetDisplacement={OnsetDisplacement:F3}mm, TriggerDisplacement={TriggerDisplacement:F3}mm, FlushedPointCount={FlushedPointCount}",
|
||||||
TestNumber,
|
TestNumber,
|
||||||
trigger,
|
trigger,
|
||||||
onset.TimeSeconds,
|
onset.TimeSeconds,
|
||||||
|
triggerPoint.TimeSeconds,
|
||||||
slidingBaselineFrictionN,
|
slidingBaselineFrictionN,
|
||||||
|
onset.HorizontalFrictionN,
|
||||||
|
triggerPoint.HorizontalFrictionN,
|
||||||
|
triggerPoint.HorizontalFrictionN - onset.HorizontalFrictionN,
|
||||||
slidingStartDisplacementMm,
|
slidingStartDisplacementMm,
|
||||||
|
triggerPoint.DisplacementMm,
|
||||||
currentRun.Count);
|
currentRun.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user