Skip to content

Commit 7c4708d

Browse files
authored
Unity service example (#199)
* added example of implementing a UnityService * adding tutorial for unity service * added a couple comments to the example code * typos and code standard fixes * consistency: changing the service name for position_service to pos_srv * updating the tutorial to match the corresponding script
1 parent 5ae4bb2 commit 7c4708d

File tree

11 files changed

+230
-18
lines changed

11 files changed

+230
-18
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env python
2+
3+
from __future__ import print_function
4+
5+
import random
6+
import rospy
7+
import sys
8+
9+
from robotics_demo.srv import ObjectPoseService, ObjectPoseServiceResponse
10+
11+
12+
def get_object_pose_client(name):
13+
rospy.wait_for_service('obj_pose_srv')
14+
try:
15+
get_obj_pose = rospy.ServiceProxy('obj_pose_srv', ObjectPoseService)
16+
obj_pose_resp = get_obj_pose(name)
17+
return obj_pose_resp.object_pose
18+
except rospy.ServiceException as e:
19+
print("Service call failed: %s"%e)
20+
21+
22+
def usage():
23+
return "%s [object_name]"%sys.argv[0]
24+
25+
if __name__ == "__main__":
26+
if len(sys.argv) == 2:
27+
name = str(sys.argv[1])
28+
else:
29+
print(usage())
30+
sys.exit(1)
31+
print("Requesting pose for %s"%(name))
32+
print("Pose for %s: %s"%(name, get_object_pose_client(name)))

tutorials/ros_packages/robotics_demo/scripts/position_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def new_position(req):
1818

1919
def translate_position_server():
2020
rospy.init_node('position_server')
21-
s = rospy.Service('position_service', PositionService, new_position)
21+
s = rospy.Service('pos_srv', PositionService, new_position)
2222
print("Ready to move cubes!")
2323
rospy.spin()
2424

tutorials/ros_packages/robotics_demo/scripts/server_endpoint.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import rospy
44

5-
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService
5+
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService, UnityService
66
from robotics_demo.msg import PosRot, UnityColor
7-
from robotics_demo.srv import PositionService
7+
from robotics_demo.srv import PositionService, ObjectPoseService
88

99
def main():
1010
ros_node_name = rospy.get_param("/TCP_NODE_NAME", 'TCPServer')
@@ -14,9 +14,10 @@ def main():
1414
rospy.init_node(ros_node_name, anonymous=True)
1515

1616
tcp_server.start({
17-
'pos_srv': RosService('position_service', PositionService),
1817
'pos_rot': RosPublisher('pos_rot', PosRot, queue_size=10),
19-
'color': RosSubscriber('color', UnityColor, tcp_server)
18+
'color': RosSubscriber('color', UnityColor, tcp_server),
19+
'pos_srv': RosService('pos_srv', PositionService),
20+
'obj_pose_srv': UnityService('obj_pose_srv', ObjectPoseService, tcp_server),
2021
})
2122

2223
rospy.spin()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
string object_name
2+
---
3+
geometry_msgs/Pose object_pose

tutorials/ros_unity_integration/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ The `ROSConnection` plugin (also from [ROS TCP Connector](https://github.com/Uni
1717
- [ROS–Unity Integration: Publisher](publisher.md) - Adding a Publisher to a Unity Scene
1818
- [ROS–Unity Integration: Subscriber](subscriber.md) - Adding a Subscriber to a Unity Scene
1919
- [ROS–Unity Integration: Service](service.md) - Adding a Service call to a Unity Scene
20+
- [ROS–Unity Integration: UnityService](unity_service.md) - Adding a Service that runs in a Unity Scene
2021
- [ROS–Unity Integration: Server Endpoint](server_endpoint.md) - How to write a Server Endpoint
2122

2223
## Example Unity Scripts
@@ -26,8 +27,12 @@ Example scripts implemented in tutorials:
2627
- `unity_scripts/RosPublisherExample.cs`
2728
- Publishes the position of a GameObject every 0.5 seconds.
2829

30+
- `unity_scripts/RosSubscriberExample.cs`
31+
- Subscribes to a topic that accepts color messages and uses them to change the color of a GameObject in the Unity scene.
32+
2933
- `unity_scripts/RosServiceExample.cs`
3034
- Returns a destination position for a GameObject to move towards each time the service is called.
3135

32-
- `unity_scripts/RosSubscriberExample.cs`
33-
- Subscribes to a topic that accepts color messages and uses them to change the color of a GameObject in the Unity scene.
36+
- `unity_scripts/RosUnityServiceExample.cs`
37+
- Runs a service in the Unity scene that takes a GameObject's name and responds with the Pose of that object.
38+
-25.2 KB
Loading
-29.9 KB
Loading

tutorials/ros_unity_integration/server_endpoint.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ The following is an example of a server endpoint Python script that:
1414

1515
import rospy
1616

17-
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService
17+
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService, UnityService
1818
from robotics_demo.msg import PosRot, UnityColor
19-
from robotics_demo.srv import PositionService
19+
from robotics_demo.srv import PositionService, ObjectPoseService
2020

2121
def main():
2222
ros_node_name = rospy.get_param("/TCP_NODE_NAME", 'TCPServer')
@@ -26,9 +26,10 @@ def main():
2626
rospy.init_node(ros_node_name, anonymous=True)
2727

2828
tcp_server.start({
29-
'pos_srv': RosService('position_service', PositionService),
3029
'pos_rot': RosPublisher('pos_rot', PosRot, queue_size=10),
31-
'color': RosSubscriber('color', UnityColor, tcp_server)
30+
'color': RosSubscriber('color', UnityColor, tcp_server),
31+
'pos_srv': RosService('pos_srv', PositionService),
32+
'obj_pose_srv': UnityService('obj_pose_srv', ObjectPoseService, tcp_server),
3233
})
3334

3435
rospy.spin()
@@ -41,9 +42,9 @@ if __name__ == "__main__":
4142

4243
## Import Statements for Services and Messages
4344
```python
44-
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService
45+
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService, UnityService
4546
from robotics_demo.msg import PosRot, UnityColor
46-
from robotics_demo.srv import PositionService
47+
from robotics_demo.srv import PositionService, ObjectPoseService
4748
```
4849

4950
## Creating the Server
@@ -68,9 +69,10 @@ The `ros_node_name` argument is required and the `buffer_size` and `connections`
6869

6970
```python
7071
tcp_server.start({
71-
'pos_srv': RosService('position_service', PositionService),
7272
'pos_rot': RosPublisher('pos_rot', PosRot, queue_size=10),
73-
'color': RosSubscriber('color', UnityColor, tcp_server)
73+
'color': RosSubscriber('color', UnityColor, tcp_server),
74+
'pos_srv': RosService('pos_srv', PositionService),
75+
'obj_pose_srv': UnityService('obj_pose_srv', ObjectPoseService, tcp_server),
7476
})
7577

7678
rospy.spin()
@@ -104,7 +106,7 @@ A ROS Service is similar to a RosPublisher, in that a Unity component sends a Re
104106
- Service name
105107
- ROS Service class generated from running `catkin_make` command
106108

107-
`RosService('position_service', PositionService)`
109+
`RosService('pos_srv', PositionService)`
108110

109111
## Unity Service
110112

@@ -114,7 +116,7 @@ A Unity Service is similar to a RosSubscriber, in that a Unity component receive
114116
- ROS Service class generated from running `catkin_make` command
115117
- The tcp server that will connect to Unity
116118

117-
`UnityService('unity_service', PositionService, tcp_server)`
119+
`UnityService('obj_pose_srv', ObjectPoseService, tcp_server)`
118120

119121

120122
## Parameters

tutorials/ros_unity_integration/service.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Once the server_endpoint has started, it will print something similar to `[INFO]
2929

3030
## Setting Up Unity Scene
3131
- Generate the C# code for `PositionService`'s messages by going to `Robotics` -> `Generate ROS Messages...`
32-
- Set the input file path to `PATH/TO/Unity-Robotics-Hub/tutorials/ros_packages/robotics_demo`, expand the robotics_demo folder and click `Build 1 srv`.
32+
- Set the input file path to `PATH/TO/Unity-Robotics-Hub/tutorials/ros_packages/robotics_demo`, expand the robotics_demo folder and click `Build 2 srvs`.
3333

3434
![](images/generate_messages_2.png)
3535

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using RosMessageTypes.RoboticsDemo;
2+
using UnityEngine;
3+
using Unity.Robotics.ROSTCPConnector;
4+
using Unity.Robotics.ROSTCPConnector.ROSGeometry;
5+
6+
/// <summary>
7+
/// Example demonstration of implementing a UnityService that receives a Request message from another ROS node and sends a Response back
8+
/// </summary>
9+
public class RosUnityServiceExample : MonoBehaviour
10+
{
11+
[SerializeField]
12+
string m_ServiceName = "obj_pose_srv";
13+
14+
void Start()
15+
{
16+
// register the service with ROS
17+
ROSConnection.instance.ImplementService<MObjectPoseServiceRequest>(m_ServiceName, GetObjectPose);
18+
}
19+
20+
/// <summary>
21+
/// Callback to respond to the request
22+
/// </summary>
23+
/// <param name="request">service request containing the object name</param>
24+
/// <returns>service response containing the object pose (or 0 if object not found)</returns>
25+
private MObjectPoseServiceResponse GetObjectPose(MObjectPoseServiceRequest request)
26+
{
27+
// process the service request
28+
Debug.Log("Received request for object: " + request.object_name);
29+
30+
// prepare a response
31+
MObjectPoseServiceResponse objectPoseResponse = new MObjectPoseServiceResponse();
32+
// Find a game object with the requested name
33+
GameObject gameObject = GameObject.Find(request.object_name);
34+
if (gameObject)
35+
{
36+
// Fill-in the response with the object pose converted from Unity coordinate to ROS coordinate system
37+
objectPoseResponse.object_pose.position = gameObject.transform.position.To<FLU>();
38+
objectPoseResponse.object_pose.orientation = gameObject.transform.rotation.To<FLU>();
39+
}
40+
41+
return objectPoseResponse;
42+
}
43+
}

0 commit comments

Comments
 (0)