Skip to content

Commit d0018d5

Browse files
authored
Merge pull request #167 from tsender/ros1
Cleaned up converters, added improvements, and more
2 parents 8cc3475 + 0b7d9ae commit d0018d5

File tree

98 files changed

+1461
-1372
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1461
-1372
lines changed

README.md

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,31 @@ It uses http://mongoc.org/libbson/ to encode and decode the whole ROS communicat
3838
Since BSON is not included in Unreal Engine (yet), its code has to be added to this plugin.
3939
Currently, this plugin comes with a pre-compiled libbson for Windows x64 and Linux x64 which doesn't need any additional configuration.
4040

41-
To enable the communcation between Unreal and ROS, you will need a running ROSBridge (https://github.com/RobotWebTools/rosbridge_suite) with bson_mode. As an example for ROS kinetic, you can install it with:
41+
To enable the communcation between Unreal and ROS, you will need a running ROSBridge (https://github.com/RobotWebTools/rosbridge_suite) with bson_mode. Note: Please use rosbridge with version=>0.8.0 to get full BSON support.
42+
43+
The recommended way to install rosbridge is from source (requires the `rosauth` package):
44+
```
45+
sudo apt-get install ros-ROS1_DISTRO-rosauth # Replace ROS1_DISTRO with the distro you are using
46+
cd ~/ros_workspace/
47+
source devel/setup.bash
48+
cd src/
49+
git clone -b ros1 https://github.com/RobotWebTools/rosbridge_suite.git
50+
cd ..
51+
catkin_make
52+
source devel/setup.bash
53+
```
54+
Even though you could install rosbridge using apt via:
4255
```
43-
sudo apt-get install ros-kinetic-rosbridge-suite
56+
sudo apt-get install ros-ROS1_DISTRO-rosbridge-suite # Replace ROS1_DISTRO with the distro you are using
4457
```
45-
Note: Please use rosbridge with version=>0.8.0 to get full BSON support. After installing rosbridge, you can enable the bson_mode like this:
58+
there have been numersous issues where these apt packages do not reflect the code in the `ros1` branch. Hence, it is best to install from source. After installing rosbridge, you can enable the bson_mode like this:
4659

4760
```
4861
roslaunch rosbridge_server rosbridge_tcp.launch bson_only_mode:=True
4962
```
50-
**Important**: The most recent rosbridge versions changed the transmission method. Since ROSIntegration can not handle this new method yet, please make sure to check out these issue on how to install a compatible rosbridge version: https://github.com/code-iai/ROSIntegration/issues/141 & https://github.com/code-iai/ROSIntegration/issues/139
63+
**How to verify the rosbridge-UE4 connection:** Make sure UE4 is configured to use the ROSIntegrationGameInstance (see below) and set the connection parameters. If UE4 and rosbridge are both running, then you should see the rosbridge node subscribe to two topics with the prefix `/unreal_ros/`. If you do NOT see this, then you likely have a problem with your rosbridge installation.
64+
65+
<!-- **Important**: The most recent rosbridge versions changed the transmission method. Since ROSIntegration can not handle this new method yet, please make sure to check out these issue on how to install a compatible rosbridge version: https://github.com/code-iai/ROSIntegration/issues/141 & https://github.com/code-iai/ROSIntegration/issues/139 -->
5166

5267
In our testing, we usually installed rosbridge on a Ubuntu Linux with ROS while the UE4 with ROSIntegration can be run on a Windows or Linux hosts. ROSBridge and UE4 with ROSIntegration don't need to be run on the same machine. So in order to run UE4 with ROSIntegration on Windows, you can either install a Linux Virtual Machine on your Windows Hosts or have a seperate, physical machine with Linux running in your network.
5368

@@ -60,6 +75,8 @@ This plugin has previously been tested with Unreal Engine versions;
6075
* 4.20.3
6176
* **4.23** (by [Luigi Freda](http://www.luigifreda.com), fixed bugs with smart pointer management)
6277
* 4.24
78+
* 4.25
79+
* 4.26
6380

6481
Please note that this list is a tracker of which UE4 versions have been previously tested. It is not guaranteed that the most recent version of ROSIntegration is working with all previous UE4 versions.
6582

@@ -202,6 +219,7 @@ geometry_msgs/Quaternion | ✓ | ✓
202219
geometry_msgs/Transform | ✓ | ✓
203220
geometry_msgs/TransformStamped | ✓ | ✓
204221
geometry_msgs/Twist | ✓ | ✓
222+
geometry_msgs/TwistStamped | ✓ | ✓
205223
geometry_msgs/TwistWithCovariance | ✓ | ✓
206224
geometry_msgs/Vector3 | ✓ | ✓
207225
grid_map_msgs/GridMap | ✓ | ✓
@@ -247,6 +265,11 @@ PrivateIncludePaths.AddRange(
247265

248266
Then you can create the message definition and the converter in your own projects source tree. You can just copy and paste the files of a similar standard message, but don't forget to replace the `ROSINTEGRATION_API` with your own API macro created by Unreal.
249267

268+
### Overriding the rosbridge Connection Settings from Within the Level
269+
You can now add a `ROSBridgeParamOverride` actor to a level, allowing you to use different rosbridge connection settings for that level only (compared to what is defined in the ROSIntegrationGameInstance settings).
270+
271+
When might this be useful? Say you have a powerful enough computer that can handle multiple independent UE4 simulations at the same time, and you want to run as many simulations as possible to collect data effeciently (perhaps you are training a reinforcement learning algorithm). If you create copies of your main level (saved with different names) and use different ROS topic names within each level, then you can launch each level in a new UE4 editor on the same computer. If using a single rosbridge node for all of these UE4 instances results in considerable delays, then you can then add the `ROSBridgeParamOverride` actor to each level so that each level uses its own rosbridge node.
272+
250273
### FAQ
251274
* Question: My Topic/Service gets closed/unadvertised or my UE4 crashes around one minute after Begin Play.
252275
Answer: This might be a problem relating to the Garbage Collection of UE4. Please make sure that you declare your class member attributes as UPROPERTYs. See also: https://github.com/code-iai/ROSIntegration/issues/32
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#pragma once
2+
3+
#include "CoreMinimal.h"
4+
#include "GameFramework/Actor.h"
5+
#include "ROSBridgeParamOverride.generated.h"
6+
7+
/**
8+
* If you place this actor in the world, then you may override the parameters set in the ROSIntegrationGameInstance with the ones defined here.
9+
* The purpose of this actor is to allow you to launch multiple UE editors on the same computer (each with a different level open) and use different rosbridge connection parameters in each level.
10+
* This can be especially useful if you need to run independent parallel simulations on a single computer, each using a separate rosbridge node to distribute the load.
11+
*/
12+
UCLASS()
13+
class ROSINTEGRATION_API AROSBridgeParamOverride : public AActor
14+
{
15+
GENERATED_BODY()
16+
17+
public:
18+
AROSBridgeParamOverride()
19+
{
20+
PrimaryActorTick.bCanEverTick = false; // No need to tick
21+
}
22+
23+
// IP address of the rosbridge websocket server
24+
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "ROS")
25+
FString ROSBridgeServerHost = "127.0.0.1";
26+
27+
// Port number to access the rosbridge websocket server
28+
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "ROS")
29+
int32 ROSBridgeServerPort = 9090;
30+
31+
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "ROS")
32+
bool bConnectToROS = true;
33+
34+
UPROPERTY(EditAnywhere, Category = "ROS")
35+
bool bSimulateTime = true;
36+
37+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ROS")
38+
bool bUseFixedUpdateInterval = false;
39+
40+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ROS")
41+
float FixedUpdateInterval = 0.01666666667;
42+
43+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ROS")
44+
bool bCheckHealth = true;
45+
};

Source/ROSIntegration/Private/Conversion/Messages/BaseMessageConverter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#include "Conversion/Messages/BaseMessageConverter.h"
22

33

4-
UBaseMessageConverter::UBaseMessageConverter(const FObjectInitializer& ObjectInitializer)
5-
: Super(ObjectInitializer)
4+
UBaseMessageConverter::UBaseMessageConverter()
65
{
76
}
87

Source/ROSIntegration/Private/Conversion/Messages/BaseMessageConverter.h

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
#pragma once
22

3-
#include <CoreMinimal.h>
3+
#include "CoreMinimal.h"
44

55
#if PLATFORM_WINDOWS
66
#include "Windows/WindowsHWrapper.h"
77
#endif // PLATFORM_WINDOWS
88

99
#include "ROSIntegrationCore.h"
10-
#include <UObject/ObjectMacros.h>
11-
#include <UObject/Object.h>
1210
#include "rosbridge2cpp/messages/rosbridge_publish_msg.h"
1311
#include <cstring>
1412
#include <functional>
1513
#include <bson.h>
1614
#include "std_msgs/Header.h"
15+
#include "ROSTime.h"
1716

1817
#include "BaseMessageConverter.generated.h"
1918

2019
UCLASS()
2120
class ROSINTEGRATION_API UBaseMessageConverter: public UObject
2221
{
23-
GENERATED_UCLASS_BODY()
22+
GENERATED_BODY()
2423

2524
public:
25+
UBaseMessageConverter();
26+
2627
UPROPERTY()
2728
FString _MessageType;
2829

@@ -64,13 +65,35 @@ class ROSINTEGRATION_API UBaseMessageConverter: public UObject
6465
return value;
6566
}
6667

68+
static int64 GetInt64FromBSON(FString Key, bson_t* msg, bool &KeyFound, bool LogOnErrors = true)
69+
{
70+
assert(msg != nullptr);
71+
72+
int64 value = rosbridge2cpp::Helper::get_int64_by_key(TCHAR_TO_UTF8(*Key), *msg, KeyFound);
73+
if (!KeyFound && LogOnErrors) {
74+
UE_LOG(LogROS, Error, TEXT("Key %s not present in data"), *Key);
75+
}
76+
return value;
77+
}
78+
6779
static bool GetBoolFromBSON(FString Key, bson_t* msg, bool &KeyFound, bool LogOnErrors = true)
6880
{
6981
assert(msg != nullptr);
7082

7183
bool value = rosbridge2cpp::Helper::get_bool_by_key(TCHAR_TO_UTF8(*Key), *msg, KeyFound);
7284
if (!KeyFound && LogOnErrors) {
73-
UE_LOG(LogTemp, Error, TEXT("Key %s not present in data"), *Key);
85+
UE_LOG(LogROS, Error, TEXT("Key %s not present in data"), *Key);
86+
}
87+
return value;
88+
}
89+
90+
static const uint8* GetBinaryFromBSON(FString Key, bson_t* msg, bool &KeyFound, bool LogOnErrors = true)
91+
{
92+
assert(msg != nullptr);
93+
uint32_t binary_data_length = 0; // Gets populated by get_binary_by_key()
94+
const uint8* value = rosbridge2cpp::Helper::get_binary_by_key(TCHAR_TO_UTF8(*Key), *msg, binary_data_length, KeyFound);
95+
if (!KeyFound && LogOnErrors) {
96+
UE_LOG(LogROS, Error, TEXT("Key %s not present in data"), *Key);
7497
}
7598
return value;
7699
}
@@ -124,15 +147,11 @@ class ROSINTEGRATION_API UBaseMessageConverter: public UObject
124147
return GetTArrayFromBSON<int32>(Key, msg, KeyFound, [](FString subKey, bson_t* subMsg, bool& subKeyFound) { return GetInt32FromBSON(subKey, subMsg, subKeyFound, false); }, LogOnErrors);
125148
}
126149

127-
protected:
128-
129-
// Helper function to append a TArray<float> to a bson_t
130-
static void _bson_append_float_tarray(bson_t *b, const char *key, const TArray<float>& tarray)
150+
static TArray<bool> GetBoolTArrayFromBSON(FString Key, bson_t* msg, bool &KeyFound, bool LogOnErrors = true)
131151
{
132-
// float -> double doesn't loose precision
133-
_bson_append_double_tarray(b, key, (TArray<double>)tarray);
152+
return GetTArrayFromBSON<bool>(Key, msg, KeyFound, [](FString subKey, bson_t* subMsg, bool& subKeyFound) { return GetBoolFromBSON(subKey, subMsg, subKeyFound, false); }, LogOnErrors);
134153
}
135-
154+
136155
template<class T>
137156
static void _bson_append_tarray(bson_t *b, const char *key, const TArray<T>& tarray, const std::function<void(bson_t*, const char*, const T&)>& appendT)
138157
{
@@ -154,6 +173,13 @@ class ROSINTEGRATION_API UBaseMessageConverter: public UObject
154173
_bson_append_tarray<double>(b, key, tarray, [](bson_t *subb, const char *subKey, double d) { BSON_APPEND_DOUBLE(subb, subKey, d); });
155174
}
156175

176+
// Helper function to append a TArray<float> to a bson_t
177+
static void _bson_append_float_tarray(bson_t *b, const char *key, const TArray<float>& tarray)
178+
{
179+
// float -> double doesn't loose precision
180+
_bson_append_double_tarray(b, key, (TArray<double>)tarray);
181+
}
182+
157183
// Helper function to append a TArray<uint8> to a bson_t
158184
static void _bson_append_uint8_tarray(bson_t *b, const char *key, const TArray<uint8>& tarray)
159185
{
@@ -172,4 +198,27 @@ class ROSINTEGRATION_API UBaseMessageConverter: public UObject
172198
{
173199
_bson_append_tarray<uint32>(b, key, tarray, [](bson_t *subb, const char *subKey, uint32 i) { BSON_APPEND_INT32(subb, subKey, i); });
174200
}
175-
};
201+
202+
// Helper function to append a TArray<bool> to a bson_t
203+
static void _bson_append_bool_tarray(bson_t *b, const char *key, const TArray<bool>& tarray)
204+
{
205+
_bson_append_tarray<bool>(b, key, tarray, [](bson_t *subb, const char *subKey, bool i) { BSON_APPEND_BOOL(subb, subKey, i); });
206+
}
207+
208+
static bool _bson_extract_child_ros_time(bson_t *b, FString key, FROSTime *time, bool LogOnErrors = true)
209+
{
210+
bool KeyFound = false;
211+
time->_Sec = GetInt32FromBSON(key + ".secs", b, KeyFound, LogOnErrors); if (!KeyFound) return false;
212+
time->_NSec = GetInt32FromBSON(key + ".nsecs", b, KeyFound, LogOnErrors); if (!KeyFound) return false;
213+
return true;
214+
}
215+
216+
static void _bson_append_child_ros_time(bson_t *b, const char* key, const FROSTime* time)
217+
{
218+
bson_t child;
219+
BSON_APPEND_DOCUMENT_BEGIN(b, key, &child);
220+
BSON_APPEND_INT32(&child, "secs", time->_Sec);
221+
BSON_APPEND_INT32(&child, "nsecs", time->_NSec);
222+
bson_append_document_end(b, &child);
223+
}
224+
};
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
#include "Conversion/Messages/actionlib_msgs/ActionlibMsgsGoalIDConverter.h"
22

