Agrarsense
Vehicle.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
6#include "Vehicle.h"
7
13
17
18#include "Kismet/GameplayStatics.h"
19#include "NiagaraFunctionLibrary.h"
20#include "NiagaraComponent.h"
21#include "NiagaraSystem.h"
22
24{
25 PrimaryActorTick.bCanEverTick = false;
26 SensorsManager = CreateDefaultSubobject<USensorsManagerComponent>(TEXT("SensorsManagerComp"));
27 InteractableName = NSLOCTEXT("Agrarsense", "VehicleInteractableName", "Vehicle");
28}
29
31{
32 Super::BeginPlay();
33
34 TogglePhysics(true);
35
36 UROSHandler* ROSHandler = UAgrarsenseStatics::GetROSHandle(GetWorld());
37 if (ROSHandler)
38 {
39 ROSHandler->OnROSStateChanged.AddUniqueDynamic(this, &AVehicle::ROSBridgeStateChanged);
40 }
41
42 bool IsDrone = GetVehicleType() == EVehicleTypes::Drone;
43
44
45 FTransform transform = GetTransform();
46
47 // Create Collision sensor
48 FString VehicleCollisionSensorID = ActorID + "/collision";
49 FSensorSpawnParameters CollisionSensorSpawnParams;
50 CollisionSensorSpawnParams.Transform = transform;
51 CollisionSensorSpawnParams.SensorIdentifier = VehicleCollisionSensorID;
52 CollisionSensorSpawnParams.SensorName = "collision";
53 CollisionSensorSpawnParams.SimulateSensor = true;
54 CollisionSensorSpawnParams.Parent = this;
55
56 CollisionSensor = USensorFactory::SpawnCollisionSensor(CollisionSensorSpawnParams);
57
58 if (!IsDrone)
59 {
60 // Create Transform sensor for forwarder and harvester
61 FString VehicleTransformSensorID = ActorID + "/transform";
62 FSensorSpawnParameters TransformSensorSpawnParams;
63 TransformSensorSpawnParams.Transform = transform;
64 TransformSensorSpawnParams.SensorIdentifier = VehicleTransformSensorID;
65 TransformSensorSpawnParams.SensorName = "transform";
66 TransformSensorSpawnParams.SimulateSensor = true;
67 TransformSensorSpawnParams.Parent = this;
68
69 FTransformSensorParameters SensorParams;
70 SensorParams.SaveTransformDataToDisk = true;
71 SensorParams.OwningActor = this;
72
73 TransformSensor = USensorFactory::SpawnTransformSensor(TransformSensorSpawnParams, SensorParams);
74 }
75
76
77 // If in the bluerprint side, we have added extra transform sensor positions,
78 // we will create Transform sensors for those positions as well (eg. forwarder/harvester front and back sensors).
79 for (UStaticMeshComponent* Comp : ExtraTransformSensorPositions)
80 {
81 if (Comp)
82 {
83 FString CompName = Comp->GetName();
84
85 const FString VehicleTransformSensorID = FString::Printf(TEXT("%s/%s/transform"), *ActorID, *CompName);
86
87 FSensorSpawnParameters TransformSensorSpawnParams;
88 TransformSensorSpawnParams.Transform = transform;
89 TransformSensorSpawnParams.SensorIdentifier = VehicleTransformSensorID;
90 TransformSensorSpawnParams.SensorName = "transform";
91 TransformSensorSpawnParams.SimulateSensor = true;
92 TransformSensorSpawnParams.Parent = this;
93
95 Params.OwningActor = this;
96 Params.SaveTransformDataToDisk = false;
97 Params.UseOwningActorTransform = false;
98 Params.UsePrimiteRelativeTransform = false;
99 Params.PrimitiveComponent = Cast<UPrimitiveComponent>(Comp);
100
101 ExtraTransformSensors.AddUnique(USensorFactory::SpawnTransformSensor(TransformSensorSpawnParams, Params));
102 }
103 }
104
105 float NiagaraComponentHeight = 500.0f;
106 float OverlapBoundsSize = 50.0f;
107
108 if (IsDrone)
109 {
110 NiagaraComponentHeight = 200.0f;
111 }
112
113 FVector RelativePosition = FVector(0.0f, 0.0f, 0.0f);
115 {
116 // TODO make better solution for this.
117 RelativePosition = FVector(150.0f, -120.0f, 250.0f);
118 }
119
120 if (!IsDrone)
121 {
122 // Create overlap sensor for Forwarder and Harvester
123 // Drone overlap sensor(s) are created in PIDDrone BeginPlay
124
125 FString OverlapSensorID = ActorID + "/overlap";
126
127 FSensorSpawnParameters OverlapSensorSpawnParams;
128 OverlapSensorSpawnParams.Transform = transform;
129 OverlapSensorSpawnParams.SensorIdentifier = OverlapSensorID;
130 OverlapSensorSpawnParams.SensorName = "transform";
131 OverlapSensorSpawnParams.SimulateSensor = true;
132 OverlapSensorSpawnParams.Parent = this;
133
134 FOverlapSensorParameters SensorParams;
135 SensorParams.OwningActor = this;
136 SensorParams.Size = FVector(OverlapBoundsSize, OverlapBoundsSize, OverlapBoundsSize);
137 SensorParams.RelativePosition = RelativePosition;
138
139 OverlapSensor = USensorFactory::SpawnOverlapSensor(OverlapSensorSpawnParams, SensorParams);
140 }
141
142 // Load and setup rain/snow fall niagara system
143 UNiagaraSystem* NiagaraSystem = LoadObject<UNiagaraSystem>(nullptr, TEXT("/Game/Agrarsense/Particles/WaterAndSnow/NS_Particles.NS_Particles"));
144 if (NiagaraSystem)
145 {
146 NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(NiagaraSystem, this->GetRootComponent(),
147 FName("NiagaraEmitterSocketName"),
148 FVector(0.0, 0.0, NiagaraComponentHeight), FRotator::ZeroRotator, EAttachLocation::KeepRelativeOffset, true);
149 }
150 else
151 {
152 UE_LOG(LogTemp, Warning, TEXT("Vehicle.cpp: Couldn't find NS_Particles"));
153 }
154
156}
157
158void AVehicle::EndPlay(const EEndPlayReason::Type EndPlayReason)
159{
160 Super::EndPlay(EndPlayReason);
161
162 UROSHandler* ROSHandler = UAgrarsenseStatics::GetROSHandle(GetWorld());
163 if (ROSHandler)
164 {
165 ROSHandler->OnROSStateChanged.RemoveDynamic(this, &AVehicle::ROSBridgeStateChanged);
166 }
167
168 if (TransformSensor)
169 {
170 TransformSensor->Destroy();
171 TransformSensor = nullptr;
172 }
173
174 for (int32 i = 0; i < ExtraTransformSensors.Num(); i++)
175 {
176 if (ATransformSensor* SensorPtr = ExtraTransformSensors[i])
177 {
178 SensorPtr->Destroy();
179 }
180 }
181 ExtraTransformSensors.Empty();
182
183 if (CollisionSensor)
184 {
185 CollisionSensor->Destroy();
186 CollisionSensor = nullptr;
187 }
188
189 if (OverlapSensor)
190 {
191 OverlapSensor->Destroy();
192 OverlapSensor = nullptr;
193 }
194
195 // Destroy attached sensors when vehicle is destroyed
196 if (IsValid(SensorsManager) && EndPlayReason == EEndPlayReason::Destroyed)
197 {
198 SensorsManager->DestroyAllSensors();
199 }
200
202 {
203 NiagaraComponent->UnregisterComponent();
204 NiagaraComponent->DestroyComponent();
205 NiagaraComponent = nullptr;
206 }
207
208 // Destroy all remaining Actors that are attached to this vehicle, if any
209 TArray<AActor*> AttachedActors;
210 GetAttachedActors(AttachedActors);
211 for (AActor* Actor : AttachedActors)
212 {
213 if (Actor)
214 {
215 Actor->Destroy();
216 }
217 }
218}
219
221{
222
223}
224
226{
227 VehicleParameters = NewParameters;
228
230 {
232
234 {
235 const float BoundsSizeMEters = VehicleParameters.OverlapRadiusMeters;
236 OverlapSensor->SetOverlapBounds(FVector(BoundsSizeMEters, BoundsSizeMEters, BoundsSizeMEters));
237 }
238 }
239
240 // BlueprintImplementableEvent, this is handled in BP_Forwarder and BP_harvester.
242}
243
244void AVehicle::PossessedBy(AController* NewController)
245{
246 Super::PossessedBy(NewController);
247
248 ResetCamera();
249}
250
251void AVehicle::TeleportVehicleTo_Implementation(FVector NewLocation, FRotator NewRotation)
252{
253 SetActorLocationAndRotation(NewLocation, NewRotation, false, nullptr, ETeleportType::TeleportPhysics);
254}
255
257{
258 if (OverlapSensor)
259 {
261 }
262}
263
264FString AVehicle::ExportToJsonFile(const FString& FileName)
265{
266 bool OverrideTransform = IsVehicleInGarage();
267
268 FTransform TransformToUse = GetActorTransform();
269
270 if (OverrideTransform)
271 {
272 TransformToUse = MovedFromGarageTransform;
273 }
274
275 return USimulatorJsonExporter::ExportVehicleAndSensorsToJSON(FileName, this, OverrideTransform, TransformToUse);
276}
EROSState
Definition: ROSState.h:16
void SetVisualizeOverlapArea(bool Visualize)
void SetOverlapBounds(const FVector &NewSize)
ACollisionSensor * CollisionSensor
Definition: Vehicle.h:290
FTransform MovedFromGarageTransform
Definition: Vehicle.h:315
TArray< UStaticMeshComponent * > ExtraTransformSensorPositions
Definition: Vehicle.h:304
FWheeledVehicleParameters VehicleParameters
Definition: Vehicle.h:281
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
Definition: Vehicle.cpp:158
void SetVehicleParameters(FWheeledVehicleParameters NewParameters)
Definition: Vehicle.cpp:225
FText InteractableName
Definition: Vehicle.h:263
virtual void BeginPlay() override
Definition: Vehicle.cpp:30
virtual void PossessedBy(AController *NewController) override
Definition: Vehicle.cpp:244
void ResetCamera()
TArray< ATransformSensor * > ExtraTransformSensors
Definition: Vehicle.h:319
virtual void TeleportVehicleTo_Implementation(FVector NewLocation, FRotator NewRotation)
Definition: Vehicle.cpp:251
bool IsVehicleInGarage() const
Definition: Vehicle.h:133
FString ActorID
Definition: Vehicle.h:310
FString ExportToJsonFile(const FString &FileName)
Definition: Vehicle.cpp:264
AVehicle()
Definition: Vehicle.cpp:23
void SetVisualizeVehicleOverlapArea(bool Visible)
Definition: Vehicle.cpp:256
AOverlapSensor * OverlapSensor
Definition: Vehicle.h:296
virtual EVehicleTypes GetVehicleType() const
Definition: Vehicle.h:54
void ApplyVehicleParameters(FWheeledVehicleParameters CurrentParameters)
void TogglePhysics(bool isOn)
ATransformSensor * TransformSensor
Definition: Vehicle.h:293
UNiagaraComponent * NiagaraComponent
Definition: Vehicle.h:299
virtual void ROSBridgeStateChanged(EROSState ROSState)
Definition: Vehicle.cpp:220
TObjectPtr< USensorsManagerComponent > SensorsManager
Definition: Vehicle.h:287
static UROSHandler * GetROSHandle(const UObject *WorldContextObject)
FROSDelegate_ROState OnROSStateChanged
Definition: ROSHandler.h:81
static ATransformSensor * SpawnTransformSensor(const FSensorSpawnParameters SpawnParameters, FTransformSensorParameters SensorParameters)
static ACollisionSensor * SpawnCollisionSensor(const FSensorSpawnParameters SpawnParameters)
static AOverlapSensor * SpawnOverlapSensor(const FSensorSpawnParameters SpawnParameters, FOverlapSensorParameters SensorParameters)
static FString ExportVehicleAndSensorsToJSON(FString FileName, AVehicle *Vehicle, bool OverrideTransform=false, const FTransform &Transform=FTransform())
UPrimitiveComponent * PrimitiveComponent