Agrarsense
SimulatorJsonExporter.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
18
28
29#include "GenericPlatform/GenericPlatformFile.h"
30#include "Serialization/JsonSerializer.h"
31#include "Serialization/JsonWriter.h"
32#include "Misc/DefaultValueHelper.h"
33#include "HAL/PlatformFileManager.h"
34#include "Misc/FileHelper.h"
35
36#include "Engine/GameViewportClient.h"
37#include "Engine/Engine.h"
38#include "Engine/World.h"
39
40FString USimulatorJsonExporter::ExportVehicleAndSensorsToJSON(FString FileName, AVehicle* Vehicle, bool OverrideTransform, const FTransform& Transform)
41{
42 FString FilePath;
43 if (!Vehicle)
44 {
45 return FilePath;
46 }
47
48 EVehicleTypes VehicleType = Vehicle->GetVehicleType();
49 FString VehicleName;
50
51 switch (VehicleType)
52 {
54 VehicleName = "Forwarder";
55 break;
56
58 VehicleName = "Harvester";
59 break;
60
62 VehicleName = "Drone";
63 break;
64
66 default:
67 break;
68 }
69
70 // If the vehicle name is empty, return
71 if (VehicleName.IsEmpty())
72 {
73 return FilePath;
74 }
75
76 // Remove invalid characters from the filename, and replace them with undescores.
77 // Will not remove spaces, maybe they should be?
78 FString ValidatedFileName = FPaths::MakeValidFileName(FileName, TEXT('_'));
79 FilePath = CreateUniqueFilePath(ValidatedFileName);
80
81 TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
82 TArray<TSharedPtr<FJsonValue>> ObjectsArray;
83
84 TSharedPtr<FJsonObject> VehicleObject = MakeShareable(new FJsonObject);
85 VehicleObject->SetStringField("type", "vehicle");
86 VehicleObject->SetStringField("model", VehicleName);
87 VehicleObject->SetBoolField("teleportSpectator", false);
88 VehicleObject->SetBoolField("followObject", false);
89 VehicleObject->SetBoolField("destroyOverlappingObjects", false);
90 VehicleObject->SetStringField("id", Vehicle->GetActorID_Implementation());
91
92 TSharedPtr<FJsonObject> VehicleSpawnPoint = MakeShareable(new FJsonObject);
93
94 FVector SpawnLocation;
95 FRotator SpawnRotation;
96
97 if (OverrideTransform)
98 {
99 SpawnLocation = Transform.GetLocation();
100 SpawnRotation = Transform.Rotator();
101 }
102 else
103 {
104 SpawnLocation = Vehicle->GetActorLocation();
105 SpawnRotation = Vehicle->GetActorRotation();
106 }
107
108 // Export vehicle spawnpoint to json
109 SetSpawnPoint(VehicleObject, SpawnLocation, SpawnRotation, Transform.GetScale3D());
110
111 // If the vehicle is drone, export its parameters to json
112 if (Vehicle->GetVehicleType() == EVehicleTypes::Drone)
113 {
114 SetDroneParameters(VehicleObject, Vehicle);
115 }
116
117 // Export all sensors attached to the vehicle
118 TArray<TSharedPtr<FJsonValue>> SensorsArray;
119
120 USensorsManagerComponent* SensorManager = Vehicle->GetSensorsManager();
121 if (SensorManager)
122 {
123 // Parse different sensor types and add them to the SensorsArray
124 SensorsArray.Append(ParseLidars(SensorManager->GetLidars()));
125 SensorsArray.Append(ParseCameras(SensorManager->GetCameras()));
126 SensorsArray.Append(ParseDepthCameras(SensorManager->GetDepthCameras()));
127 SensorsArray.Append(ParseThermalCameras(SensorManager->GetThermalCameras()));
128 SensorsArray.Append(ParseDVSCameras(SensorManager->GetDVSCameras()));
129 SensorsArray.Append(ParseRadars(SensorManager->GetRadars()));
130 }
131
132 // Add the sensors array to the vehicle object if it's not empty
133 if (SensorsArray.Num() > 0)
134 {
135 VehicleObject->SetArrayField("sensors", SensorsArray);
136 }
137
138 ObjectsArray.Add(MakeShareable(new FJsonValueObject(VehicleObject)));
139
140 JsonObject->SetArrayField("objects", ObjectsArray);
141
142 FString JsonString;
143 TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<>::Create(&JsonString);
144 FJsonSerializer::Serialize(JsonObject.ToSharedRef(), JsonWriter);
145
146 // Save the JSON string to the file
147 bool Saved = FFileHelper::SaveStringToFile(JsonString, *FilePath);
148 if (!Saved)
149 {
150 return FString();
151 }
152
153 // Publish and log info
154 FString Msg = FString::Printf(TEXT("Exported vehicle JSON file to: %s"), *FilePath);
156
157 return FilePath;
158}
159
160FString USimulatorJsonExporter::ExportWeatherToJSON(const FString& FileName, const FWeatherParameters& WeatherParameters)
161{
162 // Remove invalid characters from the filename, and replace them with undescores.
163 // Will not remove spaces, maybe they should be?
164 FString ValidatedFileName = FPaths::MakeValidFileName(FileName, TEXT('_'));
165
166 FString FilePath = CreateUniqueFilePath(ValidatedFileName);
167
168 // Create the JSON object from FWeatherParameters struct
169 TSharedPtr<FJsonObject> ParametersObject = MakeShareable(new FJsonObject);
170 FJsonObjectConverter::UStructToJsonObject(FWeatherParameters::StaticStruct(), &WeatherParameters, ParametersObject.ToSharedRef());
171
172 TSharedPtr<FJsonObject> RootObject = MakeShareable(new FJsonObject);
173 TArray<TSharedPtr<FJsonValue>> ObjectsArray;
174 TSharedPtr<FJsonObject> WeatherObject = MakeShareable(new FJsonObject);
175 WeatherObject->SetStringField("type", "weather");
176
177 WeatherObject->SetObjectField("parameters", ParametersObject);
178
179 ObjectsArray.Add(MakeShareable(new FJsonValueObject(WeatherObject)));
180
181 RootObject->SetArrayField("objects", ObjectsArray);
182
183 FString JsonString;
184 TSharedRef<TJsonWriter<>> JsonWriter = TJsonWriterFactory<>::Create(&JsonString);
185 FJsonSerializer::Serialize(RootObject.ToSharedRef(), JsonWriter);
186
187 bool Saved = FFileHelper::SaveStringToFile(JsonString, *FilePath);
188 if (!Saved)
189 {
190 return FString();
191 }
192
193 // Publish and log info
194 FString Msg = FString::Printf(TEXT("Exported Weather JSON file to: %s"), *FilePath);
196
197 return FilePath;
198}
199
200FString USimulatorJsonExporter::ExportInstancedActorsToJSON(const FString FileName, const TArray<AInstancedActor*>& Actors)
201{
202 // Remove invalid characters from the filename, and replace them with undescores.
203 // Will not remove spaces, maybe they should be?
204 FString ValidatedFileName = FPaths::MakeValidFileName(FileName, TEXT('_'));
205
206 FString FilePath;
207
208 if (Actors.IsEmpty())
209 {
210#if WITH_EDITOR
211 UE_LOG(LogTemp, Warning, TEXT("ROSJsonExporter.cpp: Actors TArray is empty."));
212#endif
213 return FilePath;
214 }
215
216 FilePath = CreateUniqueFilePath(ValidatedFileName);
217
218 TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
219
220 TArray<TSharedPtr<FJsonValue>> ObjectsArray;
221 for (AInstancedActor* Actor : Actors)
222 {
223 if (!Actor)
224 {
225 continue;
226 }
227
228 FString type = Actor->GetTypeIDString();
229 FString model = Actor->GetModelIDString();
230
231 // If these are not set, continue
232 if (type == "none" || model == "none")
233 {
234 continue;
235 }
236
237 TSharedPtr<FJsonObject> ObjectEntry = MakeShareable(new FJsonObject);
238 ObjectEntry->SetStringField("type", type);
239 ObjectEntry->SetStringField("model", model);
240
241 // Create a spawnPoint object
242 TSharedPtr<FJsonObject> SpawnPoint = MakeShareable(new FJsonObject);
243 FVector SpawnLocation = Actor->GetActorLocation();
244 FRotator SpawnRotation = Actor->GetActorRotation();
245 FVector Scale = Actor->GetActorScale();
246 SetSpawnPoint(ObjectEntry, SpawnLocation, SpawnRotation, Scale);
247 ObjectsArray.Add(MakeShareable(new FJsonValueObject(ObjectEntry)));
248 }
249
250 JsonObject->SetArrayField("objects", ObjectsArray);
251
252 FString JsonString;
253 TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<>::Create(&JsonString);
254 FJsonSerializer::Serialize(JsonObject.ToSharedRef(), JsonWriter);
255
256 bool Saved = FFileHelper::SaveStringToFile(JsonString, *FilePath);
257 if (!Saved)
258 {
259 return FString();
260 }
261
262 // Publish and log info
263 FString Msg = FString::Printf(TEXT("Exported Actors JSON file to: %s"), *FilePath);
265
266 return FilePath;
267}
268
269FString USimulatorJsonExporter::ExportWalkerToJSON(const FString& FileName, AWalker* Walker)
270{
271 FString FilePath;
272 if (!Walker)
273 {
274 return FilePath;
275 }
276
277 // Remove invalid characters from the filename, and replace them with undescores.
278 // Will not remove spaces, maybe they should be?
279 FString ValidatedFileName = FPaths::MakeValidFileName(FileName, TEXT('_'));
280
281 FilePath = CreateUniqueFilePath(ValidatedFileName);
282
283 // Root Json object
284 TSharedPtr<FJsonObject> RootJsonObject = MakeShareable(new FJsonObject);
285
286 // Json structure "Objects" array
287 TArray<TSharedPtr<FJsonValue>> ObjectsArray;
288 TSharedPtr<FJsonObject> ObjectEntry = MakeShareable(new FJsonObject);
289
290 // Get Walker parameters
291 FWalkerParameters WalkerParameters = Walker->GetWalkerParameters();
292
293 // Set type and model
294 ObjectEntry->SetStringField("type", "Walker");
295 ObjectEntry->SetStringField("model", UEnumUtilities::ConvertWalkerTypeToString(WalkerParameters.WalkerType));
296 ObjectEntry->SetStringField("id", Walker->GetActorID_Implementation());
297
298 // Create and set the JSON object from FWeatherParameters struct
299 TSharedPtr<FJsonObject> ParametersObject = MakeShareable(new FJsonObject);
300 FJsonObjectConverter::UStructToJsonObject(FWalkerParameters::StaticStruct(), &WalkerParameters, ParametersObject.ToSharedRef());
301
302 // Remove "Points" field
303 ParametersObject->RemoveField(TEXT("points"));
304
305 if (WalkerParameters.Points.Num() >= 2)
306 {
307 // If we have at least 2 Points, re-create "points" field manually
308 // so it's compatible with ROSJsonParser Transform parsing logic.
309 TSharedPtr<FJsonObject> PointsObject = MakeShareable(new FJsonObject);
310 for (int32 i = 0; i < WalkerParameters.Points.Num(); ++i)
311 {
312 FString PointName = FString::Printf(TEXT("point%d"), i);
313
314 FTransform Transform = WalkerParameters.Points[i];
315 FVector Location = Transform.GetLocation();
316 FRotator Rotation = Transform.Rotator();
317
318 // Adding location and rotation to the point data
319 TSharedPtr<FJsonObject> PointData = MakeShareable(new FJsonObject);
320 PointData->SetNumberField(TEXT("x"), Location.X);
321 PointData->SetNumberField(TEXT("y"), Location.Y);
322 PointData->SetNumberField(TEXT("z"), Location.Z);
323 PointData->SetNumberField(TEXT("roll"), Rotation.Roll);
324 PointData->SetNumberField(TEXT("pitch"), Rotation.Pitch);
325 PointData->SetNumberField(TEXT("yaw"), Rotation.Yaw);
326
327 // Adding point data to the PointsObject
328 PointsObject->SetObjectField(PointName, PointData);
329 }
330
331 // Add created PointsObject to ParametersObject "points" field
332 ParametersObject->SetObjectField(TEXT("points"), PointsObject);
333 }
334 else
335 {
336 // else create a "spawnPoint" since we don't have enough Points in the WalkerParameters.
337 TSharedPtr<FJsonObject> SpawnPoint = MakeShareable(new FJsonObject);
338
339 FVector SpawnLocation;
340 FRotator SpawnRotation;
341 if (WalkerParameters.Points.IsEmpty())
342 {
343 // If for whatever reason Points is empty,
344 // use Walker current location and rotation.
345 SpawnLocation = Walker->GetActorLocation();
346 SpawnRotation = Walker->GetActorRotation();
347 }
348 else
349 {
350 // Else use first point which should be the spawn point of the Walker
351 FTransform Transform = WalkerParameters.Points[0];
352 SpawnLocation = Transform.GetLocation();
353 SpawnRotation = Transform.Rotator();
354 }
355
356 SetSpawnPoint(ParametersObject, SpawnLocation, SpawnRotation, Walker->GetActorScale());
357 }
358
359 // Set the parameters object in the entry
360 ObjectEntry->SetObjectField("parameters", ParametersObject);
361
362 // Add the entry to the ObjectsArray
363 ObjectsArray.Add(MakeShareable(new FJsonValueObject(ObjectEntry)));
364
365 // Set the ObjectsArray in the root JSON object
366 RootJsonObject->SetArrayField("objects", ObjectsArray);
367
368 // Serialize the root JSON object to a string
369 FString JsonString;
370 TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<>::Create(&JsonString);
371 FJsonSerializer::Serialize(RootJsonObject.ToSharedRef(), JsonWriter);
372
373 // Save the JSON string to a file
374 bool Saved = FFileHelper::SaveStringToFile(JsonString, *FilePath);
375 if (!Saved)
376 {
377 // If saving fails, return empty string
378 return FString();
379 }
380
381 // Publish and log info
382 FString Msg = FString::Printf(TEXT("Exported Actors JSON file to: %s"), *FilePath);
384
385 return FilePath;
386}
387
388FString USimulatorJsonExporter::ExportSensorToJSON(const FString& FileName, ASensor* Sensor)
389{
390 FString FilePath;
391 if (!Sensor)
392 {
393 return FilePath;
394 }
395
396 // Remove invalid characters from the filename, and replace them with undescores.
397 // Will not remove spaces, maybe they should be?
398 FString ValidatedFileName = FPaths::MakeValidFileName(FileName, TEXT('_'));
399
400 FilePath = CreateUniqueFilePath(ValidatedFileName);
401
402 ESensorTypes SensorType = Sensor->GetSensorType();
403 FString SensorTypeString = UEnumUtilities::ConvertSensorTypeToString(SensorType);
404
405 TSharedPtr<FJsonObject> ParametersObject = MakeShareable(new FJsonObject);
406
407 bool Success = false;
408
409 switch (SensorType)
410 {
412 {
413 ALidar* LidarPtr = Cast<ALidar>(Sensor);
414 if (LidarPtr)
415 {
416 FLidarParameters LidarParameters = LidarPtr->GetLidarParameters();
417 FJsonObjectConverter::UStructToJsonObject(FLidarParameters::StaticStruct(), &LidarParameters, ParametersObject.ToSharedRef());
418 Success = true;
419 }
420 }
421 break;
422
423 // RGB and Semantic segmentation cameras share same parameters
426 {
427 ACamera* CameraPtr = Cast<ACamera>(Sensor);
428 if (CameraPtr)
429 {
430 ParametersObject = CameraParametersToJSONObject(CameraPtr->GetCameraParameters());
431 Success = true;
432 }
433 }
434 break;
435
437 {
438 AThermalCamera* ThermalCameraPtr = Cast<AThermalCamera>(Sensor);
439 if (ThermalCameraPtr)
440 {
441 FThermalCameraParameters ThermalCameraParameters = ThermalCameraPtr->GetThermalCameraParameters();
442 FJsonObjectConverter::UStructToJsonObject(FThermalCameraParameters::StaticStruct(), &ThermalCameraParameters, ParametersObject.ToSharedRef());
443 Success = true;
444 }
445 }
446 break;
447
449 {
450 ACamera* CameraPtr = Cast<ACamera>(Sensor);
451 if (CameraPtr)
452 {
453 ADepthCamera* DepthCameraPtr = Cast<ADepthCamera>(Sensor);
454 if (DepthCameraPtr)
455 {
456 FDepthCameraParameters DepthCameraParameters = DepthCameraPtr->GetDepthCameraParameters();
457 FJsonObjectConverter::UStructToJsonObject(FDepthCameraParameters::StaticStruct(), &DepthCameraParameters, ParametersObject.ToSharedRef());
458 }
459 Success = true;
460 }
461 }
462 break;
463
465 {
466 ADVSCamera* DVSPtr = Cast<ADVSCamera>(Sensor);
467 if (DVSPtr)
468 {
469 FDVSCameraParameters CameraParameters = DVSPtr->GetDVSCameraParameters();
470 FJsonObjectConverter::UStructToJsonObject(FDVSCameraParameters::StaticStruct(), &CameraParameters, ParametersObject.ToSharedRef());
471 Success = true;
472 }
473 }
474 break;
475
477 {
478 ARadar* RadaPtr = Cast<ARadar>(Sensor);
479 if (RadaPtr)
480 {
481 FRadarParameters RadarParameters = RadaPtr->GetRadarParameters();
482 FJsonObjectConverter::UStructToJsonObject(FRadarParameters::StaticStruct(), &RadarParameters, ParametersObject.ToSharedRef());
483 Success = true;
484 }
485 }
486 break;
487
488 // Don't export these sensors since these are automatically created for Vehicles
492#if WITH_EDITOR
493 UE_LOG(LogTemp, Warning, TEXT("ROSJsonExporter.cpp: Exporting Collision/Transform or Overlap sensor is not supported."));
494#endif
495 break;
496
497 default:
498 break;
499 }
500
501 if (!Success)
502 {
503 return FString();
504 }
505
506 // Root Json object
507 TSharedPtr<FJsonObject> RootJsonObject = MakeShareable(new FJsonObject);
508
509 // Json structure "Objects" array
510 TArray<TSharedPtr<FJsonValue>> ObjectsArray;
511 TSharedPtr<FJsonObject> ObjectEntry = MakeShareable(new FJsonObject);
512
513 // Set type and model
514 ObjectEntry->SetStringField("type", "Sensor");
515 ObjectEntry->SetStringField("model", SensorTypeString);
516 ObjectEntry->SetStringField("id", Sensor->GetActorID_Implementation());
517
518 FVector SpawnLocation = Sensor->GetActorLocation();
519 FRotator SpawnRotation = Sensor->GetActorRotation();
520 SetSpawnPoint(ObjectEntry, SpawnLocation, SpawnRotation, Sensor->GetActorScale());
521
522 // Set the parameters object to ObjectEntry
523 ObjectEntry->SetObjectField("parameters", ParametersObject);
524
525 // Add the entry to ObjectsArray
526 ObjectsArray.Add(MakeShareable(new FJsonValueObject(ObjectEntry)));
527
528 // Set the ObjectsArray in the root JSON object
529 RootJsonObject->SetArrayField("objects", ObjectsArray);
530
531 // Serialize the root JSON object to a string
532 FString JsonString;
533 TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<>::Create(&JsonString);
534 FJsonSerializer::Serialize(RootJsonObject.ToSharedRef(), JsonWriter);
535
536 // Save the JSON string to a file
537 bool Saved = FFileHelper::SaveStringToFile(JsonString, *FilePath);
538 if (!Saved)
539 {
540 return FString();
541 }
542
543 // Publish and log info
544 FString Msg = FString::Printf(TEXT("Exported Actors JSON file to: %s"), *FilePath);
546
547 return FilePath;
548}
549
550TArray<TSharedPtr<FJsonValue>> USimulatorJsonExporter::ParseLidars(const TArray<ALidar*>& Lidars)
551{
552 TArray<TSharedPtr<FJsonValue>> LidarArray;
553
554 for (ALidar* Lidar : Lidars)
555 {
556 if (!Lidar)
557 {
558 continue;
559 }
560
561 FTransform Transform = Lidar->GetRootComponent()->GetRelativeTransform();
562 TSharedPtr<FJsonObject> SensorObject = CreateSensorJSONObject(Cast<ASensor>(Lidar), "Lidar");
563
564 TSharedPtr<FJsonObject> ParametersObject = MakeShareable(new FJsonObject);
565 FLidarParameters Params = Lidar->GetLidarParameters();
566
567 FJsonObjectConverter::UStructToJsonObject(FLidarParameters::StaticStruct(), &Params, ParametersObject.ToSharedRef());
568
569 SensorObject->SetObjectField("parameters", ParametersObject);
570
571 LidarArray.Add(MakeShareable(new FJsonValueObject(SensorObject)));
572 }
573
574 return LidarArray;
575}
576
577TArray<TSharedPtr<FJsonValue>> USimulatorJsonExporter::ParseCameras(const TArray<ACamera*>& Cameras)
578{
579 TArray<TSharedPtr<FJsonValue>> CameraArray;
580
581 for (ACamera* Camera : Cameras)
582 {
583 if (!Camera)
584 {
585 continue;
586 }
587
588 FTransform Transform = Camera->GetRootComponent()->GetRelativeTransform();
589 TSharedPtr<FJsonObject> SensorObject = CreateSensorJSONObject(Cast<ASensor>(Camera), "RGBCamera");
590
591 FCameraBaseParameters Params = Camera->GetCameraParameters();
592
593 TSharedPtr<FJsonObject> ParametersObject = CameraParametersToJSONObject(Params);
594
595 SensorObject->SetObjectField("parameters", ParametersObject);
596
597 CameraArray.Add(MakeShareable(new FJsonValueObject(SensorObject)));
598 }
599
600 return CameraArray;
601}
602
603TArray<TSharedPtr<FJsonValue>> USimulatorJsonExporter::ParseDepthCameras(const TArray<ADepthCamera*>& DepthCameras)
604{
605 TArray<TSharedPtr<FJsonValue>> CameraArray;
606
607 for (ADepthCamera* Camera : DepthCameras)
608 {
609 if (!Camera)
610 {
611 continue;
612 }
613
614 FTransform Transform = Camera->GetRootComponent()->GetRelativeTransform();
615 TSharedPtr<FJsonObject> SensorObject = CreateSensorJSONObject(Cast<ASensor>(Camera), "DepthCamera");
616
617 TSharedPtr<FJsonObject> DepthCameraParametersObject = MakeShareable(new FJsonObject);
618
619 FDepthCameraParameters Params = Camera->GetDepthCameraParameters();
620 FJsonObjectConverter::UStructToJsonObject(FDepthCameraParameters::StaticStruct(), &Params, DepthCameraParametersObject.ToSharedRef());
621
622 SensorObject->SetObjectField("parameters", DepthCameraParametersObject);
623
624 CameraArray.Add(MakeShareable(new FJsonValueObject(SensorObject)));
625 }
626
627 return CameraArray;
628}
629
630TArray<TSharedPtr<FJsonValue>> USimulatorJsonExporter::ParseThermalCameras(const TArray<AThermalCamera*>& ThermalCameras)
631{
632 TArray<TSharedPtr<FJsonValue>> CameraArray;
633
634 for (AThermalCamera* Camera : ThermalCameras)
635 {
636 if (!Camera)
637 {
638 continue;
639 }
640
641 FTransform Transform = Camera->GetRootComponent()->GetRelativeTransform();
642 TSharedPtr<FJsonObject> SensorObject = CreateSensorJSONObject(Cast<ASensor>(Camera), "ThermalCamera");
643
644 TSharedPtr<FJsonObject> ThermalCameraParametersObject = MakeShareable(new FJsonObject);
645
646 FThermalCameraParameters Params = Camera->GetThermalCameraParameters();
647 FJsonObjectConverter::UStructToJsonObject(FThermalCameraParameters::StaticStruct(), &Params, ThermalCameraParametersObject.ToSharedRef());
648
649 SensorObject->SetObjectField("parameters", ThermalCameraParametersObject);
650
651 CameraArray.Add(MakeShareable(new FJsonValueObject(SensorObject)));
652 }
653
654 return CameraArray;
655}
656
657TArray<TSharedPtr<FJsonValue>> USimulatorJsonExporter::ParseDVSCameras(const TArray<ADVSCamera*>& DVSCameras)
658{
659 TArray<TSharedPtr<FJsonValue>> CameraArray;
660
661 for (ADVSCamera* Camera : DVSCameras)
662 {
663 if (!Camera)
664 {
665 continue;
666 }
667
668 FTransform Transform = Camera->GetRootComponent()->GetRelativeTransform();
669 TSharedPtr<FJsonObject> SensorObject = CreateSensorJSONObject(Cast<ASensor>(Camera), "DVSCamera");
670
671 TSharedPtr<FJsonObject> DVSCameraParametersObject = MakeShareable(new FJsonObject);
672
673 FDVSCameraParameters Params = Camera->GetDVSCameraParameters();
674 FJsonObjectConverter::UStructToJsonObject(FDVSCameraParameters::StaticStruct(), &Params, DVSCameraParametersObject.ToSharedRef());
675
676 SensorObject->SetObjectField("parameters", DVSCameraParametersObject);
677
678 CameraArray.Add(MakeShareable(new FJsonValueObject(SensorObject)));
679 }
680
681 return CameraArray;
682}
683
684TArray<TSharedPtr<FJsonValue>> USimulatorJsonExporter::ParseRadars(const TArray<ARadar*>& Radars)
685{
686 TArray<TSharedPtr<FJsonValue>> RadarArray;
687
688 for (ARadar* Radar : Radars)
689 {
690 if (!Radar)
691 {
692 continue;
693 }
694
695 FTransform Transform = Radar->GetRootComponent()->GetRelativeTransform();
696 TSharedPtr<FJsonObject> SensorObject = CreateSensorJSONObject(Cast<ASensor>(Radar), "Radar");
697
698 TSharedPtr<FJsonObject> RadarParametersObject = MakeShareable(new FJsonObject);
699
700 FRadarParameters Params = Radar->GetRadarParameters();
701 FJsonObjectConverter::UStructToJsonObject(FRadarParameters::StaticStruct(), &Params, RadarParametersObject.ToSharedRef());
702
703 SensorObject->SetObjectField("parameters", RadarParametersObject);
704
705 RadarArray.Add(MakeShareable(new FJsonValueObject(SensorObject)));
706 }
707
708 return RadarArray;
709}
710
711TSharedPtr<FJsonObject> USimulatorJsonExporter::CreateSensorJSONObject(const ASensor* SensorPtr, FString SensorName)
712{
713 TSharedPtr<FJsonObject> SensorObject = MakeShareable(new FJsonObject);
714
715 if (!SensorPtr)
716 {
717#if WITH_EDITOR
718 UE_LOG(LogTemp, Warning, TEXT("ROSJsonExporter.cpp: SensorPtr is nullptr!"));
719#endif
720 return SensorObject;
721 }
722
723 FJsonObject* SensorJsonObject = SensorObject.Get();
724 SensorJsonObject->SetStringField("type", "sensor");
725 SensorJsonObject->SetStringField("model", SensorName);
726 SensorJsonObject->SetStringField("name", SensorPtr->GetSensorName());
727 SensorJsonObject->SetStringField("id", SensorPtr->GetActorID_Implementation());
728 SensorJsonObject->SetStringField("attachedToComponent", SensorPtr->AttachedToComponent);
729 SensorJsonObject->SetStringField("attachedToBone", SensorPtr->AttachedToBone.ToString());
730
731 FTransform Transform = SensorPtr->GetRootComponent()->GetRelativeTransform();
732 FVector SensorLocation = Transform.GetLocation();
733 FRotator SensorRotation = Transform.Rotator();
734 SetSpawnPoint(SensorObject, SensorLocation, SensorRotation, Transform.GetScale3D());
735
736 return SensorObject;
737}
738
740{
741 TSharedPtr<FJsonObject> ParametersObject = MakeShareable(new FJsonObject);
742 FJsonObjectConverter::UStructToJsonObject(FCameraBaseParameters::StaticStruct(), &Parameters, ParametersObject.ToSharedRef());
743
744 return ParametersObject;
745}
746
747void USimulatorJsonExporter::SetSpawnPoint(TSharedPtr<FJsonObject>& ObjectEntry, const FVector& Location, const FRotator& Rotation, const FVector& Scale)
748{
749 TSharedPtr<FJsonObject> SpawnPoint = MakeShareable(new FJsonObject);
750
751 // Set Location
752 SpawnPoint->SetNumberField("x", Location.X);
753 SpawnPoint->SetNumberField("y", Location.Y);
754 SpawnPoint->SetNumberField("z", Location.Z);
755
756 // Set Rotation
757 SpawnPoint->SetNumberField("roll", Rotation.Roll);
758 SpawnPoint->SetNumberField("pitch", Rotation.Pitch);
759 SpawnPoint->SetNumberField("yaw", Rotation.Yaw);
760
761 // Set Scale
762 SpawnPoint->SetNumberField("scaleX", Scale.X);
763 SpawnPoint->SetNumberField("scaleY", Scale.Y);
764 SpawnPoint->SetNumberField("scaleZ", Scale.Z);
765
766 ObjectEntry->SetObjectField("spawnPoint", SpawnPoint);
767}
768
769void USimulatorJsonExporter::SetDroneParameters(TSharedPtr<FJsonObject>& ObjectEntry, AVehicle* VehiclePtr)
770{
771 APIDDrone* DronePtr = Cast<APIDDrone>(VehiclePtr);
772 if (!ObjectEntry.IsValid() || !DronePtr)
773 {
774 return;
775 }
776
777 TSharedPtr<FJsonObject> VehicleParams = MakeShareable(new FJsonObject);
778
779 FDroneParameters DroneParams = DronePtr->GetDroneParameters();
780
781 FString DroneActionString = UEnum::GetDisplayValueAsText(DroneParams.DroneAction).ToString();
782 VehicleParams->SetStringField("droneAction", DroneActionString);
783
784 FString DroneEndActionString = UEnum::GetDisplayValueAsText(DroneParams.DroneEndAction).ToString();
785 VehicleParams->SetStringField("DroneEndAction", DroneEndActionString);
786
787 if (!DroneParams.Points.IsEmpty())
788 {
789 // Create an array to hold the points
790 TArray<TSharedPtr<FJsonValue>> PointsArray;
791 PointsArray.Reserve(DroneParams.Points.Num());
792
793 for (const FTransform& Transform : DroneParams.Points)
794 {
795 TSharedPtr<FJsonObject> PointObject = MakeShareable(new FJsonObject);
796
797 // Serialize translation
798 FVector Translation = Transform.GetLocation();
799 PointObject->SetNumberField("X", Translation.X);
800 PointObject->SetNumberField("Y", Translation.Y);
801 PointObject->SetNumberField("Z", Translation.Z);
802
803 // Serialize rotation (as a rotator or quaternion)
804 FRotator Rotation = Transform.GetRotation().Rotator();
805 PointObject->SetNumberField("Pitch", Rotation.Pitch);
806 PointObject->SetNumberField("Yaw", Rotation.Yaw);
807 PointObject->SetNumberField("Roll", Rotation.Roll);
808
809 // Add the point object to the array
810 PointsArray.Add(MakeShareable(new FJsonValueObject(PointObject)));
811 }
812
813 // Add the points array to the VehicleParams JSON object
814 VehicleParams->SetArrayField("points", PointsArray);
815 }
816
817 // Add the VehicleParams object to the main VehicleObject
818 ObjectEntry->SetObjectField("parameters", VehicleParams);
819}
820
822{
823 if (FileName.IsEmpty())
824 {
825 // If user didn't specify file name, give it a default name
826 FileName = "ExportedJsonFile";
827 }
828
829 // Trim leading and trailing whitespace
830 FileName = FileName.TrimStartAndEnd();
831
832 // Check for invalid characters
833 FString InvalidChars = TEXT("\\/:*?\"<>|");
834 for (TCHAR InvalidChar : InvalidChars)
835 {
836 FileName.ReplaceCharInline(InvalidChar, TEXT('_'), ESearchCase::CaseSensitive);
837 }
838
839 FString DataPathFolder = UAgrarsensePaths::GetDataFolder();
840 FString BaseFileName = FileName;
841 FString FinalPath;
842
843 int32 FileIndex = 0;
844
845 // To avoid overriding existing file,
846 // find available filename by adding FILENAME_[NUM].json to the end
847 do
848 {
849 FString IndexString = (FileIndex > 0) ? FString::Printf(TEXT("_%d"), FileIndex) : FString();
850 FinalPath = DataPathFolder / FString::Printf(TEXT("ExportedJsonFiles/%s%s.json"), *BaseFileName, *IndexString);
851 FileIndex++;
852 } while (FPlatformFileManager::Get().GetPlatformFile().FileExists(*FinalPath));
853
854
855 return FinalPath;
856}
ESensorTypes
Definition: SensorTypes.h:15
@ SemanticSegmentationCamera
EVehicleTypes
Definition: VehicleTypes.h:15
Definition: Camera.h:52
FCameraBaseParameters GetCameraParameters()
Definition: Camera.h:90
FDVSCameraParameters GetDVSCameraParameters() const
Definition: DVSCamera.h:58
FDepthCameraParameters GetDepthCameraParameters()
Definition: DepthCamera.h:38
Definition: Lidar.h:34
FLidarParameters GetLidarParameters() const
Definition: Lidar.h:82
FDroneParameters GetDroneParameters()
Definition: PIDDrone.h:63
Definition: Radar.h:26
FRadarParameters GetRadarParameters()
Definition: Radar.h:64
Definition: Sensor.h:44
FString GetSensorName() const
Definition: Sensor.h:95
virtual ESensorTypes GetSensorType() const
Definition: Sensor.h:64
virtual FString GetActorID_Implementation() const override
Definition: Sensor.h:207
FString AttachedToComponent
Definition: Sensor.h:272
FName AttachedToBone
Definition: Sensor.h:275
FThermalCameraParameters GetThermalCameraParameters() const
Definition: ThermalCamera.h:33
Definition: Walker.h:28
static void Log(const FString &Message, bool LogToTextFile=true, bool LogToROS=true)
static FString GetDataFolder()
static FString ConvertSensorTypeToString(ESensorTypes Sensortype)
static FString ConvertWalkerTypeToString(EWalkerType WalkerType)
static FString ExportWalkerToJSON(const FString &FileName, AWalker *Walker)
static FString ExportWeatherToJSON(const FString &FileName, const FWeatherParameters &WeatherParameters)
static FString CreateUniqueFilePath(FString FileName)
static FString ExportVehicleAndSensorsToJSON(FString FileName, AVehicle *Vehicle, bool OverrideTransform=false, const FTransform &Transform=FTransform())
static FString ExportSensorToJSON(const FString &FileName, ASensor *Sensor)
static TArray< TSharedPtr< FJsonValue > > ParseDepthCameras(const TArray< ADepthCamera * > &DepthCameras)
static TArray< TSharedPtr< FJsonValue > > ParseDVSCameras(const TArray< ADVSCamera * > &DVSCameras)
static TArray< TSharedPtr< FJsonValue > > ParseLidars(const TArray< ALidar * > &Lidars)
static TArray< TSharedPtr< FJsonValue > > ParseThermalCameras(const TArray< AThermalCamera * > &ThermalCameras)
static TSharedPtr< FJsonObject > CreateSensorJSONObject(const ASensor *SensorPtr, FString SensorName)
static FString ExportInstancedActorsToJSON(FString FileName, const TArray< AInstancedActor * > &Actors)
static void SetSpawnPoint(TSharedPtr< FJsonObject > &ObjectEntry, const FVector &Location, const FRotator &Rotation, const FVector &Scale)
static void SetDroneParameters(TSharedPtr< FJsonObject > &ObjectEntry, AVehicle *VehiclePtr)
static TSharedPtr< FJsonObject > CameraParametersToJSONObject(const FCameraBaseParameters &Parameters)
static TArray< TSharedPtr< FJsonValue > > ParseCameras(const TArray< ACamera * > &Cameras)
static TArray< TSharedPtr< FJsonValue > > ParseRadars(const TArray< ARadar * > &Radars)
EDroneEndAction DroneEndAction
EDroneAction DroneAction
TArray< FTransform > Points
TArray< FTransform > Points
EWalkerType WalkerType