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 TArray<FString> Parts;
536 Variable.TrimStartAndEnd().ParseIntoArrayWS(Parts);
537
538 if (Parts.Num() < 2)
539 {
540 return;
541 }
542
543 int32 LabelIndex = 0;
544 int32 InstanceID = 0;
545
546 if (!LexTryParseString(LabelIndex, *Parts[0]) || !LexTryParseString(InstanceID, *Parts[1]))
547 {
548 return;
549 }
550
551 TArray<AActor*> Taggers;
552 UGameplayStatics::GetAllActorsOfClass(GetGameWorld(), ATagger::StaticClass(), Taggers);
553 ATagger* Tagger = Cast<ATagger>(Taggers[0]);
554
555 if (Tagger)
556 {
557 AActor* Actor = Tagger->TryGetActorByInstanceID(LabelIndex, InstanceID);
558 if (Actor)
559 {
561 {
562 Spectator->TeleportSpectator(Actor->GetActorTransform());
563 }
564 }
565 }
566}
567
568void UROSCommands::HandleTeleportActorByID(const FString& Variable)
569{
570 FString ID;
571 FString TransformString;
572
573 // Split the ID and rest of the message
574 TArray<FString> Tokens;
575 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
576 if (Tokens.Num() >= 2)
577 {
578 ID = Tokens[0];
579 TransformString = Variable.RightChop(ID.Len() + 1);
580 }
581 else
582 {
583 SimulatorLog::Log("Invalid input. Input should be in format: ID,X,Y,Z or ID,X,Y,Z,YAW,PITCH,ROLL");
584 return;
585 }
586
587 // Check if this ID matches any Actor
588 AActor* Actor = IActorInformation::GetActorByID(ID);
589 if (!Actor)
590 {
591 FString log = FString::Printf(TEXT("Could not find Actor with ID: %s"), *ID);
593 return;
594 }
595
596 // Parse rest of the string to Transform
597 TArray<FString> Components;
598 TransformString.ParseIntoArray(Components, TEXT(","), true);
599
600 if (Components.Num() >= 3)
601 {
602 FVector Location;
603 FQuat Rotation;
604
605 // Convert the first three components to float values for location
606 float X = FCString::Atof(*Components[0]);
607 float Y = FCString::Atof(*Components[1]);
608 float Z = FCString::Atof(*Components[2]);
609
610 Location = FVector(X, Y, Z);
611
612 if (Components.Num() >= 6)
613 {
614 // If there are six or more components, try to parse them as rotation values
615 float Pitch = FCString::Atof(*Components[3]);
616 float Yaw = FCString::Atof(*Components[4]);
617 float Roll = FCString::Atof(*Components[5]);
618
619 // Convert the Euler angles to a quaternion
620 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
621 }
622
623 FTransform Transform;
624 Transform.SetLocation(Location);
625 Transform.SetRotation(Rotation);
626
627 if (InMeters)
628 {
630 }
631
632#if WITH_EDITOR
633 UE_LOG(LogTemp, Warning, TEXT("Teleporting Actor with ID: %s to: %s"), *ID, *TransformString);
634#endif
635
636 // Check if this Actor is Vehicle
637 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
638 if (VehiclePtr)
639 {
640 // Disable vehicle physics so it can be teleported
641 VehiclePtr->TogglePhysics(false);
642
643 Actor->SetActorTransform(Transform);
644
645 // Enable vehicle physics back on after teleporting vehicle
646 VehiclePtr->TogglePhysics(true);
647 }
648 else
649 {
650 // Else set the Actor transform
651 Actor->SetActorTransform(Transform);
652 }
653 }
654}
655
656void UROSCommands::HandleTryDestroyObjectByID(const FString& Variable)
657{
658 bool success = IActorInformation::DestroyActorByID(Variable);
659
660 FString Message;
661 if (success)
662 {
663 Message = FString::Printf(TEXT("Object with ID %s successfully destroyed."), *Variable);
664 }
665 else
666 {
667 Message = FString::Printf(TEXT("Failed to destroy object with ID %s."), *Variable);
668 }
669
670 SimulatorLog::Log(Message);
671}
672
673void UROSCommands::HandleDestroyAllSensors(const FString& Variable)
674{
676}
677
678void UROSCommands::HandleDestroyAllWalkers(const FString& Variable)
679{
681}
682
683void UROSCommands::HandleDestroyAllVehicles(const FString& Variable)
684{
685 UWorld* World = GetGameWorld();
686 if (!World)
687 {
688 return;
689 }
690
691 TArray<AActor*> Vehicles;
692 UGameplayStatics::GetAllActorsOfClass(World, AVehicle::StaticClass(), Vehicles);
693 for (AActor* Actor : Vehicles)
694 {
695 AVehicle* Vehicle = Cast<AVehicle>(Actor);
696 if (Vehicle)
697 {
698 Vehicle->Destroy();
699 }
700 }
701}
702
704{
705 TArray<FString> Parts;
706 Variable.TrimStartAndEnd().ParseIntoArrayWS(Parts);
707
708 if (Parts.Num() < 2)
709 {
710 return;
711 }
712
713 int32 LabelIndex = 0;
714 int32 InstanceID = 0;
715
716 if (!LexTryParseString(LabelIndex, *Parts[0]) || !LexTryParseString(InstanceID, *Parts[1]))
717 {
718 return;
719 }
720
721 TArray<AActor*> Taggers;
722 UGameplayStatics::GetAllActorsOfClass(GetGameWorld(), ATagger::StaticClass(), Taggers);
723 ATagger* Tagger = Cast<ATagger>(Taggers[0]);
724
725 if (Tagger)
726 {
727 AActor* Actor = Tagger->TryGetActorByInstanceID(LabelIndex, InstanceID);
728 if (Actor)
729 {
730 Actor->Destroy();
731 }
732 }
733}
734
735void UROSCommands::HandlePrintMaps(const FString& Variable)
736{
737 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
738 if (AgrarsenseSettings)
739 {
740 TArray<FString> Maps = AgrarsenseSettings->GetMapNames();
741
742 FString message;
743
744 for (const FString& map : Maps)
745 {
746 message += FString::Printf(TEXT("%s, "), *map);
747 }
748
749 SimulatorLog::Log(message);
750 }
751}
752
753void UROSCommands::HandlePrintAllSensors(const FString& Variable)
754{
755 PrintActorInformation(Variable, ASensor::StaticClass(), "sensor");
756}
757
758void UROSCommands::HandlePrintAllVehicles(const FString& Variable)
759{
760 PrintActorInformation(Variable, AVehicle::StaticClass(), "vehicle");
761}
762
763void UROSCommands::HandlePrintAllWalkers(const FString& Variable)
764{
765 PrintActorInformation(Variable, AWalker::StaticClass(), "walker");
766}
767
768void UROSCommands::PrintActorInformation(const FString& Variable, UClass* ActorClass, const FString& ActorTypeName)
769{
770 TArray<AActor*> Actors;
771 UGameplayStatics::GetAllActorsWithInterface(GetGameWorld(), UActorInformation::StaticClass(), Actors);
772
773 TArray<AActor*> TypedActors;
774 for (AActor* Actor : Actors)
775 {
776 if (Actor->IsA(ActorClass))
777 {
778 TypedActors.Add(Actor);
779 }
780 }
781
782 FString Msg;
783 if (!TypedActors.IsEmpty())
784 {
785 Msg = FString::Printf(TEXT("Simulation has %d %ss \n "), TypedActors.Num(), *ActorTypeName);
786 for (AActor* Actor : TypedActors)
787 {
788 if (Actor)
789 {
790 if (Actor->Implements<UActorInformation>())
791 {
792 FString ActorInfo = IActorInformation::Execute_GetActorInformation(Actor);
793 Msg += FString::Printf(TEXT("%s \n \n "), *ActorInfo);
794 }
795
796 }
797 }
798 }
799 else
800 {
801 Msg = FString::Printf(TEXT("Simulation has 0 %ss."), *ActorTypeName);
802 }
803
805}
806
807void UROSCommands::HandlePrintIds(const FString& Variable)
808{
810}
811
813{
814 if (Variable.IsNumeric())
815 {
816 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
817 if (AgrarsenseSettings)
818 {
819 int32 IntValue = FCString::Atoi(*Variable);
820 AgrarsenseSettings->SetGlobalTargetFrameRate(IntValue);
821 }
822 }
823}
824
825void UROSCommands::HandleSetGlobalTimeDilation(const FString& Variable)
826{
827 if (Variable.IsNumeric())
828 {
829 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
830 if (AgrarsenseSettings)
831 {
832 float FloatValue = FCString::Atof(*Variable);
833 AgrarsenseSettings->SetGlobalTimeDilation(FloatValue);
834 }
835 }
836}
837
838void UROSCommands::HandleSetQualityLevel(const FString& Variable)
839{
840 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
841 if (AgrarsenseSettings)
842 {
843 AgrarsenseSettings->SetQualityLevelFromString(Variable);
844 }
845}
846
847void UROSCommands::HandleSetWorldRendering(const FString& Variable)
848{
849 bool RenderWorld;
850 if (!TryParseBoolean(Variable, RenderWorld))
851 {
852 // Failed to parse, return
853 return;
854 }
855
856 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
857 if (AgrarsenseSettings)
858 {
859 AgrarsenseSettings->SetWorldRendering(RenderWorld);
860 }
861}
862
863void UROSCommands::HandleSetGrassVisibility(const FString& Variable)
864{
865 bool RenderGrass;
866 if (!TryParseBoolean(Variable, RenderGrass))
867 {
868 // Failed to parse, return
869 return;
870 }
871
872 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
873 if (AgrarsenseSettings)
874 {
875 AgrarsenseSettings->SetGrassVisibility(RenderGrass);
876 }
877}
878
880{
881 bool Save;
882 if (!TryParseBoolean(Variable, Save))
883 {
884 // Failed to parse, return
885 return;
886 }
887
889 if (LidarManager)
890 {
891 LidarManager->SetSaveCombinedCloudToDisk(Save);
892 }
893}
894
895void UROSCommands::HandleSpawnObjects(const FString& Variable)
896{
898}
899
900void UROSCommands::HandleExportAll(const FString& Variable)
901{
902 // Below export functions do not need any incoming variable but require FString
903 FString EmptyString;
904
905 HandleExportWeather(EmptyString);
906 HandleExportWalkers(EmptyString);
907
908 // HandleExportSensors exports vehicles as well
909 //HandleExportVehicles(EmptyString);
910 HandleExportSensors(EmptyString);
911
912 HandleExportFoliage(EmptyString);
913 HandleExportProps(EmptyString);
914}
915
916void UROSCommands::HandleExportWeather(const FString& Variable)
917{
919 if (Weather)
920 {
921 Weather->ExportToJSON("ExportedWeather");
922 }
923}
924
925void UROSCommands::HandleExportWalkers(const FString& Variable)
926{
927 TArray<AWalker*> Walkers = UAssetLibrary::GetAllWalkers();
928 for (AWalker* Walker : Walkers)
929 {
930 if (Walker)
931 {
932 Walker->ExportToJsonFile("ExportedWalker");
933 }
934 }
935}
936
937void UROSCommands::HandleExportVehicles(const FString& Variable)
938{
939 TArray<FVehicleData> Vehicles = UAssetLibrary::GetSpawnedVehicles();
940 for (const FVehicleData& VehicleData : Vehicles)
941 {
942 AVehicle* VehiclePtr = VehicleData.Vehicle.Get();
943 if (VehiclePtr)
944 {
945 VehiclePtr->ExportToJsonFile("ExportedVehicle");
946 }
947 }
948}
949
950void UROSCommands::HandleExportSensors(const FString& Variable)
951{
952 UWorld* World = GetGameWorld();
953 if (!World)
954 {
955 return;
956 }
957
958 // Export all Vehicles and attached sensors
959 TArray<AActor*> Vehicles;
960 UGameplayStatics::GetAllActorsOfClass(World, AVehicle::StaticClass(), Vehicles);
961 for (AActor* Actor : Vehicles)
962 {
963 AVehicle* VehiclePtr = Cast<AVehicle>(Actor);
964 if (VehiclePtr)
965 {
966 VehiclePtr->ExportToJsonFile("ExportedVehicle");
967 }
968 }
969
970 // Export all Sensors separately as well
971 TArray<AActor*> Sensors;
972 UGameplayStatics::GetAllActorsOfClass(World, ASensor::StaticClass(), Sensors);
973 for (AActor* Actor : Sensors)
974 {
975 ASensor* SensorPtr = Cast<ASensor>(Actor);
976 if (SensorPtr)
977 {
978 SensorPtr->ExportToJsonFile("ExportedSensor");
979 }
980 }
981}
982
983void UROSCommands::HandleExportFoliage(const FString& Variable)
984{
985 TArray<AInstancedActor*> FoliageActors = UAssetLibrary::GetAllAddedFoliageActors();
986 USimulatorJsonExporter::ExportInstancedActorsToJSON("ExportedFoliage", FoliageActors);
987}
988
989void UROSCommands::HandleExportObjects(const FString& Variable)
990{
991 UWorld* World = GetGameWorld();
992 if (!World)
993 {
994 return;
995 }
996
997 TArray<AActor*> Taggers;
998 UGameplayStatics::GetAllActorsOfClass(World, ATagger::StaticClass(), Taggers);
999
1000 if (ATagger* Tagger = Cast<ATagger>(Taggers[0]))
1001 {
1002 Tagger->ExportObjectLocationsToCSV();
1003 }
1004}
1005
1006void UROSCommands::HandleExportProps(const FString& Variable)
1007{
1008 TArray<AInstancedActor*> PropActors = UAssetLibrary::GetAllAddedPropActors();
1009 USimulatorJsonExporter::ExportInstancedActorsToJSON("ExportedProps", PropActors);
1010}
1011
1013{
1014 bool Visualize;
1015 if (!TryParseBoolean(Variable, Visualize))
1016 {
1017 // Failed to parse, return
1018 return;
1019 }
1020
1021 UWorld* World = GetGameWorld();
1022 if (World)
1023 {
1024 TArray<AActor*> OverlapSensors;
1025 UGameplayStatics::GetAllActorsOfClass(World, AOverlapSensor::StaticClass(), OverlapSensors);
1026
1027 for (AActor* SensorActor : OverlapSensors)
1028 {
1029 AOverlapSensor* Sensor = Cast<AOverlapSensor>(SensorActor);
1030 if (Sensor)
1031 {
1032 Sensor->SetVisualizeOverlapArea(Visualize);
1033 }
1034 }
1035 }
1036}
1037
1039{
1040 FString ID;
1041 FString BoundsString;
1042
1043 TArray<FString> Tokens;
1044 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1045
1046 if (Tokens.Num() < 2)
1047 {
1048 // Incoming parameters were invalid, return
1049 return;
1050 }
1051
1052 ID = Tokens[0];
1053 BoundsString = Tokens[1];
1054
1055 if (BoundsString.IsNumeric())
1056 {
1057 float Radius = FCString::Atof(*BoundsString);
1058
1059 AActor* Actor = IActorInformation::GetActorByID(ID);
1060 AOverlapSensor* Sensor = Cast<AOverlapSensor>(Actor);
1061 if (Sensor)
1062 {
1063 Sensor->SetOverlapBounds(FVector(Radius, Radius, Radius));
1064 }
1065 }
1066}
1067
1069{
1070 FString ID;
1071 FString BoundsString;
1072
1073 TArray<FString> Tokens;
1074 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1075
1076 if (Tokens.Num() < 2)
1077 {
1078 // Incoming parameters were invalid, return
1079 return;
1080 }
1081
1082 ID = Tokens[0];
1083 BoundsString = Tokens[1];
1084
1085 FVector RelativePosition;
1086 TArray<FString> BoundsTokens;
1087 BoundsString.ParseIntoArray(BoundsTokens, TEXT(","), true);
1088
1089 if (BoundsTokens.Num() >= 3)
1090 {
1091 RelativePosition.X = FCString::Atof(*BoundsTokens[0]);
1092 RelativePosition.Y = FCString::Atof(*BoundsTokens[1]);
1093 RelativePosition.Z = FCString::Atof(*BoundsTokens[2]);
1094
1095 AActor* Actor = IActorInformation::GetActorByID(ID);
1096 AOverlapSensor* Sensor = Cast<AOverlapSensor>(Actor);
1097 if (Sensor)
1098 {
1099 Sensor->SetOverlapRelativePosition(RelativePosition);
1100 }
1101 }
1102}
1103
1105{
1107}
1108
1109void UROSCommands::HandleMoveWalkerToAndStop(const FString& Variable)
1110{
1112}
1113
1114void UROSCommands::HandleMoveDroneToAndStop(const FString& Variable)
1115{
1117}
1118
1119void UROSCommands::HandleMoveWalkerTo(const FString& Variable, EWalkerEndAction EndAction)
1120{
1121 // This function overrides the current parameters of the Walker identified by the given ID,
1122 // moving the Walker to the specified x,y,z position and stopping upon reaching the target.
1123 // Usage: "movewalkerto reindeer 0,0,0" where 'reindeer' is the Walker ID.
1124
1125 FString ID;
1126 FString TransformString;
1127
1128 // Split the ID and rest of the message
1129 TArray<FString> Tokens;
1130 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1131 if (Tokens.Num() >= 2)
1132 {
1133 ID = Tokens[0];
1134 TransformString = Variable.RightChop(ID.Len() + 1);
1135 }
1136 else
1137 {
1138 return;
1139 }
1140
1141 // Check if this ID matches any Actor
1142 AActor* Actor = IActorInformation::GetActorByID(ID);
1143 if (!Actor)
1144 {
1145 return;
1146 }
1147
1148 AWalker* Walker = Cast<AWalker>(Actor);
1149 if (!Walker)
1150 {
1151 return;
1152 }
1153
1154 // Parse rest of the string to Transform
1155 TArray<FString> Components;
1156 TransformString.ParseIntoArray(Components, TEXT(","), true);
1157
1158 if (Components.Num() >= 3)
1159 {
1160 FVector Location;
1161 FQuat Rotation;
1162
1163 // Convert the first three components to float values for location
1164 float X = FCString::Atof(*Components[0]);
1165 float Y = FCString::Atof(*Components[1]);
1166 float Z = FCString::Atof(*Components[2]);
1167
1168 Location = FVector(X, Y, Z);
1169
1170 if (Components.Num() >= 6)
1171 {
1172 // If there are six or more components, try to parse them as rotation values
1173 float Pitch = FCString::Atof(*Components[3]);
1174 float Yaw = FCString::Atof(*Components[4]);
1175 float Roll = FCString::Atof(*Components[5]);
1176
1177 // Convert the Euler angles to a quaternion
1178 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
1179 }
1180
1181 FTransform Transform;
1182 Transform.SetLocation(Location);
1183 Transform.SetRotation(Rotation);
1184
1185 // Create new walker parameters
1186 FWalkerParameters NewParams;
1188 NewParams.WalkerEndAction = EndAction;
1189 NewParams.Points.Add(Transform);
1190
1191 // Change Walker parameters
1192 Walker->ChangeWalkerParameters(NewParams);
1193 }
1194}
1195
1196void UROSCommands::HandleStopWalker(const FString& Variable)
1197{
1198 HandleSetWalkerMovement(Variable, true);
1199}
1200
1201void UROSCommands::HandleResumeWalker(const FString& Variable)
1202{
1203 HandleSetWalkerMovement(Variable, false);
1204}
1205
1206void UROSCommands::HandleSetWalkerMovement(const FString& Variable, bool IsPaused)
1207{
1208 AActor* Actor = IActorInformation::GetActorByID(Variable);
1209 AWalker* Walker = Cast<AWalker>(Actor);
1210 if (!Walker)
1211 {
1212 return;
1213 }
1214
1215 if (IsPaused)
1216 {
1217 Walker->PauseWalker();
1218 }
1219 else
1220 {
1221 Walker->ResumeWalker();
1222 }
1223}
1224
1225void UROSCommands::HandleResetDrone(const FString& Variable)
1226{
1227 AActor* Actor = IActorInformation::GetActorByID(Variable);
1228 if (Actor)
1229 {
1230 APIDDrone* Drone = Cast<APIDDrone>(Actor);
1231 if (Drone)
1232 {
1233 Drone->ResetDroneEvent();
1234 }
1235 }
1236}
1237
1238void UROSCommands::HandleMoveDroneTo(const FString& Variable, EDroneEndAction EndAction)
1239{
1240 // This function overrides the current parameters of the Drone identified by the given ID,
1241 // moving the Drone to the specified x,y,z position and stopping upon reaching the target.
1242 // Usage: "movedroneto drone 0,0,0" where 'drone' is the Drone ID.
1243
1244 FString ID;
1245 FString TransformString;
1246
1247 // Split the ID and rest of the message
1248 TArray<FString> Tokens;
1249 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1250 if (Tokens.Num() >= 2)
1251 {
1252 ID = Tokens[0];
1253 TransformString = Variable.RightChop(ID.Len() + 1);
1254 }
1255 else
1256 {
1257 return;
1258 }
1259
1260 // Check if this ID matches any Actor
1261 AActor* Actor = IActorInformation::GetActorByID(ID);
1262 if (!Actor)
1263 {
1264 return;
1265 }
1266
1267 APIDDrone* Drone = Cast<APIDDrone>(Actor);
1268 if (!Drone)
1269 {
1270 return;
1271 }
1272
1273 // Parse rest of the string to Transform
1274 TArray<FString> Components;
1275 TransformString.ParseIntoArray(Components, TEXT(","), true);
1276
1277 if (Components.Num() >= 3)
1278 {
1279 FVector Location;
1280 FQuat Rotation;
1281
1282 // Convert the first three components to float values for location
1283 float X = FCString::Atof(*Components[0]);
1284 float Y = FCString::Atof(*Components[1]);
1285 float Z = FCString::Atof(*Components[2]);
1286
1287 Location = FVector(X, Y, Z);
1288
1289 if (Components.Num() >= 6)
1290 {
1291 // If there are six or more components, try to parse them as rotation values
1292 float Pitch = FCString::Atof(*Components[3]);
1293 float Yaw = FCString::Atof(*Components[4]);
1294 float Roll = FCString::Atof(*Components[5]);
1295
1296 // Convert the Euler angles to a quaternion
1297 Rotation = FQuat(FRotator(Pitch, Yaw, Roll));
1298 }
1299
1300 FTransform Transform;
1301 Transform.SetLocation(Location);
1302 Transform.SetRotation(Rotation);
1303
1304 // Create new drone parameters
1305 FDroneParameters NewParams;
1307 NewParams.DroneEndAction = EndAction;
1308 //NewParams.Points.Add(Transform);
1309
1310 Drone->ChangeDroneParameters(NewParams);
1311
1312 // Change drone parameters
1313 Drone->MoveDroneToPosition(Transform);
1314 }
1315}
1316
1317void UROSCommands::HandleSetAllSensorsEnabled(const FString& Variable)
1318{
1319 bool EnableSensors;
1320 if (!TryParseBoolean(Variable, EnableSensors))
1321 {
1322 // Failed to parse, return
1323 return;
1324 }
1325
1326 if (EnableSensors)
1327 {
1329 }
1330 else
1331 {
1333 }
1334}
1335
1336void UROSCommands::HandleEnableAllSensors(const FString& Variable)
1337{
1339}
1340
1341void UROSCommands::HandleDisableAllSensors(const FString& Variable)
1342{
1344}
1345
1346void UROSCommands::HandleSetSensorEnabled(const FString& Variable)
1347{
1348 TArray<FString> Tokens;
1349 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1350 if (Tokens.Num() < 2)
1351 {
1352 // Not enough arguments, return
1353 return;
1354 }
1355
1356 const FString& ID = Tokens[0];
1357
1358 AActor* Actor = IActorInformation::GetActorByID(ID);
1359 if (!Actor)
1360 {
1361 return;
1362 }
1363
1364 ASensor* Sensor = Cast<ASensor>(Actor);
1365 if (!Sensor)
1366 {
1367 return;
1368 }
1369
1370 FString BooleanString = Tokens[1].ToLower();
1371
1372 bool SimulateSensor;
1373 if (!TryParseBoolean(BooleanString, SimulateSensor))
1374 {
1375 // Failed to parse, return
1376 return;
1377 }
1378
1379 Sensor->SetSimulateSensor(SimulateSensor);
1380}
1381
1382void UROSCommands::HandleSetWPO(const FString& Variable)
1383{
1384 if (Variable.IsNumeric())
1385 {
1386 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
1387 if (AgrarsenseSettings)
1388 {
1389 int32 IntValue = FCString::Atoi(*Variable);
1390 AgrarsenseSettings->SetWorldPositionOffsetRenderDistance(IntValue);
1391 }
1392 }
1393}
1394
1396{
1397 if (Variable.IsNumeric())
1398 {
1399 UAgrarsenseSettings* AgrarsenseSettings = GetSettings();
1400 if (AgrarsenseSettings)
1401 {
1402 float Value = FCString::Atof(*Variable);
1403 AgrarsenseSettings->SetNaniteMaxPixelsPerEdge(Value);
1404 }
1405 }
1406}
1407
1408void UROSCommands::HandleDestroyTreesArea(const FString& Variable)
1409{
1410 HandleDestroyActors(Variable, true);
1411}
1412
1413void UROSCommands::HandleDestroyActorsArea(const FString& Variable)
1414{
1415 HandleDestroyActors(Variable, false);
1416}
1417
1418void UROSCommands::HandleDestroyActors(const FString& Variable, bool OnlyTrees)
1419{
1420 TArray<FString> ParsedStrings;
1421 Variable.ParseIntoArray(ParsedStrings, TEXT(" "), true);
1422
1423 if (ParsedStrings.Num() != 2)
1424 {
1425 return;
1426 }
1427
1428 // Parse position
1429 TArray<FString> PositionComponents;
1430 ParsedStrings[0].ParseIntoArray(PositionComponents, TEXT(","), true);
1431
1432 if (PositionComponents.Num() != 3)
1433 {
1434 return;
1435 }
1436
1437 FVector Position(FCString::Atof(*PositionComponents[0]), FCString::Atof(*PositionComponents[1]), FCString::Atof(*PositionComponents[2]));
1438
1439 // Parse bounds
1440 TArray<FString> BoundsComponents;
1441 ParsedStrings[1].ParseIntoArray(BoundsComponents, TEXT(","), true);
1442
1443 if (BoundsComponents.Num() != 3)
1444 {
1445 return;
1446 }
1447
1448 FVector Bounds(FCString::Atof(*BoundsComponents[0]), FCString::Atof(*BoundsComponents[1]), FCString::Atof(*BoundsComponents[2]));
1449
1450 FTransform VolumeTransform;
1451 VolumeTransform.SetLocation(Position);
1452
1453 UWorld* World = GetGameWorld();
1454 if (World)
1455 {
1456 ADeletionVolume* Volume = World->SpawnActor<ADeletionVolume>(ADeletionVolume::StaticClass(), VolumeTransform);
1457 if (Volume)
1458 {
1459 // Change volume bounds
1460 Volume->ChangeOverlapBounds(Bounds);
1461
1462 // Destroy overlapping actors,
1463 // this Actor gets deleted automatically after calling this.
1464 Volume->DestroyOverlappingActors(OnlyTrees);
1465 }
1466 }
1467}
1468
1470{
1471 TArray<FString> Tokens;
1472 Variable.ParseIntoArray(Tokens, TEXT(" "), true);
1473
1474 if (Tokens.Num() < 2)
1475 {
1476 return;
1477 }
1478
1479 const FString& ID = Tokens[0];
1480 const FString Param = Variable.RightChop(ID.Len() + 1);
1481
1482 bool bVisible = true;
1483 if (!TryParseBoolean(Param, bVisible))
1484 {
1485 return; // Invalid parameter
1486 }
1487
1488 if (AActor* Actor = IActorInformation::GetActorByID(ID))
1489 {
1490 if (AVehicle* Vehicle = Cast<AVehicle>(Actor))
1491 {
1492 Vehicle->SetVehicleMeshVisibility(bVisible);
1493 }
1494 }
1495}
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 * TryGetActorByInstanceID(int32 LabelIndex, int32 InstanceID)
Definition: Tagger.cpp:207
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