Merge pull request 'Noah_DataTransfer_1.0' (#39) from Noah_DataTransfer_1.0 into main
Reviewed-on: #39 Reviewed-by: evanvyktori <evan@luckyrobots.com>
This commit is contained in:
commit
22e2b0a419
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
{
|
||||
"BuildId": "37670630",
|
||||
"Modules":
|
||||
{
|
||||
"LuckyDataTransfer": "UnrealEditor-LuckyDataTransfer.dll"
|
||||
}
|
||||
}
|
23
Plugins/LuckyDataTransfer/LuckyDataTransfer.uplugin
Normal file
23
Plugins/LuckyDataTransfer/LuckyDataTransfer.uplugin
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "LuckyDataTransfer",
|
||||
"Description": "Lucky data transfer that transfers data with great luck.",
|
||||
"Category": "Other",
|
||||
"CreatedBy": "Noah Bowers",
|
||||
"CreatedByURL": "",
|
||||
"DocsURL": "",
|
||||
"MarketplaceURL": "",
|
||||
"CanContainContent": true,
|
||||
"IsBetaVersion": false,
|
||||
"IsExperimentalVersion": false,
|
||||
"Installed": false,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "LuckyDataTransfer",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
BIN
Plugins/LuckyDataTransfer/Resources/Icon128.png
Normal file
BIN
Plugins/LuckyDataTransfer/Resources/Icon128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,57 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class LuckyDataTransfer : ModuleRules
|
||||
{
|
||||
public LuckyDataTransfer(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"WebSockets",
|
||||
"Json",
|
||||
"JsonUtilities",
|
||||
"ImageWriteQueue"
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore", "ImageWriteQueue",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "LuckyDataTransfer.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FLuckyDataTransferModule"
|
||||
|
||||
void FLuckyDataTransferModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
}
|
||||
|
||||
void FLuckyDataTransferModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FLuckyDataTransferModule, LuckyDataTransfer)
|
@ -0,0 +1,153 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "LuckyDataTransferSubsystem.h"
|
||||
#include "JsonUtilities.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "WebSocketsModule.h"
|
||||
#include "Slate/SceneViewport.h"
|
||||
|
||||
ULuckyDataTransferSubsystem::ULuckyDataTransferSubsystem()
|
||||
{
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Deinitialize()
|
||||
{
|
||||
Super::Deinitialize();
|
||||
|
||||
if (Socket.IsValid() && Socket->IsConnected())
|
||||
{
|
||||
Socket->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Internal_OpenWebsocket(const FString& URL, const FString& Protocol)
|
||||
{
|
||||
const FString NewUrl = URL.IsEmpty() ? TEXT("ws://127.0.0.1:3000/ws") : URL;
|
||||
const FString NewProtocol = Protocol.IsEmpty() ? TEXT("ws") : Protocol;
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT("Opening WebSocket URL: %s"), *NewUrl);
|
||||
|
||||
if (!FModuleManager::Get().IsModuleLoaded("WebSockets"))
|
||||
{
|
||||
FModuleManager::Get().LoadModule("WebSockets");
|
||||
}
|
||||
|
||||
Socket = FWebSocketsModule::Get().CreateWebSocket(NewUrl);
|
||||
Socket->Connect();
|
||||
|
||||
//Set up callbacks
|
||||
Socket->OnConnectionError().AddUObject(this, &ULuckyDataTransferSubsystem::Callback_OnConnectionError);
|
||||
Socket->OnConnected().AddUObject(this, &ULuckyDataTransferSubsystem::Callback_OnConnected);
|
||||
Socket->OnMessage().AddUObject(this, &ULuckyDataTransferSubsystem::Callback_OnMessage);
|
||||
}
|
||||
|
||||
//Callbacks
|
||||
void ULuckyDataTransferSubsystem::Callback_OnConnected()
|
||||
{
|
||||
if (OnSocketReady.IsBound())
|
||||
{
|
||||
OnSocketReady.Broadcast(true);
|
||||
UE_LOG(LogTemp, VeryVerbose, TEXT("WebSocket connected successfully"));
|
||||
}
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Callback_OnConnectionError(const FString& Error)
|
||||
{
|
||||
UE_LOG(LogTemp, VeryVerbose, TEXT("Websocket connection error: %s"), *Error)
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Callback_OnMessage(const FString& Message)
|
||||
{
|
||||
if (!Message.IsEmpty())
|
||||
{
|
||||
CommandReady(InterpretData(Message));
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT("The message received from the websocket is invalid"));
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Internal_OnMessageSent(const FString& Message)
|
||||
{
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::Callback_OnConnectionClosed()
|
||||
{
|
||||
}
|
||||
|
||||
//Blueprint Exposed Implementation
|
||||
void ULuckyDataTransferSubsystem::ConnectToWebsocket(const FString& URL, const FString& Protocol)
|
||||
{
|
||||
Internal_OpenWebsocket(URL, Protocol);
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::SendMessage(const FString& Message)
|
||||
{
|
||||
if (Socket.IsValid() && Socket->IsConnected())
|
||||
{
|
||||
Socket->Send(Message);
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT("WebSocket outgoing message failed"));
|
||||
}
|
||||
|
||||
FPayload ULuckyDataTransferSubsystem::InterpretData(const FString& Message)
|
||||
{
|
||||
FPayload Payload = FPayload();
|
||||
|
||||
if (!Message.IsEmpty())
|
||||
{
|
||||
TSharedPtr<FJsonObject> JsonObj;
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Message);
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonObj) && JsonObj.IsValid())
|
||||
{
|
||||
for (auto& Elem : JsonObj->Values)
|
||||
{
|
||||
FCommand Command = FCommand();
|
||||
Command.Key = FString(Elem.Key);
|
||||
Command.Value = Elem.Value->AsNumber();
|
||||
|
||||
Payload.Commands.Add(Command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Payload;
|
||||
}
|
||||
|
||||
void ULuckyDataTransferSubsystem::CommandReady(const FPayload& Payload)
|
||||
{
|
||||
if (OnCommandReady.IsBound())
|
||||
{
|
||||
OnCommandReady.Broadcast(Payload);
|
||||
}
|
||||
}
|
||||
|
||||
//Blueprint Callable function - Use CreateJsonPayload_Observation in C++
|
||||
bool ULuckyDataTransferSubsystem::MakeObservationPayload(const FObservationPayload& Data)
|
||||
{
|
||||
return CreateJsonPayload_Observation(Data);
|
||||
}
|
||||
|
||||
bool ULuckyDataTransferSubsystem::CreateJsonPayload_Observation(const FObservationPayload& Data)
|
||||
{
|
||||
bool bSuccess = false;
|
||||
ObservationPayloadString = FString();
|
||||
|
||||
if (!Data.ObservationState.IsEmpty())
|
||||
{
|
||||
FJsonObjectConverter::UStructToJsonObjectString(Data, ObservationPayloadString);
|
||||
UE_LOG(LogTemp, Warning, TEXT("Payload observation: %s"), *ObservationPayloadString);
|
||||
bSuccess = true;
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FLuckyDataTransferModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
@ -0,0 +1,113 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IWebSocket.h"
|
||||
//#include "LuckyWriteThread.h"
|
||||
#include "ObservationData.h"
|
||||
#include "Subsystems/WorldSubsystem.h"
|
||||
#include "LuckyDataTransferSubsystem.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FCommand
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Command")
|
||||
FString Key = FString();
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Command")
|
||||
float Value = 0.f;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FPayload
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Command")
|
||||
TArray<FCommand> Commands;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Command")
|
||||
int32 Index = 0;
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCommandReady, const FPayload&, Payload);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSocketReady, bool, bSuccessful);
|
||||
|
||||
UCLASS()
|
||||
class LUCKYDATATRANSFER_API ULuckyDataTransferSubsystem : public UWorldSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ULuckyDataTransferSubsystem();
|
||||
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection);
|
||||
|
||||
virtual void Deinitialize();
|
||||
|
||||
TSharedPtr<IWebSocket> Socket;
|
||||
|
||||
//internal references
|
||||
|
||||
void Internal_OpenWebsocket(const FString& URL, const FString& Protocol);
|
||||
|
||||
FPayload InterpretData(const FString& Message);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FCommandReady OnCommandReady;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSocketReady OnSocketReady;
|
||||
|
||||
//Callbacks
|
||||
UFUNCTION()
|
||||
void Callback_OnConnected();
|
||||
|
||||
UFUNCTION()
|
||||
void Callback_OnConnectionError(const FString& Error);
|
||||
|
||||
UFUNCTION()
|
||||
void Callback_OnMessage(const FString& Message);
|
||||
|
||||
UFUNCTION()
|
||||
void Internal_OnMessageSent(const FString& Message);
|
||||
|
||||
UFUNCTION()
|
||||
void Callback_OnConnectionClosed();
|
||||
|
||||
//Exposed Blueprint Functions
|
||||
UFUNCTION(BlueprintCallable, Category = "Websocket")
|
||||
void ConnectToWebsocket(const FString& URL, const FString& Protocol);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Websocket")
|
||||
void SendMessage(const FString& Message);
|
||||
|
||||
UFUNCTION()
|
||||
void CommandReady(const FPayload& Payload);
|
||||
|
||||
//---Observations (Sent to server from Unreal)--------------//
|
||||
//Feature Data declarations
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FString ObservationPayloadString = FString();
|
||||
|
||||
//Internal Functions
|
||||
bool CreateJsonPayload_Observation(const FObservationPayload& Data);
|
||||
|
||||
//Blueprint Callable Functions
|
||||
UFUNCTION(BlueprintCallable, Category = "Websocket")
|
||||
bool MakeObservationPayload(const FObservationPayload& Data);
|
||||
//---------------------------------------------------------//
|
||||
|
||||
protected:
|
||||
//LuckyWriteThread* WriteThread = nullptr;
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HAL/Runnable.h"
|
||||
#include "ObservationData.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FImageShape
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Observation")
|
||||
float image_width = 640.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Observation")
|
||||
float image_height = 480.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Observation")
|
||||
int32 channel = 3;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FObservationCameraInfo
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
TMap<FString, FString> info = {
|
||||
{"video_fps", "30"},
|
||||
{"video_codec", "mp4v"},
|
||||
{"video_pix_fmt", "yuv420p"},
|
||||
{"video_is_depth_map", "false"},
|
||||
{"has_audio", "false"}
|
||||
};
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FObservationCameraObject
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FString cameraName = TEXT("front_camera");
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FString dtype = TEXT("image");
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FImageShape shape = FImageShape();
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FString filePath = FString();
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FObservationPayload
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FString timeStamp = FString();
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
FString id = FString();
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
TMap<FString, float> ObservationState;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Observation")
|
||||
TArray<FObservationCameraObject> ObservationCameras;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user