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("setvehiclemeshvisibility"), FCommand(&UROSCommands::HandleVehicleMeshVisibility, 0.05f, TEXT("ID true/false")));
188
189 // Drone commands
190 CommandHandlers.Add(TEXT("movedroneto"), FCommand(&UROSCommands::HandleMoveDroneToAndStop, 0.05f, TEXT("ID (position)")));
191 CommandHandlers.Add(TEXT("resetdrone"), FCommand(&UROSCommands::HandleResetDrone, 0.15f, TEXT("Drone ID")));
192}
193
195{
196 switch (state)
197 {
200 break;
201
204 break;
205 }
206}
207
209{
210 if (CommandTopic)
211 {
212 CommandTopic->Unadvertise();
213 CommandTopic->Unsubscribe();
214 CommandTopic->MarkAsDisconnected();
215 CommandTopic->ConditionalBeginDestroy();
216 CommandTopic = nullptr;
217 }
218}
219
221{
222 UWorld* World = GetGameWorld();
223 if (!World)
224 {
225 return;
226 }
227
229 if (!CommandTopic && RosInstance && RosInstance->IsROSConnected())
230 {
231 CommandTopic = NewObject<UTopic>(UTopic::StaticClass());
232 CommandTopic->Init(RosInstance->ROSIntegrationCore, TEXT("/agrarsense/in/commands"), TEXT("std_msgs/String"));
233 CommandTopic->Advertise();
234
235 // Create a std::function callback object
236 std::function<void(TSharedPtr<FROSBaseMsg>)> SubscribeCallback = [this](TSharedPtr<FROSBaseMsg> msg) -> void
237 {
238 auto Concrete = StaticCastSharedPtr<ROSMessages::std_msgs::String>(msg);
239 if (Concrete.IsValid())
240 {
241 FString message = *(Concrete->_Data);
242 AsyncTask(ENamedThreads::GameThread, [this, message]()
243 {
244 // Parse message on GameThread since many commands are NOT thread-safe
245 ParseIncomingMessage(message);
246 });
247 }
248 return;
249 };
250
251 // Subscribe to the topic
252 CommandTopic->Subscribe(SubscribeCallback);
253 }
254}
255
256void UROSCommands::ParseIncomingMessage(const FString Message)
257{
258 // Parse incoming string message into {COMMAND} {VARIABLE} format
259 int32 SpaceIndex;
260 FString Command;
261 FString Variable;
262
263 if (Message.FindChar(' ', SpaceIndex))
264 {
265 // Extract the command as the substring before the first space
266 Command = Message.Left(SpaceIndex).ToLower();
267
268 // Extract the rest of the message as the variable
269 Variable = Message.Mid(SpaceIndex + 1);
270 }
271 else
272 {
273 // If no space is found, consider the entire message as the command
274 Command = Message.ToLower();
275 }
276
277 // Log incoming message into text file for debugging purposes
278 FString CommandMsg = FString::Printf(TEXT("Incoming [command variable]: %s %s"), *Command, *Variable);
279 SimulatorLog::Log(CommandMsg);
280
281 FCommand* CommandInfo = CommandHandlers.Find(Command);
282 if (CommandInfo)
283 {
284 // Check if enough time has passed since the last execution.
285 double CurrentTime = FPlatformTime::Seconds();
286 double TimeSinceLastExecution = CurrentTime - CommandInfo->LastExecutionTime;
287
288 if (TimeSinceLastExecution >= CommandInfo->CooldownTime)
289 {
290 // Call the handler function with the variable.
291 (this->*(CommandInfo->Handler))(Variable);
292
293 // Update the last execution time.
294 CommandInfo->LastExecutionTime = CurrentTime;
295 }
296 else
297 {
298 float CoolDownTimeLeft = CommandInfo->CooldownTime - TimeSinceLastExecution;
299 FString Msg = FString::Printf(TEXT("Command '%s' on cooldown. Retry in %.2f sec."), *Command, CoolDownTimeLeft);
301 }
302 }
303 else
304 {
305 FString Msg = FString::Printf(TEXT("Couldn't find command: '%s'"), *Command);
307 }
308}
309
310bool UROSCommands::TryParseBoolean(const FString& String, bool& OutBool) const
311{
312 FString LoweredString = String.ToLower();
313
314 if (LoweredString.Equals("true") || LoweredString.Equals("1"))
315 {
316 OutBool = true;
317 return true;
318 }
319 else if (LoweredString.Equals("false") || LoweredString.Equals("0"))
320 {
321 OutBool = false;
322 return true;
323 }
324
325 // Invalid boolean value
326 return false;
327}
328
330{
331 if (!CommandTopic)
332 {
333 return;
334 }
335
336 FString message = "Available Simulator ROS commands {COMMAND} {VALUE} || ";
337
338 for (const TPair<FString, FCommand>& CommandPair : CommandHandlers)
339 {
340 const FString& CommandString = CommandPair.Key;
341 const FCommand& CommandInfo = CommandPair.Value;
342 if (CommandInfo.DefaultValue.IsEmpty())
343 {
344 message += FString::Printf(TEXT("%s || "), *CommandString);
345 }
346 else
347 {
348 message += FString::Printf(TEXT("%s %s || "), *CommandString, *CommandInfo.DefaultValue);
349 }
350 }
351
352 SimulatorLog::Log(message);
353}
354
355void UROSCommands::HandleQuit(const FString& Variable)
356{
357 UWorld* World = GetGameWorld();
358 if (GEngine && World)
359 {
360 GEngine->Exec(World, TEXT("quit force"));
361 }
362}
363
364void UROSCommands::HandlePauseSimulator(const FString& Variable)
365{
366 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
367 if (AgrarsenseSettings)
368 {
369 AgrarsenseSettings->PauseSimulationEndOfThisFrame();
370 }
371}
372
373void UROSCommands::HandleUnPauseSimulator(const FString& Variable)
374{
375 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
376 if (AgrarsenseSettings)
377 {
378 AgrarsenseSettings->UnPauseSimulation();
379 }
380}
381
382void UROSCommands::HandleAdvanceOneFrame(const FString& Variable)
383{
384 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
385 if (AgrarsenseSettings)
386 {
387 AgrarsenseSettings->AdvanceFrameCount(1);
388 }
389}
390
391void UROSCommands::HandleAdvanceFrames(const FString& Variable)
392{
393 int32 FrameCount = 0;
394 if (!Variable.IsNumeric())
395 {
396 return;
397 }
398
399 FrameCount = FCString::Atoi(*Variable);
400 if (FrameCount != 0)
401 {
402 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
403 if (AgrarsenseSettings)
404 {
405 AgrarsenseSettings->AdvanceFrameCount(FrameCount);
406 }
407 }
408}
409
410void UROSCommands::HandleAdvanceTime(const FString& Variable)
411{
412 float Time = 0.0f;
413 if (!Variable.IsNumeric())
414 {
415 return;
416 }
417
418 Time = FCString::Atof(*Variable);
419 if (Time != 0.0f)
420 {
421 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
422 if (AgrarsenseSettings)
423 {
424 AgrarsenseSettings->AdvanceTime(Time);
425 }
426 }
427}
428
429void UROSCommands::HandleChangeMap(const FString& Variable)
430{
431 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
432 if (AgrarsenseSettings)
433 {
434 AgrarsenseSettings->ChangeMapByName(Variable);
435 }
436}
437
438void UROSCommands::HandleUnrealCommand(const FString& Variable)
439{
440 UWorld* World = GetGameWorld();
441 if (GEngine && World)
442 {
443 GEngine->Exec(World, *Variable);
444 }
445}
446
448{
449 if (!Variable.IsNumeric())
450 {
451 return;
452 }
453
454 float Radius = FCString::Atof(*Variable);
455
456 if (UWorld* World = GetGameWorld())
457 {
458 if (ASpectator* Spectator = UAgrarsenseStatics::GetSpectator(World))
459 {
460 if (AOverlapSensor* OverlapSensor = Spectator->GetOverlapSensor())
461 {
462 OverlapSensor->SetOverlapBounds(FVector(Radius, Radius, Radius));
463 }
464 }
465 }
466}
467
469{
471 HandleTeleportSpectator(Variable);
473}
474
475void UROSCommands::HandleTeleportSpectator(const FString& Variable)
476{
477 // Split the comma-separated string into components
478 TArray<FString> Components;
479 Variable.ParseIntoArray(Components, TEXT(","), true);
480
481 if (Components.Num() >= 3)
482 {
483 FVector Location;
484 FQuat Rotation;
485
486 // Convert the first three components to float values for location
487 float X = FCString::Atof(*Components[0]);
488 float Y = FCString::Atof(*Components[1]);
489 float Z = FCString::Atof(*Components[2]);
490
491 Location = FVector(X, Y, Z);
492
493 if (Components.Num() >= 6)
494 {
495 // If there are six or more components, try to parse them as rotation values
496 float Pitch = FCString::Atof(*Components[3]);
497 float Yaw = FCString::Atof(*Components[4]);
498 float Roll = FCString::Atof(*Components[5]);
499
500 // Convert the Euler angles to a quaternion
501 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
502 }
503
504 UWorld* World = GetGameWorld();
505 if (World)
506 {
508 if (Spectator)
509 {
510 FTransform Transform;
511 Transform.SetLocation(Location);
512 Transform.SetRotation(Rotation);
513
514
516 {
518 }
519
520 Spectator->TeleportSpectator(Transform);
521 }
522 }
523 }
524}
525
527{
528 InMeters = true;
529 HandleTeleportActorByID(Variable);
530 InMeters = false;
531}
532
534{
535 if (!Variable.IsNumeric())
536 {
537 return;
538 }
539
540 TArray<AActor*> Taggers;
541 UGameplayStatics::GetAllActorsOfClass(GetGameWorld(), ATagger::StaticClass(), Taggers);
542 ATagger* Tagger = Cast<ATagger>(Taggers[0]);
543
544 if (Tagger)
545 {
546 AActor* Actor = Tagger->GetActorByInstanceID(FCString::Atof(*Variable));
547 if (Actor)
548 {
550 {
551 Spectator->TeleportSpectator(Actor->GetActorTransform());
552 }
553 }
554 }
555}
556
557void UROSCommands::HandleTeleportActorByID(const FString& Variable)
558{
559 FString ID;
560 FString TransformString;
561
562 // Split the ID and rest of the message
563 TArray<FString> Tokens;
564 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
565 if (Tokens.Num() >= 2)
566 {
567 ID = Tokens[0];
568 TransformString = Variable.RightChop(ID.Len() + 1);
569 }
570 else
571 {
572 SimulatorLog::Log("Invalid input. Input should be in format: ID,X,Y,Z or ID,X,Y,Z,YAW,PITCH,ROLL");
573 return;
574 }
575
576 // Check if this ID matches any Actor
577 AActor* Actor = IActorInformation::GetActorByID(ID);
578 if (!Actor)
579 {
580 FString log = FString::Printf(TEXT("Could not find Actor with ID: %s"), *ID);
582 return;
583 }
584
585 // Parse rest of the string to Transform
586 TArray<FString> Components;
587 TransformString.ParseIntoArray(Components, TEXT(","), true);
588
589 if (Components.Num() >= 3)
590 {
591 FVector Location;
592 FQuat Rotation;
593
594 // Convert the first three components to float values for location
595 float X = FCString::Atof(*Components[0]);
596 float Y = FCString::Atof(*Components[1]);
597 float Z = FCString::Atof(*Components[2]);
598
599 Location = FVector(X, Y, Z);
600
601 if (Components.Num() >= 6)
602 {
603 // If there are six or more components, try to parse them as rotation values
604 float Pitch = FCString::Atof(*Components[3]);
605 float Yaw = FCString::Atof(*Components[4]);
606 float Roll = FCString::Atof(*Components[5]);
607
608 // Convert the Euler angles to a quaternion
609 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
610 }
611
612 FTransform Transform;
613 Transform.SetLocation(Location);
614 Transform.SetRotation(Rotation);
615
616 if (InMeters)
617 {
619 }
620
621#if WITH_EDITOR
622 UE_LOG(LogTemp, Warning, TEXT("Teleporting Actor with ID: %s to: %s"), *ID, *TransformString);
623#endif
624
625 // Check if this Actor is Vehicle
626 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
627 if (VehiclePtr)
628 {
629 // Disable vehicle physics so it can be teleported
630 VehiclePtr->TogglePhysics(false);
631
632 Actor->SetActorTransform(Transform);
633
634 // Enable vehicle physics back on after teleporting vehicle
635 VehiclePtr->TogglePhysics(true);
636 }
637 else
638 {
639 // Else set the Actor transform
640 Actor->SetActorTransform(Transform);
641 }
642 }
643}
644
645void UROSCommands::HandleTryDestroyObjectByID(const FString& Variable)
646{
647 bool success = IActorInformation::DestroyActorByID(Variable);
648
649 FString Message;
650 if (success)
651 {
652 Message = FString::Printf(TEXT("Object with ID %s successfully destroyed."), *Variable);
653 }
654 else
655 {
656 Message = FString::Printf(TEXT("Failed to destroy object with ID %s."), *Variable);
657 }
658
659 SimulatorLog::Log(Message);
660}
661
662void UROSCommands::HandleDestroyAllSensors(const FString& Variable)
663{
665}
666
667void UROSCommands::HandleDestroyAllWalkers(const FString& Variable)
668{
670}
671
672void UROSCommands::HandleDestroyAllVehicles(const FString& Variable)
673{
674 UWorld* World = GetGameWorld();
675 if (!World)
676 {
677 return;
678 }
679
680 TArray<AActor*> Vehicles;
681 UGameplayStatics::GetAllActorsOfClass(World, AVehicle::StaticClass(), Vehicles);
682 for (AActor* Actor : Vehicles)
683 {
684 AVehicle* Vehicle = Cast<AVehicle>(Actor);
685 if (Vehicle)
686 {
687 Vehicle->Destroy();
688 }
689 }
690}
691
693{
694 if (!Variable.IsNumeric())
695 {
696 return;
697 }
698
699 TArray<AActor*> Taggers;
700 UGameplayStatics::GetAllActorsOfClass(GetGameWorld(), ATagger::StaticClass(), Taggers);
701 ATagger* Tagger = Cast<ATagger>(Taggers[0]);
702
703 if (Tagger)
704 {
705 AActor* Actor = Tagger->GetActorByInstanceID(FCString::Atof(*Variable));
706 if (Actor)
707 {
708 Actor->Destroy();
709 }
710 }
711}
712
713void UROSCommands::HandlePrintMaps(const FString& Variable)
714{
715 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
716 if (AgrarsenseSettings)
717 {
718 TArray<FString> Maps = AgrarsenseSettings->GetMapNames();
719
720 FString message;
721
722 for (const FString& map : Maps)
723 {
724 message += FString::Printf(TEXT("%s, "), *map);
725 }
726
727 SimulatorLog::Log(message);
728 }
729}
730
731void UROSCommands::HandlePrintAllSensors(const FString& Variable)
732{
733 PrintActorInformation(Variable, ASensor::StaticClass(), "sensor");
734}
735
736void UROSCommands::HandlePrintAllVehicles(const FString& Variable)
737{
738 PrintActorInformation(Variable, AVehicle::StaticClass(), "vehicle");
739}
740
741void UROSCommands::HandlePrintAllWalkers(const FString& Variable)
742{
743 PrintActorInformation(Variable, AWalker::StaticClass(), "walker");
744}
745
746void UROSCommands::PrintActorInformation(const FString& Variable, UClass* ActorClass, const FString& ActorTypeName)
747{
748 TArray<AActor*> Actors;
749 UGameplayStatics::GetAllActorsWithInterface(GetGameWorld(), UActorInformation::StaticClass(), Actors);
750
751 TArray<AActor*> TypedActors;
752 for (AActor* Actor : Actors)
753 {
754 if (Actor->IsA(ActorClass))
755 {
756 TypedActors.Add(Actor);
757 }
758 }
759
760 FString Msg;
761 if (!TypedActors.IsEmpty())
762 {
763 Msg = FString::Printf(TEXT("Simulation has %d %ss \n "), TypedActors.Num(), *ActorTypeName);
764 for (AActor* Actor : TypedActors)
765 {
766 if (Actor)
767 {
768 if (Actor->Implements<UActorInformation>())
769 {
770 FString ActorInfo = IActorInformation::Execute_GetActorInformation(Actor);
771 Msg += FString::Printf(TEXT("%s \n \n "), *ActorInfo);
772 }
773
774 }
775 }
776 }
777 else
778 {
779 Msg = FString::Printf(TEXT("Simulation has 0 %ss."), *ActorTypeName);
780 }
781
783}
784
785void UROSCommands::HandlePrintIds(const FString& Variable)
786{
788}
789
791{
792 if (Variable.IsNumeric())
793 {
794 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
795 if (AgrarsenseSettings)
796 {
797 int32 IntValue = FCString::Atoi(*Variable);
798 AgrarsenseSettings->SetGlobalTargetFrameRate(IntValue);
799 }
800 }
801}
802
803void UROSCommands::HandleSetGlobalTimeDilation(const FString& Variable)
804{
805 if (Variable.IsNumeric())
806 {
807 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
808 if (AgrarsenseSettings)
809 {
810 float FloatValue = FCString::Atof(*Variable);
811 AgrarsenseSettings->SetGlobalTimeDilation(FloatValue);
812 }
813 }
814}
815
816void UROSCommands::HandleSetQualityLevel(const FString& Variable)
817{
818 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
819 if (AgrarsenseSettings)
820 {
821 AgrarsenseSettings->SetQualityLevelFromString(Variable);
822 }
823}
824
825void UROSCommands::HandleSetWorldRendering(const FString& Variable)
826{
827 bool RenderWorld;
828 if (!TryParseBoolean(Variable, RenderWorld))
829 {
830 // Failed to parse, return
831 return;
832 }
833
834 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
835 if (AgrarsenseSettings)
836 {
837 AgrarsenseSettings->SetWorldRendering(RenderWorld);
838 }
839}
840
841void UROSCommands::HandleSetGrassVisibility(const FString& Variable)
842{
843 bool RenderGrass;
844 if (!TryParseBoolean(Variable, RenderGrass))
845 {
846 // Failed to parse, return
847 return;
848 }
849
850 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
851 if (AgrarsenseSettings)
852 {
853 AgrarsenseSettings->SetGrassVisibility(RenderGrass);
854 }
855}
856
858{
859 bool Save;
860 if (!TryParseBoolean(Variable, Save))
861 {
862 // Failed to parse, return
863 return;
864 }
865
867 if (LidarManager)
868 {
869 LidarManager->SetSaveCombinedCloudToDisk(Save);
870 }
871}
872
873void UROSCommands::HandleSpawnObjects(const FString& Variable)
874{
876}
877
878void UROSCommands::HandleExportAll(const FString& Variable)
879{
880 // Below export functions do not need any incoming variable but require FString
881 FString EmptyString;
882
883 HandleExportWeather(EmptyString);
884 HandleExportWalkers(EmptyString);
885
886 // HandleExportSensors exports vehicles as well
887 //HandleExportVehicles(EmptyString);
888 HandleExportSensors(EmptyString);
889
890 HandleExportFoliage(EmptyString);
891 HandleExportProps(EmptyString);
892}
893
894void UROSCommands::HandleExportWeather(const FString& Variable)
895{
897 if (Weather)
898 {
899 Weather->ExportToJSON("ExportedWeather");
900 }
901}
902
903void UROSCommands::HandleExportWalkers(const FString& Variable)
904{
905 TArray<AWalker*> Walkers = UAssetLibrary::GetAllWalkers();
906 for (AWalker* Walker : Walkers)
907 {
908 if (Walker)
909 {
910 Walker->ExportToJsonFile("ExportedWalker");
911 }
912 }
913}
914
915void UROSCommands::HandleExportVehicles(const FString& Variable)
916{
917 TArray<FVehicleData> Vehicles = UAssetLibrary::GetSpawnedVehicles();
918 for (const FVehicleData& VehicleData : Vehicles)
919 {
920 AVehicle* VehiclePtr = VehicleData.Vehicle.Get();
921 if (VehiclePtr)
922 {
923 VehiclePtr->ExportToJsonFile("ExportedVehicle");
924 }
925 }
926}
927
928void UROSCommands::HandleExportSensors(const FString& Variable)
929{
930 UWorld* World = GetGameWorld();
931 if (!World)
932 {
933 return;
934 }
935
936 // Export all Vehicles and attached sensors
937 TArray<AActor*> Vehicles;
938 UGameplayStatics::GetAllActorsOfClass(World, AVehicle::StaticClass(), Vehicles);
939 for (AActor* Actor : Vehicles)
940 {
941 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
942 if (VehiclePtr)
943 {
944 VehiclePtr->ExportToJsonFile("ExportedVehicle");
945 }
946 }
947
948 // Export all Sensors separately as well
949 TArray<AActor*> Sensors;
950 UGameplayStatics::GetAllActorsOfClass(World, ASensor::StaticClass(), Sensors);
951 for (AActor* Actor : Sensors)
952 {
953 ASensor* SensorPtr = Cast<ASensor>(Actor);
954 if (SensorPtr)
955 {
956 SensorPtr->ExportToJsonFile("ExportedSensor");
957 }
958 }
959}
960
961void UROSCommands::HandleExportFoliage(const FString& Variable)
962{
963 TArray<AInstancedActor*> FoliageActors = UAssetLibrary::GetAllAddedFoliageActors();
964 USimulatorJsonExporter::ExportInstancedActorsToJSON("ExportedFoliage", FoliageActors);
965}
966
967void UROSCommands::HandleExportObjects(const FString& Variable)
968{
969 UWorld* World = GetGameWorld();
970 if (!World)
971 {
972 return;
973 }
974
975 TArray<AActor*> Taggers;
976 UGameplayStatics::GetAllActorsOfClass(World, ATagger::StaticClass(), Taggers);
977
978 if (ATagger* Tagger = Cast<ATagger>(Taggers[0]))
979 {
980 Tagger->ExportObjectLocationsToCSV();
981 }
982}
983
984void UROSCommands::HandleExportProps(const FString& Variable)
985{
986 TArray<AInstancedActor*> PropActors = UAssetLibrary::GetAllAddedPropActors();
987 USimulatorJsonExporter::ExportInstancedActorsToJSON("ExportedProps", PropActors);
988}
989
991{
992 bool Visualize;
993 if (!TryParseBoolean(Variable, Visualize))
994 {
995 // Failed to parse, return
996 return;
997 }
998
999 UWorld* World = GetGameWorld();
1000 if (World)
1001 {
1002 TArray<AActor*> OverlapSensors;
1003 UGameplayStatics::GetAllActorsOfClass(World, AOverlapSensor::StaticClass(), OverlapSensors);
1004
1005 for (AActor* SensorActor : OverlapSensors)
1006 {
1007 AOverlapSensor* Sensor = Cast<AOverlapSensor>(SensorActor);
1008 if (Sensor)
1009 {
1010 Sensor->SetVisualizeOverlapArea(Visualize);
1011 }
1012 }
1013 }
1014}
1015
1017{
1018 FString ID;
1019 FString BoundsString;
1020
1021 TArray<FString> Tokens;
1022 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1023
1024 if (Tokens.Num() < 2)
1025 {
1026 // Incoming parameters were invalid, return
1027 return;
1028 }
1029
1030 ID = Tokens[0];
1031 BoundsString = Tokens[1];
1032
1033 if (BoundsString.IsNumeric())
1034 {
1035 float Radius = FCString::Atof(*BoundsString);
1036
1037 AActor* Actor = IActorInformation::GetActorByID(ID);
1038 AOverlapSensor* Sensor = Cast<AOverlapSensor>(Actor);
1039 if (Sensor)
1040 {
1041 Sensor->SetOverlapBounds(FVector(Radius, Radius, Radius));
1042 }
1043 }
1044}
1045
1047{
1048 FString ID;
1049 FString BoundsString;
1050
1051 TArray<FString> Tokens;
1052 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1053
1054 if (Tokens.Num() < 2)
1055 {
1056 // Incoming parameters were invalid, return
1057 return;
1058 }
1059
1060 ID = Tokens[0];
1061 BoundsString = Tokens[1];
1062
1063 FVector RelativePosition;
1064 TArray<FString> BoundsTokens;
1065 BoundsString.ParseIntoArray(BoundsTokens, TEXT(","), true);
1066
1067 if (BoundsTokens.Num() >= 3)
1068 {
1069 RelativePosition.X = FCString::Atof(*BoundsTokens[0]);
1070 RelativePosition.Y = FCString::Atof(*BoundsTokens[1]);
1071 RelativePosition.Z = FCString::Atof(*BoundsTokens[2]);
1072
1073 AActor* Actor = IActorInformation::GetActorByID(ID);
1074 AOverlapSensor* Sensor = Cast<AOverlapSensor>(Actor);
1075 if (Sensor)
1076 {
1077 Sensor->SetOverlapRelativePosition(RelativePosition);
1078 }
1079 }
1080}
1081
1083{
1085}
1086
1087void UROSCommands::HandleMoveWalkerToAndStop(const FString& Variable)
1088{
1090}
1091
1092void UROSCommands::HandleMoveDroneToAndStop(const FString& Variable)
1093{
1095}
1096
1097void UROSCommands::HandleMoveWalkerTo(const FString& Variable, EWalkerEndAction EndAction)
1098{
1099 // This function overrides the current parameters of the Walker identified by the given ID,
1100 // moving the Walker to the specified x,y,z position and stopping upon reaching the target.
1101 // Usage: "movewalkerto reindeer 0,0,0" where 'reindeer' is the Walker ID.
1102
1103 FString ID;
1104 FString TransformString;
1105
1106 // Split the ID and rest of the message
1107 TArray<FString> Tokens;
1108 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1109 if (Tokens.Num() >= 2)
1110 {
1111 ID = Tokens[0];
1112 TransformString = Variable.RightChop(ID.Len() + 1);
1113 }
1114 else
1115 {
1116 return;
1117 }
1118
1119 // Check if this ID matches any Actor
1120 AActor* Actor = IActorInformation::GetActorByID(ID);
1121 if (!Actor)
1122 {
1123 return;
1124 }
1125
1126 AWalker* Walker = Cast<AWalker>(Actor);
1127 if (!Walker)
1128 {
1129 return;
1130 }
1131
1132 // Parse rest of the string to Transform
1133 TArray<FString> Components;
1134 TransformString.ParseIntoArray(Components, TEXT(","), true);
1135
1136 if (Components.Num() >= 3)
1137 {
1138 FVector Location;
1139 FQuat Rotation;
1140
1141 // Convert the first three components to float values for location
1142 float X = FCString::Atof(*Components[0]);
1143 float Y = FCString::Atof(*Components[1]);
1144 float Z = FCString::Atof(*Components[2]);
1145
1146 Location = FVector(X, Y, Z);
1147
1148 if (Components.Num() >= 6)
1149 {
1150 // If there are six or more components, try to parse them as rotation values
1151 float Pitch = FCString::Atof(*Components[3]);
1152 float Yaw = FCString::Atof(*Components[4]);
1153 float Roll = FCString::Atof(*Components[5]);
1154
1155 // Convert the Euler angles to a quaternion
1156 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
1157 }
1158
1159 FTransform Transform;
1160 Transform.SetLocation(Location);
1161 Transform.SetRotation(Rotation);
1162
1163 // Create new walker parameters
1164 FWalkerParameters NewParams;
1166 NewParams.WalkerEndAction = EndAction;
1167 NewParams.Points.Add(Transform);
1168
1169 // Change Walker parameters
1170 Walker->ChangeWalkerParameters(NewParams);
1171 }
1172}
1173
1174void UROSCommands::HandleStopWalker(const FString& Variable)
1175{
1176 HandleSetWalkerMovement(Variable, true);
1177}
1178
1179void UROSCommands::HandleResumeWalker(const FString& Variable)
1180{
1181 HandleSetWalkerMovement(Variable, false);
1182}
1183
1184void UROSCommands::HandleSetWalkerMovement(const FString& Variable, bool IsPaused)
1185{
1186 AActor* Actor = IActorInformation::GetActorByID(Variable);
1187 AWalker* Walker = Cast<AWalker>(Actor);
1188 if (!Walker)
1189 {
1190 return;
1191 }
1192
1193 if (IsPaused)
1194 {
1195 Walker->PauseWalker();
1196 }
1197 else
1198 {
1199 Walker->ResumeWalker();
1200 }
1201}
1202
1203void UROSCommands::HandleResetDrone(const FString& Variable)
1204{
1205 AActor* Actor = IActorInformation::GetActorByID(Variable);
1206 if (Actor)
1207 {
1208 APIDDrone* Drone = Cast<APIDDrone>(Actor);
1209 if (Drone)
1210 {
1211 Drone->ResetDroneEvent();
1212 }
1213 }
1214}
1215
1216void UROSCommands::HandleMoveDroneTo(const FString& Variable, EDroneEndAction EndAction)
1217{
1218 // This function overrides the current parameters of the Drone identified by the given ID,
1219 // moving the Drone to the specified x,y,z position and stopping upon reaching the target.
1220 // Usage: "movedroneto drone 0,0,0" where 'drone' is the Drone ID.
1221
1222 FString ID;
1223 FString TransformString;
1224
1225 // Split the ID and rest of the message
1226 TArray<FString> Tokens;
1227 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1228 if (Tokens.Num() >= 2)
1229 {
1230 ID = Tokens[0];
1231 TransformString = Variable.RightChop(ID.Len() + 1);
1232 }
1233 else
1234 {
1235 return;
1236 }
1237
1238 // Check if this ID matches any Actor
1239 AActor* Actor = IActorInformation::GetActorByID(ID);
1240 if (!Actor)
1241 {
1242 return;
1243 }
1244
1245 APIDDrone* Drone = Cast<APIDDrone>(Actor);
1246 if (!Drone)
1247 {
1248 return;
1249 }
1250
1251 // Parse rest of the string to Transform
1252 TArray<FString> Components;
1253 TransformString.ParseIntoArray(Components, TEXT(","), true);
1254
1255 if (Components.Num() >= 3)
1256 {
1257 FVector Location;
1258 FQuat Rotation;
1259
1260 // Convert the first three components to float values for location
1261 float X = FCString::Atof(*Components[0]);
1262 float Y = FCString::Atof(*Components[1]);
1263 float Z = FCString::Atof(*Components[2]);
1264
1265 Location = FVector(X, Y, Z);
1266
1267 if (Components.Num() >= 6)
1268 {
1269 // If there are six or more components, try to parse them as rotation values
1270 float Pitch = FCString::Atof(*Components[3]);
1271 float Yaw = FCString::Atof(*Components[4]);
1272 float Roll = FCString::Atof(*Components[5]);
1273
1274 // Convert the Euler angles to a quaternion
1275 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
1276 }
1277
1278 FTransform Transform;
1279 Transform.SetLocation(Location);
1280 Transform.SetRotation(Rotation);
1281
1282 // Create new drone parameters
1283 FDroneParameters NewParams;
1285 NewParams.DroneEndAction = EndAction;
1286 //NewParams.Points.Add(Transform);
1287
1288 Drone->ChangeDroneParameters(NewParams);
1289
1290 // Change drone parameters
1291 Drone->MoveDroneToPosition(Transform);
1292 }
1293}
1294
1295void UROSCommands::HandleSetAllSensorsEnabled(const FString& Variable)
1296{
1297 bool EnableSensors;
1298 if (!TryParseBoolean(Variable, EnableSensors))
1299 {
1300 // Failed to parse, return
1301 return;
1302 }
1303
1304 if (EnableSensors)
1305 {
1307 }
1308 else
1309 {
1311 }
1312}
1313
1314void UROSCommands::HandleEnableAllSensors(const FString& Variable)
1315{
1317}
1318
1319void UROSCommands::HandleDisableAllSensors(const FString& Variable)
1320{
1322}
1323
1324void UROSCommands::HandleSetSensorEnabled(const FString& Variable)
1325{
1326 TArray<FString> Tokens;
1327 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1328 if (Tokens.Num() < 2)
1329 {
1330 // Not enough arguments, return
1331 return;
1332 }
1333
1334 const FString& ID = Tokens[0];
1335
1336 AActor* Actor = IActorInformation::GetActorByID(ID);
1337 if (!Actor)
1338 {
1339 return;
1340 }
1341
1342 ASensor* Sensor = Cast<ASensor>(Actor);
1343 if (!Sensor)
1344 {
1345 return;
1346 }
1347
1348 FString BooleanString = Tokens[1].ToLower();
1349
1350 bool SimulateSensor;
1351 if (!TryParseBoolean(BooleanString, SimulateSensor))
1352 {
1353 // Failed to parse, return
1354 return;
1355 }
1356
1357 Sensor->SetSimulateSensor(SimulateSensor);
1358}
1359
1360void UROSCommands::HandleSetWPO(const FString& Variable)
1361{
1362 if (Variable.IsNumeric())
1363 {
1364 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
1365 if (AgrarsenseSettings)
1366 {
1367 int32 IntValue = FCString::Atoi(*Variable);
1368 AgrarsenseSettings->SetWorldPositionOffsetRenderDistance(IntValue);
1369 }
1370 }
1371}
1372
1374{
1375 if (Variable.IsNumeric())
1376 {
1377 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
1378 if (AgrarsenseSettings)
1379 {
1380 float Value = FCString::Atof(*Variable);
1381 AgrarsenseSettings->SetNaniteMaxPixelsPerEdge(Value);
1382 }
1383 }
1384}
1385
1386void UROSCommands::HandleDestroyTreesArea(const FString& Variable)
1387{
1388 HandleDestroyActors(Variable, true);
1389}
1390
1391void UROSCommands::HandleDestroyActorsArea(const FString& Variable)
1392{
1393 HandleDestroyActors(Variable, false);
1394}
1395
1396void UROSCommands::HandleDestroyActors(const FString& Variable, bool OnlyTrees)
1397{
1398 TArray<FString> ParsedStrings;
1399 Variable.ParseIntoArray(ParsedStrings, TEXT(" "), true);
1400
1401 if (ParsedStrings.Num() != 2)
1402 {
1403 return;
1404 }
1405
1406 // Parse position
1407 TArray<FString> PositionComponents;
1408 ParsedStrings[0].ParseIntoArray(PositionComponents, TEXT(","), true);
1409
1410 if (PositionComponents.Num() != 3)
1411 {
1412 return;
1413 }
1414
1415 FVector Position(FCString::Atof(*PositionComponents[0]), FCString::Atof(*PositionComponents[1]), FCString::Atof(*PositionComponents[2]));
1416
1417 // Parse bounds
1418 TArray<FString> BoundsComponents;
1419 ParsedStrings[1].ParseIntoArray(BoundsComponents, TEXT(","), true);
1420
1421 if (BoundsComponents.Num() != 3)
1422 {
1423 return;
1424 }
1425
1426 FVector Bounds(FCString::Atof(*BoundsComponents[0]), FCString::Atof(*BoundsComponents[1]), FCString::Atof(*BoundsComponents[2]));
1427
1428 FTransform VolumeTransform;
1429 VolumeTransform.SetLocation(Position);
1430
1431 UWorld* World = GetGameWorld();
1432 if (World)
1433 {
1434 ADeletionVolume* Volume = World->SpawnActor<ADeletionVolume>(ADeletionVolume::StaticClass(), VolumeTransform);
1435 if (Volume)
1436 {
1437 // Change volume bounds
1438 Volume->ChangeOverlapBounds(Bounds);
1439
1440 // Destroy overlapping actors,
1441 // this Actor gets deleted automatically after calling this.
1442 Volume->DestroyOverlappingActors(OnlyTrees);
1443 }
1444 }
1445}
1446
1448{
1449 TArray<FString> Tokens;
1450 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1451
1452 if (Tokens.Num() < 2)
1453 {
1454 return;
1455 }
1456
1457 const FString& ID = Tokens[0];
1458 const FString Param = Variable.RightChop(ID.Len() + 1);
1459
1460 bool bVisible = true;
1461 if (!TryParseBoolean(Param, bVisible))
1462 {
1463 return; // Invalid parameter
1464 }
1465
1466 if (AActor* Actor = IActorInformation::GetActorByID(ID))
1467 {
1468 if (AVehicle* Vehicle = Cast<AVehicle>(Actor))
1469 {
1470 Vehicle->SetVehicleMeshVisibility(bVisible);
1471 }
1472 }
1473}
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:154
void TeleportSpectator(const FTransform &Transform)
Definition: Spectator.cpp:75
Definition: Tagger.h:51
AActor * GetActorByInstanceID(float InstanceID)
Definition: Tagger.cpp:226
FString ExportToJsonFile(const FString &FileName)
Definition: Vehicle.cpp:269
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 SetGlobalTargetFrameRate(int32 NewTargetFrameRate)
void SetGlobalTimeDilation(float TimeDilation)
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 HandleResetDrone(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