更新202606222

This commit is contained in:
GukSang.Jin
2026-06-22 11:04:39 +08:00
parent 7241d043c0
commit 4e751755bc
2 changed files with 111 additions and 29 deletions

View File

@@ -36,10 +36,13 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
private const double MinimumAnalysisLoadRatio = 0.8;
// 预触发缓冲:滑动检测前持续缓存的力/位移历史长度,用于回溯真实滑动起点(保证第一个摩擦力峰值被采到)。
private const double PreTriggerWindowSeconds = 0.5;
// 滑动检测:载荷达标后,水平摩擦力较静置接触基线上升超过该值即判定已进入滑动
private const double SlidingFrictionTriggerRiseN = 5.0;
// 回溯滑动起点:从检测点向前回溯,直到摩擦力回到基线附近(该裕度内)即认定为 onsett=0
private const double SlidingOnsetFrictionMarginN = 2.0;
// 滑动检测:载荷达标后只接受明显陡升,避免低幅慢漂移提前把曲线 0 点定错
private const double SlidingFrictionTriggerRiseN = 35.0;
private const double SlidingFrictionTriggerLookbackSeconds = 0.12;
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 int StaticPeakDropConfirmationPointCount = 3;
@@ -900,26 +903,67 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
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;
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 void MarkSlidingStartFromBuffer(string trigger)
private SlipDataPoint? FindLookbackPoint(double targetTime)
{
var onsetIndex = preTriggerBuffer.Count - 1;
while (onsetIndex > 0
&& preTriggerBuffer[onsetIndex - 1].HorizontalFrictionN > slidingBaselineFrictionN + SlidingOnsetFrictionMarginN)
for (var index = preTriggerBuffer.Count - 1; index >= 0; index--)
{
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];
slidingStartTimeSeconds = onset.TimeSeconds;
slidingStartDisplacementMm = onset.DisplacementMm;
@@ -940,12 +984,17 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
CurrentStatus = "已检测到有效滑动开始:曲线从 0.000 s 开始记录";
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,
trigger,
onset.TimeSeconds,
triggerPoint.TimeSeconds,
slidingBaselineFrictionN,
onset.HorizontalFrictionN,
triggerPoint.HorizontalFrictionN,
triggerPoint.HorizontalFrictionN - onset.HorizontalFrictionN,
slidingStartDisplacementMm,
triggerPoint.DisplacementMm,
currentRun.Count);
}