Agrarsense
SimulatorJsonParser.cpp
Go to the documentation of this file.
1// Copyright (c) 2023 FrostBit Software Lab at the Lapland University of Applied Sciences
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
7
13
21
24
26
41
43
44#include "Kismet/GameplayStatics.h"
45#include "Camera/PlayerCameraManager.h"
46#include "GenericPlatform/GenericPlatformFile.h"
47#include "Serialization/JsonSerializer.h"
48#include "Serialization/JsonWriter.h"
49#include "Misc/DefaultValueHelper.h"
50#include "HAL/PlatformFileManager.h"
51#include "GameFramework/Pawn.h"
52#include "Misc/FileHelper.h"
53#include "Dom/JsonObject.h"
54#include "GameFramework/PlayerController.h"
55#include "CollisionQueryParams.h"
56#include "Engine/GameViewportClient.h"
57#include "Engine/EngineTypes.h"
58#include "Engine/Engine.h"
59#include "Engine/World.h"
60
63
65{
67 {
68 SimulatorLog::Log("SimulatorJsonParser: Spawning objects in main menu is disabled.");
69 return;
70 }
71
72 if (!FPaths::FileExists(Path))
73 {
74 SimulatorLog::Log(FString::Printf(TEXT("SimulatorJsonParser: Path %s doesn't exist."), *Path));
75 return;
76 }
77
78 if (!FPaths::GetExtension(Path).Equals(TEXT("json"), ESearchCase::IgnoreCase))
79 {
80 SimulatorLog::Log("SimulatorJsonParser: Invalid file extension. Only .json files are supported.");
81 return;
82 }
83
84 FString JsonString;
85 if (!FFileHelper::LoadFileToString(JsonString, *Path))
86 {
87 SimulatorLog::Log("SimulatorJsonParser: Failed to read the json file.");
88 return;
89 }
90
91 TSharedPtr<FJsonObject> RootJsonObject = MakeShareable(new FJsonObject);
92 TSharedRef<TJsonReader<TCHAR>> Reader = TJsonReaderFactory<TCHAR>::Create(JsonString);
93 if (!FJsonSerializer::Deserialize(Reader, RootJsonObject))
94 {
95 SimulatorLog::Log("SimulatorJsonParser: Failed to deserialize json file.");
96 return;
97 }
98
99 const TArray<TSharedPtr<FJsonValue>>* JsonObjects;
100 if (!RootJsonObject->TryGetArrayField(TEXT("objects"), JsonObjects))
101 {
102 SimulatorLog::Log("json content doesn't contain 'objects' field. Make sure your json structure is correct.");
103 return;
104 }
105
106 // The key in the JSON object that we are searching for
107 FString FieldTypeString = "type";
108
109 // Pre-process incoming json objects
110 bool JsonContainsSensorType = false;
111 bool JsonContainsDataCaptureType = false;
112 TArray<TSharedPtr<FJsonObject>> FilteredJsonObjects;
113
114 for (const TSharedPtr<FJsonValue>& JsonObjectValue : *JsonObjects)
115 {
116 if (JsonObjectValue->Type != EJson::Object)
117 {
118 continue;
119 }
120
121 TSharedPtr<FJsonObject> JsonObject = JsonObjectValue->AsObject();
122 FString ObjectType;
123 if (!JsonObject->TryGetStringField(FieldTypeString, ObjectType))
124 {
125 continue;
126 }
127
128 // Convert ObjectType to lowercase to avoid case-sensitive checks below.
129 ObjectType.ToLowerInline();
130
131 FilteredJsonObjects.Add(JsonObject);
132
133 if (ObjectType == "sensor")
134 {
135 JsonContainsSensorType = true;
136 }
137 else if (ObjectType == "datacapture")
138 {
139 JsonContainsDataCaptureType = true;
140 }
141 }
142
143 // Check if both "sensor" and "datacapture" types are present in the JSON.
144 // If so, set IsDataCapture to true, indicating that spawned sensors should be tracked
145 // and added to the ADataCapture actor.
146 IsDataCapture = JsonContainsSensorType && JsonContainsDataCaptureType;
147
148 // Process json objects
149 for (const TSharedPtr<FJsonObject>& JsonObject : FilteredJsonObjects)
150 {
151 FString ObjectType;
152 if (!JsonObject->TryGetStringField(FieldTypeString, ObjectType))
153 {
154 continue;
155 }
156
157 ObjectType.ToLowerInline();
158
159 if (ObjectType == "vehicle")
160 {
161 ParseVehicle(JsonObject);
162 }
163 else if (ObjectType == "weather")
164 {
165 ChangeWeather(JsonObject);
166 }
167 else if (ObjectType == "walker")
168 {
169 SpawnWalker(JsonObject);
170 }
171 else if (ObjectType == "sensor")
172 {
173 SpawnSensorWorld(JsonObject);
174 }
175 else if (ObjectType == "prop")
176 {
177 ParsePropOrFoliage(JsonObject, "prop");
178 }
179 else if (ObjectType == "foliage")
180 {
181 ParsePropOrFoliage(JsonObject, "foliage");
182 }
183 else if (ObjectType == "semanticcolors")
184 {
185 ParseAndSetSemanticColors(JsonObject);
186 }
187 else if (ObjectType == "commands")
188 {
189 ParseCommands(JsonObject);
190 }
191 else if (ObjectType == "volumedeletion")
192 {
193 ParseVolumeDeletion(JsonObject);
194 }
195 else if (ObjectType == "datacapture")
196 {
197 ParseDataCapture(JsonObject);
198 }
199 }
200
201 // If IsDataCapture was true, clear array.
202 if (IsDataCapture)
203 {
205 IsDataCapture = false;
206 }
207}
208
209void USimulatorJsonParser::ParseVehicle(const TSharedPtr<FJsonObject>& JsonObject)
210{
211 FString Model;
212 if (!JsonObject->TryGetStringField(TEXT("model"), Model))
213 {
214 // If json doesn't specifiy model, return
215 return;
216 }
217
218 FString Name, ID;
219 JsonObject->TryGetStringField(TEXT("name"), Name);
220 JsonObject->TryGetStringField(TEXT("id"), ID);
221 if (ID.IsEmpty())
222 {
223 ID = Model;
224 }
225
227 bool IsDrone = VehicleType == EVehicleTypes::Drone;
228
229 FTransform SpawnTransform = ParseTransform("spawnPoint", JsonObject);
230
231 // Should use Z value as height from the ground instead of given Z value
232 bool ZIsHeightAboveGround = false;
233 JsonObject->TryGetBoolField(TEXT("zIsHeightAboveGround"), ZIsHeightAboveGround);
234 if (ZIsHeightAboveGround)
235 {
237 }
238
239 bool DestroyCollidedObjectsOnSpawn = false;
240 JsonObject->TryGetBoolField(TEXT("destroyOverlappingObjects"), DestroyCollidedObjectsOnSpawn);
241
242 AVehicle* VehiclePtr = UAssetLibrary::SpawnVehicle(VehicleType, SpawnTransform, Name, ID, false, 150.0f, DestroyCollidedObjectsOnSpawn);
243
244 if (VehiclePtr)
245 {
246 if (IsDrone)
247 {
248 ParseAndSetDroneParameters(Cast<APIDDrone>(VehiclePtr), JsonObject);
249 }
250 else
251 {
252 ParseAndSetWheeledVehicleParameters(VehiclePtr, JsonObject);
253 }
254
255 HandleSpectatorMovement(JsonObject, Cast<AActor>(VehiclePtr), SpawnTransform);
256 }
257 else
258 {
259 // If Vehicle is nullptr, return
260 return;
261 }
262
263
264 bool HideVehicleMeshForCameras = false;
265 JsonObject->TryGetBoolField(TEXT("hideVehicleMeshForCameras"), HideVehicleMeshForCameras);
266
267 // Parse possible sensors which will be attached to spawned vehicle
268 const TArray<TSharedPtr<FJsonValue>>* SensorJsonObjects;
269 if (JsonObject->TryGetArrayField(TEXT("sensors"), SensorJsonObjects))
270 {
271 for (const TSharedPtr<FJsonValue>& SensorValue : *SensorJsonObjects)
272 {
273 if (SensorValue->Type == EJson::Object)
274 {
275 TSharedPtr<FJsonObject> SensorJsonObject = SensorValue->AsObject();
276 SpawnSensorToVehicle(VehiclePtr, SensorJsonObject, HideVehicleMeshForCameras);
277 }
278 }
279 }
280}
281
282void USimulatorJsonParser::ParsePropOrFoliage(const TSharedPtr<FJsonObject>& JsonObject, const FString& ObjectType)
283{
284 FString Model;
285 if (!JsonObject->TryGetStringField(TEXT("model"), Model))
286 {
287 // If json doesn't specifiy model, return
288 return;
289 }
290
291 bool RandomZRotation = false;
292 bool SnapToGround = false;
293 JsonObject->TryGetBoolField(TEXT("snap_to_ground"), SnapToGround);
294 JsonObject->TryGetBoolField(TEXT("random_z_rotation"), RandomZRotation);
295
296 FString Name, ID;
297 JsonObject->TryGetStringField(TEXT("name"), Name);
298 JsonObject->TryGetStringField(TEXT("id"), ID);
299
300 FTransform SpawnTransform = ParseTransform("spawnPoint", JsonObject);
301
302 if (ObjectType.Equals("prop", ESearchCase::IgnoreCase))
303 {
305 UAssetLibrary::SpawnProp(Type, SpawnTransform, Name, ID, RandomZRotation, SnapToGround);
306 }
307 else if (ObjectType.Equals("foliage", ESearchCase::IgnoreCase))
308 {
310 UAssetLibrary::SpawnFoliage(Type, SpawnTransform, Name, ID, RandomZRotation, SnapToGround);
311 }
312}
313
314void USimulatorJsonParser::SpawnSensorToVehicle(AVehicle* Vehicle, const TSharedPtr<FJsonObject>& SensorObject, bool HideVehicleMeshForCameras)
315{
316 if (!Vehicle || !SensorObject.IsValid())
317 {
318 return;
319 }
320
321 USensorsManagerComponent* VehicleSensorManager = Vehicle->GetSensorsManager();
322 if (!VehicleSensorManager)
323 {
324 return;
325 }
326
327 TSharedPtr<FJsonObject> ParametersObject = SensorObject->GetObjectField(TEXT("parameters"));
328 if (!ParametersObject.IsValid())
329 {
330 return;
331 }
332
333 // Sensor spawn point (relative)
334 FTransform RelativeTransform = ParseTransform("spawnPoint", SensorObject);
335
336 // Parse ESensorTypes from string
337 FString SensorTypeString;
338 SensorObject->TryGetStringField(TEXT("model"), SensorTypeString);
339 ESensorTypes SensorType = UEnumUtilities::ConvertStringToSensorType(SensorTypeString);
340
341 // It's fine if these are empty,
342 // USensorsManagerComponent will just generate random name and identifier
343 FString SensorIdentifier, Name;
344 SensorObject->TryGetStringField(TEXT("name"), Name);
345 SensorObject->TryGetStringField(TEXT("id"), SensorIdentifier);
346
347 FString AttachedToComponent;
348 SensorObject->TryGetStringField(TEXT("attachedToComponent"), AttachedToComponent);
349
350 FString AttachedToBoneString;
351 FName AttachedToBone;
352 if (SensorObject->TryGetStringField(TEXT("attachedToBone"), AttachedToBoneString))
353 {
354 AttachedToBone = FName(*AttachedToBoneString);
355 }
356
357 ASensorModel* TempActor = nullptr;
358 ASensor* SensorPtr = nullptr;
359 USceneComponent* AttachToComponent = VehicleSensorManager->GetComponentByHierarchyName(AttachedToComponent);
360
361 // Here sensors are spawned through VehicleSensorManager Actor so it can keep track of the spawned sensors.
362 switch (SensorType)
363 {
365 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnLidar(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FLidarParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
366 break;
367
369 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnCamera(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FCameraBaseParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
370 break;
371
373 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnThermalCamera(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FThermalCameraParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
374 break;
375
377 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnDepthCamera(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FDepthCameraParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
378 break;
379
381 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnRadar(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FRadarParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
382 break;
383
385 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnSegmentationCamera(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FCameraBaseParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
386 break;
387
389 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnInstanceSegmentationCamera(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FCameraBaseParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
390 break;
391
393 SensorPtr = Cast<ASensor>(VehicleSensorManager->SpawnDVSCamera(RelativeTransform, true, SensorIdentifier, Name, ParseParameters<FDVSCameraParameters>(ParametersObject), true, TempActor, AttachToComponent, AttachedToBone));
394 break;
395
396 default:
397 break;
398 }
399
400 if (HideVehicleMeshForCameras)
401 {
402 if (ACamera* CameraPtr = Cast<ACamera>(SensorPtr))
403 {
404 CameraPtr->AddHiddenActor(Vehicle);
405 }
406 }
407
408 // If the vehicle we are attaching is drone,
409 // and the spawned sensor is camera
410 // check if user has given "useGimbal" parameter.
411 if(APIDDrone* DronePtr = Cast<APIDDrone>(Vehicle))
412 {
413 if (ACamera* CameraPtr = Cast<ACamera>(SensorPtr))
414 {
415 bool UseGimbal = false;
416 SensorObject->TryGetBoolField(TEXT("useGimbal"), UseGimbal);
417 CameraPtr->SetUseGimbal(UseGimbal);
418 }
419 }
420}
421
422void USimulatorJsonParser::SpawnSensorWorld(const TSharedPtr<FJsonObject>& SensorObject)
423{
424 UWorld* World = nullptr;
425 if (GEngine && GEngine->GameViewport)
426 {
427 World = GEngine->GameViewport->GetWorld();
428 }
429
430 if (!World
431 || !SensorObject.IsValid()
432 || !SensorObject->HasField(TEXT("parameters"))
433 || !SensorObject->HasField(TEXT("model")))
434 {
435 return;
436 }
437
438 TSharedPtr<FJsonObject> ParametersObject = SensorObject->GetObjectField(TEXT("parameters"));
439 if (!ParametersObject.IsValid())
440 {
441 return;
442 }
443
444 FString SensorTypeString, SensorName, SensorIdentifier;
445 SensorObject->TryGetStringField(TEXT("model"), SensorTypeString);
446 SensorObject->TryGetStringField(TEXT("name"), SensorName);
447 SensorObject->TryGetStringField(TEXT("id"), SensorIdentifier);
448
449 FTransform SpawnTransform = ParseTransform("spawnPoint", SensorObject);
450
451 // Should use Z value as height from the ground instead of given Z value
452 bool ZIsHeightAboveGround = false;
453 SensorObject->TryGetBoolField(TEXT("zIsHeightAboveGround"), ZIsHeightAboveGround);
454 if (ZIsHeightAboveGround)
455 {
457 }
458
459 AActor* ActorPtr = nullptr;
460 ESensorTypes SensorType = UEnumUtilities::ConvertStringToSensorType(SensorTypeString);
461
463 if (!SimulationLevelManager)
464 {
465 SimulatorLog::Log("Failed to spawn Sensor. Reason: Coulnd't to find SimulationLevelManager Actor!");
466 return;
467 }
468
469 USensorsManagerComponent* WorldSensorManager = SimulationLevelManager->GetSensorsManager();
470 if (!WorldSensorManager)
471 {
472 SimulatorLog::Log("Failed to spawn Sensor. Reason: Coulnd't to find USensorsManagerComponent Component!");
473 return;
474 }
475
476 ASensorModel* TempActor = nullptr;
477
478 // Here sensors are spawned through WorldSensorManager Actor so it can keep track of the spawned sensors.
479 switch (SensorType)
480 {
482 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnLidar(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FLidarParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
483 break;
484
486 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnRadar(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FRadarParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
487 break;
488
490 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnCamera(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FCameraBaseParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
491 break;
492
494 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnThermalCamera(SpawnTransform, false, SensorIdentifier, SensorName, ParseThermalCameraParameters(ParametersObject), true, TempActor, nullptr, NAME_None));
495 break;
496
498 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnDepthCamera(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FDepthCameraParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
499 break;
500
502 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnSegmentationCamera(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FCameraBaseParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
503 break;
504
506 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnInstanceSegmentationCamera(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FCameraBaseParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
507 break;
508
510 ActorPtr = Cast<AActor>(WorldSensorManager->SpawnDVSCamera(SpawnTransform, false, SensorIdentifier, SensorName, ParseParameters<FDVSCameraParameters>(ParametersObject), true, TempActor, nullptr, NAME_None));
511 break;
512
513 default:
514 break;
515 }
516
517 if (IsDataCapture)
518 {
519 ACamera* CameraPtr = Cast<ACamera>(ActorPtr);
520 if (CameraPtr)
521 {
522 SpawnedSensorsForDataCapture.Add(Cast<ASensor>(ActorPtr));
523 }
524
525 ALidar* LidarPtr = Cast<ALidar>(ActorPtr);
526 if (LidarPtr)
527 {
528 SpawnedSensorsForDataCapture.Add(Cast<ASensor>(ActorPtr));
529 }
530 }
531
532 bool AttachToSpectator = false;
533 SensorObject->TryGetBoolField(TEXT("attachToSpectator"), AttachToSpectator);
534
535 if (AttachToSpectator)
536 {
538 }
539 else
540 {
541 HandleSpectatorMovement(SensorObject, ActorPtr, SpawnTransform);
542 }
543}
544
545void USimulatorJsonParser::SpawnWalker(const TSharedPtr<FJsonObject>& JsonObject)
546{
547 if (!JsonObject.IsValid())
548 {
549 SimulatorLog::Log("SimulatorJsonParser failed to parse Walker json: Invalid JsonObject");
550 return;
551 }
552
553 FString WalkerTypeString;
554 if (!JsonObject->TryGetStringField(TEXT("model"), WalkerTypeString))
555 {
556 SimulatorLog::Log("SimulatorJsonParser failed to parse Walker json: Model field is missing");
557 return;
558 }
559
560 EWalkerType WalkerType = UEnumUtilities::ConvertStringToWalkerType(WalkerTypeString);
561 if (WalkerType == EWalkerType::NONE)
562 {
563 SimulatorLog::Log("SimulatorJsonParser failed to parse Walker json: Walker is None");
564 return;
565 }
566
567 TSharedPtr<FJsonObject> ParametersObject = JsonObject->GetObjectField(TEXT("parameters"));
568 if (!ParametersObject.IsValid())
569 {
570 SimulatorLog::Log("SimulatorJsonParser failed to parse Walker json: ParametersObject is invalid or missing");
571 return;
572 }
573
574 FString WalkerActionString;
575 if (!ParametersObject->TryGetStringField(TEXT("walkerAction"), WalkerActionString))
576 {
577 SimulatorLog::Log("SimulatorJsonParser failed to parse Walker json: walkerAction field is missing");
578 return;
579 }
580
581 EWalkerAction WalkerAction = UEnumUtilities::ConvertStringToWalkerActionType(WalkerActionString);
582 if (WalkerAction == EWalkerAction::Roaming && !ParametersObject->HasField(TEXT("spawnPoint")))
583 {
584 SimulatorLog::Log("SimulatorJsonParser failed to parse Walker json: Roaming Walker requires spawnPoint");
585 return;
586 }
587
588 // Retrieve the WalkerEndAction
589 FString WalkerEndActionString;
590 ParametersObject->TryGetStringField(TEXT("walkerEndAction"), WalkerEndActionString);
591 EWalkerEndAction WalkerEndAction = UEnumUtilities::ConvertStringToWalkerEndActionType(WalkerEndActionString);
592
593 // Create and populate WalkerParameters
594 FWalkerParameters WalkerParams;
595 WalkerParams.WalkerType = WalkerType;
596 WalkerParams.WalkerAction = WalkerAction;
597 WalkerParams.WalkerEndAction = WalkerEndAction;
598 WalkerParams.WalkerSpeed = GetIntValueOrDefault(ParametersObject, "walkerSpeed", 50);
599 WalkerParams.CreateTransformTopic = true;
600
601 bool CreateTransformTopic = false;
602 if (ParametersObject->TryGetBoolField(TEXT("createTransformTopic"), CreateTransformTopic))
603 {
604 UE_LOG(LogTemp, Warning, TEXT("The boolean value is %s"), (CreateTransformTopic ? TEXT("true") : TEXT("false")));
605 WalkerParams.CreateTransformTopic = CreateTransformTopic;
606 }
607
608 // Parse points or spawnPoint into WalkerParams.Points
609 ParseWalkerSpawnPoints(ParametersObject, WalkerParams);
610
611 // Retrieve optional name and id fields
612 FString Name, ID;
613 ParametersObject->TryGetStringField(TEXT("name"), Name);
614 ParametersObject->TryGetStringField(TEXT("id"), ID);
615
616 // Retrieve the startAutomatically field
617 bool StartAutomatically = true;
618 if (ParametersObject->HasField(TEXT("startAutomatically")))
619 {
620 ParametersObject->TryGetBoolField(TEXT("startAutomatically"), StartAutomatically);
621 }
622
623 // Finally spawn the Walker
624 AWalker* Walker = UAssetLibrary::SpawnWalker(WalkerParams, Name, ID, StartAutomatically);
625 if (Walker)
626 {
627 HandleSpectatorMovement(JsonObject, Cast<AActor>(Walker), WalkerParams.Points[0]);
628 }
629}
630
631void USimulatorJsonParser::ParseWalkerSpawnPoints(const TSharedPtr<FJsonObject>& ParametersObject, FWalkerParameters& WalkerParams)
632{
633 if (ParametersObject->HasField(TEXT("points")))
634 {
635 // If the JSON has "points" field, parse those points into WalkerParams.Points
636 TSharedPtr<FJsonObject> PointsObject = ParametersObject->GetObjectField(TEXT("points"));
637 if (PointsObject.IsValid())
638 {
639 int32 PointIndex = 0;
640 while (true)
641 {
642 FString PointName = FString::Printf(TEXT("point%d"), PointIndex);
643 if (!PointsObject->HasField(PointName))
644 {
645 break;
646 }
647
648 TSharedPtr<FJsonObject> PointObject = PointsObject->GetObjectField(PointName);
649 if (PointObject.IsValid())
650 {
651 FTransform PointTransform = ParseTransform(PointName, PointsObject);
652 WalkerParams.Points.Add(PointTransform);
653 }
654
655 PointIndex++;
656 }
657 }
658 }
659 else if (ParametersObject->HasField(TEXT("spawnPoint")))
660 {
661 // If the JSON doesn't have "points" field but has "spawnPoint", parse that into WalkerParams.Points
662 FTransform PointTransform = ParseTransform("spawnPoint", ParametersObject);
663 WalkerParams.Points.Add(PointTransform);
664 }
665}
666
667void USimulatorJsonParser::ChangeWeather(const TSharedPtr<FJsonObject>& JsonObject)
668{
669 if (!JsonObject.IsValid())
670 {
671 return;
672 }
673
674 TSharedPtr<FJsonObject> Parameters = JsonObject->GetObjectField(TEXT("parameters"));
675 if (Parameters.IsValid() && GEngine && GEngine->GameViewport)
676 {
677 UWorld* World = GEngine->GameViewport->GetWorld();
678 AWeather* WeatherActor = UAgrarsenseStatics::GetWeatherActor(World);
679 if (WeatherActor)
680 {
681 FWeatherParameters Params = WeatherActor->GetCurrentWeather();
682 FJsonObjectConverter::JsonObjectToUStruct(Parameters.ToSharedRef(), FWeatherParameters::StaticStruct(), &Params);
683 WeatherActor->UpdateWeather(Params, true);
684 }
685 }
686}
687
688static EDroneAction GetDroneAction(FString actionstring)
689{
690 if (actionstring == "stationary") { return EDroneAction::Stationary; }
691 if (actionstring == "manual") { return EDroneAction::Manual; }
692 if (actionstring == "roaming") { return EDroneAction::Roaming; }
693 if (actionstring == "followpath") { return EDroneAction::FollowPath; }
694 else { return EDroneAction::Stationary; }
695}
696
697static EDroneEndAction GetDroneEndAction(FString endActionstring)
698{
699 if (endActionstring == "destroy") { return EDroneEndAction::Destroy; }
700 if (endActionstring == "repeatfrombeginning") { return EDroneEndAction::RepeatFromBeginning; }
701 if (endActionstring == "gobackwards") { return EDroneEndAction::GoBackwards; }
702 if (endActionstring == "generaterandomnew") { return EDroneEndAction::GenerateRandomNew; }
703 if (endActionstring == "stop") { return EDroneEndAction::Stop; }
704 else { return EDroneEndAction::Stop; }
705}
706
707void USimulatorJsonParser::ParseAndSetDroneParameters(APIDDrone* DronePtr, const TSharedPtr<FJsonObject>& JsonObject)
708{
709 if (!DronePtr || !JsonObject.IsValid())
710 {
711 return;
712 }
713
714 TSharedPtr<FJsonObject> ParametersObject = JsonObject->GetObjectField(TEXT("parameters"));
715
716 if (ParametersObject.IsValid())
717 {
718 // Should use Z value as height from the ground instead of given Z value
719 bool ZIsHeightAboveGround = false;
720 ParametersObject->TryGetBoolField(TEXT("zIsHeightAboveGround"), ZIsHeightAboveGround);
721
722 FDroneParameters DroneParameters;
723
724 // Manual parsing due unreal automatic struct parsing doesn't work for enums
725
726 // Attempt to parse FDroneParameters from the json
727 FString DroneActionObject = ParametersObject->GetStringField(TEXT("droneAction"));
728 if (!DroneActionObject.IsEmpty())
729 {
730 EDroneAction droneAction = GetDroneAction(DroneActionObject.ToLower());
731 DroneParameters.DroneAction = droneAction;
732 }
733
734 FString DroneEndActionObject = ParametersObject->GetStringField(TEXT("droneEndAction"));
735 if (!DroneEndActionObject.IsEmpty())
736 {
737 EDroneEndAction droneEndAction = GetDroneEndAction(DroneEndActionObject);
738 DroneParameters.DroneEndAction = droneEndAction;
739 }
740
741 TSharedPtr<FJsonObject> PointsObject = ParametersObject->GetObjectField(TEXT("points"));
742 if (PointsObject.IsValid())
743 {
744 int32 PointIndex = 0;
745 while (true)
746 {
747 FString PointName = FString::Printf(TEXT("point%d"), PointIndex);
748 if (!PointsObject->HasField(PointName))
749 {
750 break;
751 }
752
753 TSharedPtr<FJsonObject> PointObject = PointsObject->GetObjectField(PointName);
754 if (PointObject.IsValid())
755 {
756 FTransform PointTransform = ParseTransform(PointName, PointsObject);
757
758 if (ZIsHeightAboveGround)
759 {
761 }
762
763 DroneParameters.Points.Add(PointTransform);
764 }
765
766 PointIndex++;
767 }
768 }
769
770 bool ShowForwardArrow = false;
771 ParametersObject->TryGetBoolField(TEXT("showForwardArrow"), ShowForwardArrow);
772 DroneParameters.ShowForwardArrow = ShowForwardArrow;
773
774 bool CollisionsEnabled = false;
775 ParametersObject->TryGetBoolField(TEXT("collisionsEnabled"), CollisionsEnabled);
776 DroneParameters.CollisionsEnabled = CollisionsEnabled;
777
778 bool CreateInnerOverlapSensor = false;
779 ParametersObject->TryGetBoolField(TEXT("createInnerOverlapSensor"), CreateInnerOverlapSensor);
780 DroneParameters.CreateInnerOverlapSensor = CreateInnerOverlapSensor;
781
782 float OverlapRadiusMeters = 25.0f;
783 ParametersObject->TryGetNumberField(TEXT("overlapRadiusMeters"), OverlapRadiusMeters);
784 DroneParameters.OverlapRadiusMeters = OverlapRadiusMeters;
785
786 bool VisualizeOverlap = false;
787 ParametersObject->TryGetBoolField(TEXT("visualizeOverlap"), VisualizeOverlap);
788 DroneParameters.VisualizeOverlap = VisualizeOverlap;
789
790 float InnerOverlapRadiusMeters = 2.0f;
791 ParametersObject->TryGetNumberField(TEXT("innerOverlapRadiusMeters"), InnerOverlapRadiusMeters);
792 DroneParameters.InnerOverlapRadiusMeters = InnerOverlapRadiusMeters;
793
794 float DroneSlowToPointModifier = 1.0f;
795 ParametersObject->TryGetNumberField(TEXT("droneSlowToPointModifier"), DroneSlowToPointModifier);
796 DroneParameters.DroneSlowToPointModifier = DroneSlowToPointModifier;
797
798 bool DebugPointTransforms = false;
799 ParametersObject->TryGetBoolField(TEXT("debugPointTransforms"), DebugPointTransforms);
800
801 DronePtr->ChangeDroneParameters(DroneParameters);
802 DronePtr->SetShowForwardArrow(DroneParameters.ShowForwardArrow);
803 DronePtr->SetDrawDebugPoints(DebugPointTransforms);
804 }
805}
806
807void USimulatorJsonParser::ParseAndSetWheeledVehicleParameters(AVehicle* VehiclePtr, const TSharedPtr<FJsonObject>& JsonObject)
808{
809 if (!VehiclePtr || !JsonObject.IsValid() || !JsonObject->HasField(TEXT("parameters")))
810 {
811 return;
812 }
813
814 // Get current vehicle parameters
815 FWheeledVehicleParameters Parameters = VehiclePtr->GetVehicleParameters();
816
817 // parse and set new parameters from json
818 TSharedPtr<FJsonObject> ParametersObject = JsonObject->GetObjectField(TEXT("parameters"));
819
820 Parameters = ParseParameters<FWheeledVehicleParameters>(ParametersObject);
821
822 // Get cargo load separately
823 FString cargoLoad = "empty";
824 ParametersObject->TryGetStringField(TEXT("cargoLoad"), cargoLoad);
825
826 // Get correct enum using string
827 const UEnum* Enum = StaticEnum<ForwarderCargoLoad>();
828 FString Normalized = cargoLoad.TrimStartAndEnd().ToLower();
829 for (int32 i = 0; i < Enum->NumEnums(); ++i)
830 {
831 FString Name = Enum->GetNameStringByIndex(i).ToLower();
832 if (Name == Normalized)
833 {
834 Parameters.CargoLoad = static_cast<ForwarderCargoLoad>(Enum->GetValueByIndex(i));
835 break;
836 }
837 }
838
839 VehiclePtr->SetVehicleParameters(Parameters);
840}
841
842void USimulatorJsonParser::HandleSpectatorMovement(const TSharedPtr<FJsonObject>& JsonObject, AActor* Actor, const FTransform& Transform)
843{
844 if (!JsonObject.IsValid() || !Actor)
845 {
846 return;
847 }
848
849 bool follow = false;
850 bool teleport = false;
851 JsonObject->TryGetBoolField(TEXT("followObject"), follow);
852 JsonObject->TryGetBoolField(TEXT("teleportSpectator"), teleport);
853
854 if (!follow && !teleport)
855 {
856 // If neither is set, return
857 return;
858 }
859
860 if (GEngine && GEngine->GameViewport)
861 {
862 UWorld* World = GEngine->GameViewport->GetWorld();
864 if (Spectator)
865 {
866 if (follow)
867 {
868 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
869 if (VehiclePtr)
870 {
872 if (SimulationLevelManager)
873 {
874 SimulationLevelManager->TakeManualControlOfVehicle(VehiclePtr);
875 }
876 }
877 /*else
878 {
879 Spectator->FollowActor(Actor, false, 150.0f, 50.0f);
880 }*/
881 }
882 else if (teleport)
883 {
884 Spectator->TeleportSpectator(Transform);
885 }
886 }
887 }
888}
889
891{
892 if (!ActorPtr || !GEngine || !GEngine->GameViewport)
893 {
894 return;
895 }
896
897 UWorld* World = GEngine->GameViewport->GetWorld();
898 if (!World)
899 {
900 return;
901 }
902
904 APlayerController* PlayerController = UGameplayStatics::GetPlayerController(World, 0);
905 if (PlayerController && Spectator)
906 {
907 APlayerCameraManager* CameraManager = PlayerController->PlayerCameraManager;
908 if (CameraManager)
909 {
910 USceneComponent* CameraRootComponent = CameraManager->GetRootComponent();
911 if (CameraRootComponent)
912 {
913 // Set initial location and rotation to Spectator location
914 ActorPtr->SetActorLocation(Spectator->GetActorLocation());
915 ActorPtr->SetActorRotation(Spectator->GetActorRotation());
916
917 // Now attach ActorPtr to PlayerCameraManager CameraRootComponent so it follows the camera movement
918 ActorPtr->AttachToComponent(CameraRootComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
919
920 // Delete sensor model from the sensor after attaching to Spectator.
921 ASensor* SensorPtr = Cast<ASensor>(ActorPtr);
922 if (SensorPtr)
923 {
924 auto* SensorModelPtr = SensorPtr->GetSensorModel();
925 if (SensorModelPtr)
926 {
927 SensorModelPtr->Destroy();
928 }
929 }
930 }
931 }
932 }
933}
934
935void USimulatorJsonParser::ParseAndSetSemanticColors(const TSharedPtr<FJsonObject>& JsonObject)
936{
937 UWorld* World = nullptr;
938 if (GEngine && GEngine->GameViewport)
939 {
940 World = GEngine->GameViewport->GetWorld();
941 }
942
943 if (!World)
944 {
945 return;
946 }
947
948 UMaterialParameterCollectionInstance* CollectionInstance = UMaterialParameterCollectionUtilities::LoadMaterialParameterCollectionInstance(World, "/Game/Agrarsense/Data/Semantic/MPC_SemanticCameraColors");
949 if (!CollectionInstance)
950 {
951 SimulatorLog::Log("ROSJsonParser.cpp: Failed to load MaterialParameterCollectionInstance!");
952 return;
953 }
954
955 // Access the "colors" object
956 const TSharedPtr<FJsonObject>* ColorsObjectPtr = nullptr;
957 if (JsonObject->TryGetObjectField(TEXT("colors"), ColorsObjectPtr) && ColorsObjectPtr != nullptr)
958 {
959 const TSharedPtr<FJsonObject>& ColorsObject = *ColorsObjectPtr;
960 for (const auto& Elem : ColorsObject->Values)
961 {
962 FName Type = FName(*Elem.Key);
963 FString VectorString = Elem.Value->AsString();
964
965 // Parse the FVector4 value from the string
966 FVector4 ParsedVector;
967 TArray<FString> ParsedValues;
968 VectorString.ParseIntoArray(ParsedValues, TEXT(","), true);
969 if (ParsedValues.Num() == 4)
970 {
971 ParsedVector.X = FCString::Atof(*ParsedValues[0]);
972 ParsedVector.Y = FCString::Atof(*ParsedValues[1]);
973 ParsedVector.Z = FCString::Atof(*ParsedValues[2]);
974 ParsedVector.W = FCString::Atof(*ParsedValues[3]);
975
976 // try to update the material collection vector value
977 bool success = UMaterialParameterCollectionUtilities::UpdateMaterialCollectionVectorValue(CollectionInstance, Type, ParsedVector);
978 }
979 }
980 }
981}
982
983void USimulatorJsonParser::ParseCommands(const TSharedPtr<FJsonObject>& JsonObject)
984{
985 // Parse json that contains "commands" array of Unreal console commands to execute
986
987 if (!GEngine || !GEngine->GameViewport)
988 {
989 return;
990 }
991
992 UWorld* World = GEngine->GameViewport->GetWorld();
993 if (World)
994 {
995 const TArray<TSharedPtr<FJsonValue>>* CommandsArray;
996 if (JsonObject->TryGetArrayField(TEXT("commands"), CommandsArray))
997 {
998 for (const TSharedPtr<FJsonValue>& CommandValue : *CommandsArray)
999 {
1000 FString Command;
1001 if (CommandValue->TryGetString(Command))
1002 {
1003 GEngine->Exec(World, *Command);
1004 }
1005 }
1006 }
1007 }
1008}
1009
1010void USimulatorJsonParser::ParseVolumeDeletion(const TSharedPtr<FJsonObject>& JsonObject)
1011{
1012 if (!GEngine || !GEngine->GameViewport || !JsonObject.IsValid())
1013 {
1014 return;
1015 }
1016
1017 // Parse spawn location for this volume
1018 FTransform SpawnTransform = ParseTransform("spawnPoint", JsonObject);
1019
1020 // We can use ParseTransform function to parse bounds as the json structure is similar.
1021 FTransform TransformBounds = ParseTransform("bounds", JsonObject);
1022 FVector Bounds = TransformBounds.GetLocation();
1023
1024 bool OnlyDestroyTrees = true; // default to only destroy trees
1025 JsonObject->TryGetBoolField(TEXT("onlyDestroyTrees"), OnlyDestroyTrees);
1026
1027 UWorld* World = GEngine->GameViewport->GetWorld();
1028
1029 if (World)
1030 {
1031 ADeletionVolume* Volume = World->SpawnActor<ADeletionVolume>(ADeletionVolume::StaticClass(), SpawnTransform);
1032 if (Volume)
1033 {
1034 Volume->ChangeOverlapBounds(Bounds);
1035 Volume->DestroyOverlappingActors(OnlyDestroyTrees);
1036 }
1037 }
1038}
1039
1040void USimulatorJsonParser::ParseDataCapture(const TSharedPtr<FJsonObject>& JsonObject)
1041{
1042 if (!JsonObject.IsValid() || !GEngine || !GEngine->GameViewport)
1043 {
1044 return;
1045 }
1046
1047 FCaptureData CaptureData;
1048 TSharedPtr<FJsonObject> ParametersObject = JsonObject->GetObjectField(TEXT("parameters"));
1049
1050 if (ParametersObject.IsValid())
1051 {
1052 // Should use Z value as height from the ground instead of given Z value
1053 bool ZIsHeightAboveGround = false;
1054 ParametersObject->TryGetBoolField(TEXT("zIsHeightAboveGround"), ZIsHeightAboveGround);
1055
1056 bool UseGPS = false;
1057 UseGPS = ParametersObject->GetBoolField(TEXT("useGPSLocation"));
1058 CaptureData.UseGPSLocation = UseGPS;
1059 CaptureData.UseHeightAboveGround = ZIsHeightAboveGround;
1060
1061 CaptureData.CaptureRotatedViews = ParametersObject->GetBoolField(TEXT("captureRotatedViews"));
1062
1063 TSharedPtr<FJsonObject> PointsObject = ParametersObject->GetObjectField(TEXT("points"));
1064 if (PointsObject.IsValid())
1065 {
1066 int32 PointIndex = 0;
1067 while (true)
1068 {
1069 FString PointName = FString::Printf(TEXT("point%d"), PointIndex);
1070 if (!PointsObject->HasField(PointName))
1071 {
1072 break;
1073 }
1074
1075 TSharedPtr<FJsonObject> PointObject = PointsObject->GetObjectField(PointName);
1076 if (PointObject.IsValid())
1077 {
1078 FTransform PointTransform = ParseTransform(PointName, PointsObject);
1079
1080 if (ZIsHeightAboveGround && !UseGPS)
1081 {
1083 }
1084
1085 CaptureData.CapturePositions.Add(PointTransform);
1086 }
1087
1088 PointIndex++;
1089 }
1090 }
1091 }
1092
1093 UWorld* World = GEngine->GameViewport->GetWorld();
1094 if (CaptureData.CapturePositions.Num() != 0 && SpawnedSensorsForDataCapture.Num() != 0 && World)
1095 {
1096
1097 CaptureData.Sensors.Append(SpawnedSensorsForDataCapture);
1098 ADataCapture* DataCaptureActor = World->SpawnActor<ADataCapture>(ADataCapture::StaticClass(), CaptureData.CapturePositions[0]);
1099 DataCaptureActor->SetupDataCapture(CaptureData);
1100 }
1101}
1102
1103FTransform USimulatorJsonParser::ParseTransform(const FString& FieldName, const TSharedPtr<FJsonObject>& Object)
1104{
1105 FTransform SpawnTransform;
1106
1107 const TSharedPtr<FJsonObject>* SpawnPointObject = nullptr;
1108 if (!Object->TryGetObjectField(FieldName, SpawnPointObject))
1109 {
1110 return SpawnTransform;
1111 }
1112
1113 const auto& SPO = *SpawnPointObject->Get();
1114
1115 double LocationX = 0.0, LocationY = 0.0, LocationZ = 0.0;
1116 if (!SPO.TryGetNumberField(TEXT("x"), LocationX) ||
1117 !SPO.TryGetNumberField(TEXT("y"), LocationY) ||
1118 !SPO.TryGetNumberField(TEXT("z"), LocationZ))
1119 {
1120 return SpawnTransform;
1121 }
1122
1123 double Yaw = 0.0, Pitch = 0.0, Roll = 0.0;
1124 SPO.TryGetNumberField(TEXT("yaw"), Yaw);
1125 SPO.TryGetNumberField(TEXT("pitch"), Pitch);
1126 SPO.TryGetNumberField(TEXT("roll"), Roll);
1127
1128 const FVector Location(LocationX, LocationY, LocationZ);
1129 const FRotator Rotation(Pitch, Yaw, Roll);
1130 SpawnTransform.SetLocation(Location);
1131 SpawnTransform.SetRotation(Rotation.Quaternion());
1132
1133 double ScaleX = 1.0, ScaleY = 1.0, ScaleZ = 1.0;
1134 if (SPO.TryGetNumberField(TEXT("scaleX"), ScaleX) &&
1135 SPO.TryGetNumberField(TEXT("scaleY"), ScaleY) &&
1136 SPO.TryGetNumberField(TEXT("scaleZ"), ScaleZ))
1137 {
1138 SpawnTransform.SetScale3D(FVector(ScaleX, ScaleY, ScaleZ));
1139 }
1140
1141 return SpawnTransform;
1142}
1143
1144FVector4 USimulatorJsonParser::ParseVector4(const FString& FieldName, const TSharedPtr<FJsonObject>& Object)
1145{
1146 FVector4 Vector;
1147 const TSharedPtr<FJsonObject>* VectorObject;
1148
1149 if (Object->TryGetObjectField(FieldName, VectorObject))
1150 {
1151 double X, Y, Z, W;
1152 (*VectorObject)->TryGetNumberField(TEXT("x"), X);
1153 (*VectorObject)->TryGetNumberField(TEXT("y"), Y);
1154 (*VectorObject)->TryGetNumberField(TEXT("z"), Z);
1155 (*VectorObject)->TryGetNumberField(TEXT("w"), W);
1156 Vector = FVector4(X, Y, Z, W);
1157 }
1158
1159 return Vector;
1160}
1161
1163{
1164 FThermalCameraParameters ThermalCameraParams;
1165
1166 if (ParametersObject.IsValid())
1167 {
1168 // Parse fields manually because FJsonObjectConverter::JsonObjectToUStruct couldn't parse these properly.
1169 ThermalCameraParams.WarmColor = ParseVector4(TEXT("warmColor"), ParametersObject);
1170 ThermalCameraParams.ColdColor = ParseVector4(TEXT("coldColor"), ParametersObject);
1171 ParametersObject->TryGetBoolField(TEXT("allowCustomNoiseResolution"), ThermalCameraParams.AllowCustomNoiseResolution);
1172 ParametersObject->TryGetNumberField(TEXT("widthResolutionNoise"), ThermalCameraParams.WidthResolutionNoise);
1173 ParametersObject->TryGetNumberField(TEXT("heightResolutionNoise"), ThermalCameraParams.HeightResolutionNoise);
1174
1175 // Parse FCameraBaseParameters
1176 TSharedPtr<FJsonObject> CameraParametersObject = ParametersObject->GetObjectField(TEXT("cameraParameters"));
1177 if (CameraParametersObject.IsValid())
1178 {
1179 ThermalCameraParams.CameraParameters = ParseParameters<FCameraBaseParameters>(CameraParametersObject);
1180 }
1181 }
1182
1183 return ThermalCameraParams;
1184}
1185
1186int32 USimulatorJsonParser::GetIntValueOrDefault(const TSharedPtr<FJsonObject>& JsonObject, const FString& FieldName, int32 DefaultValue)
1187{
1188 int32 Value = DefaultValue;
1189
1190 if (JsonObject.IsValid() && JsonObject->HasField(FieldName))
1191 {
1192 JsonObject->TryGetNumberField(FieldName, Value);
1193 }
1194
1195 return Value;
1196}
EDroneAction
Definition: DroneAction.h:15
EDroneEndAction
EFoliageTypes
Definition: FoliageTypes.h:15
EPropTypes
Definition: PropTypes.h:15
ESensorTypes
Definition: SensorTypes.h:15
@ SemanticSegmentationCamera
@ InstanceSegmentationCamera
static EDroneEndAction GetDroneEndAction(FString endActionstring)
static EDroneAction GetDroneAction(FString actionstring)
EVehicleTypes
Definition: VehicleTypes.h:15
EWalkerAction
Definition: WalkerAction.h:15
EWalkerEndAction
EWalkerType
Definition: WalkerType.h:16
Definition: Camera.h:53
void SetupDataCapture(FCaptureData NewCaptureData)
Definition: DataCapture.cpp:27
void DestroyOverlappingActors(bool OnlyTrees)
void ChangeOverlapBounds(FVector Bounds)
Definition: Lidar.h:35
void SetDrawDebugPoints(bool show)
Definition: PIDDrone.h:177
void ChangeDroneParameters(const FDroneParameters &newParameters)
Definition: PIDDrone.cpp:36
void SetShowForwardArrow(bool Show)
Definition: PIDDrone.h:172
Definition: Sensor.h:45
ASensorModel * GetSensorModel() const
Definition: Sensor.h:181
bool TakeManualControlOfVehicle(AVehicle *Vehicle)
USensorsManagerComponent * GetSensorsManager() const
void TeleportSpectator(const FTransform &Transform)
Definition: Spectator.cpp:75
FWheeledVehicleParameters GetVehicleParameters() const
Definition: Vehicle.h:249
void SetVehicleParameters(FWheeledVehicleParameters NewParameters)
Definition: Vehicle.cpp:230
Definition: Walker.h:30
void UpdateWeather(const FWeatherParameters &WeatherParameters, bool updateToROS)
Definition: Weather.cpp:103
const FWeatherParameters & GetCurrentWeather() const
Definition: Weather.h:76
static void Log(const FString &Message, bool LogToTextFile=true, bool LogToROS=true)
static bool IsPlayingInMainMenu()
static ASpectator * GetSpectator(const UObject *WorldContextObject)
static AWeather * GetWeatherActor(const UObject *WorldContextObject)
static ASimulationLevelManager * GetSimulationLevelManager(const UObject *WorldContextObject)
static AVehicle * SpawnVehicle(EVehicleTypes VehicleType, FTransform SpawnTransform, const FString &ActorName, const FString &ActorID, bool SnapAboveGround=false, float AboveOffset=150.0f, bool DestroyOverlappingActors=false)
static AActor * SpawnProp(EPropTypes PropType, FTransform Transform, FString ActorName="", FString ActorID="", bool RandomZRotation=false, bool SnapToGround=false)
static AWalker * SpawnWalker(FWalkerParameters Parameters, const FString &ActorName="", const FString &ActorID="", bool StartAutomatically=true)
static AActor * SpawnFoliage(EFoliageTypes FoliageType, FTransform Transform, FString ActorName="", FString ActorID="", bool RandomZRotation=true, bool SnapToGround=true)
static EWalkerEndAction ConvertStringToWalkerEndActionType(const FString &String)
static ESensorTypes ConvertStringToSensorType(const FString &String)
static EWalkerAction ConvertStringToWalkerActionType(const FString &String)
static EVehicleTypes ConvertStringToVehicleType(const FString &String)
static EWalkerType ConvertStringToWalkerType(const FString &String)
static EPropTypes ConvertStringToPropType(const FString &String)
static EFoliageTypes ConvertStringToFoliageType(const FString &String)
static bool UpdateMaterialCollectionVectorValue(UMaterialParameterCollectionInstance *MPCInstance, const FName ParameterName, const FVector4 Value)
static UMaterialParameterCollectionInstance * LoadMaterialParameterCollectionInstance(const UObject *WorldContextObject, const FString &Path)
static bool AlignTransformFromGroundInMeters(AActor *Actor, FTransform &InTransform)
static FTransform ParseTransform(const FString &FieldName, const TSharedPtr< FJsonObject > &Object)
static FVector4 ParseVector4(const FString &FieldName, const TSharedPtr< FJsonObject > &Object)
static void ParseAndSetDroneParameters(APIDDrone *DronePtr, const TSharedPtr< FJsonObject > &JsonObject)
static void ParseAndOperateJSONFile(const FString &Path)
static FThermalCameraParameters ParseThermalCameraParameters(const TSharedPtr< FJsonObject > &ParametersObject)
static void AttachActorToSpectatorCamera(AActor *ActorPtr)
static TArray< ASensor * > SpawnedSensorsForDataCapture
static void ParsePropOrFoliage(const TSharedPtr< FJsonObject > &JsonObject, const FString &ObjectType)
static void ParseVehicle(const TSharedPtr< FJsonObject > &JsonObject)
static void ParseAndSetWheeledVehicleParameters(AVehicle *VehiclePtr, const TSharedPtr< FJsonObject > &JsonObject)
static void ParseVolumeDeletion(const TSharedPtr< FJsonObject > &JsonObject)
static void ParseDataCapture(const TSharedPtr< FJsonObject > &JsonObject)
static void SpawnSensorToVehicle(AVehicle *Vehicle, const TSharedPtr< FJsonObject > &SensorObject, bool HideVehicleMeshForCameras=false)
static void HandleSpectatorMovement(const TSharedPtr< FJsonObject > &JsonObject, AActor *Actor, const FTransform &Transform)
static void ParseWalkerSpawnPoints(const TSharedPtr< FJsonObject > &ParametersObject, FWalkerParameters &WalkerParams)
static void ParseCommands(const TSharedPtr< FJsonObject > &JsonObject)
static void ParseAndSetSemanticColors(const TSharedPtr< FJsonObject > &JsonObject)
static void ChangeWeather(const TSharedPtr< FJsonObject > &JsonObject)
static void SpawnWalker(const TSharedPtr< FJsonObject > &JsonObject)
static int32 GetIntValueOrDefault(const TSharedPtr< FJsonObject > &JsonObject, const FString &FieldName, int32 DefaultValue)
static void SpawnSensorWorld(const TSharedPtr< FJsonObject > &SensorObject)
bool UseGPSLocation
Definition: DataCapture.h:44
bool UseHeightAboveGround
Definition: DataCapture.h:57
TArray< FTransform > CapturePositions
Definition: DataCapture.h:32
bool CaptureRotatedViews
Definition: DataCapture.h:38
TArray< ASensor * > Sensors
Definition: DataCapture.h:23
float InnerOverlapRadiusMeters
EDroneEndAction DroneEndAction
EDroneAction DroneAction
float DroneSlowToPointModifier
TArray< FTransform > Points
FCameraBaseParameters CameraParameters
EWalkerAction WalkerAction
TArray< FTransform > Points
EWalkerType WalkerType
EWalkerEndAction WalkerEndAction