OneEuroFilterUnreal
OneEuroFilterUnreal copied to clipboard
Rotator wrap around error.
With Rotator One Euro Filters the wrap around 0 to 360 degrees is not handled. E.g. if raw yaw is currently 295 degrees and the new yaw is 3 degrees that should be a +8 degrees difference. Instead it is seen as a -292 degree difference and so the interpolation in the filter slews the long way around the yaw circle.
The correct way to do it is to have the input check incoming new values of rotation against the current raw value and if the difference is > 180 or < -180 fudge the incoming angle by adding or subtracting 360 degrees. I did this in blueprints and it works.
It should be in the C++. I may submit a C++ code fix and pull request.
Ok, fixed. But I do not have permission to push (even as a branch).
Here is the code in OneEuroFilterBlueprintDatatypes.cpp...
void FOneEuroFilterRotator::SetValue(FRotator NewValue) {
if (!bInitialized)
{
TheFilter = MakeShareable(new OneEuroFilter<FRotator>(Frequency, MinCutoff, Beta, DCutoff));
bInitialized = true;
}
// Compensate for circle degrees wrap around.
float diff = NewValue.Roll - Value.Roll;
if (diff > 180.0f)
NewValue.Roll -= 360.0f;
else if (diff < -180.0)
NewValue.Roll += 360.0f;
diff = NewValue.Pitch - Value.Pitch;
if (diff > 180.0f)
NewValue.Pitch -= 360.0f;
else if (diff < -180.0)
NewValue.Pitch += 360.0f;
diff = NewValue.Yaw - Value.Yaw;
if (diff > 180.0f)
NewValue.Yaw -= 360.0f;
else if (diff < -180.0)
NewValue.Yaw += 360.0f;
Value = NewValue;
if (TheFilter.IsValid())
FilteredValue = TheFilter->Filter(Value);
};
Note that the Unity version of the filter has this problem. The solution there would be to flag Rotator style values as needing wrap around and then do a very similar fix for those.