33

4-
UActionlibMsgsGoalIDConverter::UActionlibMsgsGoalIDConverter(const FObjectInitializer& ObjectInitializer)
5-
: Super(ObjectInitializer)
4+
UActionlibMsgsGoalIDConverter::UActionlibMsgsGoalIDConverter()
65
{
76
_MessageType = "actionlib_msgs/GoalID";
87
}
98

109
bool UActionlibMsgsGoalIDConverter::ConvertIncomingMessage(const ROSBridgePublishMsg* message, TSharedPtr<FROSBaseMsg> &BaseMsg)
1110
{
12-
auto g = new ROSMessages::actionlib_msgs::GoalID();
13-
BaseMsg = TSharedPtr<FROSBaseMsg>(g);
14-
return _bson_extract_child_goal_id(message->full_msg_bson_, "msg", g);
11+
auto msg = new ROSMessages::actionlib_msgs::GoalID();
12+
BaseMsg = TSharedPtr<FROSBaseMsg>(msg);
13+
return _bson_extract_child_goal_id(message->full_msg_bson_, "msg", msg);
1514
}
1615

1716
bool UActionlibMsgsGoalIDConverter::ConvertOutgoingMessage(TSharedPtr<FROSBaseMsg> BaseMsg, bson_t** message)
1817
{
19-
auto GoalID = StaticCastSharedPtr<ROSMessages::actionlib_msgs::GoalID>(BaseMsg);
20-
18+
auto CastMSG = StaticCastSharedPtr<ROSMessages::actionlib_msgs::GoalID>(BaseMsg);
2119
*message = bson_new();
22-
_bson_append_goal_id(*message, GoalID.Get());
23-
20+
_bson_append_goal_id(*message, CastMSG.Get());
2421
return true;
2522
}
Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#pragma once
22

