Стабилизация гироскопии наклоняется в боковойC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Стабилизация гироскопии наклоняется в боковой

Сообщение Anonymous »

Я строю систему индивидуальной движения для своего проекта (своего рода основанная на физике структура движения).
Все отлично работает, за исключением одной раздражающей проблемы с гирозовой стабилизацией.
Видео демонстрация проблемы < /p>
Вот настройка иерархия: < /p>

Код: Выделить всё

Wheel -> Direction

Код: Выделить всё

Wheel -> Gyro -> Turner -> Body -> Head< /code> < /p>
Визуальное представление иерархии:

 < /p>
Колесо является корневым компонентом, и это коренное соединение, и это Drives wepints /indants wealsment whefant while -whealcment while -whealcment while -whiponts while -whefants /indignmess /indignmess /> < /p>
. /> Гиропейт применяет пружинную стабилизацию, чтобы сохранить выровненную игрока с гравитационной или поверхностной нормой, если он достаточно быстрый (для выполнения таких трюков, как петли смерти и т. Д.) [b] Идеально < /strong>-он колеблется немного вперед и назад (как пружина), что является  то, что я хочу < /strong> < /p>
, но когда я езжу на рампу, вращающуюся вокруг оси z (например, примерно на 20 градусов в сторону),
, гипов, начинает раскачивать сторону, он также должен добавить его, как и он, как и он, он также должен добавить, как он должен быть вроде. стабилизируется в оси высот (вперед /назад /задний наклон), а не начинайте скручиваться в сторону. < /p>
Похоже, что стабилизация каким -то образом смешивается в рысках, но я не могу точно определить, где. < /p>
 Соответствующий код < /h1>
Здесь.  компонент) 
 функция, которая преобразует вектор в ротатор (честно говоря, я использовал Chatgpt для этого, потому что мой не работает): [/b] 
FRotator UFG_MovementComponent::MakeAlignedRotator(const FVector &FSurfaceNormal, const FRotator &CurrentRotation)
{
FRotator Rot = CurrentRotation;
Rot.Roll = FMath::GridSnap(Rot.Roll, RotMinStep);
Rot.Pitch = FMath::GridSnap(Rot.Pitch, RotMinStep);
Rot.Yaw = FMath::GridSnap(Rot.Yaw, RotMinStep);
FVector N = FSurfaceNormal;
FVector Fwd = UKismetMathLibrary::GetForwardVector(Rot);
FVector Up = UKismetMathLibrary::GetUpVector(Rot);

// Calculate the axis and angle between the current up and normal vectors
FVector Axis = FVector::CrossProduct(Up, N);
float AxisLen = Axis.Size();

FVector NewFwd;

if (AxisLen < KINDA_SMALL_NUMBER)
{
// If the vectors are almost parallel (0° or 180°)
if (FVector::DotProduct(Up, N) <  0.0f)
{
// If it's a 180° angle, reverse the forward vector
NewFwd = -Fwd;
}
else
{
// If the vectors are the same, leave the forward vector as is
NewFwd = Fwd;
}
}
else
{
Axis /= AxisLen;
float Angle = FMath::Acos(FMath::Clamp(FVector::DotProduct(Up, N), -1.0f, 1.0f));
FQuat Q(Axis, Angle);
NewFwd = Q.RotateVector(Fwd);
}

// Project the new forward vector onto the plane perpendicular to the normal vector (to ensure no component along the normal vector)
NewFwd = (NewFwd - N * FVector::DotProduct(NewFwd, N)).GetSafeNormal();

// Combine the matrix and convert it to a rotation
FRotationMatrix RotM = UKismetMathLibrary::MakeRotFromXZ(NewFwd, N);
FRotator NewRot = RotM.Rotator();
NewRot.Roll = FMath::GridSnap(NewRot.Roll, RotMinStep);
NewRot.Pitch = FMath::GridSnap(NewRot.Pitch, RotMinStep);
NewRot.Yaw = FMath::GridSnap(NewRot.Yaw, RotMinStep);
return NewRot;

}
функция, которая выравнивает колесо и направление на поверхность:

Код: Выделить всё

void UFG_MovementComponent::AlignToSurface(float DeltaTime)
{
// If the wheel or gyro does not exist, or if the direction is not set, exit
if (!Wheel || !Gyro || !Direction)
return;

// Check if the wheel is currently on the ground
if (!GetGroundStatus(TraceLength))
return;

// Get the surface normal
FVector NewSurfaceNormal = GetSurfaceNormal(NormalTraceLength, SurfaceNormal);

if (NewSurfaceNormal == SurfaceNormal)
return;

SurfaceNormal = NewSurfaceNormal;

// Get the current rotation of the wheel
FRotator CurrentRot = Wheel->GetComponentRotation();
FRotator GyroRot = Gyro->GetComponentRotation();
FRotator CurrentDirectionRot = Direction->GetComponentRotation();

// Calculate the target rotation based on the surface normal and current rotation
FRotator TargetRot = MakeAlignedRotator(SurfaceNormal, CurrentRot);
// Apply the target rotation to the wheel
Wheel->SetWorldRotation(TargetRot);
Gyro->SetWorldRotation(GyroRot);

FRotator TargetDirectionRot = MakeAlignedRotator(SurfaceNormal, CurrentDirectionRot);
Direction->SetWorldRotation(TargetDirectionRot);

}
Функция, выравнивающая колесо и направление по нормали поверхности

