15 #include "chrono_vehicle/utils/ChUtilsJSON.h" 24 float MaxSubstepDeltaTime,
26 FString PowertrainJSON,
32 if (!VehicleJSON.IsEmpty())
36 if (!PowertrainJSON.IsEmpty())
40 if (!TireJSON.IsEmpty())
44 if (!BaseJSONPath.IsEmpty())
51 ChronoMovementComponent->RegisterComponent();
53 UE_LOG(LogCarla, Warning, TEXT(
"Error: Chrono is not enabled") );
59 using namespace chrono;
60 using namespace chrono::vehicle;
62 constexpr
double CMTOM = 0.01;
63 ChVector<> UE4LocationToChrono(
const FVector&
Location)
65 return CMTOM*ChVector<>(Location.X, -Location.Y, Location.Z);
67 constexpr
double MTOCM = 100;
68 FVector ChronoToUE4Location(
const ChVector<>& position)
70 return MTOCM*FVector(position.x(), -position.y(), position.z());
72 ChVector<> UE4DirectionToChrono(
const FVector&
Location)
74 return ChVector<>(Location.X, -Location.Y, Location.Z);
76 FVector ChronoToUE4Direction(
const ChVector<>& position)
78 return FVector(position.x(), -position.y(), position.z());
80 ChQuaternion<> UE4QuatToChrono(
const FQuat& Quat)
82 return ChQuaternion<>(Quat.W, -Quat.X, Quat.Y, -Quat.Z);
84 FQuat ChronoToUE4Quat(
const ChQuaternion<>& quat)
86 return FQuat(-quat.e1(), quat.e2(), -quat.e3(), quat.e0());
89 UERayCastTerrain::UERayCastTerrain(
91 chrono::vehicle::ChVehicle* ChrVehicle)
94 std::pair<bool, FHitResult>
95 UERayCastTerrain::GetTerrainProperties(
const FVector &
Location)
const 97 const double MaxDistance = 1000000;
99 FVector EndLocation = Location + FVector(0,0,-1)*MaxDistance;
101 FCollisionQueryParams CollisionQueryParams;
103 bool bDidHit =
CarlaVehicle->GetWorld()->LineTraceSingleByChannel(
107 ECC_GameTraceChannel2,
108 CollisionQueryParams,
109 FCollisionResponseParams()
111 return std::make_pair(bDidHit, Hit);
114 double UERayCastTerrain::GetHeight(
const ChVector<>& loc)
const 116 FVector
Location = ChronoToUE4Location(loc + ChVector<>(0,0,0.5));
117 auto point_pair = GetTerrainProperties(Location);
118 if (point_pair.first)
120 double Height = CMTOM*
static_cast<double>(point_pair.second.Location.Z);
125 ChVector<> UERayCastTerrain::GetNormal(
const ChVector<>& loc)
const 127 FVector
Location = ChronoToUE4Location(loc);
128 auto point_pair = GetTerrainProperties(Location);
129 if (point_pair.first)
131 FVector Normal = point_pair.second.Normal;
132 auto ChronoNormal = UE4DirectionToChrono(Normal);
135 return UE4DirectionToChrono(FVector(0,0,1));
137 float UERayCastTerrain::GetCoefficientFriction(
const ChVector<>& loc)
const 149 Sys.Set_G_acc(ChVector<>(0, 0, -9.81));
150 Sys.SetSolverType(ChSolver::Type::BARZILAIBORWEIN);
151 Sys.SetSolverMaxIterations(150);
152 Sys.SetMaxPenetrationRecoverySpeed(4.0);
154 InitializeChronoVehicle();
159 CarlaVehicle->OnActorHit.AddDynamic(
161 CarlaVehicle->GetMesh()->OnComponentBeginOverlap.AddDynamic(
163 CarlaVehicle->GetMesh()->SetCollisionResponseToChannel(
164 ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Overlap);
167 void UChronoMovementComponent::InitializeChronoVehicle()
170 FVector VehicleLocation =
CarlaVehicle->GetActorLocation() + FVector(0,0,25);
171 FQuat VehicleRotation =
CarlaVehicle->GetActorRotation().Quaternion();
172 auto ChronoLocation = UE4LocationToChrono(VehicleLocation);
173 auto ChronoRotation = UE4QuatToChrono(VehicleRotation);
176 vehicle::SetDataPath(carla::rpc::FromFString(
BaseJSONPath));
178 std::string BasePath_string = carla::rpc::FromFString(
BaseJSONPath);
183 std::string VehicleJSON_string = carla::rpc::FromFString(
VehicleJSON);
184 std::string VehiclePath_string = BasePath_string + VehicleJSON_string;
185 FString VehicleJSONPath = carla::rpc::ToFString(VehiclePath_string);
187 std::string PowerTrainJSON_string = carla::rpc::FromFString(
PowertrainJSON);
188 std::string PowerTrain_string = BasePath_string + PowerTrainJSON_string;
189 FString PowerTrainJSONPath = carla::rpc::ToFString(PowerTrain_string);
191 std::string TireJSON_string = carla::rpc::FromFString(
TireJSON);
192 std::string Tire_string = BasePath_string + TireJSON_string;
193 FString TireJSONPath = carla::rpc::ToFString(Tire_string);
195 UE_LOG(LogCarla, Log, TEXT(
"Loading Chrono files: Vehicle: %s, PowerTrain: %s, Tire: %s"),
200 Vehicle = chrono_types::make_shared<WheeledVehicle>(
203 Vehicle->Initialize(ChCoordsys<>(ChronoLocation, ChronoRotation));
204 Vehicle->GetChassis()->SetFixed(
false);
206 auto powertrain = ReadPowertrainJSON(
208 Vehicle->InitializePowertrain(powertrain);
210 for (
auto& axle :
Vehicle->GetAxles()) {
211 for (
auto& wheel : axle->GetWheels()) {
212 auto tire = ReadTireJSON(Tire_string);
213 Vehicle->InitializeTire(tire, wheel, VisualizationType::MESH);
221 auto PowerTrain =
Vehicle->GetPowertrain();
226 PowerTrain->SetDriveMode(ChPowertrain::DriveMode::REVERSE);
230 PowerTrain->SetDriveMode(ChPowertrain::DriveMode::FORWARD);
235 void UChronoMovementComponent::TickComponent(
float DeltaTime,
237 FActorComponentTickFunction* ThisTickFunction)
239 TRACE_CPUPROFILER_EVENT_SCOPE(UChronoMovementComponent::TickComponent);
242 uint64_t NumberSubSteps =
246 for (uint64_t i = 0; i < NumberSubSteps; ++i)
251 if (RemainingTime > 0)
253 AdvanceChronoSimulation(RemainingTime);
261 AdvanceChronoSimulation(SubDelta);
267 AdvanceChronoSimulation(DeltaTime);
270 const auto ChronoPositionOffset = ChVector<>(0,0,-0.25f);
271 auto VehiclePos =
Vehicle->GetVehiclePos() + ChronoPositionOffset;
272 auto VehicleRot =
Vehicle->GetVehicleRot();
273 double Time =
Vehicle->GetSystem()->GetChTime();
275 FVector NewLocation = ChronoToUE4Location(VehiclePos);
276 FQuat NewRotation = ChronoToUE4Quat(VehicleRot);
277 if(NewLocation.ContainsNaN() || NewRotation.ContainsNaN())
279 UE_LOG(LogCarla, Warning, TEXT(
280 "Error: Chrono vehicle position or rotation contains NaN. Disabling chrono physics..."));
285 FRotator NewRotator = NewRotation.Rotator();
287 const float ChronoPitchOffset = 2.5f;
288 NewRotator.Add(ChronoPitchOffset, 0.f, 0.f);
292 void UChronoMovementComponent::AdvanceChronoSimulation(
float StepSize)
294 double Time =
Vehicle->GetSystem()->GetChTime();
298 Vehicle->Synchronize(Time, {Steering, Throttle, Brake}, *Terrain.get());
300 Sys.DoStepDynamics(StepSize);
307 return ChronoToUE4Location(
308 Vehicle->GetVehiclePointVelocity(ChVector<>(0,0,0)));
317 auto PowerTrain =
Vehicle->GetPowertrain();
320 return PowerTrain->GetCurrentTransmissionGear();
335 void UChronoMovementComponent::EndPlay(
const EEndPlayReason::Type EndPlayReason)
344 CarlaVehicle->GetMesh()->OnComponentBeginOverlap.RemoveDynamic(
347 ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
353 this->SetComponentTickEnabled(
false);
356 CarlaVehicle->GetMesh()->OnComponentBeginOverlap.RemoveDynamic(
359 ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
361 carla::log_warning(
"Chrono physics does not support collisions yet, reverting to default PhysX physics.");
366 FVector NormalImpulse,
367 const FHitResult &Hit)
378 int32 OtherBodyIndex,
380 const FHitResult & SweepResult)
382 if (OtherComp->GetCollisionResponseToChannel(
383 ECollisionChannel::ECC_WorldDynamic) ==
384 ECollisionResponse::ECR_Block)
virtual void ProcessControl(FVehicleControl &Control)
void OnVehicleHit(AActor *Actor, AActor *OtherActor, FVector NormalImpulse, const FHitResult &Hit)
void DisableUE4VehiclePhysics()
virtual FVector GetVelocity() const
ACarlaWheeledVehicle * CarlaVehicle
void DisableChronoPhysics()
float MaxSubstepDeltaTime
virtual void BeginPlay() override
carla::SharedPtr< cc::Actor > Actor
void OnVehicleOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
static void log_warning(Args &&... args)
static void CreateChronoMovementComponent(ACarlaWheeledVehicle *Vehicle, uint64_t MaxSubsteps, float MaxSubstepDeltaTime, FString VehicleJSON="", FString PowertrainJSON="", FString TireJSON="", FString BaseJSONPath="")
virtual int32 GetVehicleCurrentGear() const
virtual float GetVehicleForwardSpeed() const
void EnableUE4VehiclePhysics(bool bResetVelocity=true)
Base class for CARLA wheeled vehicles.
static void CreateDefaultMovementComponent(ACarlaWheeledVehicle *Vehicle)
FVehicleControl VehicleControl
void SetCarlaMovementComponent(UBaseCarlaMovementComponent *MoementComponent)