33
#include "CoreMinimal.h"
4-
#include "UObject/ObjectMacros.h"
5-
#include "UObject/Object.h"
64
#include "Conversion/Messages/BaseMessageConverter.h"
75
#include "actionlib_msgs/GoalID.h"
86
#include "ActionlibMsgsGoalIDConverter.generated.h"
@@ -11,38 +9,39 @@
119
UCLASS()
1210
class ROSINTEGRATION_API UActionlibMsgsGoalIDConverter : public UBaseMessageConverter
1311
{
14-
GENERATED_UCLASS_BODY()
12+
GENERATED_BODY()
1513

1614
public:
15+
UActionlibMsgsGoalIDConverter();
1716
virtual bool ConvertIncomingMessage(const ROSBridgePublishMsg* message, TSharedPtr<FROSBaseMsg> &BaseMsg);
1817
virtual bool ConvertOutgoingMessage(TSharedPtr<FROSBaseMsg> BaseMsg, bson_t** message);
1918

20-
static bool _bson_extract_child_goal_id(bson_t *b, FString key, ROSMessages::actionlib_msgs::GoalID *g, bool LogOnErrors = true)
19+
static bool _bson_extract_child_goal_id(bson_t *b, FString key, ROSMessages::actionlib_msgs::GoalID *msg, bool LogOnErrors = true)
2120
{
2221
bool KeyFound = false;
2322
int32 Sec = GetInt32FromBSON(key + ".stamp.secs", b, KeyFound, LogOnErrors); if (!KeyFound) return false;
2423
int32 NSec = GetInt32FromBSON(key + ".stamp.nsecs", b, KeyFound, LogOnErrors); if (!KeyFound) return false;
25-
g->id = GetFStringFromBSON(key + ".id", b, KeyFound, LogOnErrors); if (!KeyFound) return false;
26-
g->stamp = FROSTime(Sec, NSec);
24+
msg->id = GetFStringFromBSON(key + ".id", b, KeyFound, LogOnErrors); if (!KeyFound) return false;
25+
msg->stamp = FROSTime(Sec, NSec);
2726

2827
return true;
2928
}
3029

31-
static void _bson_append_child_goal_id(bson_t *b, const char *key, const ROSMessages::actionlib_msgs::GoalID *g)
30+
static void _bson_append_child_goal_id(bson_t *b, const char *key, const ROSMessages::actionlib_msgs::GoalID *msg)
3231
{
33-
bson_t goalID;
34-
BSON_APPEND_DOCUMENT_BEGIN(b, key, &goalID);
35-
_bson_append_goal_id(&goalID, g);
36-
bson_append_document_end(b, &goalID);
32+
bson_t child;
33+
BSON_APPEND_DOCUMENT_BEGIN(b, key, &child);
34+
_bson_append_goal_id(&child, msg);
35+
bson_append_document_end(b, &child);
3736
}
3837

39-
static void _bson_append_goal_id(bson_t *b, const ROSMessages::actionlib_msgs::GoalID *g)
38+
static void _bson_append_goal_id(bson_t *b, const ROSMessages::actionlib_msgs::GoalID *msg)
4039
{
4140
bson_t stamp;
4241
BSON_APPEND_DOCUMENT_BEGIN(b, "stamp", &stamp);
43-
BSON_APPEND_INT32(&stamp, "secs", g->stamp._Sec);
44-
BSON_APPEND_INT32(&stamp, "nsecs", g->stamp._NSec);
42+
BSON_APPEND_INT32(&stamp, "secs", msg->stamp._Sec);
43+
BSON_APPEND_INT32(&stamp, "nsecs", msg->stamp._NSec);
4544
bson_append_document_end(b, &stamp);
46-
BSON_APPEND_UTF8(b, "id", TCHAR_TO_UTF8(*g->id));
45+
BSON_APPEND_UTF8(b, "id", TCHAR_TO_UTF8(*msg->id));
4746
}
4847
};
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
#include "Conversion/Messages/actionlib_msgs/ActionlibMsgsGoalStatusArrayConverter.h"
22

