Skip to content

Commit ab00368

Browse files
Added API docs for ROS core, nodes, and services (#299)
* updated docstring * added topic_to_type docstring * improved docstring for record * updated docstring for playback * added ROS section to docs * added docstring to node * updated docstring for __getitem__ * documented node manager * added docstring to node manager * added import and removed excess whitespace * updated service docstrings * added returns to docstring * updated node docstring * added services to API ref docs
1 parent 503202d commit ab00368

File tree

4 files changed

+183
-58
lines changed

4 files changed

+183
-58
lines changed

docs/api.rst

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ the roswire library.
88

99
.. py:module:: roswire
1010
.. autoclass:: ROSWire
11-
:members:
11+
:members:
1212

1313

1414
System
@@ -26,6 +26,40 @@ with a :code:`bash` shell inside the application container.
2626
:members:
2727

2828

29+
ROS
30+
---
31+
32+
.. py:module:: roswire.proxy
33+
.. autoclass:: ROSProxy()
34+
:members:
35+
36+
.. autoclass:: NodeManagerProxy()
37+
:show-inheritance:
38+
:members:
39+
:inherited-members:
40+
41+
.. automethod:: __getitem__
42+
.. automethod:: __delitem__
43+
.. automethod:: __iter__
44+
.. automethod:: __len__
45+
46+
.. autoclass:: NodeProxy()
47+
:members:
48+
49+
.. autoclass:: ServiceManagerProxy()
50+
:show-inheritance:
51+
:members:
52+
:inherited-members:
53+
54+
.. automethod:: __getitem__
55+
.. automethod:: __delitem__
56+
.. automethod:: __iter__
57+
.. automethod:: __len__
58+
59+
.. autoclass:: ServiceProxy()
60+
:members:
61+
62+
2963
Shell
3064
-----
3165

@@ -42,7 +76,7 @@ Filesystem
4276

4377
.. py:module:: roswire.proxy.file
4478
.. autoclass:: FileProxy()
45-
:members:
79+
:members:
4680

4781

4882
Descriptions

src/roswire/proxy/__init__.py

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'ParameterServerProxy',
66
'NodeManagerProxy',
77
'NodeProxy',
8+
'ServiceProxy',
89
'ROSProxy',
910
'BagRecorderProxy',
1011
'BagPlayerProxy',
@@ -31,7 +32,7 @@
3132
from .parameters import ParameterServerProxy
3233
from .bag import BagRecorderProxy, BagPlayerProxy
3334
from .node import NodeProxy, NodeManagerProxy
34-
from .service import ServiceManagerProxy
35+
from .service import ServiceProxy, ServiceManagerProxy
3536
from ..description import SystemDescription
3637
from ..exceptions import ROSWireException
3738

@@ -40,7 +41,23 @@
4041

4142

4243
class ROSProxy:
43-
"""Provides access to a remote ROS master via XML-RPC."""
44+
"""Provides access to a remote ROS master via XML-RPC.
45+
46+
Attributes
47+
----------
48+
uri: str
49+
The URI of the ROS Master.
50+
connection: xmlrpc.client.ServerProxy
51+
The XML-RPC connection to the ROS master.
52+
nodes: NodeManagerProxy
53+
Provides access to the nodes running on this ROS Master.
54+
services: ServiceManagerProxy
55+
Provides access to the services advertised on this ROS Master.
56+
parameters: ParameterServerProxy
57+
Provides access to the parameter server for this ROS Master.
58+
topic_to_type: Dict[str, str]
59+
A mapping from topic names to the names of their message types.
60+
"""
4461
def __init__(self,
4562
description: SystemDescription,
4663
shell: ShellProxy,
@@ -71,29 +88,20 @@ def __init__(self,
7188
self.__connection,
7289
self.__shell)
7390

74-
@property
75-
def uri(self) -> str:
76-
"""The URI of the ROS Master."""
77-
return self.__uri
78-
7991
@property
8092
def nodes(self) -> NodeManagerProxy:
81-
"""Provides access to the nodes running on this ROS master."""
8293
return self.__nodes
8394

8495
@property
8596
def services(self) -> ServiceManagerProxy:
86-
"""Provides access to the services advertised on this ROS master."""
8797
return self.__services
8898

8999
@property
90100
def parameters(self) -> ParameterServerProxy:
91-
"""Provides access to the parameter server for this ROS Master."""
92101
return self.__parameters
93102

94103
@property
95104
def connection(self) -> xmlrpc.client.ServerProxy:
96-
"""The XML-RPC connection to the ROS master."""
97105
return self.__connection
98106

99107
@property
@@ -116,7 +124,8 @@ def launch(self,
116124
Parameters
117125
----------
118126
filename: str
119-
The name of the launch file (or an absolute path).
127+
The name of the launch file, or an absolute path to the launch
128+
file inside the container.
120129
package: str, optional
121130
The name of the package to which the launch file belongs.
122131
args: Dict[str, Union[int, str]], optional
@@ -141,7 +150,26 @@ def record(self,
141150
fn: str,
142151
exclude_topics: Optional[Collection[str]] = None
143152
) -> BagRecorderProxy:
144-
"""Provides an interface to rosbag for recording ROS topics."""
153+
"""Provides an interface to rosbag for recording ROS topics to disk.
154+
155+
Note
156+
----
157+
This method records bag files to the host machine, and not to the
158+
container where the ROS instance is running.
159+
160+
Parameters
161+
----------
162+
fn: str
163+
The name of the file, on the host machine, to which the bag should
164+
be recorded
165+
exclude_topics: Collection[str], optional
166+
An optional collection of topics that should not be recorded.
167+
168+
Returns
169+
-------
170+
BagRecorderProxy
171+
An interface for dynamically interacting with the bag recorder.
172+
"""
145173
return BagRecorderProxy(fn,
146174
self.__ws_host,
147175
self.__shell,
@@ -153,7 +181,22 @@ def playback(self,
153181
*,
154182
file_on_host: bool = True
155183
) -> BagPlayerProxy:
156-
"""Provides an interface to rosbag for replaying bag files."""
184+
"""Provides an interface to rosbag for replaying bag files from disk.
185+
186+
Parameters
187+
----------
188+
fn: str
189+
The bag file that should be replayed.
190+
file_on_host: bool
191+
If :code:`True`, as by default, :code:`fn` will be considered to
192+
be a file on the host machine. If :code:`False`, :code:`fn` will
193+
be considered to be a file inside the container.
194+
195+
Returns
196+
-------
197+
BagPlayerProxy
198+
An interface for dynamically controlling the bag player.
199+
"""
157200
fn_ctr: str
158201
delete_file_after_use: bool = False
159202
if file_on_host:

src/roswire/proxy/node.py

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
__all__ = ('NodeManagerProxy', 'NodeProxy')
23

34
from typing import Iterator, Set, Mapping, Optional
@@ -15,42 +16,45 @@
1516

1617

1718
class NodeProxy:
19+
"""Provides access to a ROS node.
20+
21+
Attributes
22+
----------
23+
api: xmlrpc.client.ServerProxy
24+
An XML-RPC API client for this node.
25+
name: str
26+
The fully qualified name of this node.
27+
url: str
28+
URL used to access this node from the host network.
29+
pid: int
30+
The container PID of the main process for this node.
31+
pid_host: int
32+
The host PID of the main process for this node.
33+
"""
1834
def __init__(self,
1935
name: str,
2036
url_host_network: str,
2137
shell: ShellProxy
2238
) -> None:
23-
"""
24-
Constructs a proxy for a given name.
25-
26-
Parameters:
27-
name: the name of the node.
28-
url_host_network: the URL of the node on the host network.
29-
shell: a shell proxy.
30-
"""
3139
self.__name = name
3240
self.__url = url_host_network
3341
self.__shell = shell
3442
self.__pid_host: Optional[int] = None
3543

3644
@property
3745
def api(self) -> xmlrpc.client.ServerProxy:
38-
"""Provides access to the XML-RPC API for this node."""
3946
return xmlrpc.client.ServerProxy(self.url)
4047

4148
@property
4249
def name(self) -> str:
43-
"""The fully qualified name of this node."""
4450
return self.__name
4551

4652
@property
4753
def url(self) -> str:
48-
"""URL used to access this node from the host network."""
4954
return self.__url
5055

5156
@property
5257
def pid(self) -> int:
53-
"""The container PID of the main process for this node."""
5458
code, status, pid = self.api.getPid('/.roswire')
5559
if code != 1:
5660
m = f"failed to obtain PID [{self.name}]: {status} (code: {code})"
@@ -61,24 +65,26 @@ def pid(self) -> int:
6165

6266
@property
6367
def pid_host(self) -> int:
64-
"""The host PID of the main process for this node."""
6568
if self.__pid_host is None:
6669
self.__pid_host = self.__shell.local_to_host_pid(self.pid)
6770
assert self.__pid_host is not None
6871
return self.__pid_host
6972

7073
def is_alive(self) -> bool:
74+
"""Determines whether this node is alive."""
7175
# TODO check start time to ensure this is the same process!
7276
try:
7377
return psutil.pid_exists(self.pid_host)
7478
except ROSWireException:
7579
return False
7680

7781
def shutdown(self) -> None:
82+
"""Instructs this node to shutdown."""
7883
self.__shell.execute(f'rosnode kill {self.name}')
7984

8085

8186
class NodeManagerProxy(Mapping[str, NodeProxy]):
87+
"""Provides access to all nodes on a ROS graph."""
8288
def __init__(self,
8389
host_ip_master: str,
8490
api: xmlrpc.client.ServerProxy,
@@ -104,23 +110,30 @@ def __get_node_names(self) -> Set[str]:
104110
return names
105111

106112
def __len__(self) -> int:
107-
"""
108-
Returns a count of the number of active nodes.
109-
"""
113+
"""Returns a count of the number of active nodes."""
110114
return len(self.__get_node_names())
111115

112116
def __iter__(self) -> Iterator[str]:
113-
"""
114-
Returns an iterator over the names of all active nodes.
115-
"""
117+
"""Returns an iterator over the names of all active nodes."""
116118
yield from self.__get_node_names()
117119

118120
def __getitem__(self, name: str) -> NodeProxy:
119-
"""
120-
Attempts to fetch a given node.
121-
122-
Raises:
123-
NodeNotFoundError: if there is no node with the given name.
121+
"""Attempts to fetch a given node.
122+
123+
Parameters
124+
----------
125+
name: str
126+
The name of the node.
127+
128+
Returns
129+
-------
130+
NodeProxy
131+
An interface to the given node.
132+
133+
Raises
134+
------
135+
NodeNotFoundError
136+
If there is no node with the given name.
124137
"""
125138
code, status, uri_container = self.api.lookupNode('/.roswire', name)
126139
if code == -1:
@@ -135,11 +148,17 @@ def __getitem__(self, name: str) -> NodeProxy:
135148
return NodeProxy(name, uri_host, self.__shell)
136149

137150
def __delitem__(self, name: str) -> None:
138-
"""
139-
Shutdown and deregister a given node.
151+
"""Shutdown and deregister a given node.
152+
153+
Parameters
154+
----------
155+
name: str
156+
The name of the node.
140157
141-
Raises:
142-
NodeNotFoundError: no node found with given name.
158+
Raises
159+
------
160+
NodeNotFoundError
161+
no node found with given name.
143162
"""
144163
try:
145164
node = self[name]

0 commit comments

Comments
 (0)