Compare commits
No commits in common. "4e9c33778c4ac30d3dc58187c0a312fe5e9cc225" and "83188b1fa1c721dba2a4c25d320aea74701cf89b" have entirely different histories.
4e9c33778c
...
83188b1fa1
@ -14,10 +14,7 @@
|
||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_153607.csv\")",
|
||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_160323.csv\")",
|
||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_164341.csv\")",
|
||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_170543.csv\")",
|
||||
"Bash(find C:ASTERIONSVNDEVPROSERVE_UE_5_5Plugins -type f \\\\\\(-name *.cpp -o -name *.h \\\\\\))",
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)"
|
||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_170543.csv\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -92,9 +92,8 @@ void UEBBarrel::UpdateTransformHistory()
|
||||
|
||||
TransformHistory.Add(Sample);
|
||||
|
||||
// Trim buffer: remove samples older than AntiRecoilBufferTimeMs
|
||||
// Trim buffer: remove samples older than AntiRecoilBufferTime
|
||||
// During calibration, keep a larger buffer (0.5s min) for reliable 3-sigma analysis
|
||||
const float AntiRecoilBufferTime = AntiRecoilBufferTimeMs / 1000.0f;
|
||||
float EffectiveBufferTime = CalibrateAntiRecoil
|
||||
? FMath::Max(AntiRecoilBufferTime, 0.5f)
|
||||
: AntiRecoilBufferTime;
|
||||
@ -129,7 +128,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
||||
|
||||
case EAntiRecoilMode::ARM_LinearExtrapolation:
|
||||
{
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN >= 2)
|
||||
{
|
||||
PredictLinearExtrapolation(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||
@ -149,7 +148,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
||||
|
||||
case EAntiRecoilMode::ARM_WeightedRegression:
|
||||
{
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN >= 2)
|
||||
{
|
||||
PredictWeightedRegression(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||
@ -169,7 +168,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
||||
|
||||
case EAntiRecoilMode::ARM_WeightedLinearRegression:
|
||||
{
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN >= 2)
|
||||
{
|
||||
PredictWeightedLinearRegression(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||
@ -189,7 +188,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
||||
|
||||
case EAntiRecoilMode::ARM_KalmanFilter:
|
||||
{
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN > 0)
|
||||
{
|
||||
// Feed only the latest SAFE sample to the Kalman filter
|
||||
@ -212,7 +211,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
||||
|
||||
case EAntiRecoilMode::ARM_AdaptiveExtrapolation:
|
||||
{
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN >= 2)
|
||||
{
|
||||
PredictAdaptiveExtrapolation(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||
@ -238,7 +237,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
||||
|
||||
void UEBBarrel::PredictLinearExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||
{
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN < 2)
|
||||
{
|
||||
OutLocation = TransformHistory[0].Location;
|
||||
@ -318,7 +317,7 @@ void UEBBarrel::PredictLinearExtrapolation(double CurrentTime, FVector& OutLocat
|
||||
|
||||
void UEBBarrel::PredictWeightedLinearRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||
{
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN < 2)
|
||||
{
|
||||
OutLocation = TransformHistory[0].Location;
|
||||
@ -391,7 +390,7 @@ void UEBBarrel::PredictWeightedLinearRegression(double CurrentTime, FVector& Out
|
||||
|
||||
void UEBBarrel::PredictWeightedRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||
{
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN < 2)
|
||||
{
|
||||
OutLocation = TransformHistory[0].Location;
|
||||
@ -707,7 +706,7 @@ void UEBBarrel::PredictKalmanFilter(double CurrentTime, FVector& OutLocation, FV
|
||||
|
||||
void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||
{
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
||||
if (SafeN < 2)
|
||||
{
|
||||
OutLocation = TransformHistory[0].Location;
|
||||
@ -783,68 +782,30 @@ void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLoc
|
||||
float RecentAimSpeed = RecentAimVel.Size();
|
||||
|
||||
// Confidence: ratio of recent speed to average speed.
|
||||
// Dead zone: ratios above AdaptiveDeadZone are treated as 1.0 (no correction).
|
||||
// Only ratios BELOW AdaptiveDeadZone trigger extrapolation reduction.
|
||||
// Below dead zone: remap [0, deadzone] → [0, 1] then apply sensitivity exponent.
|
||||
// Minimum speed threshold: below this, speed ratios are unreliable (noise dominates),
|
||||
// so we keep full confidence to avoid false deceleration detection.
|
||||
const float MinSpeedThreshold = AdaptiveMinSpeed;
|
||||
|
||||
// Dead zone: ratios above AdaptiveDeadZone are treated as 1.0 (normal fluctuations).
|
||||
// Remapped ratio: (ratio - deadzone) / (1 - deadzone), clamped to [0, 1].
|
||||
// AdaptiveSensitivity is the power exponent on the remapped ratio.
|
||||
float PosRatio = 1.0f;
|
||||
float PosConfidence = 1.0f;
|
||||
float PosRemapped = 1.0f;
|
||||
if (AvgPosSpeed > MinSpeedThreshold)
|
||||
if (AvgPosSpeed > SMALL_NUMBER)
|
||||
{
|
||||
PosRatio = FMath::Clamp(RecentPosSpeed / AvgPosSpeed, 0.0f, 1.0f);
|
||||
if (PosRatio >= AdaptiveDeadZone)
|
||||
{
|
||||
// Inside dead zone: no correction, full confidence
|
||||
PosRemapped = 1.0f;
|
||||
PosConfidence = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Below dead zone: real deceleration detected
|
||||
// Remap [0, deadzone] → [0, 1]
|
||||
PosRemapped = (AdaptiveDeadZone > SMALL_NUMBER)
|
||||
? FMath::Clamp(PosRatio / AdaptiveDeadZone, 0.0f, 1.0f)
|
||||
: 0.0f;
|
||||
float PosRemapped = (AdaptiveDeadZone < 1.0f)
|
||||
? FMath::Clamp((PosRatio - AdaptiveDeadZone) / (1.0f - AdaptiveDeadZone), 0.0f, 1.0f)
|
||||
: (PosRatio >= 1.0f ? 1.0f : 0.0f);
|
||||
PosConfidence = FMath::Pow(PosRemapped, AdaptiveSensitivity);
|
||||
}
|
||||
}
|
||||
// else: AvgPosSpeed <= MinSpeedThreshold → keep defaults (Ratio=1, Conf=1)
|
||||
|
||||
float AimRatio = 1.0f;
|
||||
float AimConfidence = 1.0f;
|
||||
float AimRemapped = 1.0f;
|
||||
if (AvgAimSpeed > MinSpeedThreshold)
|
||||
if (AvgAimSpeed > SMALL_NUMBER)
|
||||
{
|
||||
AimRatio = FMath::Clamp(RecentAimSpeed / AvgAimSpeed, 0.0f, 1.0f);
|
||||
if (AimRatio >= AdaptiveDeadZone)
|
||||
{
|
||||
// Inside dead zone: no correction, full confidence
|
||||
AimRemapped = 1.0f;
|
||||
AimConfidence = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Below dead zone: real deceleration detected
|
||||
// Remap [0, deadzone] → [0, 1]
|
||||
AimRemapped = (AdaptiveDeadZone > SMALL_NUMBER)
|
||||
? FMath::Clamp(AimRatio / AdaptiveDeadZone, 0.0f, 1.0f)
|
||||
: 0.0f;
|
||||
float AimRemapped = (AdaptiveDeadZone < 1.0f)
|
||||
? FMath::Clamp((AimRatio - AdaptiveDeadZone) / (1.0f - AdaptiveDeadZone), 0.0f, 1.0f)
|
||||
: (AimRatio >= 1.0f ? 1.0f : 0.0f);
|
||||
AimConfidence = FMath::Pow(AimRemapped, AdaptiveSensitivity);
|
||||
}
|
||||
}
|
||||
// else: AvgAimSpeed <= MinSpeedThreshold → keep defaults (Ratio=1, Conf=1)
|
||||
|
||||
// Debug logs for dead zone diagnosis
|
||||
UE_LOG(LogTemp, Log, TEXT("[AdaptiveExtrap] DZ=%.3f Sens=%.2f MinSpd=%.1f | Pos: Ratio=%.4f Remap=%.4f Conf=%.4f (Avg=%.2f Recent=%.2f %s) | Aim: Ratio=%.4f Remap=%.4f Conf=%.4f (Avg=%.2f Recent=%.2f %s)"),
|
||||
AdaptiveDeadZone, AdaptiveSensitivity, MinSpeedThreshold,
|
||||
PosRatio, PosRemapped, PosConfidence, AvgPosSpeed, RecentPosSpeed,
|
||||
(AvgPosSpeed <= MinSpeedThreshold) ? TEXT("[LOW]") : (PosRatio >= AdaptiveDeadZone ? TEXT("[DZ]") : TEXT("[DEC]")),
|
||||
AimRatio, AimRemapped, AimConfidence, AvgAimSpeed, RecentAimSpeed,
|
||||
(AvgAimSpeed <= MinSpeedThreshold) ? TEXT("[LOW]") : (AimRatio >= AdaptiveDeadZone ? TEXT("[DZ]") : TEXT("[DEC]")));
|
||||
|
||||
// Extrapolate from last safe sample
|
||||
const FTimestampedTransform& LastSafe = TransformHistory[SafeN - 1];
|
||||
@ -853,8 +814,6 @@ void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLoc
|
||||
// Write debug values for HUD display
|
||||
DbgPosRatio = PosRatio;
|
||||
DbgAimRatio = AimRatio;
|
||||
DbgPosRemapped = PosRemapped;
|
||||
DbgAimRemapped = AimRemapped;
|
||||
DbgPosConfidence = PosConfidence;
|
||||
DbgAimConfidence = AimConfidence;
|
||||
DbgAvgPosSpeed = AvgPosSpeed;
|
||||
|
||||
@ -17,7 +17,6 @@ void UEBBarrel::Shoot(bool Trigger, int nextFireID) {
|
||||
if (ClientSideAim && GetOwner()->GetRemoteRole() == ROLE_Authority && Trigger) {
|
||||
Aim = GetComponentTransform().GetUnitAxis(EAxis::X);
|
||||
Location = GetComponentTransform().GetLocation();
|
||||
ApplyAimStabilization();
|
||||
nextFireEventID = nextFireID;
|
||||
ShootRepCSA(Trigger, UGameplayStatics::RebaseLocalOriginOntoZero(GetWorld(), Location), Aim, nextFireID);
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ FPrimitiveSceneProxy* UEBBarrel::CreateSceneProxy() {
|
||||
const FLinearColor DrawColor = GetViewSelectionColor(FColor::Green, *View, IsSelected(), IsHovered(), true, IsIndividuallySelected());
|
||||
|
||||
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
|
||||
DrawDirectionalArrow(PDI, Transform, DrawColor, Component->DebugArrowSize, Component->DebugArrowSize*0.1f, 16, 0.0f);
|
||||
DrawDirectionalArrow(PDI, Transform, DrawColor, Component->DebugArrowSize, Component->DebugArrowSize*0.1f, 16, Component->DebugArrowSize*0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,41 +45,6 @@ void UEBBarrel::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
void UEBBarrel::ApplyAimStabilization()
|
||||
{
|
||||
if (AimDeadZoneDegrees <= 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bStabilizedAimInitialized)
|
||||
{
|
||||
StabilizedAim = Aim;
|
||||
bStabilizedAimInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute angle between current aim and last stable aim
|
||||
float AngleDeg = FMath::RadiansToDegrees(FMath::Acos(FMath::Clamp(FVector::DotProduct(Aim, StabilizedAim), -1.0f, 1.0f)));
|
||||
if (AngleDeg <= AimDeadZoneDegrees)
|
||||
{
|
||||
// Within dead zone: keep previous stable aim (filter jitter)
|
||||
Aim = StabilizedAim;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside dead zone: smooth transition to avoid jumps
|
||||
// Subtract the dead zone from the angle so movement starts from zero
|
||||
float ExcessDeg = AngleDeg - AimDeadZoneDegrees;
|
||||
float BlendAlpha = FMath::Clamp(ExcessDeg / AngleDeg, 0.0f, 1.0f);
|
||||
|
||||
// Slerp from stabilized aim toward real aim, removing the dead zone portion
|
||||
StabilizedAim = FMath::Lerp(StabilizedAim, Aim, BlendAlpha).GetSafeNormal();
|
||||
Aim = StabilizedAim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
@ -93,7 +58,6 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
if (TimeSinceAimUpdate >= 1.0f / ClientAimUpdateFrequency) {
|
||||
|
||||
ComputeAntiRecoilTransform();
|
||||
ApplyAimStabilization();
|
||||
|
||||
ClientAim(UGameplayStatics::RebaseLocalOriginOntoZero(GetWorld(),Location), Aim);
|
||||
TimeSinceAimUpdate = FMath::Fmod(TimeSinceAimUpdate, 1.0f / ClientAimUpdateFrequency);
|
||||
@ -101,7 +65,6 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
}else{
|
||||
if (!RemoteAimReceived) {
|
||||
ComputeAntiRecoilTransform();
|
||||
ApplyAimStabilization();
|
||||
}
|
||||
else {
|
||||
FVector LocOffset = (Location - GetComponentLocation());
|
||||
@ -114,7 +77,6 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
}
|
||||
else {
|
||||
ComputeAntiRecoilTransform();
|
||||
ApplyAimStabilization();
|
||||
}
|
||||
|
||||
// Debug visualization: raw tracker (green) vs predicted aim (red)
|
||||
@ -142,9 +104,9 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
DrawDebugLine(GetWorld(), Location, Location + Aim * DebugAntiRecoilLineLength,
|
||||
FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||
|
||||
// Small dots at origins for clarity
|
||||
DrawDebugPoint(GetWorld(), RawLocation, 3.0f, FColor::Green, false, -1.0f, 0);
|
||||
DrawDebugPoint(GetWorld(), Location, 3.0f, FColor::Red, false, -1.0f, 0);
|
||||
// Small spheres at origins for clarity
|
||||
DrawDebugSphere(GetWorld(), RawLocation, 1.5f, 6, FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness * 0.5f);
|
||||
DrawDebugSphere(GetWorld(), Location, 1.5f, 6, FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness * 0.5f);
|
||||
|
||||
// Yellow line: shows where shot would land WITHOUT anti-recoil correction
|
||||
// Captures raw aim at shock onset and persists for DebugIMUShockDisplayTime seconds
|
||||
@ -169,7 +131,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
DrawDebugLine(GetWorld(), DebugIMUShockCapturedLocation,
|
||||
DebugIMUShockCapturedLocation + DebugIMUShockCapturedAim * DebugAntiRecoilLineLength,
|
||||
FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||
DrawDebugPoint(GetWorld(), DebugIMUShockCapturedLocation, 3.0f, FColor::Green, false, -1.0f, 0);
|
||||
DrawDebugSphere(GetWorld(), DebugIMUShockCapturedLocation, 3.0f, 8, FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -185,7 +147,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
DrawDebugLine(GetWorld(), DebugCorrectedShotCapturedLocation,
|
||||
DebugCorrectedShotCapturedLocation + DebugCorrectedShotCapturedAim * DebugAntiRecoilLineLength,
|
||||
FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||
DrawDebugPoint(GetWorld(), DebugCorrectedShotCapturedLocation, 3.0f, FColor::Red, false, -1.0f, 0);
|
||||
DrawDebugSphere(GetWorld(), DebugCorrectedShotCapturedLocation, 3.0f, 8, FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -223,7 +185,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
FVector RealPos = GetComponentTransform().GetLocation();
|
||||
FVector RealAim = GetComponentTransform().GetUnitAxis(EAxis::X);
|
||||
// Count safe samples (same logic as GetSafeCount in AntiRecoilPredict.cpp)
|
||||
double SafeCutoff = GetWorld()->GetTimeSeconds() - (AntiRecoilDiscardTimeMs / 1000.0f);
|
||||
double SafeCutoff = GetWorld()->GetTimeSeconds() - AntiRecoilDiscardTime;
|
||||
int32 SafeN = 0;
|
||||
for (int32 si = 0; si < TransformHistory.Num(); si++)
|
||||
{
|
||||
@ -278,26 +240,17 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudTitle,
|
||||
TEXT("====== ADAPTIVE EXTRAPOLATION ======"));
|
||||
|
||||
// Dead zone info
|
||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudVal,
|
||||
FString::Printf(TEXT(" DeadZone=%.2f Sensitivity=%.1f"),
|
||||
AdaptiveDeadZone, AdaptiveSensitivity));
|
||||
|
||||
// Speed ratio + confidence (position)
|
||||
bool bPosInDeadZone = (DbgPosRatio >= AdaptiveDeadZone);
|
||||
FColor PosColor = bPosInDeadZone ? HudGood : HudWarn;
|
||||
FColor PosColor = (DbgPosConfidence > 0.9f) ? HudGood : HudWarn;
|
||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, PosColor,
|
||||
FString::Printf(TEXT(" Pos: ratio=%.3f %s remap=%.3f conf=%.3f spd=%.1f/%.1f"),
|
||||
DbgPosRatio, bPosInDeadZone ? TEXT("[DZ]") : TEXT("[!!]"),
|
||||
DbgPosRemapped, DbgPosConfidence, DbgRecentPosSpeed, DbgAvgPosSpeed));
|
||||
FString::Printf(TEXT(" Pos: ratio=%.2f conf=%.2f speed=%.1f/%.1f cm/s"),
|
||||
DbgPosRatio, DbgPosConfidence, DbgRecentPosSpeed, DbgAvgPosSpeed));
|
||||
|
||||
// Speed ratio + confidence (aim)
|
||||
bool bAimInDeadZone = (DbgAimRatio >= AdaptiveDeadZone);
|
||||
FColor AimColor = bAimInDeadZone ? HudGood : HudWarn;
|
||||
FColor AimColor = (DbgAimConfidence > 0.9f) ? HudGood : HudWarn;
|
||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, AimColor,
|
||||
FString::Printf(TEXT(" Aim: ratio=%.3f %s remap=%.3f conf=%.3f spd=%.4f/%.4f"),
|
||||
DbgAimRatio, bAimInDeadZone ? TEXT("[DZ]") : TEXT("[!!]"),
|
||||
DbgAimRemapped, DbgAimConfidence, DbgRecentAimSpeed, DbgAvgAimSpeed));
|
||||
FString::Printf(TEXT(" Aim: ratio=%.2f conf=%.2f speed=%.4f/%.4f /s"),
|
||||
DbgAimRatio, DbgAimConfidence, DbgRecentAimSpeed, DbgAvgAimSpeed));
|
||||
|
||||
// Extrapolation time
|
||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudVal,
|
||||
@ -367,11 +320,11 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
||||
LastCalibrationResult.AvgPeakAngleDeviation,
|
||||
LastCalibrationResult.AvgPeakPositionDeviation));
|
||||
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
||||
FString::Printf(TEXT(" >> DiscardTime: %.1f ms"),
|
||||
LastCalibrationResult.RecommendedDiscardTime * 1000.0f));
|
||||
FString::Printf(TEXT(" >> DiscardTime: %.4fs"),
|
||||
LastCalibrationResult.RecommendedDiscardTime));
|
||||
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
||||
FString::Printf(TEXT(" >> BufferTime: %.1f ms"),
|
||||
LastCalibrationResult.RecommendedBufferTime * 1000.0f));
|
||||
FString::Printf(TEXT(" >> BufferTime: %.4fs"),
|
||||
LastCalibrationResult.RecommendedBufferTime));
|
||||
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
||||
FString::Printf(TEXT(" >> KalmanProcessNoise: %.3f"),
|
||||
LastCalibrationResult.RecommendedKalmanProcessNoise));
|
||||
|
||||
@ -120,8 +120,6 @@ public:
|
||||
// Debug HUD state (written by const prediction functions, read by TickComponent)
|
||||
mutable float DbgPosRatio = 0.0f;
|
||||
mutable float DbgAimRatio = 0.0f;
|
||||
mutable float DbgPosRemapped = 0.0f;
|
||||
mutable float DbgAimRemapped = 0.0f;
|
||||
mutable float DbgPosConfidence = 0.0f;
|
||||
mutable float DbgAimConfidence = 0.0f;
|
||||
mutable float DbgAvgPosSpeed = 0.0f;
|
||||
@ -144,13 +142,13 @@ public:
|
||||
float DebugIMUShockDisplayTime = 3.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Selects the anti-recoil compensation algorithm. Hover over each option in the dropdown for a detailed description of how it works."))
|
||||
EAntiRecoilMode AntiRecoilMode = EAntiRecoilMode::ARM_AdaptiveExtrapolation;
|
||||
EAntiRecoilMode AntiRecoilMode = EAntiRecoilMode::ARM_KalmanFilter;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Total time window (ms) of tracker history to keep. Determines how far back in time samples are stored. Must be greater than DiscardTime. Example: 200ms at 60fps stores ~12 samples.", ClampMin = "5"))
|
||||
float AntiRecoilBufferTimeMs = 300.0f;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Total time window (seconds) of tracker history to keep. Determines how far back in time samples are stored. Must be greater than DiscardTime. Example: 0.2s at 60fps stores ~12 samples.", ClampMin = "0.05"))
|
||||
float AntiRecoilBufferTime = 0.15f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Time window (ms) of most recent samples to exclude as potentially contaminated by IMU recoil shock. The prediction algorithms only use samples older than this. Increase if the shock lasts longer. Safe window = BufferTime - DiscardTime.", ClampMin = "0.0"))
|
||||
float AntiRecoilDiscardTimeMs = 40.0f;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Time window (seconds) of most recent samples to exclude as potentially contaminated by IMU recoil shock. The prediction algorithms only use samples older than this. Increase if the shock lasts longer. Safe window = BufferTime - DiscardTime.", ClampMin = "0.0"))
|
||||
float AntiRecoilDiscardTime = 0.03f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Controls how the weight curve grows across safe samples in regression modes. 1.0 = linear growth, >1.0 = recent samples weighted much more heavily (convex curve), <1.0 = more uniform weighting (concave curve), 0.0 = all samples weighted equally. Formula: weight = pow(sampleIndex+1, exponent).", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_WeightedRegression || AntiRecoilMode == EAntiRecoilMode::ARM_WeightedLinearRegression", ClampMin = "0.0", ClampMax = "5.0"))
|
||||
float RegressionWeightExponent = 2.0f;
|
||||
@ -162,19 +160,13 @@ public:
|
||||
float KalmanMeasurementNoise = 0.01f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Power curve exponent for deceleration detection. Controls how aggressively slowing down reduces extrapolation. confidence = (remappedRatio)^sensitivity. 1.0 = linear (gentle). 2.0 = quadratic (aggressive). 0.5 = square root (very gentle). During steady movement, ratio is ~1 so confidence is always 1 regardless of this value.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.1", ClampMax = "5.0"))
|
||||
float AdaptiveSensitivity = 1.5f;
|
||||
float AdaptiveSensitivity = 1.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Dead zone for deceleration detection. Speed ratios (recent/avg) above this value are treated as 1.0 (no correction). Only ratios below trigger extrapolation reduction. Higher = more tolerant to natural speed fluctuations (less false positives). Lower = more sensitive to deceleration. 0.8 = ignore normal jitter, only react to real braking.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.0", ClampMax = "0.95"))
|
||||
float AdaptiveDeadZone = 0.8f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Minimum average speed (cm/s) required for deceleration detection. Below this threshold, speed ratios are unreliable due to noise, so confidence stays at 1.0 (full extrapolation). Prevents false deceleration detection during slow/small movements. 0 = disabled.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.0", ClampMax = "200.0"))
|
||||
float AdaptiveMinSpeed = 30.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Velocity damping during extrapolation. 0 = disabled (default). Higher values cause extrapolated velocity to decay exponentially toward zero over the discard window. Reduces overshoot on fast draw-aim-fire sequences where the user stops moving before firing. Applies to all prediction modes except Buffer. Typical range: 5-15.", ClampMin = "0.0", ClampMax = "50.0"))
|
||||
float ExtrapolationDamping = 8.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AimStabilization", meta = (ToolTip = "Angular dead zone in degrees. If the aim direction changes by less than this angle since the last stable aim, the change is ignored (aim stays locked). Eliminates micro-jitter from VR tracker vibrations. 0 = disabled. Typical: 0.1 to 0.5 degrees.", ClampMin = "0.0", ClampMax = "5.0"))
|
||||
float AimDeadZoneDegrees = 0.0f;
|
||||
float ExtrapolationDamping = 0.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Velocity", meta = (ToolTip = "Bullet inherits barrel velocity, only works with physics enabled or with additional velocity set")) float InheritVelocity = 1.0f;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Velocity", meta = (ToolTip = "Amount of recoil applied to the barrel, only works with physics enabled")) float RecoilMultiplier = 1.0f;
|
||||
@ -304,10 +296,6 @@ private:
|
||||
FVector Aim;
|
||||
FVector Location;
|
||||
|
||||
// Aim stabilization: last accepted aim direction (outside dead zone)
|
||||
FVector StabilizedAim = FVector::ForwardVector;
|
||||
bool bStabilizedAimInitialized = false;
|
||||
|
||||
TArray<FTimestampedTransform> TransformHistory;
|
||||
|
||||
// Debug IMU shock simulation state
|
||||
@ -348,7 +336,6 @@ private:
|
||||
|
||||
void UpdateTransformHistory();
|
||||
void ComputeAntiRecoilTransform();
|
||||
void ApplyAimStabilization();
|
||||
void PredictLinearExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
||||
void PredictWeightedLinearRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
||||
void PredictWeightedRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user