33

4-
UActionlibMsgsGoalStatusArrayConverter::UActionlibMsgsGoalStatusArrayConverter(const FObjectInitializer& ObjectInitializer)
5-
: Super(ObjectInitializer)
4+
UActionlibMsgsGoalStatusArrayConverter::UActionlibMsgsGoalStatusArrayConverter()
65
{
76
_MessageType = "actionlib_msgs/GoalStatusArray";
87
}
98

109
bool UActionlibMsgsGoalStatusArrayConverter::ConvertIncomingMessage(const ROSBridgePublishMsg* message, TSharedPtr<FROSBaseMsg> &BaseMsg)
1110
{
12-
auto g = new ROSMessages::actionlib_msgs::GoalStatusArray();
13-
BaseMsg = TSharedPtr<FROSBaseMsg>(g);
14-
return _bson_extract_child_goal_status_array(message->full_msg_bson_, "msg", g);
11+
auto msg = new ROSMessages::actionlib_msgs::GoalStatusArray();
12+
BaseMsg = TSharedPtr<FROSBaseMsg>(msg);
13+
return _bson_extract_child_goal_status_array(message->full_msg_bson_, "msg", msg);
1514
}
1615

1716
bool UActionlibMsgsGoalStatusArrayConverter::ConvertOutgoingMessage(TSharedPtr<FROSBaseMsg> BaseMsg, bson_t** message)
1817
{
19-
auto GoalStatusArray = StaticCastSharedPtr<ROSMessages::actionlib_msgs::GoalStatusArray>(BaseMsg);
20-
18+
auto CastMSG = StaticCastSharedPtr<ROSMessages::actionlib_msgs::GoalStatusArray>(BaseMsg);
2119
*message = bson_new();
22-
_bson_append_goal_status_array(*message, GoalStatusArray.Get());
23-
20+
_bson_append_goal_status_array(*message, CastMSG.Get());
2421
return true;
2522
}

0 commit comments

Comments
 (0)