Skip to content

Commit 3967c91

Browse files
Internal commands are serialized as Json, not as ros messages
1 parent 37f2fca commit 3967c91

File tree

11 files changed

+112
-177
lines changed

11 files changed

+112
-177
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ROS_IP: 127.0.0.1
1+
ROS_IP: 0.0.0.0

ROS_Packages/ros_tcp_endpoint/src/ros_tcp_endpoint/client.py

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from io import BytesIO
1919

2020
import threading
21+
import json
2122

2223
from .exceptions import TopicOrServiceNameDoesNotExistError
2324
from unity_interfaces.msg import RosUnitySrvMessage
@@ -145,6 +146,43 @@ def serialize_message(destination, message):
145146

146147
return serialized_message
147148

149+
@staticmethod
150+
def serialize_command(command, params):
151+
cmd_bytes = command.encode("utf-8")
152+
cmd_length = len(cmd_bytes)
153+
cmd_info = struct.pack("<I%ss" % cmd_length, cmd_length, cmd_bytes)
154+
155+
json_bytes = json.dumps(params.__dict__).encode("utf-8")
156+
json_length = len(json_bytes)
157+
json_info = struct.pack("<I%ss" % json_length, json_length, json_bytes)
158+
159+
return cmd_info + json_info
160+
161+
def send_ros_service_request(self, srv_id, destination, data):
162+
if destination not in self.tcp_server.source_destination_dict.keys():
163+
error_msg = "Service destination '{}' is not registered! Known topics are: {} ".format(
164+
destination, self.tcp_server.source_destination_dict.keys()
165+
)
166+
self.tcp_server.send_unity_error(error_msg)
167+
rospy.logerr(error_msg)
168+
# TODO: send a response to Unity anyway?
169+
return
170+
else:
171+
ros_communicator = self.tcp_server.source_destination_dict[
172+
destination
173+
]
174+
response = ros_communicator.send(data)
175+
if not response:
176+
error_msg = "No response data from service '{}'!".format(
177+
destination
178+
)
179+
self.tcp_server.send_unity_error(error_msg)
180+
rospy.logerr(error_msg)
181+
# TODO: send a response to Unity anyway?
182+
return
183+
184+
self.tcp_server.unity_tcp_sender.send_ros_service_response(srv_id, destination, response)
185+
148186
def run(self):
149187
"""
150188
Read a message and determine where to send it based on the source_destination_dict
@@ -166,51 +204,20 @@ def run(self):
166204
try:
167205
while not halt_event.is_set():
168206
destination, data = self.read_message(self.conn)
169-
170-
if destination == "":
207+
208+
if self.tcp_server.pending_srv_id is not None:
209+
# if we've been told that the next message will be a service request/response, process it as such
210+
if self.tcp_server.pending_srv_is_request:
211+
self.send_ros_service_request(self.tcp_server.pending_srv_id, destination, data)
212+
else:
213+
self.tcp_server.send_unity_service_response(self.tcp_server.pending_srv_id, data)
214+
self.tcp_server.pending_srv_id = None
215+
elif destination == "":
171216
# ignore this keepalive message, listen for more
172217
pass
173-
elif destination == "__syscommand":
218+
elif destination.startswith("__"):
174219
# handle a system command, such as registering new topics
175-
self.tcp_server.handle_syscommand(data)
176-
elif destination == "__srv":
177-
# handle a ros service message request, or a unity service message response
178-
srv_message = RosUnitySrvMessage().deserialize(data)
179-
if not srv_message.is_request:
180-
self.tcp_server.send_unity_service_response(
181-
srv_message.srv_id, srv_message.payload
182-
)
183-
continue
184-
elif srv_message.topic == "__topic_list":
185-
response = self.tcp_server.topic_list(data)
186-
elif srv_message.topic not in self.tcp_server.source_destination_dict.keys():
187-
error_msg = "Service destination '{}' is not registered! Known topics are: {} ".format(
188-
srv_message.topic, self.tcp_server.source_destination_dict.keys()
189-
)
190-
self.tcp_server.send_unity_error(error_msg)
191-
rospy.logerr(error_msg)
192-
# TODO: send a response to Unity anyway?
193-
continue
194-
else:
195-
ros_communicator = self.tcp_server.source_destination_dict[
196-
srv_message.topic
197-
]
198-
response = ros_communicator.send(srv_message.payload)
199-
if not response:
200-
error_msg = "No response data from service '{}'!".format(
201-
srv_message.topic
202-
)
203-
self.tcp_server.send_unity_error(error_msg)
204-
rospy.logerr(error_msg)
205-
# TODO: send a response to Unity anyway?
206-
continue
207-
208-
serial_response = BytesIO()
209-
response.serialize(serial_response)
210-
response_message = RosUnitySrvMessage(
211-
srv_message.srv_id, False, "", serial_response.getvalue()
212-
)
213-
self.tcp_server.unity_tcp_sender.send_unity_message("__srv", response_message)
220+
self.tcp_server.handle_syscommand(destination, data)
214221
elif destination in self.tcp_server.source_destination_dict:
215222
ros_communicator = self.tcp_server.source_destination_dict[destination]
216223
response = ros_communicator.send(data)

ROS_Packages/ros_tcp_endpoint/src/ros_tcp_endpoint/server.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def __init__(self, node_name, buffer_size=1024, connections=2, tcp_ip="", tcp_po
6161
self.buffer_size = buffer_size
6262
self.connections = connections
6363
self.syscommands = SysCommands(self)
64+
self.pending_srv_id = None
65+
self.pending_srv_is_request = False
6466

6567
def start(self, source_destination_dict=None):
6668
if source_destination_dict is not None:
@@ -96,27 +98,26 @@ def send_unity_message(self, topic, message):
9698
self.unity_tcp_sender.send_unity_message(topic, message)
9799

98100
def send_unity_service(self, topic, service_class, request):
99-
return self.unity_tcp_sender.send_unity_service(topic, service_class, request)
101+
return self.unity_tcp_sender.send_unity_service_request(topic, service_class, request)
100102

101103
def send_unity_service_response(self, srv_id, data):
102104
self.unity_tcp_sender.send_unity_service_response(srv_id, data)
103105

104106
def topic_list(self, data):
105107
return RosUnityTopicListResponse(self.source_destination_dict.keys())
106108

107-
def handle_syscommand(self, data):
108-
message = RosUnitySysCommand().deserialize(data)
109-
function = getattr(self.syscommands, message.command)
109+
def handle_syscommand(self, topic, data):
110+
function = getattr(self.syscommands, topic[2:])
110111
if function is None:
111112
self.send_unity_error(
112-
"Don't understand SysCommand.'{}'({})".format(message.command, message.params_json)
113+
"Don't understand SysCommand.'{}'".format(topic)
113114
)
114115
return
115116
else:
116-
params = json.loads(message.params_json)
117+
message_json = data.decode("utf-8")
118+
params = json.loads(message_json)
117119
function(**params)
118120

119-
120121
class SysCommands:
121122
def __init__(self, tcp_server):
122123
self.tcp_server = tcp_server
@@ -222,6 +223,15 @@ def unity_service(self, topic, message_name):
222223
self.tcp_server.source_destination_dict[topic] = UnityService(
223224
topic.encode("ascii"), message_class, self.tcp_server
224225
)
226+
227+
def response(self, srv_id): # the next message is a service response
228+
self.tcp_server.pending_srv_id = srv_id
229+
self.tcp_server.pending_srv_is_request = False
230+
231+
def request(self, srv_id): # the next message is a service request
232+
self.tcp_server.pending_srv_id = srv_id
233+
self.tcp_server.pending_srv_is_request = True
234+
225235

226236

227237
def resolve_message_name(name, extension="msg"):

ROS_Packages/ros_tcp_endpoint/src/ros_tcp_endpoint/tcp_sender.py

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
class UnityTcpSender:
3636
"""
37-
Connects and sends messages to the server on the Unity side.
37+
Sends messages to Unity.
3838
"""
3939

4040
def __init__(self):
@@ -51,29 +51,55 @@ def __init__(self):
5151
self.srv_lock = threading.Lock()
5252
self.services_waiting = {}
5353

54-
def send_unity_error(self, error):
55-
self.send_unity_message("__error", RosUnityError(error))
54+
def send_unity_info(self, text):
55+
if self.queue is not None:
56+
command = SysCommand_Log()
57+
command.text = text
58+
serialized_bytes = ClientThread.serialize_command("__log", command)
59+
self.queue.put(serialized_bytes)
60+
61+
def send_unity_warning(self, text):
62+
if self.queue is not None:
63+
command = SysCommand_Log()
64+
command.text = text
65+
serialized_bytes = ClientThread.serialize_command("__warn", command)
66+
self.queue.put(serialized_bytes)
67+
68+
def send_unity_error(self, text):
69+
if self.queue is not None:
70+
command = SysCommand_Log()
71+
command.text = text
72+
serialized_bytes = ClientThread.serialize_command("__error", command)
73+
self.queue.put(serialized_bytes)
74+
75+
def send_ros_service_response(self, srv_id, destination, response):
76+
if self.queue is not None:
77+
command = SysCommand_Service()
78+
command.srv_id = srv_id
79+
serialized_bytes = ClientThread.serialize_command("__response", command)
80+
self.queue.put(serialized_bytes)
81+
self.send_unity_message(destination, response)
5682

5783
def send_unity_message(self, topic, message):
58-
serialized_message = ClientThread.serialize_message(topic, message)
5984
if self.queue is not None:
85+
serialized_message = ClientThread.serialize_message(topic, message)
6086
self.queue.put(serialized_message)
6187

62-
def send_unity_service(self, topic, service_class, request):
63-
request_bytes = BytesIO()
64-
request.serialize(request_bytes)
88+
def send_unity_service_request(self, topic, service_class, request):
89+
if self.queue is None:
90+
return None
91+
6592
thread_pauser = ThreadPauser()
66-
6793
with self.srv_lock:
6894
srv_id = self.next_srv_id
6995
self.next_srv_id += 1
7096
self.services_waiting[srv_id] = thread_pauser
7197

72-
payload = request_bytes.getvalue()
73-
srv_message = RosUnitySrvMessage(srv_id, True, topic, payload)
74-
serialized_message = ClientThread.serialize_message("__srv", srv_message)
75-
if self.queue is not None:
76-
self.queue.put(serialized_message)
98+
command = SysCommand_Service()
99+
command.srv_id = srv_id
100+
serialized_bytes = ClientThread.serialize_command("__request", command)
101+
self.queue.put(serialized_bytes)
102+
self.send_unity_message(topic, request)
77103

78104
# rospy starts a new thread for each service request,
79105
# so it won't break anything if we sleep now while waiting for the response
@@ -130,3 +156,9 @@ def sender_loop(self, conn, tid, halt_event):
130156
with self.queue_lock:
131157
if self.queue is local_queue:
132158
self.queue = None
159+
160+
class SysCommand_Log:
161+
text = ""
162+
163+
class SysCommand_Service:
164+
srv_id = 0

ROS_Packages/unity_interfaces/CMakeLists.txt

Lines changed: 0 additions & 22 deletions
This file was deleted.

ROS_Packages/unity_interfaces/msg/RosUnityError.msg

Lines changed: 0 additions & 1 deletion
This file was deleted.

ROS_Packages/unity_interfaces/msg/RosUnitySrvMessage.msg

Lines changed: 0 additions & 4 deletions
This file was deleted.

ROS_Packages/unity_interfaces/msg/RosUnitySysCommand.msg

Lines changed: 0 additions & 2 deletions
This file was deleted.

ROS_Packages/unity_interfaces/package.xml

Lines changed: 0 additions & 23 deletions
This file was deleted.

ROS_Packages/unity_interfaces/srv/RosUnityTopicList.srv

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)