Files
UnrealEngine/Engine/Plugins/Experimental/LearningAgents/Source/LearningAgentsTraining/Private/LearningAgentsCommunicator.cpp
2025-05-18 13:04:45 +08:00

234 lines
9.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "LearningAgentsCommunicator.h"
#include "LearningAgentsInteractor.h"
#include "LearningExternalTrainer.h"
#include "Misc/CommandLine.h"
#include "Misc/Guid.h"
#include "Misc/Paths.h"
FLearningAgentsCommunicator ULearningAgentsCommunicatorLibrary::MakeSharedMemoryTrainingProcess(
const FLearningAgentsTrainerProcessSettings& TrainerProcessSettings,
const FLearningAgentsSharedMemoryCommunicatorSettings& SharedMemorySettings)
{
FLearningAgentsSharedMemoryTrainerProcess TrainerProcess = SpawnSharedMemoryTrainingProcess(TrainerProcessSettings, SharedMemorySettings);
return MakeSharedMemoryCommunicator(TrainerProcess, TrainerProcessSettings, SharedMemorySettings);
}
FLearningAgentsSharedMemoryTrainerProcess ULearningAgentsCommunicatorLibrary::SpawnSharedMemoryTrainingProcess(
const FLearningAgentsTrainerProcessSettings& TrainerProcessSettings,
const FLearningAgentsSharedMemoryCommunicatorSettings& SharedMemorySettings)
{
FLearningAgentsSharedMemoryTrainerProcess TrainerProcess;
if (FParse::Param(FCommandLine::Get(), TEXT("LearningAgentsUseExternalTrainingProcess")) || SharedMemorySettings.bUseExternalTrainingProcess)
{
UE_LOG(LogLearning, Display, TEXT("SpawnSharedMemoryTrainingProcess: Skipping spawning because bUseExternalTrainingProcess is True."));
return TrainerProcess;
}
const FString PythonExecutablePath = UE::Learning::Trainer::GetPythonExecutablePath(TrainerProcessSettings.GetIntermediatePath());
if (!FPaths::FileExists(PythonExecutablePath))
{
UE_LOG(LogLearning, Error, TEXT("SpawnSharedMemoryTrainingProcess: Can't find Python executable \"%s\"."), *PythonExecutablePath);
return TrainerProcess;
}
const FString PythonContentPath = UE::Learning::Trainer::GetPythonContentPath(TrainerProcessSettings.GetEditorEnginePath());
if (!FPaths::DirectoryExists(PythonContentPath))
{
UE_LOG(LogLearning, Error, TEXT("SpawnSharedMemoryTrainingProcess: Can't find LearningAgents plugin Content \"%s\"."), *PythonContentPath);
return TrainerProcess;
}
const FString IntermediatePath = UE::Learning::Trainer::GetIntermediatePath(TrainerProcessSettings.GetIntermediatePath());
const FString CustomTrainerModulePath = TrainerProcessSettings.GetCustomTrainerModulePath();
if (!CustomTrainerModulePath.IsEmpty() and !FPaths::DirectoryExists(CustomTrainerModulePath))
{
UE_LOG(LogLearning, Error, TEXT("SpawnSharedMemoryTrainingProcess: Can't find custom trainer module \"%s\"."), *CustomTrainerModulePath);
return TrainerProcess;
}
TrainerProcess.TrainerProcess = MakeShared<UE::Learning::FSharedMemoryTrainerServerProcess>(
TrainerProcessSettings.TaskName,
CustomTrainerModulePath,
TrainerProcessSettings.TrainerFileName,
PythonExecutablePath,
PythonContentPath,
IntermediatePath,
SharedMemorySettings.Timeout);
return TrainerProcess;
}
FLearningAgentsCommunicator ULearningAgentsCommunicatorLibrary::MakeSharedMemoryCommunicator(
FLearningAgentsSharedMemoryTrainerProcess TrainerProcess,
const FLearningAgentsTrainerProcessSettings& TrainerProcessSettings,
const FLearningAgentsSharedMemoryCommunicatorSettings& SharedMemorySettings)
{
FLearningAgentsCommunicator Communicator;
// Task Name
FString CmdLineTaskName;
bool bTaskNameOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsTaskName="), CmdLineTaskName);
if (bTaskNameOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Overriding Task Name from the cmdline: %s"), *CmdLineTaskName);
}
// Timeout
float CmdLineTimeout;
bool bTimeoutOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsTimeout="), CmdLineTimeout);
if (bTimeoutOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Overriding Timeout with value from the cmdline: %f"), CmdLineTimeout);
}
// Controls Guid
// We have to use FGuid::Parse to accept more guid formats
FString CmdLineControlsGuidString;
FGuid CmdLineControlsGuid;
if (FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsControlsGuid="), CmdLineControlsGuidString) && FGuid::Parse(CmdLineControlsGuidString, CmdLineControlsGuid))
{
UE_LOG(LogLearning, Display, TEXT("Overriding Controls Guid with value from the cmdline: %s"), *CmdLineControlsGuid.ToString(PLATFORM_MAC ? EGuidFormats::Short : EGuidFormats::DigitsWithHyphensInBraces));
}
// Config Path
FString CmdLineConfigPath;
bool bConfigPathOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsConfigPath="), CmdLineConfigPath);
if (bConfigPathOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Overriding Config Path with value from the cmdline: %s"), *CmdLineConfigPath);
}
Communicator.Trainer = MakeShared<UE::Learning::FSharedMemoryTrainer>(
bTaskNameOverridden ? CmdLineTaskName : TrainerProcessSettings.TaskName,
TrainerProcess.TrainerProcess,
FParse::Param(FCommandLine::Get(), TEXT("LearningAgentsUseExternalTrainingProcess")) || SharedMemorySettings.bUseExternalTrainingProcess,
CmdLineControlsGuid.IsValid() ? CmdLineControlsGuid : SharedMemorySettings.ControlsGuid,
bConfigPathOverridden ? CmdLineConfigPath : SharedMemorySettings.ConfigPath.Path,
UE::Learning::Trainer::GetIntermediatePath(TrainerProcessSettings.GetIntermediatePath()),
bTimeoutOverridden ? CmdLineTimeout : SharedMemorySettings.Timeout);
return Communicator;
}
FLearningAgentsCommunicator ULearningAgentsCommunicatorLibrary::MakeSocketTrainingProcess(
const FLearningAgentsTrainerProcessSettings& TrainerProcessSettings,
const FLearningAgentsSocketCommunicatorSettings& SocketSettings)
{
FLearningAgentsSocketTrainerProcess TrainerProcess = SpawnSocketTrainingProcess(TrainerProcessSettings, SocketSettings);
return MakeSocketCommunicator(TrainerProcess, SocketSettings);
}
FLearningAgentsSocketTrainerProcess ULearningAgentsCommunicatorLibrary::SpawnSocketTrainingProcess(
const FLearningAgentsTrainerProcessSettings& TrainerProcessSettings,
const FLearningAgentsSocketCommunicatorSettings& SocketSettings)
{
FLearningAgentsSocketTrainerProcess TrainerProcess;
if (FParse::Param(FCommandLine::Get(), TEXT("LearningAgentsUseExternalTrainingProcess")) || SocketSettings.bUseExternalTrainingProcess)
{
UE_LOG(LogLearning, Display, TEXT("SpawnSocketTrainingProcess: Skipping spawning because bUseExternalTrainingProcess is True."));
return TrainerProcess;
}
const FString PythonExecutablePath = UE::Learning::Trainer::GetPythonExecutablePath(TrainerProcessSettings.GetIntermediatePath());
if (!FPaths::FileExists(PythonExecutablePath))
{
UE_LOG(LogLearning, Error, TEXT("SpawnSocketTrainingProcess: Can't find Python executable \"%s\"."), *PythonExecutablePath);
return TrainerProcess;
}
const FString PythonContentPath = UE::Learning::Trainer::GetPythonContentPath(TrainerProcessSettings.GetEditorEnginePath());
if (!FPaths::DirectoryExists(PythonContentPath))
{
UE_LOG(LogLearning, Error, TEXT("SpawnSocketTrainingProcess: Can't find LearningAgents plugin Content \"%s\"."), *PythonContentPath);
return TrainerProcess;
}
const FString IntermediatePath = UE::Learning::Trainer::GetIntermediatePath(TrainerProcessSettings.GetIntermediatePath());
const FString CustomTrainerModulePath = TrainerProcessSettings.GetCustomTrainerModulePath();
if (!CustomTrainerModulePath.IsEmpty() and !FPaths::DirectoryExists(CustomTrainerModulePath))
{
UE_LOG(LogLearning, Error, TEXT("SpawnSocketTrainingProcess: Can't find custom trainer module \"%s\"."), *CustomTrainerModulePath);
return TrainerProcess;
}
TrainerProcess.TrainerProcess = MakeShared<UE::Learning::FSocketTrainerServerProcess>(
TrainerProcessSettings.TaskName,
CustomTrainerModulePath,
TrainerProcessSettings.TrainerFileName,
PythonExecutablePath,
PythonContentPath,
IntermediatePath,
*SocketSettings.IpAddress,
SocketSettings.Port,
SocketSettings.Timeout);
return TrainerProcess;
}
FLearningAgentsCommunicator ULearningAgentsCommunicatorLibrary::MakeSocketCommunicator(
FLearningAgentsSocketTrainerProcess TrainerProcess,
const FLearningAgentsSocketCommunicatorSettings& SocketSettings)
{
UE::Learning::ETrainerResponse Response = UE::Learning::ETrainerResponse::Success;
// Ip Address
FString CmdLineIpAddress;
bool bIpAddressOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsIpAddress="), CmdLineIpAddress);
// Hostname
FString CmdLineHostname;
bool bHostnameOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsHostname="), CmdLineHostname);
if (bHostnameOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Using Hostname override from the cmdline: %s"), *CmdLineHostname);
}
else if (bIpAddressOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Using Ip Address override from the cmdline: %s"), *CmdLineIpAddress);
}
// Port
uint32 CmdLinePort;
bool bPortOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsPort="), CmdLinePort);
if (bPortOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Using Port override from the cmdline: %u"), CmdLinePort);
}
// Timeout
float CmdLineTimeout;
bool bTimeoutOverridden = FParse::Value(FCommandLine::Get(), TEXT("LearningAgentsTimeout="), CmdLineTimeout);
if (bTimeoutOverridden)
{
UE_LOG(LogLearning, Display, TEXT("Overriding Timeout with value from the cmdline: %f"), CmdLineTimeout);
}
FLearningAgentsCommunicator Communicator;
Communicator.Trainer = MakeShared<UE::Learning::FSocketTrainer>(
Response,
TrainerProcess.TrainerProcess,
FParse::Param(FCommandLine::Get(), TEXT("LearningAgentsUseExternalTrainingProcess")) || SocketSettings.bUseExternalTrainingProcess,
bHostnameOverridden
? *CmdLineHostname
: bIpAddressOverridden ? *CmdLineIpAddress: *SocketSettings.IpAddress,
bPortOverridden ? CmdLinePort : SocketSettings.Port,
bTimeoutOverridden ? CmdLineTimeout : SocketSettings.Timeout,
bHostnameOverridden);
if (Response != UE::Learning::ETrainerResponse::Success)
{
UE_LOG(LogLearning, Error, TEXT("MakeSocketCommunicator: Failed to connect to training process: %s. Check log for additional errors."), UE::Learning::Trainer::GetResponseString(Response));
Communicator.Trainer->Terminate();
}
return Communicator;
}