Код: Выделить всё

void UFG_MovementComponent::AlignToSurface(float DeltaTime)
{
// If the wheel or gyro does not exist, or if the direction is not set, exit
if (!Wheel || !Gyro || !Direction)
return;

// Check if the wheel is currently on the ground
if (!GetGroundStatus(TraceLength))
return;

// Get the surface normal
FVector NewSurfaceNormal = GetSurfaceNormal(NormalTraceLength, SurfaceNormal);

if (NewSurfaceNormal == SurfaceNormal)
return;

SurfaceNormal = NewSurfaceNormal;

// Get the current rotation of the wheel
FRotator CurrentRot = Wheel-\>GetComponentRotation();
FRotator GyroRot = Gyro-\>GetComponentRotation();
FRotator CurrentDirectionRot = Direction-\>GetComponentRotation();

// Calculate the target rotation based on the surface normal and current rotation
FRotator TargetRot = MakeAlignedRotator(SurfaceNormal, CurrentRot);
// Apply the target rotation to the wheel
Wheel-\>SetWorldRotation(TargetRot);
Gyro-\>SetWorldRotation(GyroRot);

FRotator TargetDirectionRot = MakeAlignedRotator(SurfaceNormal, CurrentDirectionRot);
Direction-\>SetWorldRotation(TargetDirectionRot);
}
Тогда есть главное, что, я полагаю, вызывает эту проблему

Код: Выделить всё

void UFG_MovementComponent::ApplyGyroStabilization(float DeltaTime)
{
// Check if Gyro component is valid
if (!Gyro)
return;

// Get the current rotation of the Wheel component
FRotator WheelRot = Wheel->GetComponentRotation();

// Get the current rotation of the Gyro component
FRotator GyroRot = Gyro->GetComponentRotation();

// Get the direction of the wheel drive force
FRotator DirectionRot = MakeAlignedRotator(SurfaceNormal, WheelRot);

// Calculate the gravity aligned rotation
FRotator GravityRot = MakeAlignedRotator(-GravityDirection, WheelRot);

GEngine->AddOnScreenDebugMessage(1, 1.f, FColor::Red, FString::Printf(TEXT("GravityRot:  %f, %f, %f"), GravityRot.Roll, GravityRot.Pitch, GravityRot.Yaw));
GEngine->AddOnScreenDebugMessage(2, 1.f, FColor::Green, FString::Printf(TEXT("GravityRot: %f, %f, %f"), WheelRot.Roll, WheelRot.Pitch, WheelRot.Yaw));
// Calculate the alignment coefficient based on the wheel drive force
float AlignCoeff = FMath::GetMappedRangeValueClamped(
FVector2D(0.f, 3000.f),
FVector2D(1.f, 1.f),
FMath::Abs(WheelDriveForce)); // YOU CAN IGNORE THIS, IT JUST CALCULATE HOW, BASED ON SPEED IT WILL ALIGN TO SURFACE RATHER THAN GRAVITY

// Calculate the target rotation based on the alignment coefficient
FRotator TargetRot = UKismetMathLibrary::RLerp(
GravityRot,
DirectionRot,
AlignCoeff, true); // AND THIS ALSO

// Calculate the new rotation of the Gyro component
FRotator NewRot;

if (bGrounded)
{
NewRot = CalculateSpringRotation(DeltaTime, GyroRot, TargetRot, GyroSpringVelocity, GyroStiffness, GyroDamping);
}
else
{
NewRot = CalculateSpringRotation(DeltaTime, GyroRot, GyroRot, GyroSpringVelocity, GyroStiffness, GyroDamping);
}

// Apply the new rotation to the Gyro component
Gyro->SetWorldRotation(NewRot);

}
< /code>
Функция, которая разжигает вращение, используя скорость гниения (также изменяет переменную скорости, из-за & (да, я знаю, основные вещи, но на всякий случай)) < /p>
FRotator UFG_MovementComponent::CalculateSpringRotation(float DeltaTime, FRotator CurrentRotation, FRotator TargetRotation, FRotator &CurrentVelocity, float SpringStiffness, float SpringDamping)
{
FRotator SpringOffset = (TargetRotation - CurrentRotation).GetNormalized();

FRotator SpringAccel = SpringOffset * SpringStiffness - CurrentVelocity * SpringDamping;

CurrentVelocity += SpringAccel * FMath::Clamp(DeltaTime, 0.005f, 0.033f);

FRotator NewRot = CurrentRotation + CurrentVelocity * DeltaTime;

return NewRot;
}
Контекст:
Пользовательское движение, полностью C ++ (без символов, компонент).
wheel выравнивается в surfacenormal , а gyro применяет устойчивую пружину. Колесо не соответствует направлению, потому что, когда я пытался управлять колесом в качестве корневого компонента, это вызвало проблемы репликации. Я планирую сделать этот многопользовательский, поэтому мне пришлось разделить их, хотя мне интересно, есть ли надежный способ управлять корневым колесом, не нарушая репликацию. Sparsy, Codeium помогла с DocStrings, хотя должен быть читаемым. Ось (вперед/задний наклон) относительно направления прямого направления колеса (компонент направления, а не корень), похожая на пружину, пытающуюся сохранить равновесие.>

Подробнее здесь: https://stackoverflow.com/questions/797 ... movement-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»