CARLA
 
载入中...
搜索中...
未找到
ChronoMovementComponent.cpp
浏览该文件的文档.
1// Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3// Copyright (c) 2019 Intel Corporation
4//
5// This work is licensed under the terms of the MIT license.
6// For a copy, see <https://opensource.org/licenses/MIT>.
7
11
13#include <carla/rpc/String.h>
14#ifdef WITH_CHRONO
15#include "chrono_vehicle/utils/ChUtilsJSON.h"
16#endif
19
20
23 uint64_t MaxSubsteps,
24 float MaxSubstepDeltaTime,
25 FString VehicleJSON,
26 FString PowertrainJSON,
27 FString TireJSON,
28 FString BaseJSONPath)
29{
30 #ifdef WITH_CHRONO
31 UChronoMovementComponent* ChronoMovementComponent = NewObject<UChronoMovementComponent>(Vehicle);
32 if (!VehicleJSON.IsEmpty())
33 {
34 ChronoMovementComponent->VehicleJSON = VehicleJSON;
35 }
36 if (!PowertrainJSON.IsEmpty())
37 {
38 ChronoMovementComponent->PowertrainJSON = PowertrainJSON;
39 }
40 if (!TireJSON.IsEmpty())
41 {
42 ChronoMovementComponent->TireJSON = TireJSON;
43 }
44 if (!BaseJSONPath.IsEmpty())
45 {
46 ChronoMovementComponent->BaseJSONPath = BaseJSONPath;
47 }
48 ChronoMovementComponent->MaxSubsteps = MaxSubsteps;
49 ChronoMovementComponent->MaxSubstepDeltaTime = MaxSubstepDeltaTime;
50 Vehicle->SetCarlaMovementComponent(ChronoMovementComponent);
51 ChronoMovementComponent->RegisterComponent();
52 #else
53 UE_LOG(LogCarla, Warning, TEXT("Error: Chrono is not enabled") );
54 #endif
55}
56
57#ifdef WITH_CHRONO
58
59using namespace chrono;
60using namespace chrono::vehicle;
61
62constexpr double CMTOM = 0.01;
63ChVector<> UE4LocationToChrono(const FVector& Location)
64{
65 return CMTOM*ChVector<>(Location.X, -Location.Y, Location.Z);
66}
67constexpr double MTOCM = 100;
68FVector ChronoToUE4Location(const ChVector<>& position)
69{
70 return MTOCM*FVector(position.x(), -position.y(), position.z());
71}
72ChVector<> UE4DirectionToChrono(const FVector& Location)
73{
74 return ChVector<>(Location.X, -Location.Y, Location.Z);
75}
76FVector ChronoToUE4Direction(const ChVector<>& position)
77{
78 return FVector(position.x(), -position.y(), position.z());
79}
80ChQuaternion<> UE4QuatToChrono(const FQuat& Quat)
81{
82 return ChQuaternion<>(Quat.W, -Quat.X, Quat.Y, -Quat.Z);
83}
84FQuat ChronoToUE4Quat(const ChQuaternion<>& quat)
85{
86 return FQuat(-quat.e1(), quat.e2(), -quat.e3(), quat.e0());
87}
88
89UERayCastTerrain::UERayCastTerrain(
90 ACarlaWheeledVehicle* UEVehicle,
91 chrono::vehicle::ChVehicle* ChrVehicle)
92 : CarlaVehicle(UEVehicle), ChronoVehicle(ChrVehicle) {}
93
94std::pair<bool, FHitResult>
95 UERayCastTerrain::GetTerrainProperties(const FVector &Location) const
96{
97 const double MaxDistance = 1000000;
98 FVector StartLocation = Location;
99 FVector EndLocation = Location + FVector(0,0,-1)*MaxDistance; // search downwards
100 FHitResult Hit;
101 FCollisionQueryParams CollisionQueryParams;
102 CollisionQueryParams.AddIgnoredActor(CarlaVehicle);
103 bool bDidHit = CarlaVehicle->GetWorld()->LineTraceSingleByChannel(
104 Hit,
105 StartLocation,
106 EndLocation,
107 ECC_GameTraceChannel2, // camera (any collision)
108 CollisionQueryParams,
109 FCollisionResponseParams()
110 );
111 return std::make_pair(bDidHit, Hit);
112}
113
114double UERayCastTerrain::GetHeight(const ChVector<>& loc) const
115{
116 FVector Location = ChronoToUE4Location(loc + ChVector<>(0,0,0.5)); // small offset to detect the ground properly
117 auto point_pair = GetTerrainProperties(Location);
118 if (point_pair.first)
119 {
120 double Height = CMTOM*static_cast<double>(point_pair.second.Location.Z);
121 return Height;
122 }
123 return -1000000.0;
124}
125ChVector<> UERayCastTerrain::GetNormal(const ChVector<>& loc) const
126{
127 FVector Location = ChronoToUE4Location(loc);
128 auto point_pair = GetTerrainProperties(Location);
129 if (point_pair.first)
130 {
131 FVector Normal = point_pair.second.Normal;
132 auto ChronoNormal = UE4DirectionToChrono(Normal);
133 return ChronoNormal;
134 }
135 return UE4DirectionToChrono(FVector(0,0,1));
136}
137float UERayCastTerrain::GetCoefficientFriction(const ChVector<>& loc) const
138{
139 return 1;
140}
141
143{
144 Super::BeginPlay();
145
147
148 // // // Chrono System
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);
153
154 InitializeChronoVehicle();
155
156 // Create the terrain
157 Terrain = chrono_types::make_shared<UERayCastTerrain>(CarlaVehicle, Vehicle.get());
158
159 CarlaVehicle->OnActorHit.AddDynamic(
161 CarlaVehicle->GetMesh()->OnComponentBeginOverlap.AddDynamic(
163 CarlaVehicle->GetMesh()->SetCollisionResponseToChannel(
164 ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Overlap);
165}
166
167void UChronoMovementComponent::InitializeChronoVehicle()
168{
169 // Initial location with small offset to prevent falling through the ground
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);
174
175 // Set base path for vehicle JSON files
176 vehicle::SetDataPath(carla::rpc::FromFString(BaseJSONPath));
177
178 std::string BasePath_string = carla::rpc::FromFString(BaseJSONPath);
179
180 // Create full path for json files
181 // Do NOT use vehicle::GetDataFile() as strings from chrono lib
182 // messes with unreal's std lib
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);
186
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);
190
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);
194
195 UE_LOG(LogCarla, Log, TEXT("Loading Chrono files: Vehicle: %s, PowerTrain: %s, Tire: %s"),
196 *VehicleJSONPath,
197 *PowerTrainJSONPath,
198 *TireJSONPath);
199 // Create JSON vehicle
200 Vehicle = chrono_types::make_shared<WheeledVehicle>(
201 &Sys,
202 VehiclePath_string);
203 Vehicle->Initialize(ChCoordsys<>(ChronoLocation, ChronoRotation));
204 Vehicle->GetChassis()->SetFixed(false);
205 // Create and initialize the powertrain System
206 auto powertrain = ReadPowertrainJSON(
207 PowerTrain_string);
208 Vehicle->InitializePowertrain(powertrain);
209 // Create and initialize the tires
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);
214 }
215 }
216}
217
219{
220 VehicleControl = Control;
221 auto PowerTrain = Vehicle->GetPowertrain();
222 if (PowerTrain)
223 {
225 {
226 PowerTrain->SetDriveMode(ChPowertrain::DriveMode::REVERSE);
227 }
228 else
229 {
230 PowerTrain->SetDriveMode(ChPowertrain::DriveMode::FORWARD);
231 }
232 }
233}
234
235void UChronoMovementComponent::TickComponent(float DeltaTime,
236 ELevelTick TickType,
237 FActorComponentTickFunction* ThisTickFunction)
238{
239 TRACE_CPUPROFILER_EVENT_SCOPE(UChronoMovementComponent::TickComponent);
240 if (DeltaTime > MaxSubstepDeltaTime)
241 {
242 uint64_t NumberSubSteps =
243 FGenericPlatformMath::FloorToInt(DeltaTime/MaxSubstepDeltaTime);
244 if (NumberSubSteps < MaxSubsteps)
245 {
246 for (uint64_t i = 0; i < NumberSubSteps; ++i)
247 {
248 AdvanceChronoSimulation(MaxSubstepDeltaTime);
249 }
250 float RemainingTime = DeltaTime - NumberSubSteps*MaxSubstepDeltaTime;
251 if (RemainingTime > 0)
252 {
253 AdvanceChronoSimulation(RemainingTime);
254 }
255 }
256 else
257 {
258 double SubDelta = DeltaTime / MaxSubsteps;
259 for (uint64_t i = 0; i < MaxSubsteps; ++i)
260 {
261 AdvanceChronoSimulation(SubDelta);
262 }
263 }
264 }
265 else
266 {
267 AdvanceChronoSimulation(DeltaTime);
268 }
269
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();
274
275 FVector NewLocation = ChronoToUE4Location(VehiclePos);
276 FQuat NewRotation = ChronoToUE4Quat(VehicleRot);
277 if(NewLocation.ContainsNaN() || NewRotation.ContainsNaN())
278 {
279 UE_LOG(LogCarla, Warning, TEXT(
280 "Error: Chrono vehicle position or rotation contains NaN. Disabling chrono physics..."));
282 return;
283 }
284 CarlaVehicle->SetActorLocation(NewLocation);
285 FRotator NewRotator = NewRotation.Rotator();
286 // adding small rotation to compensate chrono offset
287 const float ChronoPitchOffset = 2.5f;
288 NewRotator.Add(ChronoPitchOffset, 0.f, 0.f);
289 CarlaVehicle->SetActorRotation(NewRotator);
290}
291
292void UChronoMovementComponent::AdvanceChronoSimulation(float StepSize)
293{
294 double Time = Vehicle->GetSystem()->GetChTime();
295 double Throttle = VehicleControl.Throttle;
296 double Steering = -VehicleControl.Steer; // RHF to LHF
298 Vehicle->Synchronize(Time, {Steering, Throttle, Brake}, *Terrain.get());
299 Vehicle->Advance(StepSize);
300 Sys.DoStepDynamics(StepSize);
301}
302
304{
305 if (Vehicle)
306 {
307 return ChronoToUE4Location(
308 Vehicle->GetVehiclePointVelocity(ChVector<>(0,0,0)));
309 }
310 return FVector();
311}
312
314{
315 if (Vehicle)
316 {
317 auto PowerTrain = Vehicle->GetPowertrain();
318 if (PowerTrain)
319 {
320 return PowerTrain->GetCurrentTransmissionGear();
321 }
322 }
323 return 0;
324}
325
327{
328 if (Vehicle)
329 {
330 return GetVelocity().X;
331 }
332 return 0.f;
333}
334
335void UChronoMovementComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
336{
337 if(!CarlaVehicle)
338 {
339 return;
340 }
341 // reset callbacks to react to collisions
342 CarlaVehicle->OnActorHit.RemoveDynamic(
344 CarlaVehicle->GetMesh()->OnComponentBeginOverlap.RemoveDynamic(
346 CarlaVehicle->GetMesh()->SetCollisionResponseToChannel(
347 ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
348}
349#endif
350
355
357{
358 this->SetComponentTickEnabled(false);
360 CarlaVehicle->OnActorHit.RemoveDynamic(this, &UChronoMovementComponent::OnVehicleHit);
361 CarlaVehicle->GetMesh()->OnComponentBeginOverlap.RemoveDynamic(
363 CarlaVehicle->GetMesh()->SetCollisionResponseToChannel(
364 ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
366}
367
369 AActor *OtherActor,
370 FVector NormalImpulse,
371 const FHitResult &Hit)
372{
373 carla::log_warning("Chrono physics does not support collisions yet, reverting to default PhysX physics.");
375}
376
377// On car mesh overlap, only works when carsim is enabled
378// (this event triggers when overlapping with static environment)
380 UPrimitiveComponent* OverlappedComponent,
381 AActor* OtherActor,
382 UPrimitiveComponent* OtherComp,
383 int32 OtherBodyIndex,
384 bool bFromSweep,
385 const FHitResult & SweepResult)
386{
387 if (OtherComp->GetCollisionResponseToChannel(
388 ECollisionChannel::ECC_WorldDynamic) ==
389 ECollisionResponse::ECR_Block)
390 {
391 carla::log_warning("Chrono physics does not support collisions yet, reverting to default PhysX physics.");
393 }
394}
Base class for CARLA wheeled vehicles.
virtual void ProcessControl(FVehicleControl &Control)
void EnableUE4VehiclePhysics(bool bResetVelocity=true)
void OnVehicleHit(AActor *Actor, AActor *OtherActor, FVector NormalImpulse, const FHitResult &Hit)
static void CreateChronoMovementComponent(ACarlaWheeledVehicle *Vehicle, uint64_t MaxSubsteps, float MaxSubstepDeltaTime, FString VehicleJSON="", FString PowertrainJSON="", FString TireJSON="", FString BaseJSONPath="")
void OnVehicleOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
virtual void DisableSpecialPhysics() override
static void CreateDefaultMovementComponent(ACarlaWheeledVehicle *Vehicle)
geom::Location Location
static void log_warning(Args &&... args)
Definition Logging.h:96