code-iai / ROSIntegration

Unreal Engine Plugin to enable ROS Support
MIT License
411 stars 133 forks source link

Why UE4 becomes stuttered after play if the rosbridge_server in another machine doesn't open? #175

Open webercheng opened 2 years ago

webercheng commented 2 years ago

In my case, I run UE4(with ROSIntegration) in win10 but I didn't start the rosbridge_server(rosbridge_tcp) in another pc. However. After I clicked the "Play" button, the UE4 world became stuttered. This will also happen if I terminate the rosbridge_server on purpose.

webercheng commented 2 years ago

I found this caused by "if (!_sock->Connect(*addr))" in "bool TCPConnection::Init(std::string ip_addr, int port)" which consumes at least 2 seconds in my system。"void UROSIntegrationGameInstance::Init()" will be called in "UROSIntegrationGameInstance::CheckROSBridgeHealth" periodically while rosbridge_server not started. I tried to fix this but still encountered some problems.

webercheng commented 2 years ago

Problem solved! The root cause is ”_sock->Connect(*addr)“ works in blocking mode, blocking time will be affected by system implementation which is unpredictable. So it's necessary to set non-block mode first.

I tried to fix like this: 1) TCPConnection.cpp bool TCPConnection::Init(std::string ip_addr, int port) { ...

if 0

if (!_sock->Connect(*addr))

else

bool bConnected = false;
_sock->SetNonBlocking(true);
bConnected = _sock->Connect(*addr);
_sock->SetNonBlocking(false);
// If using _sock->Wait also blocks
if (bConnected ) //&& _sock->Wait(ESocketWaitConditions::WaitForWrite, FTimespan::FromSeconds(2)))
{
    // do nothing
}
else

endif

{
    return false;   
}
    ...

}

2) In ROSIntegrationGameInstance.cpp

void UROSIntegrationGameInstance::Init() {

if 0

  if (!bTimerSet)
  {
      bTimerSet = true; 
      GetTimerManager().SetTimer(TimerHandle_CheckHealth, this, &UROSIntegrationGameInstance::CheckROSBridgeHealth, 1.0f, true, 5.0f);
  }
  #else
  if (!bTimerSet)
  {
      bTimerSet = true; 
      GetTimerManager().SetTimer(TimerHandle_CheckHealth, this, &UROSIntegrationGameInstance::CheckROSBridgeHealth, 5.0f, true, 5.0f);
  }
  #endif

}

This is not the optimal solution but combined these two changes does help to my case.