@@ -26,104 +26,34 @@ Simplifies dependency management and makes using a different version of python p
26
26
27
27
## Examples
28
28
29
- Check out the scripts folder for a few ` rosrun ` able scripts .
29
+ Check out the ` scripts ` folder for examples of topics, services, actions, and a composite node .
30
30
31
- ### Example Publisher and Subscriber
31
+ Take note that when using ` rospy ` and ` asyncio ` together, the following boilerplate is recommended:
32
32
33
- ``` python
34
- # !/usr/bin/env python3.6
33
+ ```
34
+ import aiorospy
35
35
import asyncio
36
36
import rospy
37
- from aiorospy import AsyncSubscriber
38
- from std_msgs.msg import String
39
-
40
- sub = AsyncSubscriber(' ping' , String)
41
- pub = rospy.Publisher(' ping' , String, queue_size = 1 )
42
-
43
- async def send_ping ():
44
- while True :
45
- pub.publish(f ' Ping! ' )
46
- await asyncio.sleep(1 )
47
-
48
- async def receive_ping ():
49
- async for message in sub.subscribe():
50
- print (f ' Received: { message.data} ' )
51
-
52
- if __name__ == ' __main__' :
53
- rospy.init_node(' example_pubsub' , disable_signals = True )
54
- try :
55
- asyncio.get_event_loop().run_until_complete(asyncio.gather(send_ping(), receive_ping())
56
- finally :
57
- rospy.signal_shutdown(' Shutting down.' )
58
- ```
59
37
60
- # ## Example Service Proxy
38
+ rospy.init_node('node_name')
61
39
62
- ```python
63
- # !/usr/bin/env python3.6
64
- import asyncio
65
- import rospy
66
- from aiorospy import AsyncServiceProxy
67
- from std_srvs.srv import SetBool, SetBoolResponse
68
-
69
- proxy = AsyncServiceProxy(' ping' , SetBool)
70
-
71
- async def call_service():
72
- while True :
73
- response = await proxy.send(True )
74
- print (response.message)
75
- await asyncio.sleep(1 )
76
-
77
- if __name__ == ' __main__' :
78
- rospy.init_node(' example_service' , disable_signals = True )
79
- try :
80
- asyncio.get_event_loop().run_until_complete(call_service())
81
- finally :
82
- rospy.signal_shutdown(' Shutting down.' )
83
- ```
40
+ loop = asyncio.get_event_loop()
84
41
42
+ tasks = asyncio.gather(
43
+ my_top_level_task(),
44
+ # ...
45
+ )
85
46
86
- # ## Example Simple Action
47
+ # Any uncaught exceptions will cause this task to get cancelled
48
+ aiorospy.cancel_on_exception(tasks)
49
+ # ROS shutdown will cause this task toget cancelled
50
+ aiorospy.cancel_on_shutdown(tasks)
87
51
88
- ```python
89
- # !/usr/bin/env python3.6
90
- import asyncio
91
- import rospy
92
- from actionlib.msg import TwoIntsAction, TwoIntsGoal, TwoIntsResult
93
- from aiorospy import AsyncSimpleActionClient, AsyncSimpleActionServer
94
-
95
- class ExampleSimpleAction:
96
-
97
- def __init__ (self ):
98
- self .server = AsyncSimpleActionServer(' add_two_ints' , TwoIntsAction, self .execute)
99
- self .server.start()
100
-
101
- self .client = AsyncSimpleActionClient(' add_two_ints' , TwoIntsAction)
102
-
103
- async def execute(self , goal):
104
- await asyncio.sleep(3 )
105
- self .server.set_succeeded(TwoIntsResult(goal.a + goal.b))
106
-
107
- async def send_goals(self ):
108
- while True :
109
- result = await self .client.send_goal(TwoIntsGoal(1 , 2 ))
110
- print (f ' The result is: { result} ' )
111
- await asyncio.sleep(5 )
112
-
113
- if __name__ == ' __main__' :
114
- rospy.init_node(' example_actionlib' , disable_signals = True )
115
- example = ExampleSimpleAction()
116
- try :
117
- asyncio.get_event_loop().run_until_complete(example.send_goals())
118
- finally :
119
- rospy.signal_shutdown(' Shutting down.' )
52
+ try:
53
+ loop.run_until_complete(tasks)
54
+ except asyncio.CancelledError:
55
+ pass
120
56
```
121
57
122
58
## How it works
123
59
There's no desire to reimplement rospy this late in its life, so this package wraps the various rospy interfaces instead. This means that there are still underlying threads that handle TCP I/O for topics and services. But unlike ` rospy ` , the API is not callbacks that run in separate threads, but rather ` awaitables ` that run in the main thread's event loop. This is accomplished by using thread-safe intermediaries such as ` asyncio.call_soon_threadsafe ` and ` janus.Queue ` .
124
-
125
- Note the use of `disable_signals=True ` and `rospy.signal_shutdown()` in the examples. This is necessary to give asyncio control of shutting down the event loop and application in general. Alternatively you can manually call `loop.stop()` and do cleanup yourself.
126
-
127
- # # TODO
128
- - Implement the non- Simple ActionClient and ActionServer
129
- - Explore need for `queue_size` to be handled.
0 commit comments