4
4
uio: packet buffer
5
5
struct: serlization
6
6
_TopicInfo: for topic negotiation
7
- already provided in rosserial_msgs
7
+ already provided in rosserial_msgs
8
8
"""
9
9
10
+ import sys
11
+ import logging
10
12
import machine as m
11
13
import uio
12
- import ustruct as struct
13
- from time import sleep , sleep_ms , sleep_us
14
14
from rosserial_msgs import TopicInfo
15
- import sys
16
- import os
17
- import logging
18
15
19
16
# for now threads are used, will be changed with asyncio in the future
20
17
if sys .platform == "esp32" :
29
26
30
27
# class to manage publish and subscribe
31
28
# COULD BE CHANGED AFTERWARDS
32
- class NodeHandle ( object ) :
33
- def __init__ ( self , serial_id = 2 , baudrate = 115200 , ** kwargs ):
29
+ class NodeHandle :
30
+ """Initiates connection through rosserial using UART ports."""
34
31
32
+ def __init__ (self , serial_id = 2 , baudrate = 115200 , ** kwargs ):
35
33
"""
36
- id: used for topics id (negotiation)
37
- advertised_topics: manage already negotiated topics
38
- subscribing_topics: topics to which will be subscribed are here
39
- serial_id: uart id
40
- baudrate: baudrate used for serial comm
41
- """
42
- self .id = 101
34
+ id: used for topics id (negotiation)
35
+ advertised_topics: manage already negotiated topics
36
+ subscribing_topics: topics to which will be subscribed are here
37
+ serial_id: uart id
38
+ baudrate: baudrate used for serial comm
39
+ """
40
+ self ._id = 101
43
41
self .advertised_topics = dict ()
44
42
self .subscribing_topics = dict ()
45
43
self .serial_id = serial_id
@@ -69,28 +67,18 @@ def __init__(self, serial_id=2, baudrate=115200, **kwargs):
69
67
70
68
# method to manage and advertise topic
71
69
# before publishing or subscribing
72
- def _advertise_topic (self , topic_name , msg , endpoint , buffer_size ):
73
-
70
+ def _advertise_topic (self , topic_name , _id , msg , endpoint , buffer_size ):
71
+ """
72
+ topic_name: eg. (Greet)
73
+ msg: message object
74
+ endpoint: corresponds to TopicInfo.msg typical topic id values
74
75
"""
75
- topic_name: eg. (Greet)
76
- msg: message object
77
- endpoint: corresponds to TopicInfo.msg typical topic id values
78
- """
79
76
register = TopicInfo ()
80
- register .topic_id = self . id
77
+ register .topic_id = _id
81
78
register .topic_name = topic_name
82
79
register .message_type = msg ._type
83
80
register .md5sum = msg ._md5sum
84
-
85
- self .advertised_topics [topic_name ] = self .id
86
-
87
- # id are summed by one
88
- self .id += 1
89
-
90
- try :
91
- register .buffer_size = buffer_size
92
- except Exception as e :
93
- logging .info ("No buffer size could be defined for topic negotiation." )
81
+ register .buffer_size = buffer_size
94
82
95
83
# serialization
96
84
packet = uio .StringIO ()
@@ -101,17 +89,31 @@ def _advertise_topic(self, topic_name, msg, endpoint, buffer_size):
101
89
length = len (packet )
102
90
103
91
# both checksums
104
- crclen = [checksum (le (length ))]
105
- crcpack = [checksum (le (endpoint ) + packet )]
92
+ crclen = [checksum (_le (length ))]
93
+ crcpack = [checksum (_le (endpoint ) + packet )]
106
94
107
95
# final packet to be sent
108
- fpacket = header + le (length ) + crclen + le (endpoint ) + packet + crcpack
96
+ fpacket = header + _le (length ) + crclen + _le (endpoint ) + packet + crcpack
109
97
self .uart .write (bytearray (fpacket ))
110
98
99
+ def _advertise_all_topics (self ):
100
+ for key , value in self .advertised_topics .items ():
101
+ self ._advertise_topic (key , value [0 ], value [1 ], value [2 ], value [3 ])
102
+
111
103
def publish (self , topic_name , msg , buffer_size = 1024 ):
104
+ """publishes messages to topics
105
+
106
+ Args:
107
+ topic_name (string): name of destination topic in ROS network.
108
+ msg (ROS message): custom message object generated by ugenpy.
109
+ buffer_size (int, optional): maximum size of buffer for message. Defaults to 1024.
110
+ """
112
111
113
112
if topic_name not in self .advertised_topics :
114
- self ._advertise_topic (topic_name , msg , 0 , buffer_size )
113
+ self .advertised_topics [topic_name ] = [self ._id , msg , 0 , buffer_size ]
114
+ # id are summed by one
115
+ self ._advertise_topic (topic_name , self ._id , msg , 0 , buffer_size )
116
+ self ._id += 1
115
117
116
118
# same as advertise
117
119
packet = uio .StringIO ()
@@ -120,23 +122,33 @@ def publish(self, topic_name, msg, buffer_size=1024):
120
122
packet = list (packet .getvalue ().encode ("utf-8" ))
121
123
length = len (packet )
122
124
123
- topic_id = le (self .advertised_topics .get (topic_name ))
124
- crclen = [checksum (le (length ))]
125
+ topic_id = _le (self .advertised_topics .get (topic_name )[ 0 ] )
126
+ crclen = [checksum (_le (length ))]
125
127
crcpack = [checksum (topic_id + packet )]
126
128
127
- fpacket = header + le (length ) + crclen + topic_id + packet + crcpack
129
+ fpacket = header + _le (length ) + crclen + topic_id + packet + crcpack
128
130
self .uart .write (bytearray (fpacket ))
129
131
130
- def subscribe (self , topic_name , msgobj , cb , buffer_size = 1024 ):
131
- assert cb is not None , "Subscribe callback is not set"
132
+ def subscribe (self , topic_name , msg , _cb , buffer_size = 1024 ):
133
+ """subscribes to a topic receiving messages and processing them by a callback function
134
+
135
+ Args:
136
+ topic_name (string): name of destiny topic to send messages.
137
+ msg (ROS message): custom message object generated by ugenpy.
138
+ cb (function): callback function to process incoming messages.
139
+ buffer_size (int, optional): maximum size of buffer for message. Defaults to 1024.
140
+ """
141
+ assert _cb is not None , "Subscribe callback is not set"
132
142
133
143
# subscribing topic attributes are added
134
- self .subscribing_topics [self .id ] = [msgobj , cb ]
144
+ self .subscribing_topics [self ._id ] = [msg , _cb ]
135
145
136
146
# advertised if not already subscribed
137
147
if topic_name not in self .advertised_topics :
138
- msg = msgobj ()
139
- self ._advertise_topic (topic_name , msg , 1 , buffer_size )
148
+ self .advertised_topics [topic_name ] = [self ._id , msg , 1 , buffer_size ]
149
+ # id are summed by one
150
+ self ._advertise_topic (topic_name , self ._id , msg , 1 , buffer_size )
151
+ self ._id += 1
140
152
141
153
def _listen (self ):
142
154
while True :
@@ -166,46 +178,47 @@ def _listen(self):
166
178
try :
167
179
# incoming object msg initialized
168
180
msgobj = self .subscribing_topics .get (inid )[0 ]
169
- except Exception :
170
- logging .info ("TX request was made or got message from not available subscribed topic." )
181
+ except (OSError , TypeError , IndexError ):
182
+ logging .info (
183
+ "TX request was made or got message from"
184
+ + "not available subscribed topic."
185
+ )
171
186
# object sent to callback
172
187
callback = self .subscribing_topics .get (inid )[1 ]
173
188
fdata = msgobj ()
174
189
fdata = fdata .deserialize (msgdata )
175
190
callback (fdata )
176
191
else :
177
192
raise ValueError ("Message plus Topic ID Checksum is wrong!" )
193
+ else :
194
+ self ._advertise_all_topics ()
178
195
179
- except Exception as e :
196
+ except ( OSError , TypeError , ValueError ) :
180
197
logging .info ("No incoming data could be read for subscribes." )
181
198
182
199
183
200
# functions to be used in class
184
- def word (l , h ):
201
+ def word (_l , _h ):
202
+ """
203
+ Given a low and high bit, converts the number back into a word.
185
204
"""
186
- Given a low and high bit, converts the number back into a word.
187
- """
188
- return (h << 8 ) + l
205
+ return (_h << 8 ) + _l
189
206
190
207
191
208
# checksum method, receives array
192
209
def checksum (arr ):
193
- return 255 - ((sum (arr )) % 256 )
194
-
210
+ """Generates checksum value of message.
195
211
196
- # little-endian method
197
- def le (h ):
198
- h &= 0xFFFF
199
- return [h & 0xFF , h >> 8 ]
212
+ Args:
213
+ arr (list): list of hexadecimal values.
200
214
215
+ Returns:
216
+ [int]: returns an value between 0 and 256
217
+ """
218
+ return 255 - ((sum (arr )) % 256 )
201
219
202
- # example code
203
- if __name__ == "__main__" :
204
- from std_msgs import String
205
- from uros import NodeHandle
206
220
207
- msg = String ()
208
- msg .data = "HiItsMeMario"
209
- node = NodeHandle (2 , 115200 )
210
- while True :
211
- node .publish ("greet" , msg )
221
+ # little-endian method
222
+ def _le (_h ):
223
+ _h &= 0xFFFF
224
+ return [_h & 0xFF , _h >> 8 ]
0 commit comments