Agrarsense
DataCapture.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 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
6#include "DataCapture.h"
14
15#include "GeoReferencingSystem.h"
16#include "TimerManager.h"
17
18ADataCapture::ADataCapture(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
19{
20 RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
21 PrimaryActorTick.bCanEverTick = true;
22 PrimaryActorTick.bStartWithTickEnabled = false;
23 PrimaryActorTick.TickGroup = TG_PrePhysics;
24 SetActorTickEnabled(false);
25}
26
28{
29 // Separate Cameras and Lidars from the Sensors array into their respective arrays
30 // after JsonParser has populated the Sensors array.
31 for (ASensor* Sensor : NewCaptureData.Sensors)
32 {
33 if (ACamera* CameraPtr = Cast<ACamera>(Sensor))
34 {
35 NewCaptureData.Cameras.Add(CameraPtr);
36 }
37 else if (ALidar* LidarPtr = Cast<ALidar>(Sensor))
38 {
39 NewCaptureData.Lidars.Add(LidarPtr);
40 }
41 }
42
43 CaptureData = NewCaptureData;
44
46 {
47 AGeoReferencingSystem* GeoReferencingSystem = AGeoReferencingSystem::GetGeoReferencingSystem(GetWorld());
48
49 if (GeoReferencingSystem)
50 {
51 for (FTransform& CaptureTransform : CaptureData.CapturePositions)
52 {
53 FVector Location = CaptureTransform.GetLocation();
54
55 float StoredZ = Location.Z;
56
57 FGeographicCoordinates GeographicCoordinates;
58 GeographicCoordinates.Latitude = Location.X;
59 GeographicCoordinates.Longitude = Location.Y;
60 GeographicCoordinates.Altitude = Location.Z;
61
62 FVector InUnrealCoordinates = UCoordinateConversionUtilities::GeographicToUnrealCoordinates(GeoReferencingSystem, GeographicCoordinates);
63
65 {
66 CaptureTransform.SetLocation(InUnrealCoordinates);
67 }
68 else
69 {
70 // If user gives wanted Z in meters from the ground, compute the height
71 InUnrealCoordinates.Z = StoredZ;
72 CaptureTransform.SetLocation(InUnrealCoordinates);
74 }
75 }
76 }
77 else
78 {
79 SimulatorLog::Log("Couldn't convert GPS coordinates into Unreal transform because couldn't find GeoReferencingSystem.");
80 }
81 }
82
84 {
85 // Loop through CapturePositions and add 4 additional positions for 360-degree capture
86 TArray<FTransform> NewCapturePositions;
87
88 for (const FTransform& OriginalTransform : CaptureData.CapturePositions)
89 {
90 FVector OriginalPosition = OriginalTransform.GetLocation();
91 FRotator OriginalRotation = OriginalTransform.GetRotation().Rotator();
92 int32 NumPhotos = 4;
93
94 NewCapturePositions.Add(OriginalTransform);
95
96 for (int32 i = 0; i < NumPhotos; i++)
97 {
98 FTransform CameraTransform = FTransform::Identity;
99
100 switch (i)
101 {
102 case 0: // Front
103 CameraTransform.SetLocation(OriginalPosition + FVector(0, 100, 0));
104 CameraTransform.SetRotation(FQuat(OriginalRotation));
105 break;
106 case 1: // Back
107 CameraTransform.SetLocation(OriginalPosition + FVector(0, -100, 0));
108 CameraTransform.SetRotation(FQuat(OriginalRotation + FRotator(0, 180, 0)));
109 break;
110 case 2: // Left
111 CameraTransform.SetLocation(OriginalPosition + FVector(-100, 0, 0));
112 CameraTransform.SetRotation(FQuat(OriginalRotation + FRotator(0, 90, 0)));
113 break;
114 case 3: // Right
115 CameraTransform.SetLocation(OriginalPosition + FVector(100, 0, 0));
116 CameraTransform.SetRotation(FQuat(OriginalRotation + FRotator(0, 270, 0)));
117 break;
118 }
119
120 // Add the new position to NewCapturePositions
121 NewCapturePositions.Add(CameraTransform);
122 }
123 }
124
125 CaptureData.CapturePositions = NewCapturePositions;
126 }
127
128 if (CaptureData.CapturePositions.Num() != 0 && CaptureData.Cameras.Num() != 0)
129 {
130 for (int32 i = 0; i < CaptureData.Cameras.Num(); i++)
131 {
132 ACamera* CameraPtr = CaptureData.Cameras[i];
133 if (CameraPtr)
134 {
135 FCameraBaseParameters params = CameraPtr->GetCameraParameters();
136 params.SaveImageToDisk = false;
137 params.SendDataToROS = false;
138 CameraPtr->ChangeCameraParameters(params);
139 }
140 }
141
143
144 // Enable This Actor tick with delay
145 FTimerHandle Handle;
146 GetWorld()->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([this]
147 {
149 SetActorTickEnabled(true);
150 }), 0.1f, false);
151 }
152 else
153 {
155 Destroy();
156 }
157}
158
160{
161 Super::BeginPlay();
162}
163
164void ADataCapture::Tick(float DeltaTime)
165{
166 Super::Tick(DeltaTime);
167 Capture();
168}
169
170void ADataCapture::EndPlay(const EEndPlayReason::Type EndPlayReason)
171{
172 Super::EndPlay(EndPlayReason);
173
174 CaptureData.Cameras.Empty();
176}
177
179{
181 {
182 // if this is the last position, we can stop capturing and destroy the sensors,
183 // as well as this Actor.
184
185 SetActorTickEnabled(false);
186
187 // Destroy this Actor with delay so Camera sensors have time to save the last images
188 FTimerHandle Handle;
189 GetWorld()->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([this]
190 {
192 Destroy();
193 }), 1.0f, false);
194
195 return;
196 }
197
198 switch (CaptureStep)
199 {
201 {
202 // Wait one frame before moving actor
204 FrameCounter = 0;
205 break;
206 }
208 {
210
211 // Move to next state
213 FrameCounter = 0;
214 break;
215 }
217 {
218 ++FrameCounter;
220 {
222
223 // Prepare for next wait before moving again
225 FrameCounter = 0;
226 }
227 break;
228 }
230 {
231 ++FrameCounter;
233 {
234 // Move to next position
237 FrameCounter = 0;
238 }
239 break;
240 }
241 }
242}
243
244void ADataCapture::UpdatePositions(const FTransform& Transform)
245{
246 for (int32 i = 0; i < CaptureData.Sensors.Num(); i++)
247 {
248 ASensor* SensorPtr = CaptureData.Sensors[i];
249 if (SensorPtr)
250 {
251 SensorPtr->SetActorTransform(Transform);
252 }
253 }
254
255 for (int32 i = 0; i < CaptureData.Lidars.Num(); i++)
256 {
257 ALidar* LidarPtr = CaptureData.Lidars[i];
258 if (LidarPtr)
259 {
260 // The Lidar sensor generates a full point cloud across multiple frames,
261 // so to ensure accurate data capture after moving the actor, we force a reset of the point cloud capture.
262 LidarPtr->ForceClearContainers();
263 }
264 }
265}
266
268{
269 for (int32 i = 0; i < CaptureData.Cameras.Num(); i++)
270 {
271 ACamera* CameraPtr = CaptureData.Cameras[i];
272 if (CameraPtr)
273 {
274 CameraPtr->SaveCurrentFrameToDisk();
275 }
276 }
277
278 for (int32 i = 0; i < CaptureData.Lidars.Num(); i++)
279 {
280 ALidar* LidarPtr = CaptureData.Lidars[i];
281 if (LidarPtr)
282 {
283 LidarPtr->SaveCurrentPointCloudToDisk();
284 }
285 }
286}
287
289{
290 for (int32 i = 0; i < CaptureData.Sensors.Num(); i++)
291 {
292 ASensor* SensorPtr = CaptureData.Sensors[i];
293 if (SensorPtr)
294 {
295 SensorPtr->Destroy();
296 }
297 }
298}
@ WaitingAfterPositionUpdate
@ WaitingForPositionUpdate
Definition: Camera.h:53
void ChangeCameraParameters(FCameraBaseParameters newParameters)
Definition: Camera.cpp:55
void SaveCurrentFrameToDisk()
Definition: Camera.h:192
FCameraBaseParameters GetCameraParameters()
Definition: Camera.h:91
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
int32 FrameCounter
Definition: DataCapture.h:114
void SetupDataCapture(FCaptureData NewCaptureData)
Definition: DataCapture.cpp:27
virtual void Tick(float DeltaTime) override
ADataCapture(const FObjectInitializer &ObjectInitializer)
Definition: DataCapture.cpp:18
FCaptureData CaptureData
Definition: DataCapture.h:110
void UpdatePositions(const FTransform &Transform)
virtual void BeginPlay() override
void CaptureDataNow()
ECaptureStep CaptureStep
Definition: DataCapture.h:112
void DestroySensors()
Definition: Lidar.h:35
void ForceClearContainers()
Definition: Lidar.h:110
void SaveCurrentPointCloudToDisk()
Definition: Lidar.h:118
Definition: Sensor.h:45
static void Log(const FString &Message, bool LogToTextFile=true, bool LogToROS=true)
static FVector GeographicToUnrealCoordinates(AGeoReferencingSystem *GeoReferencingSystem, const FGeographicCoordinates &GeographicCoordinates)
static bool AlignTransformFromGroundInMeters(AActor *Actor, FTransform &InTransform)
int32 FramesToKeepInSamePosition
Definition: DataCapture.h:54
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< ACamera * > Cameras
Definition: DataCapture.h:26
TArray< ALidar * > Lidars
Definition: DataCapture.h:29
int32 CurrentCaptureIndex
Definition: DataCapture.h:47
TArray< ASensor * > Sensors
Definition: DataCapture.h:23