Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Robot Image Getter Functions #19

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
18 changes: 18 additions & 0 deletions Private/RobofleetBPFunctionLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ TArray<uint8> URobofleetBPFunctionLibrary::GetRobotImage(const FString& RobotNam
return TArray<uint8>();
}

bool URobofleetBPFunctionLibrary::IsRobotImageCompressed(const FString& RobotName)
{
if (FRobofleetUnrealClientModule::Get()->IsSessionRunning())
{
return FRobofleetUnrealClientModule::Get()->RobofleetClient->IsRobotImageCompressed(RobotName);
}
return bool();
}

void URobofleetBPFunctionLibrary::PrintRobotsSeen()
{
if (FRobofleetUnrealClientModule::Get()->IsSessionRunning())
Expand Down Expand Up @@ -140,6 +149,15 @@ FVector URobofleetBPFunctionLibrary::GetDetectedPositionGlobal(const FString& Ro
return FVector(0, 0, 0);
}

TArray<uint8> URobofleetBPFunctionLibrary::GetDetectedImage(const FString& RobotName)
{
if (FRobofleetUnrealClientModule::Get()->IsSessionRunning())
{
return FRobofleetUnrealClientModule::Get()->RobofleetClient->GetDetectedImage(RobotName);
}
return TArray<uint8>();
}

// Publish Messages to Robofleet
// *TODO: These need to be rate limited somewhere in the client as there is the potential to overload the server
void URobofleetBPFunctionLibrary::PublishStatusMsg(const FString& RobotName, const FRobotStatus& StatusMsg)
Expand Down
46 changes: 38 additions & 8 deletions Private/RobofleetClientBase.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "RobofleetClientBase.h"
#include "GameFramework/Actor.h"
#include <typeinfo>

URobofleetBase::URobofleetBase()
{
Expand All @@ -26,6 +27,7 @@ bool URobofleetBase::IsConnected()
{
if (IsValid(SocketClient))
{
//UE_LOG(LogRobofleet, Warning, TEXT("Websocket is Valid"))
return SocketClient->Socket->IsConnected();
}
return false;
Expand All @@ -45,7 +47,10 @@ void URobofleetBase::Initialize(FString HostUrl, const UObject* WorldContextObje

RegisterRobotStatusSubscription();
RegisterRobotSubscription("localization", "*");
//RegisterRobotSubscription("image_compressed/main", "*");
UE_LOG(LogRobofleet, Log, TEXT("RobofleetBase initialized"));
RegisterRobotSubscription("detected", "*");

bIsInitilized = true;

}
Expand Down Expand Up @@ -77,11 +82,12 @@ void URobofleetBase::PruneInactiveRobots() {
void URobofleetBase::WebsocketDataCB(const void* Data)
{
const fb::MsgWithMetadata* msg = flatbuffers::GetRoot<fb::MsgWithMetadata>(Data);

std::string MsgTopic = msg->__metadata()->topic()->c_str();

int NamespaceIndex = MsgTopic.substr(1, MsgTopic.length()).find('/');
FString RobotNamespace = FString(MsgTopic.substr(1, NamespaceIndex).c_str());
FString TopicIsolated = FString(MsgTopic.substr(NamespaceIndex+2, MsgTopic.length()).c_str());
FString TopicIsolated = FString(MsgTopic.substr(NamespaceIndex + 2, MsgTopic.length()).c_str());


RobotsSeenTime[RobotNamespace] = FDateTime::Now();
Expand Down Expand Up @@ -120,6 +126,7 @@ void URobofleetBase::RefreshRobotList()
UE_LOG(LogRobofleet, Log, TEXT("Refreshing robot list"));
RegisterRobotStatusSubscription();
RegisterRobotSubscription("localization", "*");
RegisterRobotSubscription("image_raw/compressed", "*");
RegisterRobotSubscription("detected", "*");
//PruneInactiveRobots();
}
Expand Down Expand Up @@ -150,6 +157,13 @@ void URobofleetBase::DecodeMsg(const void* Data, FString topic, FString RobotNam
//UE_LOG(LogTemp,Warning,TEXT("x: %f, y:%f"), rl.x, rl.y)
RobotMap[RobotNamespace]->Location = rl;
}

// Missing flatbuffer definitions
//else if (topic == "image/main") {
// RobotImageMap[RobotNamespace] = DecodeMsg<Image>(Data);
// OnImageReceived.Broadcast(RobotNamespace);
//}

else if (topic == "detected") {
DetectedItemMap[RobotNamespace] = DecodeMsg<DetectedItem>(Data);
OnDetectedItemReceived.Broadcast(RobotNamespace);
Expand All @@ -162,7 +176,6 @@ void URobofleetBase::DecodeMsg(const void* Data, FString topic, FString RobotNam
}
}


template <typename T>
void URobofleetBase::EncodeRosMsg (const T& msg, const std::string& msg_type, std::string& from_topic, const std::string& to_topic)
{ // Encoding Messages for Robofleet as ROS Messages
Expand Down Expand Up @@ -269,15 +282,24 @@ FVector URobofleetBase::GetRobotPosition(const FString& RobotName)

TArray<uint8> URobofleetBase::GetRobotImage(const FString& RobotName)
{
//needs to return type that Texture expects
FString RobotNamestd = FString(TCHAR_TO_UTF8(*RobotName));
TArray<uint8> imageData;
imageData.Append(&DetectedItemMap[RobotNamestd].cmpr_image.data[0], DetectedItemMap[RobotNamestd].cmpr_image.data.size());
// you may want an TArray<FColor>
// FColor pixelColor = {0, &RobotImageMap[Name].data[i] : i+3}
return imageData;
//returns the constructor/ init list: TArray<type>(arrayPtr, arraySize)
UE_LOG(LogTemp, Log, TEXT("Creating local image message of type TArray<uint8>."));
return TArray<uint8>(&RobotImageMap[RobotNamestd].data[0], RobotImageMap[RobotNamestd].data.size());
}

bool URobofleetBase::IsRobotImageCompressed(const FString& RobotName)
{
FString RobotNamestd = FString(TCHAR_TO_UTF8(*RobotName));
if (RobotImageMap[RobotNamestd].format.find("compressed") != std::string::npos)
{
return true;
}
else return false;

}


TArray<FString> URobofleetBase::GetAllRobotsAtSite(const FString& Location)
{
TArray<FString> RobotsAtSite;
Expand Down Expand Up @@ -325,3 +347,11 @@ FVector URobofleetBase::GetDetectedPositionGlobal(const FString& RobotName)
if (RobotMap.count(RobotNamestd) == 0) return FVector(-1, -1, -1);
return FVector(DetectedItemMap[RobotNamestd].lat, DetectedItemMap[RobotNamestd].lon, DetectedItemMap[RobotNamestd].elv);
}

TArray<uint8> URobofleetBase::GetDetectedImage(const FString& RobotName)
{
FString RobotNamestd = FString(TCHAR_TO_UTF8(*RobotName));
//returns the constructor/ init list: TArray<type>(arrayPtr, arraySize)
UE_LOG(LogTemp, Log, TEXT("Creating local image message of type TArray<uint8>."));
return TArray<uint8>(&DetectedItemMap[RobotNamestd].cmpr_image.data[0], DetectedItemMap[RobotNamestd].cmpr_image.data.size());
}
4 changes: 4 additions & 0 deletions Private/RobofleetClientBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class ROBOFLEETUNREALCLIENT_API URobofleetBase : public UObject

TArray<uint8> GetRobotImage(const FString& RobotName);

bool IsRobotImageCompressed(const FString& RobotName);

TArray<FString> GetAllRobotsAtSite(const FString& Location);

FString GetDetectedName(const FString& RobotName);
Expand All @@ -111,6 +113,8 @@ class ROBOFLEETUNREALCLIENT_API URobofleetBase : public UObject

FVector GetDetectedPositionGlobal(const FString& RobotName);

TArray<uint8> GetDetectedImage(const FString& RobotName);

bool IsRobotOk(const FString& RobotName);

void PrintRobotsSeen();
Expand Down
42 changes: 37 additions & 5 deletions Private/WebsocketClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void UWebsocketClient::Initialize(FString ServerURL /*= TEXT("ws://localhost:808
Socket->OnConnected().AddUFunction(this, FName("OnConnected"));
Socket->OnConnectionError().AddUFunction(this, FName("OnConnectionError"));
Socket->OnMessageSent().AddUFunction(this, FName("OnMessageSent"));
Socket->OnClosed().AddUFunction(this, FName("OnClosed"));

// Unreal having a problem with binding to a raw function, and a UFUNCTION doesn't like having a void* as a arg
// For now, use lambda directly
Expand All @@ -55,18 +56,50 @@ void UWebsocketClient::OnConnected()
UE_LOG(LogTemp, Log, TEXT("Connected to websocket."))
}

void UWebsocketClient::OnClosed()
{
UE_LOG(LogTemp, Log, TEXT("Websocket Closed."))
}

void UWebsocketClient::OnConnectionError()
{
UE_LOG(LogTemp, Warning, TEXT("Encountered error while trying to connect to websocket."))
}

void UWebsocketClient::OnMessageReceived(const void* Data, SIZE_T Size, SIZE_T BytesRemaining)
{

UE_LOG(LogTemp, Verbose, TEXT("Message Received"));

if (callbackRegistered) {
OnReceivedCB(Data);
// TODO: fix it frank, actually its not too terrible atm.

if (BytesRemaining)
{
if (!bIsBuffering)
{
DataBuffer = new char[Size + BytesRemaining];
memcpy(DataBuffer, Data, Size);
PrevSize = Size;
bIsBuffering = true;
}
else
{
memcpy(DataBuffer+PrevSize, Data, Size);
PrevSize += Size;
}
}
else
{
if (bIsBuffering)
{
memcpy(DataBuffer + PrevSize, Data, Size);
PrevSize = 0;
bIsBuffering = false;
OnReceivedCB(DataBuffer);
delete DataBuffer;
}
else
{
OnReceivedCB(Data);
}
}
}

Expand All @@ -77,7 +110,6 @@ void UWebsocketClient::OnMessageSent()

void UWebsocketClient::Send(const void* ptr, uint32_t size, bool isBinary)
{

UE_LOG(LogTemp, Verbose, TEXT("Message Sending"));
Socket->Send(ptr, size, isBinary);
}
Expand Down
7 changes: 7 additions & 0 deletions Private/WebsocketClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class UWebsocketClient : public UObject

UFUNCTION()
void OnConnected();

UFUNCTION()
void OnClosed();

UFUNCTION()
void OnConnectionError();
Expand All @@ -53,4 +56,8 @@ class UWebsocketClient : public UObject

void IsCallbackRegistered(bool val);

// TODO: Make a buffer struct and clean up the raw pointer, optimization wise the current implementation should be close to fastest but can be organized a bit better and made safer.
char* DataBuffer;
int PrevSize;
bool bIsBuffering = false;
};
2 changes: 1 addition & 1 deletion Private/robofleet_client_lib
6 changes: 6 additions & 0 deletions Public/RobofleetBPFunctionLibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class ROBOFLEETUNREALCLIENT_API URobofleetBPFunctionLibrary : public UBlueprintF
UFUNCTION(BlueprintCallable, Category = "Robofleet")
static TArray<uint8> GetRobotImage(const FString& RobotName);

UFUNCTION(BlueprintCallable, Category = "Robofleet")
static bool IsRobotImageCompressed(const FString& RobotName);

UFUNCTION(BlueprintCallable, Category = "Robofleet")
static void PrintRobotsSeen();

Expand All @@ -62,6 +65,9 @@ class ROBOFLEETUNREALCLIENT_API URobofleetBPFunctionLibrary : public UBlueprintF
UFUNCTION(BlueprintCallable, Category = "Robofleet")
static FVector GetDetectedPositionGlobal(const FString& RobotName);

UFUNCTION(BlueprintCallable, Category = "Robofleet")
static TArray<uint8> GetDetectedImage(const FString& RobotName);

// Publish Messages to Robofleet
UFUNCTION(BlueprintCallable, Category = "Robofleet")
static void PublishStatusMsg(const FString& RobotName, const FRobotStatus& StatusMsg);
Expand Down
2 changes: 1 addition & 1 deletion RobofleetUnrealClient.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public RobofleetUnrealClient(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

PublicDependencyModuleNames.AddRange(new string[] {"Core", "CoreUObject", "Engine", "WebSockets" });
PublicDependencyModuleNames.AddRange(new string[] {"Core", "CoreUObject", "Engine", "WebSockets", "ImageWrapper" });
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Private/robofleet_client_lib/include"));
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Private/robofleet_client_lib"));
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Private"));
Expand Down