Agrarsense
ROSCommands.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 "ROSCommands.h"
7
14
19
31
32#include "ROSIntegration/Classes/ROSIntegrationGameInstance.h"
33#include "ROSIntegration/Public/std_msgs/String.h"
34#include "ROSIntegration/Classes/RI/Topic.h"
35
36#include "Engine/GameViewportClient.h"
37#include "Engine/Engine.h"
38#include "Engine/World.h"
39#include "Misc/DateTime.h"
40#include "Async/Async.h"
41
42#include <functional>
43
44TMap<FString, FCommand> UROSCommands::CommandHandlers;
45
47{
49
51 if (ROSHandler)
52 {
53 ROSHandler->OnROSStateChanged.AddUniqueDynamic(this, &UROSCommands::ROSBridgeStateChanged);
54 }
55
57}
58
60{
62}
63
64void UROSCommands::TryExecuteCommand(const FString& Command)
65{
66 ParseIncomingMessage(Command);
67}
68
70{
71 UWorld* World = nullptr;
72 if (GEngine && GEngine->GameViewport)
73 {
74 World = GEngine->GameViewport->GetWorld();
75 }
76 return World;
77}
78
80{
82}
83
85{
86 // To call from Terminal (note all in lower case)
87 // rostopic pub /agrarsense/in/commands std_msgs/String "{COMMAND} {VARIABLE}" --once
88 // rostopic pub /agrarsense/in/commands std_msgs/String "help" --once
89
90 if (!CommandHandlers.IsEmpty())
91 {
92 return;
93 }
94
96
97 // General commands
98 CommandHandlers.Add(TEXT("help"), FCommand(&UROSCommands::HandlePrintAvailableCommands, 0.1f, "Print all commands"));
99 CommandHandlers.Add(TEXT("quit"), FCommand(&UROSCommands::HandleQuit, 1.0f, "Quits the Simulator"));
100 CommandHandlers.Add(TEXT("loadmap"), FCommand(&UROSCommands::HandleChangeMap, 5.0f, TEXT("load map by name")));
101 CommandHandlers.Add(TEXT("unrealcommand"), FCommand(&UROSCommands::HandleUnrealCommand, 0.05f, TEXT("Execute Unreal engine console command")));
102
103 // Pause commands
104 CommandHandlers.Add(TEXT("pause"), FCommand(&UROSCommands::HandlePauseSimulator, 0.01f, "Pauses the Simulator after current frame has finished"));
105 CommandHandlers.Add(TEXT("unpause"), FCommand(&UROSCommands::HandleUnPauseSimulator, 0.01f, "Un pauses the Simulator immediately upon receiving the message"));
106 CommandHandlers.Add(TEXT("nextframe"), FCommand(&UROSCommands::HandleAdvanceOneFrame, 0.01f, "Advance one frame"));
107 CommandHandlers.Add(TEXT("advanceframes"), FCommand(&UROSCommands::HandleAdvanceFrames, 0.01f, "Advance given amount of frames"));
108 CommandHandlers.Add(TEXT("advancetime"), FCommand(&UROSCommands::HandleAdvanceTime, 0.01f, "Advance given amount of time in seconds"));
109
110 // Teleport commands
111 CommandHandlers.Add(TEXT("teleportspectator"), FCommand(&UROSCommands::HandleTeleportSpectator, 0.03f, TEXT("x,y,z or x,y,z,yaw,pitch,roll")));
112 CommandHandlers.Add(TEXT("teleportspectatorheight"), FCommand(&UROSCommands::HandleTeleportSpectatorHeight, 0.03f, TEXT("x,y,z or x,y,z,yaw,pitch,roll")));
113 CommandHandlers.Add(TEXT("teleportbyid"), FCommand(&UROSCommands::HandleTeleportActorByID, 0.03f, TEXT("ID of Actor, x,y,z or x,y,z,yaw,pitch,roll")));
114 CommandHandlers.Add(TEXT("teleportSpectatorToInstanceID"), FCommand(&UROSCommands::HandleTeleportSpectatorByInstanceID, 0.03f, TEXT("Instance ID")));
115 CommandHandlers.Add(TEXT("teleportbyidheight"), FCommand(&UROSCommands::HandleTeleportActorByIDHeight, 0.05f, TEXT("ID of Actor, x,y,z or x,y,z,yaw,pitch,roll")));
116
117 // Destroy commands
118 CommandHandlers.Add(TEXT("destroyobjectbyid"), FCommand(&UROSCommands::HandleTryDestroyObjectByID, 0.05f, TEXT("Try to destroy object by id")));
119 CommandHandlers.Add(TEXT("destroyallsensors"), FCommand(&UROSCommands::HandleDestroyAllSensors, 1.0f, TEXT("Destroy all sensors")));
120 CommandHandlers.Add(TEXT("destroyallwalkers"), FCommand(&UROSCommands::HandleDestroyAllWalkers, 1.0f, TEXT("Destroy all sensors")));
121 CommandHandlers.Add(TEXT("destroyallvehicles"), FCommand(&UROSCommands::HandleDestroyAllVehicles, 1.0f, TEXT("Destroy all sensors")));
122
123 CommandHandlers.Add(TEXT("destroyobjectbyinstanceid"), FCommand(&UROSCommands::HandleDestroyObjectByInstanceID, 1.0f, TEXT("id")));
124
125 // Volume commands
126 // ex. "destroytrees 0,0,0 300,300,300" - destroys all tree actors within certain box area.
127 // ex. "destroyassets 0,0,0 300,300,300" - destroys all Instanced actors within certain box area.
128 CommandHandlers.Add(TEXT("destroytreesarea"), FCommand(&UROSCommands::HandleDestroyTreesArea, 0.05f, TEXT("x,y,z sizeX,sizeY,sizeZ")));
129 CommandHandlers.Add(TEXT("destroyassetsarea"), FCommand(&UROSCommands::HandleDestroyActorsArea, 0.05f, TEXT("x,y,z sizeX,sizeY,sizeZ")));
130
131 // Print commands
132 CommandHandlers.Add(TEXT("getmaps"), FCommand(&UROSCommands::HandlePrintMaps, 0.5f, TEXT("Print all available maps")));
133 CommandHandlers.Add(TEXT("getsensors"), FCommand(&UROSCommands::HandlePrintAllSensors, 0.1f, TEXT("Print all sensors information")));
134 CommandHandlers.Add(TEXT("getvehicles"), FCommand(&UROSCommands::HandlePrintAllVehicles, 0.1f, TEXT("Print all vehicles information")));
135 CommandHandlers.Add(TEXT("getwalkers"), FCommand(&UROSCommands::HandlePrintMaps, 0.1f, TEXT("print all walkers information")));
136 CommandHandlers.Add(TEXT("getids"), FCommand(&UROSCommands::HandlePrintIds, 0.1f, TEXT("print all ids")));
137
138 // Set commands
139 CommandHandlers.Add(TEXT("setglobaltargetframeRate"), FCommand(&UROSCommands::HandleSetGlobalTargetFrameRate, 1.0f, TEXT("0 - 300")));
140 CommandHandlers.Add(TEXT("setglobaltimedilation"), FCommand(&UROSCommands::HandleSetGlobalTimeDilation, 1.0f, TEXT("0.0f - 10.0f")));
141 CommandHandlers.Add(TEXT("setqualityLevel"), FCommand(&UROSCommands::HandleSetQualityLevel, 1.0f, TEXT("low / ultra")));
142 CommandHandlers.Add(TEXT("setworldrendering"), FCommand(&UROSCommands::HandleSetWorldRendering, 0.05f, TEXT("true / false")));
143 CommandHandlers.Add(TEXT("setgrassvisibility"), FCommand(&UROSCommands::HandleSetGrassVisibility, 0.05f, TEXT("true / false")));
144 CommandHandlers.Add(TEXT("setsavecombinedpointcloud"), FCommand(&UROSCommands::HandleSetSaveCombinedPointcloudToDisk, 0.05f, TEXT("true / false")));
145 CommandHandlers.Add(TEXT("setwpodistance"), FCommand(&UROSCommands::HandleSetWPO, 0.5f, TEXT("Set WPO render distance in cm")));
146 CommandHandlers.Add(TEXT("setnanitemaxpixelsperedge"), FCommand(&UROSCommands::HandleSetNaniteMaxPixelsPerEdge, 0.5f, TEXT("Set Nanite max pixels per edge")));
147 CommandHandlers.Add(TEXT("setspectatoroverlapradius"), FCommand(&UROSCommands::HandleSetSpectatorOverlapRadius, 0.05f, TEXT("radius in meters")));
148
149 // Sensor commands
150 CommandHandlers.Add(TEXT("setallsensorsenabled"), FCommand(&UROSCommands::HandleSetAllSensorsEnabled, 1.0f, TEXT("true / false")));
151 CommandHandlers.Add(TEXT("enableallsensors"), FCommand(&UROSCommands::HandleEnableAllSensors, 1.0f, TEXT("true / false")));
152 CommandHandlers.Add(TEXT("disableallsensors"), FCommand(&UROSCommands::HandleDisableAllSensors, 1.0f, TEXT("true / false")));
153 CommandHandlers.Add(TEXT("setsensorenabled"), FCommand(&UROSCommands::HandleSetSensorEnabled, 1.0f, TEXT("ID true/false")));
154
155 // Spawn/change objects commands. They all call the same function. They are defined separately for clarity.
156 CommandHandlers.Add(TEXT("spawn"), FCommand(&UROSCommands::HandleSpawnObjects, 0.05f, TEXT("Spawn objects from JSON file")));
157 CommandHandlers.Add(TEXT("load"), FCommand(&UROSCommands::HandleSpawnObjects, 0.05f, TEXT("Spawn objects from JSON file")));
158 CommandHandlers.Add(TEXT("loadjson"), FCommand(&UROSCommands::HandleSpawnObjects, 0.05f, TEXT("Spawn objects from JSON file")));
159 CommandHandlers.Add(TEXT("spawnobjects"), FCommand(&UROSCommands::HandleSpawnObjects, 0.05f, TEXT("Spawn objects from JSON file")));
160 CommandHandlers.Add(TEXT("changeweather"), FCommand(&UROSCommands::HandleSpawnObjects, 0.05f, TEXT("change weather from JSON file")));
161 CommandHandlers.Add(TEXT("changecolors"), FCommand(&UROSCommands::HandleSpawnObjects, 0.05f, TEXT("change semantic colors from JSON file")));
162
163 // Exports
164 CommandHandlers.Add(TEXT("exportall"), FCommand(&UROSCommands::HandleExportAll, 1.0f, TEXT("Export all spanwed things to JSON file")));
165 CommandHandlers.Add(TEXT("exportweather"), FCommand(&UROSCommands::HandleExportWeather, 1.0f, TEXT("Export current weather to JSON file")));
166 CommandHandlers.Add(TEXT("exportwalkers"), FCommand(&UROSCommands::HandleExportWalkers, 1.0f, TEXT("Export all Walkers to JSON file")));
167 CommandHandlers.Add(TEXT("exportvehicles"), FCommand(&UROSCommands::HandleExportVehicles, 1.0f, TEXT("Export all Vehicles to JSON file")));
168 CommandHandlers.Add(TEXT("exportsensors"), FCommand(&UROSCommands::HandleExportSensors, 1.0f, TEXT("Export all Sensors to JSON file")));
169 CommandHandlers.Add(TEXT("exportprops"), FCommand(&UROSCommands::HandleExportProps, 1.0f, TEXT("Export all props to JSON file")));
170 CommandHandlers.Add(TEXT("exportfoliage"), FCommand(&UROSCommands::HandleExportFoliage, 1.0f, TEXT("Export all Foliage to JSON file")));
171 CommandHandlers.Add(TEXT("exportobjects"), FCommand(&UROSCommands::HandleExportObjects, 1.0f, TEXT("Export all object locations to CSV file")));
172
173 // Overlap sensor commands
174 // changeoverlapbounds format: 'setoverlapradiusbyid sensor_id 25'
175 // changeoverlapposition format: 'setoverlappositionbyid sensor_id 0,0,0'
176 CommandHandlers.Add(TEXT("visualizeoverlaps"), FCommand(&UROSCommands::HandleVisualizeOverlapSensorsBounds, 0.05f, TEXT("true/false: Visualize all Overlap sensors")));
177 CommandHandlers.Add(TEXT("setoverlapradiusbyid"), FCommand(&UROSCommands::HandleChangeOverlapSensorBounds, 0.05f, TEXT("ID float: change overlap sensor radius by actor id")));
178 CommandHandlers.Add(TEXT("setoverlappositionbyid"), FCommand(&UROSCommands::HandleChangeOverlapSensorPosition, 0.05f, TEXT("ID float, float, float: Change Overlap sensor relative position")));
179
180 // Walker commands
181 CommandHandlers.Add(TEXT("movewalkerto"), FCommand(&UROSCommands::HandleMoveWalkerToAndStop, 0.05f, TEXT("ID (position or position,rotation)")));
182 CommandHandlers.Add(TEXT("movewalkertoanddestroy"), FCommand(&UROSCommands::HandleMoveWalkerToAndDestroy, 0.05f, TEXT("ID (position or position,rotation)")));
183 CommandHandlers.Add(TEXT("stopwalker"), FCommand(&UROSCommands::HandleStopWalker, 0.05f, TEXT("ID of the Walker")));
184 CommandHandlers.Add(TEXT("resumewalker"), FCommand(&UROSCommands::HandleResumeWalker, 0.05f, TEXT("ID of the Walker")));
185
186 // Vehicle commands
187 CommandHandlers.Add(TEXT("movedroneto"), FCommand(&UROSCommands::HandleMoveDroneToAndStop, 0.05f, TEXT("ID (position)")));
188 CommandHandlers.Add(TEXT("setvehiclemeshvisibility"), FCommand(&UROSCommands::HandleVehicleMeshVisibility, 0.05f, TEXT("ID true/false")));
189}
190
192{
193 switch (state)
194 {
197 break;
198
201 break;
202 }
203}
204
206{
207 if (CommandTopic)
208 {
209 CommandTopic->Unadvertise();
210 CommandTopic->Unsubscribe();
211 CommandTopic->MarkAsDisconnected();
212 CommandTopic->ConditionalBeginDestroy();
213 CommandTopic = nullptr;
214 }
215}
216
218{
219 UWorld* World = GetGameWorld();
220 if (!World)
221 {
222 return;
223 }
224
226 if (!CommandTopic && RosInstance && RosInstance->IsROSConnected())
227 {
228 CommandTopic = NewObject<UTopic>(UTopic::StaticClass());
229 CommandTopic->Init(RosInstance->ROSIntegrationCore, TEXT("/agrarsense/in/commands"), TEXT("std_msgs/String"));
230 CommandTopic->Advertise();
231
232 // Create a std::function callback object
233 std::function<void(TSharedPtr<FROSBaseMsg>)> SubscribeCallback = [this](TSharedPtr<FROSBaseMsg> msg) -> void
234 {
235 auto Concrete = StaticCastSharedPtr<ROSMessages::std_msgs::String>(msg);
236 if (Concrete.IsValid())
237 {
238 FString message = *(Concrete->_Data);
239 AsyncTask(ENamedThreads::GameThread, [this, message]()
240 {
241 // Parse message on GameThread since many commands are NOT thread-safe
242 ParseIncomingMessage(message);
243 });
244 }
245 return;
246 };
247
248 // Subscribe to the topic
249 CommandTopic->Subscribe(SubscribeCallback);
250 }
251}
252
253void UROSCommands::ParseIncomingMessage(const FString Message)
254{
255 // Parse incoming string message into {COMMAND} {VARIABLE} format
256 int32 SpaceIndex;
257 FString Command;
258 FString Variable;
259
260 if (Message.FindChar(' ', SpaceIndex))
261 {
262 // Extract the command as the substring before the first space
263 Command = Message.Left(SpaceIndex).ToLower();
264
265 // Extract the rest of the message as the variable
266 Variable = Message.Mid(SpaceIndex + 1);
267 }
268 else
269 {
270 // If no space is found, consider the entire message as the command
271 Command = Message.ToLower();
272 }
273
274 // Log incoming message into text file for debugging purposes
275 FString CommandMsg = FString::Printf(TEXT("Incoming [command variable]: %s %s"), *Command, *Variable);
276 SimulatorLog::Log(CommandMsg);
277
278 FCommand* CommandInfo = CommandHandlers.Find(Command);
279 if (CommandInfo)
280 {
281 // Check if enough time has passed since the last execution.
282 double CurrentTime = FPlatformTime::Seconds();
283 double TimeSinceLastExecution = CurrentTime - CommandInfo->LastExecutionTime;
284
285 if (TimeSinceLastExecution >= CommandInfo->CooldownTime)
286 {
287 // Call the handler function with the variable.
288 (this->*(CommandInfo->Handler))(Variable);
289
290 // Update the last execution time.
291 CommandInfo->LastExecutionTime = CurrentTime;
292 }
293 else
294 {
295 float CoolDownTimeLeft = CommandInfo->CooldownTime - TimeSinceLastExecution;
296 FString Msg = FString::Printf(TEXT("Command '%s' on cooldown. Retry in %.2f sec."), *Command, CoolDownTimeLeft);
298 }
299 }
300 else
301 {
302 FString Msg = FString::Printf(TEXT("Couldn't find command: '%s'"), *Command);
304 }
305}
306
307bool UROSCommands::TryParseBoolean(const FString& String, bool& OutBool) const
308{
309 FString LoweredString = String.ToLower();
310
311 if (LoweredString.Equals("true") || LoweredString.Equals("1"))
312 {
313 OutBool = true;
314 return true;
315 }
316 else if (LoweredString.Equals("false") || LoweredString.Equals("0"))
317 {
318 OutBool = false;
319 return true;
320 }
321
322 // Invalid boolean value
323 return false;
324}
325
327{
328 if (!CommandTopic)
329 {
330 return;
331 }
332
333 FString message = "Available Simulator ROS commands {COMMAND} {VALUE} || ";
334
335 for (const TPair<FString, FCommand>& CommandPair : CommandHandlers)
336 {
337 const FString& CommandString = CommandPair.Key;
338 const FCommand& CommandInfo = CommandPair.Value;
339 if (CommandInfo.DefaultValue.IsEmpty())
340 {
341 message += FString::Printf(TEXT("%s || "), *CommandString);
342 }
343 else
344 {
345 message += FString::Printf(TEXT("%s %s || "), *CommandString, *CommandInfo.DefaultValue);
346 }
347 }
348
349 SimulatorLog::Log(message);
350}
351
352void UROSCommands::HandleQuit(const FString& Variable)
353{
354 UWorld* World = GetGameWorld();
355 if (GEngine && World)
356 {
357 GEngine->Exec(World, TEXT("quit force"));
358 }
359}
360
361void UROSCommands::HandlePauseSimulator(const FString& Variable)
362{
363 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
364 if (AgrarsenseSettings)
365 {
366 AgrarsenseSettings->PauseSimulationEndOfThisFrame();
367 }
368}
369
370void UROSCommands::HandleUnPauseSimulator(const FString& Variable)
371{
372 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
373 if (AgrarsenseSettings)
374 {
375 AgrarsenseSettings->UnPauseSimulation();
376 }
377}
378
379void UROSCommands::HandleAdvanceOneFrame(const FString& Variable)
380{
381 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
382 if (AgrarsenseSettings)
383 {
384 AgrarsenseSettings->AdvanceFrameCount(1);
385 }
386}
387
388void UROSCommands::HandleAdvanceFrames(const FString& Variable)
389{
390 int32 FrameCount = 0;
391 if (!Variable.IsNumeric())
392 {
393 return;
394 }
395
396 FrameCount = FCString::Atoi(*Variable);
397 if (FrameCount != 0)
398 {
399 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
400 if (AgrarsenseSettings)
401 {
402 AgrarsenseSettings->AdvanceFrameCount(FrameCount);
403 }
404 }
405}
406
407void UROSCommands::HandleAdvanceTime(const FString& Variable)
408{
409 float Time = 0.0f;
410 if (!Variable.IsNumeric())
411 {
412 return;
413 }
414
415 Time = FCString::Atof(*Variable);
416 if (Time != 0.0f)
417 {
418 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
419 if (AgrarsenseSettings)
420 {
421 AgrarsenseSettings->AdvanceTime(Time);
422 }
423 }
424}
425
426void UROSCommands::HandleChangeMap(const FString& Variable)
427{
428 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
429 if (AgrarsenseSettings)
430 {
431 AgrarsenseSettings->ChangeMapByName(Variable);
432 }
433}
434
435void UROSCommands::HandleUnrealCommand(const FString& Variable)
436{
437 UWorld* World = GetGameWorld();
438 if (GEngine && World)
439 {
440 GEngine->Exec(World, *Variable);
441 }
442}
443
445{
446 if (!Variable.IsNumeric())
447 {
448 return;
449 }
450
451 float Radius = FCString::Atof(*Variable);
452
453 if (UWorld* World = GetGameWorld())
454 {
455 if (ASpectator* Spectator = UAgrarsenseStatics::GetSpectator(World))
456 {
457 if (AOverlapSensor* OverlapSensor = Spectator->GetOverlapSensor())
458 {
459 OverlapSensor->SetOverlapBounds(FVector(Radius, Radius, Radius));
460 }
461 }
462 }
463}
464
466{
468 HandleTeleportSpectator(Variable);
470}
471
472void UROSCommands::HandleTeleportSpectator(const FString& Variable)
473{
474 // Split the comma-separated string into components
475 TArray<FString> Components;
476 Variable.ParseIntoArray(Components, TEXT(","), true);
477
478 if (Components.Num() >= 3)
479 {
480 FVector Location;
481 FQuat Rotation;
482
483 // Convert the first three components to float values for location
484 float X = FCString::Atof(*Components[0]);
485 float Y = FCString::Atof(*Components[1]);
486 float Z = FCString::Atof(*Components[2]);
487
488 Location = FVector(X, Y, Z);
489
490 if (Components.Num() >= 6)
491 {
492 // If there are six or more components, try to parse them as rotation values
493 float Pitch = FCString::Atof(*Components[3]);
494 float Yaw = FCString::Atof(*Components[4]);
495 float Roll = FCString::Atof(*Components[5]);
496
497 // Convert the Euler angles to a quaternion
498 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
499 }
500
501 UWorld* World = GetGameWorld();
502 if (World)
503 {
505 if (Spectator)
506 {
507 FTransform Transform;
508 Transform.SetLocation(Location);
509 Transform.SetRotation(Rotation);
510
511
513 {
515 }
516
517 Spectator->TeleportSpectator(Transform);
518 }
519 }
520 }
521}
522
524{
525 InMeters = true;
526 HandleTeleportActorByID(Variable);
527 InMeters = false;
528}
529
531{
532 if (!Variable.IsNumeric())
533 {
534 return;
535 }
536
537 TArray<AActor*> Taggers;
538 UGameplayStatics::GetAllActorsOfClass(GetGameWorld(), ATagger::StaticClass(), Taggers);
539 ATagger* Tagger = Cast<ATagger>(Taggers[0]);
540
541 if (Tagger)
542 {
543 AActor* Actor = Tagger->GetActorByInstanceID(FCString::Atof(*Variable));
544 if (Actor)
545 {
547 {
548 Spectator->TeleportSpectator(Actor->GetActorTransform());
549 }
550 }
551 }
552}
553
554void UROSCommands::HandleTeleportActorByID(const FString& Variable)
555{
556 FString ID;
557 FString TransformString;
558
559 // Split the ID and rest of the message
560 TArray<FString> Tokens;
561 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
562 if (Tokens.Num() >= 2)
563 {
564 ID = Tokens[0];
565 TransformString = Variable.RightChop(ID.Len() + 1);
566 }
567 else
568 {
569 SimulatorLog::Log("Invalid input. Input should be in format: ID,X,Y,Z or ID,X,Y,Z,YAW,PITCH,ROLL");
570 return;
571 }
572
573 // Check if this ID matches any Actor
574 AActor* Actor = IActorInformation::GetActorByID(ID);
575 if (!Actor)
576 {
577 FString log = FString::Printf(TEXT("Could not find Actor with ID: %s"), *ID);
579 return;
580 }
581
582 // Parse rest of the string to Transform
583 TArray<FString> Components;
584 TransformString.ParseIntoArray(Components, TEXT(","), true);
585
586 if (Components.Num() >= 3)
587 {
588 FVector Location;
589 FQuat Rotation;
590
591 // Convert the first three components to float values for location
592 float X = FCString::Atof(*Components[0]);
593 float Y = FCString::Atof(*Components[1]);
594 float Z = FCString::Atof(*Components[2]);
595
596 Location = FVector(X, Y, Z);
597
598 if (Components.Num() >= 6)
599 {
600 // If there are six or more components, try to parse them as rotation values
601 float Pitch = FCString::Atof(*Components[3]);
602 float Yaw = FCString::Atof(*Components[4]);
603 float Roll = FCString::Atof(*Components[5]);
604
605 // Convert the Euler angles to a quaternion
606 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
607 }
608
609 FTransform Transform;
610 Transform.SetLocation(Location);
611 Transform.SetRotation(Rotation);
612
613 if (InMeters)
614 {
616 }
617
618#if WITH_EDITOR
619 UE_LOG(LogTemp, Warning, TEXT("Teleporting Actor with ID: %s to: %s"), *ID, *TransformString);
620#endif
621
622 // Check if this Actor is Vehicle
623 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
624 if (VehiclePtr)
625 {
626 // Disable vehicle physics so it can be teleported
627 VehiclePtr->TogglePhysics(false);
628
629 Actor->SetActorTransform(Transform);
630
631 // Enable vehicle physics back on after teleporting vehicle
632 VehiclePtr->TogglePhysics(true);
633 }
634 else
635 {
636 // Else set the Actor transform
637 Actor->SetActorTransform(Transform);
638 }
639 }
640}
641
642void UROSCommands::HandleTryDestroyObjectByID(const FString& Variable)
643{
644 bool success = IActorInformation::DestroyActorByID(Variable);
645
646 FString Message;
647 if (success)
648 {
649 Message = FString::Printf(TEXT("Object with ID %s successfully destroyed."), *Variable);
650 }
651 else
652 {
653 Message = FString::Printf(TEXT("Failed to destroy object with ID %s."), *Variable);
654 }
655
656 SimulatorLog::Log(Message);
657}
658
659void UROSCommands::HandleDestroyAllSensors(const FString& Variable)
660{
662}
663
664void UROSCommands::HandleDestroyAllWalkers(const FString& Variable)
665{
667}
668
669void UROSCommands::HandleDestroyAllVehicles(const FString& Variable)
670{
671 UWorld* World = GetGameWorld();
672 if (!World)
673 {
674 return;
675 }
676
677 TArray<AActor*> Vehicles;
678 UGameplayStatics::GetAllActorsOfClass(World, AVehicle::StaticClass(), Vehicles);
679 for (AActor* Actor : Vehicles)
680 {
681 AVehicle* Vehicle = Cast<AVehicle>(Actor);
682 if (Vehicle)
683 {
684 Vehicle->Destroy();
685 }
686 }
687}
688
690{
691 if (!Variable.IsNumeric())
692 {
693 return;
694 }
695
696 TArray<AActor*> Taggers;
697 UGameplayStatics::GetAllActorsOfClass(GetGameWorld(), ATagger::StaticClass(), Taggers);
698 ATagger* Tagger = Cast<ATagger>(Taggers[0]);
699
700 if (Tagger)
701 {
702 AActor* Actor = Tagger->GetActorByInstanceID(FCString::Atof(*Variable));
703 if (Actor)
704 {
705 Actor->Destroy();
706 }
707 }
708}
709
710void UROSCommands::HandlePrintMaps(const FString& Variable)
711{
712 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
713 if (AgrarsenseSettings)
714 {
715 TArray<FString> Maps = AgrarsenseSettings->GetMapNames();
716
717 FString message;
718
719 for (const FString& map : Maps)
720 {
721 message += FString::Printf(TEXT("%s, "), *map);
722 }
723
724 SimulatorLog::Log(message);
725 }
726}
727
728void UROSCommands::HandlePrintAllSensors(const FString& Variable)
729{
730 PrintActorInformation(Variable, ASensor::StaticClass(), "sensor");
731}
732
733void UROSCommands::HandlePrintAllVehicles(const FString& Variable)
734{
735 PrintActorInformation(Variable, AVehicle::StaticClass(), "vehicle");
736}
737
738void UROSCommands::HandlePrintAllWalkers(const FString& Variable)
739{
740 PrintActorInformation(Variable, AWalker::StaticClass(), "walker");
741}
742
743void UROSCommands::PrintActorInformation(const FString& Variable, UClass* ActorClass, const FString& ActorTypeName)
744{
745 TArray<AActor*> Actors;
746 UGameplayStatics::GetAllActorsWithInterface(GetGameWorld(), UActorInformation::StaticClass(), Actors);
747
748 TArray<AActor*> TypedActors;
749 for (AActor* Actor : Actors)
750 {
751 if (Actor->IsA(ActorClass))
752 {
753 TypedActors.Add(Actor);
754 }
755 }
756
757 FString Msg;
758 if (!TypedActors.IsEmpty())
759 {
760 Msg = FString::Printf(TEXT("Simulation has %d %ss \n "), TypedActors.Num(), *ActorTypeName);
761 for (AActor* Actor : TypedActors)
762 {
763 if (Actor)
764 {
765 if (Actor->Implements<UActorInformation>())
766 {
767 FString ActorInfo = IActorInformation::Execute_GetActorInformation(Actor);
768 Msg += FString::Printf(TEXT("%s \n \n "), *ActorInfo);
769 }
770
771 }
772 }
773 }
774 else
775 {
776 Msg = FString::Printf(TEXT("Simulation has 0 %ss."), *ActorTypeName);
777 }
778
780}
781
782void UROSCommands::HandlePrintIds(const FString& Variable)
783{
785}
786
788{
789 if (Variable.IsNumeric())
790 {
791 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
792 if (AgrarsenseSettings)
793 {
794 int32 IntValue = FCString::Atoi(*Variable);
795 AgrarsenseSettings->SetGlobalTargetFrameRate(IntValue);
796 }
797 }
798}
799
800void UROSCommands::HandleSetGlobalTimeDilation(const FString& Variable)
801{
802 if (Variable.IsNumeric())
803 {
804 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
805 if (AgrarsenseSettings)
806 {
807 float FloatValue = FCString::Atof(*Variable);
808 AgrarsenseSettings->SetGlobalTimeDilation(FloatValue);
809 }
810 }
811}
812
813void UROSCommands::HandleSetQualityLevel(const FString& Variable)
814{
815 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
816 if (AgrarsenseSettings)
817 {
818 AgrarsenseSettings->SetQualityLevelFromString(Variable);
819 }
820}
821
822void UROSCommands::HandleSetWorldRendering(const FString& Variable)
823{
824 bool RenderWorld;
825 if (!TryParseBoolean(Variable, RenderWorld))
826 {
827 // Failed to parse, return
828 return;
829 }
830
831 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
832 if (AgrarsenseSettings)
833 {
834 AgrarsenseSettings->SetWorldRendering(RenderWorld);
835 }
836}
837
838void UROSCommands::HandleSetGrassVisibility(const FString& Variable)
839{
840 bool RenderGrass;
841 if (!TryParseBoolean(Variable, RenderGrass))
842 {
843 // Failed to parse, return
844 return;
845 }
846
847 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
848 if (AgrarsenseSettings)
849 {
850 AgrarsenseSettings->SetGrassVisibility(RenderGrass);
851 }
852}
853
855{
856 bool Save;
857 if (!TryParseBoolean(Variable, Save))
858 {
859 // Failed to parse, return
860 return;
861 }
862
864 if (LidarManager)
865 {
866 LidarManager->SetSaveCombinedCloudToDisk(Save);
867 }
868}
869
870void UROSCommands::HandleSpawnObjects(const FString& Variable)
871{
873}
874
875void UROSCommands::HandleExportAll(const FString& Variable)
876{
877 // Below export functions do not need any incoming variable but require FString
878 FString EmptyString;
879
880 HandleExportWeather(EmptyString);
881 HandleExportWalkers(EmptyString);
882
883 // HandleExportSensors exports vehicles as well
884 //HandleExportVehicles(EmptyString);
885 HandleExportSensors(EmptyString);
886
887 HandleExportFoliage(EmptyString);
888 HandleExportProps(EmptyString);
889}
890
891void UROSCommands::HandleExportWeather(const FString& Variable)
892{
894 if (Weather)
895 {
896 Weather->ExportToJSON("ExportedWeather");
897 }
898}
899
900void UROSCommands::HandleExportWalkers(const FString& Variable)
901{
902 TArray<AWalker*> Walkers = UAssetLibrary::GetAllWalkers();
903 for (AWalker* Walker : Walkers)
904 {
905 if (Walker)
906 {
907 Walker->ExportToJsonFile("ExportedWalker");
908 }
909 }
910}
911
912void UROSCommands::HandleExportVehicles(const FString& Variable)
913{
914 TArray<FVehicleData> Vehicles = UAssetLibrary::GetSpawnedVehicles();
915 for (const FVehicleData& VehicleData : Vehicles)
916 {
917 AVehicle* VehiclePtr = VehicleData.Vehicle.Get();
918 if (VehiclePtr)
919 {
920 VehiclePtr->ExportToJsonFile("ExportedVehicle");
921 }
922 }
923}
924
925void UROSCommands::HandleExportSensors(const FString& Variable)
926{
927 UWorld* World = GetGameWorld();
928 if (!World)
929 {
930 return;
931 }
932
933 // Export all Vehicles and attached sensors
934 TArray<AActor*> Vehicles;
935 UGameplayStatics::GetAllActorsOfClass(World, AVehicle::StaticClass(), Vehicles);
936 for (AActor* Actor : Vehicles)
937 {
938 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
939 if (VehiclePtr)
940 {
941 VehiclePtr->ExportToJsonFile("ExportedVehicle");
942 }
943 }
944
945 // Export all Sensors separately as well
946 TArray<AActor*> Sensors;
947 UGameplayStatics::GetAllActorsOfClass(World, ASensor::StaticClass(), Sensors);
948 for (AActor* Actor : Sensors)
949 {
950 ASensor* SensorPtr = Cast<ASensor>(Actor);
951 if (SensorPtr)
952 {
953 SensorPtr->ExportToJsonFile("ExportedSensor");
954 }
955 }
956}
957
958void UROSCommands::HandleExportFoliage(const FString& Variable)
959{
960 TArray<AInstancedActor*> FoliageActors = UAssetLibrary::GetAllAddedFoliageActors();
961 USimulatorJsonExporter::ExportInstancedActorsToJSON("ExportedFoliage", FoliageActors);
962}
963
964void UROSCommands::HandleExportObjects(const FString& Variable)
965{
966 UWorld* World = GetGameWorld();
967 if (!World)
968 {
969 return;
970 }
971
972 TArray<AActor*> Taggers;
973 UGameplayStatics::GetAllActorsOfClass(World, ATagger::StaticClass(), Taggers);
974
975 if (ATagger* Tagger = Cast<ATagger>(Taggers[0]))
976 {
977 Tagger->ExportObjectLocationsToCSV();
978 }
979}
980
981void UROSCommands::HandleExportProps(const FString& Variable)
982{
983 TArray<AInstancedActor*> PropActors = UAssetLibrary::GetAllAddedPropActors();
984 USimulatorJsonExporter::ExportInstancedActorsToJSON("ExportedProps", PropActors);
985}
986
988{
989 bool Visualize;
990 if (!TryParseBoolean(Variable, Visualize))
991 {
992 // Failed to parse, return
993 return;
994 }
995
996 UWorld* World = GetGameWorld();
997 if (World)
998 {
999 TArray<AActor*> OverlapSensors;
1000 UGameplayStatics::GetAllActorsOfClass(World, AOverlapSensor::StaticClass(), OverlapSensors);
1001
1002 for (AActor* SensorActor : OverlapSensors)
1003 {
1004 AOverlapSensor* Sensor = Cast<AOverlapSensor>(SensorActor);
1005 if (Sensor)
1006 {
1007 Sensor->SetVisualizeOverlapArea(Visualize);
1008 }
1009 }
1010 }
1011}
1012
1014{
1015 FString ID;
1016 FString BoundsString;
1017
1018 TArray<FString> Tokens;
1019 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1020
1021 if (Tokens.Num() < 2)
1022 {
1023 // Incoming parameters were invalid, return
1024 return;
1025 }
1026
1027 ID = Tokens[0];
1028 BoundsString = Tokens[1];
1029
1030 if (BoundsString.IsNumeric())
1031 {
1032 float Radius = FCString::Atof(*BoundsString);
1033
1034 AActor* Actor = IActorInformation::GetActorByID(ID);
1035 AOverlapSensor* Sensor = Cast<AOverlapSensor>(Actor);
1036 if (Sensor)
1037 {
1038 Sensor->SetOverlapBounds(FVector(Radius, Radius, Radius));
1039 }
1040 }
1041}
1042
1044{
1045 FString ID;
1046 FString BoundsString;
1047
1048 TArray<FString> Tokens;
1049 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1050
1051 if (Tokens.Num() < 2)
1052 {
1053 // Incoming parameters were invalid, return
1054 return;
1055 }
1056
1057 ID = Tokens[0];
1058 BoundsString = Tokens[1];
1059
1060 FVector RelativePosition;
1061 TArray<FString> BoundsTokens;
1062 BoundsString.ParseIntoArray(BoundsTokens, TEXT(","), true);
1063
1064 if (BoundsTokens.Num() >= 3)
1065 {
1066 RelativePosition.X = FCString::Atof(*BoundsTokens[0]);
1067 RelativePosition.Y = FCString::Atof(*BoundsTokens[1]);
1068 RelativePosition.Z = FCString::Atof(*BoundsTokens[2]);
1069
1070 AActor* Actor = IActorInformation::GetActorByID(ID);
1071 AOverlapSensor* Sensor = Cast<AOverlapSensor>(Actor);
1072 if (Sensor)
1073 {
1074 Sensor->SetOverlapRelativePosition(RelativePosition);
1075 }
1076 }
1077}
1078
1080{
1082}
1083
1084void UROSCommands::HandleMoveWalkerToAndStop(const FString& Variable)
1085{
1087}
1088
1089void UROSCommands::HandleMoveDroneToAndStop(const FString& Variable)
1090{
1092}
1093
1094void UROSCommands::HandleMoveWalkerTo(const FString& Variable, EWalkerEndAction EndAction)
1095{
1096 // This function overrides the current parameters of the Walker identified by the given ID,
1097 // moving the Walker to the specified x,y,z position and stopping upon reaching the target.
1098 // Usage: "movewalkerto reindeer 0,0,0" where 'reindeer' is the Walker ID.
1099
1100 FString ID;
1101 FString TransformString;
1102
1103 // Split the ID and rest of the message
1104 TArray<FString> Tokens;
1105 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1106 if (Tokens.Num() >= 2)
1107 {
1108 ID = Tokens[0];
1109 TransformString = Variable.RightChop(ID.Len() + 1);
1110 }
1111 else
1112 {
1113 return;
1114 }
1115
1116 // Check if this ID matches any Actor
1117 AActor* Actor = IActorInformation::GetActorByID(ID);
1118 if (!Actor)
1119 {
1120 return;
1121 }
1122
1123 AWalker* Walker = Cast<AWalker>(Actor);
1124 if (!Walker)
1125 {
1126 return;
1127 }
1128
1129 // Parse rest of the string to Transform
1130 TArray<FString> Components;
1131 TransformString.ParseIntoArray(Components, TEXT(","), true);
1132
1133 if (Components.Num() >= 3)
1134 {
1135 FVector Location;
1136 FQuat Rotation;
1137
1138 // Convert the first three components to float values for location
1139 float X = FCString::Atof(*Components[0]);
1140 float Y = FCString::Atof(*Components[1]);
1141 float Z = FCString::Atof(*Components[2]);
1142
1143 Location = FVector(X, Y, Z);
1144
1145 if (Components.Num() >= 6)
1146 {
1147 // If there are six or more components, try to parse them as rotation values
1148 float Pitch = FCString::Atof(*Components[3]);
1149 float Yaw = FCString::Atof(*Components[4]);
1150 float Roll = FCString::Atof(*Components[5]);
1151
1152 // Convert the Euler angles to a quaternion
1153 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
1154 }
1155
1156 FTransform Transform;
1157 Transform.SetLocation(Location);
1158 Transform.SetRotation(Rotation);
1159
1160 // Create new walker parameters
1161 FWalkerParameters NewParams;
1163 NewParams.WalkerEndAction = EndAction;
1164 NewParams.Points.Add(Transform);
1165
1166 // Change Walker parameters
1167 Walker->ChangeWalkerParameters(NewParams);
1168 }
1169}
1170
1171void UROSCommands::HandleStopWalker(const FString& Variable)
1172{
1173 HandleSetWalkerMovement(Variable, true);
1174}
1175
1176void UROSCommands::HandleResumeWalker(const FString& Variable)
1177{
1178 HandleSetWalkerMovement(Variable, false);
1179}
1180
1181void UROSCommands::HandleSetWalkerMovement(const FString& Variable, bool IsPaused)
1182{
1183 AActor* Actor = IActorInformation::GetActorByID(Variable);
1184 AWalker* Walker = Cast<AWalker>(Actor);
1185 if (!Walker)
1186 {
1187 return;
1188 }
1189
1190 if (IsPaused)
1191 {
1192 Walker->PauseWalker();
1193 }
1194 else
1195 {
1196 Walker->ResumeWalker();
1197 }
1198}
1199
1200void UROSCommands::HandleMoveDroneTo(const FString& Variable, EDroneEndAction EndAction)
1201{
1202 // This function overrides the current parameters of the Drone identified by the given ID,
1203 // moving the Drone to the specified x,y,z position and stopping upon reaching the target.
1204 // Usage: "movedroneto drone 0,0,0" where 'drone' is the Drone ID.
1205
1206 FString ID;
1207 FString TransformString;
1208
1209 // Split the ID and rest of the message
1210 TArray<FString> Tokens;
1211 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1212 if (Tokens.Num() >= 2)
1213 {
1214 ID = Tokens[0];
1215 TransformString = Variable.RightChop(ID.Len() + 1);
1216 }
1217 else
1218 {
1219 return;
1220 }
1221
1222 // Check if this ID matches any Actor
1223 AActor* Actor = IActorInformation::GetActorByID(ID);
1224 if (!Actor)
1225 {
1226 return;
1227 }
1228
1229 APIDDrone* Drone = Cast<APIDDrone>(Actor);
1230 if (!Drone)
1231 {
1232 return;
1233 }
1234
1235 // Parse rest of the string to Transform
1236 TArray<FString> Components;
1237 TransformString.ParseIntoArray(Components, TEXT(","), true);
1238
1239 if (Components.Num() >= 3)
1240 {
1241 FVector Location;
1242 FQuat Rotation;
1243
1244 // Convert the first three components to float values for location
1245 float X = FCString::Atof(*Components[0]);
1246 float Y = FCString::Atof(*Components[1]);
1247 float Z = FCString::Atof(*Components[2]);
1248
1249 Location = FVector(X, Y, Z);
1250
1251 if (Components.Num() >= 6)
1252 {
1253 // If there are six or more components, try to parse them as rotation values
1254 float Pitch = FCString::Atof(*Components[3]);
1255 float Yaw = FCString::Atof(*Components[4]);
1256 float Roll = FCString::Atof(*Components[5]);
1257
1258 // Convert the Euler angles to a quaternion
1259 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
1260 }
1261
1262 FTransform Transform;
1263 Transform.SetLocation(Location);
1264 Transform.SetRotation(Rotation);
1265
1266 // Create new drone parameters
1267 FDroneParameters NewParams;
1269 NewParams.DroneEndAction = EndAction;
1270 //NewParams.Points.Add(Transform);
1271
1272 Drone->ChangeDroneParameters(NewParams);
1273
1274 // Change drone parameters
1275 Drone->MoveDroneToPosition(Transform);
1276 }
1277}
1278
1279void UROSCommands::HandleSetAllSensorsEnabled(const FString& Variable)
1280{
1281 bool EnableSensors;
1282 if (!TryParseBoolean(Variable, EnableSensors))
1283 {
1284 // Failed to parse, return
1285 return;
1286 }
1287
1288 if (EnableSensors)
1289 {
1291 }
1292 else
1293 {
1295 }
1296}
1297
1298void UROSCommands::HandleEnableAllSensors(const FString& Variable)
1299{
1301}
1302
1303void UROSCommands::HandleDisableAllSensors(const FString& Variable)
1304{
1306}
1307
1308void UROSCommands::HandleSetSensorEnabled(const FString& Variable)
1309{
1310 TArray<FString> Tokens;
1311 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1312 if (Tokens.Num() < 2)
1313 {
1314 // Not enough arguments, return
1315 return;
1316 }
1317
1318 const FString& ID = Tokens[0];
1319
1320 AActor* Actor = IActorInformation::GetActorByID(ID);
1321 if (!Actor)
1322 {
1323 return;
1324 }
1325
1326 ASensor* Sensor = Cast<ASensor>(Actor);
1327 if (!Sensor)
1328 {
1329 return;
1330 }
1331
1332 FString BooleanString = Tokens[1].ToLower();
1333
1334 bool SimulateSensor;
1335 if (!TryParseBoolean(BooleanString, SimulateSensor))
1336 {
1337 // Failed to parse, return
1338 return;
1339 }
1340
1341 Sensor->SetSimulateSensor(SimulateSensor);
1342}
1343
1344void UROSCommands::HandleSetWPO(const FString& Variable)
1345{
1346 if (Variable.IsNumeric())
1347 {
1348 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
1349 if (AgrarsenseSettings)
1350 {
1351 int32 IntValue = FCString::Atoi(*Variable);
1352 AgrarsenseSettings->SetWorldPositionOffsetRenderDistance(IntValue);
1353 }
1354 }
1355}
1356
1358{
1359 if (Variable.IsNumeric())
1360 {
1361 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
1362 if (AgrarsenseSettings)
1363 {
1364 float Value = FCString::Atof(*Variable);
1365 AgrarsenseSettings->SetNaniteMaxPixelsPerEdge(Value);
1366 }
1367 }
1368}
1369
1370void UROSCommands::HandleDestroyTreesArea(const FString& Variable)
1371{
1372 HandleDestroyActors(Variable, true);
1373}
1374
1375void UROSCommands::HandleDestroyActorsArea(const FString& Variable)
1376{
1377 HandleDestroyActors(Variable, false);
1378}
1379
1380void UROSCommands::HandleDestroyActors(const FString& Variable, bool OnlyTrees)
1381{
1382 TArray<FString> ParsedStrings;
1383 Variable.ParseIntoArray(ParsedStrings, TEXT(" "), true);
1384
1385 if (ParsedStrings.Num() != 2)
1386 {
1387 return;
1388 }
1389
1390 // Parse position
1391 TArray<FString> PositionComponents;
1392 ParsedStrings[0].ParseIntoArray(PositionComponents, TEXT(","), true);
1393
1394 if (PositionComponents.Num() != 3)
1395 {
1396 return;
1397 }
1398
1399 FVector Position(FCString::Atof(*PositionComponents[0]), FCString::Atof(*PositionComponents[1]), FCString::Atof(*PositionComponents[2]));
1400
1401 // Parse bounds
1402 TArray<FString> BoundsComponents;
1403 ParsedStrings[1].ParseIntoArray(BoundsComponents, TEXT(","), true);
1404
1405 if (BoundsComponents.Num() != 3)
1406 {
1407 return;
1408 }
1409
1410 FVector Bounds(FCString::Atof(*BoundsComponents[0]), FCString::Atof(*BoundsComponents[1]), FCString::Atof(*BoundsComponents[2]));
1411
1412 FTransform VolumeTransform;
1413 VolumeTransform.SetLocation(Position);
1414
1415 UWorld* World = GetGameWorld();
1416 if (World)
1417 {
1418 ADeletionVolume* Volume = World->SpawnActor<ADeletionVolume>(ADeletionVolume::StaticClass(), VolumeTransform);
1419 if (Volume)
1420 {
1421 // Change volume bounds
1422 Volume->ChangeOverlapBounds(Bounds);
1423
1424 // Destroy overlapping actors,
1425 // this Actor gets deleted automatically after calling this.
1426 Volume->DestroyOverlappingActors(OnlyTrees);
1427 }
1428 }
1429}
1430
1432{
1433 TArray<FString> Tokens;
1434 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1435
1436 if (Tokens.Num() < 2)
1437 {
1438 return;
1439 }
1440
1441 const FString& ID = Tokens[0];
1442 const FString Param = Variable.RightChop(ID.Len() + 1);
1443
1444 bool bVisible = true;
1445 if (!TryParseBoolean(Param, bVisible))
1446 {
1447 return; // Invalid parameter
1448 }
1449
1450 if (AActor* Actor = IActorInformation::GetActorByID(ID))
1451 {
1452 if (AVehicle* Vehicle = Cast<AVehicle>(Actor))
1453 {
1454 Vehicle->SetVehicleMeshVisibility(bVisible);
1455 }
1456 }
1457}
EDroneEndAction
EROSState
Definition: ROSState.h:16
EWalkerEndAction
void DestroyOverlappingActors(bool OnlyTrees)
void ChangeOverlapBounds(FVector Bounds)
void SetSaveCombinedCloudToDisk(bool bSaveCombinedCloud)
void SetOverlapRelativePosition(const FVector &Vector)
void SetVisualizeOverlapArea(bool Visualize)
void SetOverlapBounds(const FVector &NewSize)
Definition: Sensor.h:45
void SetSimulateSensor(bool SimulateSensor)
Definition: Sensor.h:160
FString ExportToJsonFile(const FString &FileName)
Definition: Sensor.cpp:147
void TeleportSpectator(const FTransform &Transform)
Definition: Spectator.cpp:68
Definition: Tagger.h:51
AActor * GetActorByInstanceID(float InstanceID)
Definition: Tagger.cpp:219
FString ExportToJsonFile(const FString &FileName)
Definition: Vehicle.cpp:234
void TogglePhysics(bool isOn)
Definition: Walker.h:30
FString ExportToJSON(const FString &FileName)
Definition: Weather.cpp:121
static void PrintAllIds()
static bool DestroyActorByID(const FString &ID)
static AActor * GetActorByID(const FString &ID)
static void Log(const FString &Message, bool LogToTextFile=true, bool LogToROS=true)
void SetQualityLevelFromString(const FString &QualityLevelString)
void AdvanceTime(float TimeToAdvance)
void ChangeMapByName(FString MapName)
void AdvanceFrameCount(int32 FramesToAdvance)
TArray< FString > GetMapNames() const
void SetGlobalTimeDilation(float TimeDilation)
void SetGlobalTargetFrameRate(int NewTargetFrameRate)
void SetGrassVisibility(bool Visible)
void SetWorldPositionOffsetRenderDistance(int32 WorldPositionOffsetDistance)
void SetWorldRendering(bool enabled)
void SetNaniteMaxPixelsPerEdge(float MaxPixelsPerEdge=1.0f)
static ASpectator * GetSpectator(const UObject *WorldContextObject)
static UAgrarsenseSettings * GetAgrarsenseSettings()
static AWeather * GetWeatherActor(const UObject *WorldContextObject)
static UROSIntegrationGameInstance * GetROSGameInstance(const UObject *WorldContextObject)
static ALidarManager * GetLidarManager(const UObject *WorldContextObject)
static UROSHandler * GetROSHandle(const UObject *WorldContextObject)
static TArray< AInstancedActor * > GetAllAddedPropActors()
static void DestroyAllWalkers()
static TArray< FVehicleData > GetSpawnedVehicles()
static TArray< AInstancedActor * > GetAllAddedFoliageActors()
static TArray< AWalker * > GetAllWalkers()
static bool AlignTransformFromGroundInMeters(AActor *Actor, FTransform &InTransform)
void HandleTeleportActorByID(const FString &Variable)
void HandleUnrealCommand(const FString &Variable)
void HandleSetGrassVisibility(const FString &Variable)
void HandleChangeOverlapSensorBounds(const FString &Variable)
void HandlePrintAllWalkers(const FString &Variable)
void HandleTeleportSpectator(const FString &Variable)
void HandlePrintAllVehicles(const FString &Variable)
void HandlePrintAllSensors(const FString &Variable)
UROSIntegrationGameInstance * RosInstance
Definition: ROSCommands.h:106
void HandleDestroyActorsArea(const FString &Variable)
void HandleSetWalkerMovement(const FString &Variable, bool IsPaused)
void HandleSetSpectatorOverlapRadius(const FString &Variable)
static TMap< FString, FCommand > CommandHandlers
Definition: ROSCommands.h:74
void HandleAdvanceOneFrame(const FString &Variable)
void HandleUnPauseSimulator(const FString &Variable)
bool TryParseBoolean(const FString &String, bool &OutBool) const
void HandlePrintAvailableCommands(const FString &Variable)
void PrintActorInformation(const FString &Variable, UClass *ActorClass, const FString &ActorTypeName)
void HandleAdvanceTime(const FString &Variable)
void HandleExportAll(const FString &Variable)
void HandleExportSensors(const FString &Variable)
void HandleExportVehicles(const FString &Variable)
void HandleSetSaveCombinedPointcloudToDisk(const FString &Variable)
void HandleTeleportActorByIDHeight(const FString &Variable)
void HandleDisableAllSensors(const FString &Variable)
void HandleSetWPO(const FString &Variable)
void DestroyROSTopic()
void HandleTeleportSpectatorByInstanceID(const FString &Variable)
void HandleChangeMap(const FString &Variable)
void HandleExportWalkers(const FString &Variable)
void HandleResumeWalker(const FString &Variable)
UAgrarsenseSettings * GetSettings()
Definition: ROSCommands.cpp:79
void HandleTeleportSpectatorHeight(const FString &Variable)
void AddCommands()
Definition: ROSCommands.cpp:84
void HandleMoveDroneTo(const FString &Variable, EDroneEndAction EndAction)
void HandleSetWorldRendering(const FString &Variable)
void HandleSetGlobalTimeDilation(const FString &Variable)
void HandleDestroyAllSensors(const FString &Variable)
void ParseIncomingMessage(const FString Message)
void SetupROSCommandTopic()
void HandleMoveWalkerToAndStop(const FString &Variable)
void HandleExportWeather(const FString &Variable)
void HandleExportFoliage(const FString &Variable)
void HandleQuit(const FString &Variable)
void HandleSetAllSensorsEnabled(const FString &Variable)
void HandleVehicleMeshVisibility(const FString &Variable)
void HandleChangeOverlapSensorPosition(const FString &Variable)
void HandleSetSensorEnabled(const FString &Variable)
void HandleTryDestroyObjectByID(const FString &Variable)
UWorld * GetGameWorld()
Definition: ROSCommands.cpp:69
void HandleVisualizeOverlapSensorsBounds(const FString &Variable)
void HandleEnableAllSensors(const FString &Variable)
void HandleMoveWalkerTo(const FString &Variable, EWalkerEndAction EndAction)
void HandleDestroyAllVehicles(const FString &Variable)
void HandleStopWalker(const FString &Variable)
void HandleDestroyObjectByInstanceID(const FString &Variable)
void HandleDestroyActors(const FString &Variable, bool OnlyTrees)
void HandleMoveDroneToAndStop(const FString &Variable)
void HandleDestroyAllWalkers(const FString &Variable)
void HandleMoveWalkerToAndDestroy(const FString &Variable)
void HandleSetNaniteMaxPixelsPerEdge(const FString &Variable)
void HandlePrintMaps(const FString &Variable)
void HandleSpawnObjects(const FString &Variable)
UTopic * CommandTopic
Definition: ROSCommands.h:103
void HandleDestroyTreesArea(const FString &Variable)
bool TeleportSpectatorHeight
Definition: ROSCommands.h:110
void HandleSetGlobalTargetFrameRate(const FString &Variable)
void HandlePrintIds(const FString &Variable)
void HandleAdvanceFrames(const FString &Variable)
void HandleSetQualityLevel(const FString &Variable)
void HandlePauseSimulator(const FString &Variable)
void Destroy()
Definition: ROSCommands.cpp:59
void TryExecuteCommand(const FString &Command)
Definition: ROSCommands.cpp:64
void HandleExportObjects(const FString &Variable)
void HandleExportProps(const FString &Variable)
void ROSBridgeStateChanged(EROSState state)
FROSDelegate_ROState OnROSStateChanged
Definition: ROSHandler.h:81
static void DestroyAllSensors(const UObject *WorldContextObject, bool DestroyDefaultVehicleSensors=false)
static void EnableAllSensors(const UObject *WorldContextObject)
static void DisableAllSensors(const UObject *WorldContextObject)
static FString ExportInstancedActorsToJSON(FString FileName, const TArray< AInstancedActor * > &Actors)
static void ParseAndOperateJSONFile(const FString &Path)
double LastExecutionTime
Definition: ROSCommands.h:34
FString DefaultValue
Definition: ROSCommands.h:35
float CooldownTime
Definition: ROSCommands.h:33
CommandHandler Handler
Definition: ROSCommands.h:32
EDroneEndAction DroneEndAction
EDroneAction DroneAction
EWalkerAction WalkerAction
TArray< FTransform > Points
EWalkerEndAction WalkerEndAction