High-performance ROS2 solution for Unity3D
ROS2 For Unity is a high-performance communication solution to connect Unity3D and ROS2 ecosystem in a ROS2 "native" way. Communication is not bridged as in several other solutions, but instead it uses ROS2 middleware stack (rcl layer and below), which means you can have ROS2 nodes in your simulation. Advantages of this module include:
ros2 topic
. They will respect QoS settings and can use ROS2 native time..cs
equivalents by hand.Supported OSes:
* ROS2 Galactic and Humble support only Windows 10 (ROS 2 Windows system requirements), but it is proven that it also works fine on Windows 11.
Supported ROS2 distributions:
Supported Unity3d:
Older versions of Unity3d may work, but the editor executable most probably won't be detected properly by deployment script. This would require user confirmation for using unsupported version.
This asset can be prepared in two flavours:
The best way to start quickly is to use our releases.
You can download pre-built releases of the Asset that support both platforms and specific ros2 and Unity3D versions.
Note: The project will pull
ros2cs
into the workspace, which also functions independently as it is a more general project aimed at anyC# / .Net
environment. It has its own README and scripting, but for building the Unity Asset, please use instructions and scripting in this document instead, unless you also wish to run tests or examples forros2cs
.
Please see OS-specific instructions:
Custom messages can be included in the build by either:
ros2_for_unity_custom_messages.repos
file, orsrc/ros2cs
directory. If the folder doesn't exist, you must pull repositories first (see building steps for each OS).ros2-for-unity
nor ros2cs
project into ROS2 workspace.install/asset/Ros2ForUnity
into your project Assets
folder, or.unitypackage
- import it in Unity Editor by selecting Import Package
→ Custom Package
Prerequisites
--standalone
flag then you are fine, and all you have to do is run the editorotherwise
Ros2ForUnity
version, then run the editor from within the very same terminal/console.Initializing Ros2ForUnity
Ros2ForUnity
by creating a "hook" object which will be your wrapper around ROS2. You have two options:
ROS2UnityComponent
based on MonoBehaviour
which must be attached to a GameObject
somewhere in the scene, then:
using ROS2;
...
// Example method of getting component, if ROS2UnityComponent lives in different GameObject, just use different get component methods.
ROS2UnityComponent ros2Unity = GetComponent<ROS2UnityComponent>();
ROS2UnityCore
which is a standard class that can be created anywhere
using ROS2;
...
ROS2UnityCore ros2Unity = new ROS2UnityCore();
Ros2ForUnity
is initialized correctly:
private ROS2Node ros2Node;
...
if (ros2Unity.Ok()) {
ros2Node = ros2Unity.CreateNode("ROS2UnityListenerNode");
}
Publishing messages:
private IPublisher<std_msgs.msg.String> chatter_pub;
...
if (ros2Unity.Ok()){
chatter_pub = ros2Node.CreatePublisher<std_msgs.msg.String>("chatter");
}
std_msgs.msg.String msg = new std_msgs.msg.String();
msg.Data = "Hello Ros2ForUnity!";
chatter_pub.Publish(msg);
Subscribing to a topic
private ISubscription<std_msgs.msg.String> chatter_sub;
...
if (ros2Unity.Ok()) {
chatter_sub = ros2Node.CreateSubscription<std_msgs.msg.String>(
"chatter", msg => Debug.Log("Unity listener heard: [" + msg.Data + "]"));
}
Creating a service
Create service body:
public example_interfaces.srv.AddTwoInts_Response addTwoInts( example_interfaces.srv.AddTwoInts_Request msg)
{
example_interfaces.srv.AddTwoInts_Response response = new example_interfaces.srv.AddTwoInts_Response();
response.Sum = msg.A + msg.B;
return response;
}
Create a service with a service name and callback:
IService<example_interfaces.srv.AddTwoInts_Request, example_interfaces.srv.AddTwoInts_Response> service =
ros2Node.CreateService<example_interfaces.srv.AddTwoInts_Request, example_interfaces.srv.AddTwoInts_Response>(
"add_two_ints", addTwoInts);
Calling a service
Create a client:
private IClient<example_interfaces.srv.AddTwoInts_Request, example_interfaces.srv.AddTwoInts_Response> addTwoIntsClient;
...
addTwoIntsClient = ros2Node.CreateClient<example_interfaces.srv.AddTwoInts_Request, example_interfaces.srv.AddTwoInts_Response>(
"add_two_ints");
Create a request and call a service:
example_interfaces.srv.AddTwoInts_Request request = new example_interfaces.srv.AddTwoInts_Request();
request.A = 1;
request.B = 2;
var response = addTwoIntsClient.Call(request);
You can also make an async call:
Task<example_interfaces.srv.AddTwoInts_Response> asyncTask = addTwoIntsClient.CallAsync(request);
...
asyncTask.ContinueWith((task) => { Debug.Log("Got answer " + task.Result.Sum); });
ROS2UnityComponent.cs
. This is the central Monobehavior
for Ros2ForUnity
that manages all the nodes. Refer to class documentation for details.
Note: Each example script looks for
ROS2UnityComponent
in its own game object. However, this is not a requirement, just example implementation.
Topics
ROS2TalkerExample.cs
script to the very same game object.ROS2ListenerExample.cs
script to the very same game object.Once you start the project in Unity, you should be able to see two nodes talking with each other in Unity Editor's console or use ros2 node list
and ros2 topic echo /chatter
to verify ros2 communication.
Services
ROS2ServiceExample.cs
script to the very same game object.ROS2ClientExample.cs
script to the very same game object.Once you start the project in Unity, you should be able to see client node calling an example service.
Open-source release of ROS2 For Unity was made possible through cooperation with Tier IV. Thanks to encouragement, support and requirements driven by Tier IV the project was significantly improved in terms of portability, stability, core structure and user-friendliness.