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