mirror of
https://github.com/CopterExpress/clover.git
synced 2026-05-26 21:19:35 +00:00
docs: update ros article
This commit is contained in:
183
docs/assets/ros.svg
Normal file
183
docs/assets/ros.svg
Normal file
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
viewBox="0 0 385.99219 102.04687"
|
||||
height="102.04688pt"
|
||||
width="385.99219pt"
|
||||
sodipodi:docname="Ros_logo.svg"
|
||||
inkscape:export-filename="/home/mguenther/Downloads/ros-press-kit/1280px-Ros_logo.svg.png"
|
||||
inkscape:export-xdpi="238.75999"
|
||||
inkscape:export-ydpi="238.75999"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1391"
|
||||
id="namedview33"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="3.1550388"
|
||||
inkscape:cx="232.61011"
|
||||
inkscape:cy="102.64938"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<metadata
|
||||
id="metadata58">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs4">
|
||||
<clipPath
|
||||
id="clip1">
|
||||
<path
|
||||
id="path7"
|
||||
d="M 0.0585938,2 H 22 V 25 H 0.0585938 Z m 0,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip2">
|
||||
<path
|
||||
id="path10"
|
||||
d="M 0.0585938,40 H 22 V 64 H 0.0585938 Z m 0,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip3">
|
||||
<path
|
||||
id="path13"
|
||||
d="M 0.0585938,79 H 22 v 23 H 0.0585938 Z m 0,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip4">
|
||||
<path
|
||||
id="path16"
|
||||
d="m 220,0.894531 h 82 V 102.94141 h -82 z m 0,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip5">
|
||||
<path
|
||||
id="path19"
|
||||
d="m 316,0.894531 h 70.05078 V 102.94141 H 316 Z m 0,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g
|
||||
id="surface839"
|
||||
transform="translate(-0.0585938,-0.894531)">
|
||||
<g
|
||||
id="g22"
|
||||
clip-path="url(#clip1)"
|
||||
style="clip-rule:nonzero">
|
||||
<path
|
||||
id="path24"
|
||||
d="m 21.839844,13.492188 c 0,6.230468 -4.890625,11.285156 -10.917969,11.285156 C 4.890625,24.777344 0,19.722656 0,13.492188 0,7.257812 4.890625,2.207031 10.921875,2.207031 c 6.027344,0 10.917969,5.050781 10.917969,11.285157"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
clip-path="url(#clip2)"
|
||||
style="clip-rule:nonzero">
|
||||
<path
|
||||
id="path28"
|
||||
d="m 21.839844,51.949219 c 0,6.230469 -4.890625,11.285156 -10.917969,11.285156 C 4.890625,63.234375 0,58.179688 0,51.949219 0,45.714844 4.890625,40.664062 10.921875,40.664062 c 6.027344,0 10.917969,5.050782 10.917969,11.285157"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
clip-path="url(#clip3)"
|
||||
style="clip-rule:nonzero">
|
||||
<path
|
||||
id="path32"
|
||||
d="m 21.839844,90.40625 c 0,6.230469 -4.890625,11.28516 -10.917969,11.28516 C 4.890625,101.69141 0,96.636719 0,90.40625 0,84.175781 4.890625,79.121094 10.921875,79.121094 c 6.027344,0 10.917969,5.054687 10.917969,11.285156"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
id="path34"
|
||||
d="m 59.945312,51.949219 c 0,6.230469 -4.886718,11.285156 -10.917968,11.285156 -6.03125,0 -10.921875,-5.054687 -10.921875,-11.285156 0,-6.234375 4.890625,-11.285157 10.921875,-11.285157 6.03125,0 10.917968,5.050782 10.917968,11.285157"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path36"
|
||||
d="m 59.945312,13.492188 c 0,6.230468 -4.886718,11.285156 -10.917968,11.285156 -6.03125,0 -10.921875,-5.054688 -10.921875,-11.285156 0,-6.234376 4.890625,-11.285157 10.921875,-11.285157 6.03125,0 10.917968,5.050781 10.917968,11.285157"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path38"
|
||||
d="m 98.054688,51.949219 c 0,6.230469 -4.890626,11.285156 -10.921876,11.285156 -6.03125,0 -10.917968,-5.054687 -10.917968,-11.285156 0,-6.234375 4.886718,-11.285157 10.917968,-11.285157 6.03125,0 10.921876,5.050782 10.921876,11.285157"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path40"
|
||||
d="m 98.054688,13.492188 c 0,6.230468 -4.890626,11.285156 -10.921876,11.285156 -6.03125,0 -10.917968,-5.054688 -10.917968,-11.285156 0,-6.234376 4.886718,-11.285157 10.917968,-11.285157 6.03125,0 10.921876,5.050781 10.921876,11.285157"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path42"
|
||||
d="m 98.054688,90.40625 c 0,6.230469 -4.890626,11.28516 -10.921876,11.28516 -6.03125,0 -10.917968,-5.054691 -10.917968,-11.28516 0,-6.230469 4.886718,-11.285156 10.917968,-11.285156 6.03125,0 10.921876,5.054687 10.921876,11.285156"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path44"
|
||||
d="m 59.945312,90.40625 c 0,6.230469 -4.886718,11.28516 -10.917968,11.28516 -6.03125,0 -10.921875,-5.054691 -10.921875,-11.28516 0,-6.230469 4.890625,-11.285156 10.921875,-11.285156 6.03125,0 10.917968,5.054687 10.917968,11.285156"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path46"
|
||||
d="m 171.61328,16.453125 h -27.91797 v 31.816406 h 27.91797 c 9.57813,0 16.28125,-5.089843 16.28125,-15.835937 0,-10.324219 -6.56641,-15.980469 -16.28125,-15.980469 z M 181.32812,61 200.89453,101.44531 H 184.33984 L 165.31641,62.273438 h -21.6211 V 101.44531 H 129.60156 V 2.449219 h 42.01172 c 16.69531,0 30.78906,9.195312 30.78906,29.558593 0,15.839844 -8.07422,25.597657 -21.07422,28.992188"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g48"
|
||||
clip-path="url(#clip4)"
|
||||
style="clip-rule:nonzero">
|
||||
<path
|
||||
id="path50"
|
||||
d="m 260.5625,15.746094 c -16.69531,0 -25.86328,14 -25.86328,36.203125 0,22.203125 9.16797,36.203125 25.86328,36.203125 16.83203,0 26,-14 26,-36.203125 0,-22.203125 -9.16797,-36.203125 -26,-36.203125 z m 0,87.253906 c -24.76563,0 -40.50391,-21.070312 -40.50391,-51.050781 0,-29.980469 15.73828,-51.054688 40.50391,-51.054688 24.90625,0 40.64062,21.074219 40.64062,51.054688 C 301.20312,81.929688 285.46875,103 260.5625,103"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g52"
|
||||
clip-path="url(#clip5)"
|
||||
style="clip-rule:nonzero">
|
||||
<path
|
||||
id="path54"
|
||||
d="m 350.60937,103 c -13.96093,0 -26,-6.222656 -34.07421,-15.980469 l 10.26171,-10.324219 c 6.4336,7.214844 15.875,11.738282 24.90625,11.738282 13.41016,0 19.83985,-4.808594 19.83985,-14.425782 0,-7.636718 -5.60938,-11.453124 -21.6211,-16.402343 -20.25,-6.222657 -29.96484,-11.457031 -29.96484,-29.132813 0,-17.113281 13.95703,-27.578125 31.60938,-27.578125 13,0 22.85156,4.953125 31.33593,13.4375 l -10.125,10.605469 c -6.02343,-6.363281 -12.86328,-9.476562 -22.30468,-9.476562 -11.22266,0 -16.01172,5.65625 -16.01172,12.304687 0,6.929687 4.3789,10.324219 20.9375,15.414063 18.88281,5.941406 30.65234,12.164062 30.65234,29.839843 C 386.05078,90.839844 375.10156,103 350.60937,103"
|
||||
style="fill:#212e4a;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
138
docs/en/ros.md
138
docs/en/ros.md
@@ -1,33 +1,28 @@
|
||||
ROS
|
||||
===
|
||||
# ROS
|
||||
|
||||
Main article: http://wiki.ros.org
|
||||
<img src="../assets/ros.svg" width="200" align="right">
|
||||
|
||||
ROS is a widely used framework for developing complex and distributed robotic systems.
|
||||
Main documentation: https://wiki.ros.org.
|
||||
|
||||
Installation
|
||||
---
|
||||
**ROS** is a widely used framework for developing complex and distributed robotic systems. The [Clover autonomous flights platform](programming.md) is based on ROS.
|
||||
|
||||
Main article: http://wiki.ros.org/melodic/Installation/Ubuntu
|
||||
## Installation
|
||||
|
||||
ROS is already installed on [the RPi image](image.md).
|
||||
|
||||
To use ROS on a PC, we recommend using Ubuntu Linux [or a virtual machine such as Parallels Desktop Lite](https://itunes.apple.com/ru/app/parallels-desktop-lite/id1085114709?mt=12) or [VirtualBox](https://www.virtualbox.org)).
|
||||
To install ROS on your PC you may address the [official installation documentation](https://wiki.ros.org/noetic/Installation/Ubuntu). For a quick start it's recommended to use [the virtual machine image with ROS and Clover simulator](simulation_vm.md).
|
||||
|
||||
> **Note** For ROS Melodic distribution, we recommend using Ubuntu 18.04.
|
||||
|
||||
Concepts
|
||||
---
|
||||
## Concepts
|
||||
|
||||
### Nodes
|
||||
|
||||
Main article: http://wiki.ros.org/Nodes
|
||||
Main article: https://wiki.ros.org/Nodes.
|
||||
|
||||
ROS node is a special program (usually written in Python or C++) that communicates with other nodes via ROS topics and ROS services. Dividing complex robotic systems into isolated nodes provides certain advantages: reduced coupling of the code, increases re-usability and reliability.
|
||||
ROS node is a special program (usually written in Python or C++) that communicates with other nodes via ROS topics and ROS services. Dividing complex robotic systems into isolated nodes provides certain advantages: reduced coupling of the code, increased reusability and reliability.
|
||||
|
||||
Many robotic libraries and the drivers are executed in the form of ROS-nodes.
|
||||
Many robotic libraries and drivers are made as ROS nodes.
|
||||
|
||||
In order to turn an ordinary program into a ROS node, include a `rospy` or `roscpp` library, and insert the initialization code.
|
||||
In order to turn an ordinary program into a ROS node, include the `rospy` (Python) or `roscpp` (C++) library, and insert the initialization code.
|
||||
|
||||
An example of a ROS node in Python:
|
||||
|
||||
@@ -36,32 +31,52 @@ import rospy
|
||||
|
||||
rospy.init_node('my_ros_node') # the name of the ROS node
|
||||
|
||||
rospy.spin() # entering an endless cycle...
|
||||
rospy.spin() # entering an infinite loop...
|
||||
```
|
||||
|
||||
> **Info** Any [autonomous flight script](programming.md) for Clover is a ROS node.
|
||||
|
||||
### Topics
|
||||
|
||||
Main article: http://wiki.ros.org/Topics
|
||||
Main article: https://wiki.ros.org/Topics
|
||||
|
||||
A topic is a named data bus used by the nodes for exchanging messages. Any node can *post* a message in a random topic, and *subscribe* to an arbitrary topic.
|
||||
A topic is a named data bus used by the nodes for exchanging messages. Any node can *publish* a message to any topic, and *subscribe* to any topic.
|
||||
|
||||
An example of [`std_msgs/String`](http://docs.ros.org/api/std_msgs/html/msg/String.html) (line) message type posting in topic `/foo` in Python:
|
||||
Для каждого созданного топика должен быть задан тип сообщений, которые по нему передаются. ROS включает в себя большое количество стандартных типов сообщений, покрывающих различные аспекты робототехники, но при необходимости возможно создание собственных типов сообщений. Примеры стандартных типов сообщений:
|
||||
|
||||
Each topic has the a of messages it passes. ROS include a lot of standard message types, covering different aspects of robotics. Creating custom message types is also possible. Example of standard message types:
|
||||
|
||||
|Message type|Description|
|
||||
|-|-|
|
||||
|[`std_msgs/Int64`](https://docs.ros.org/api/std_msgs/html/msg/Int64.html)|Integer number.|
|
||||
|[`std_msgs/Float64`](https://docs.ros.org/api/std_msgs/html/msg/Float64.html)|Double-precision floating-point number|
|
||||
|[`std_msgs/String`](https://docs.ros.org/api/std_msgs/html/msg/String.html)|String.|
|
||||
|[`geometry_msgs/PoseStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/PoseStamped.html)|Position and orientation of an object in a given [coordinate system](frames.md) and a time stamp (widely used for passing the robot pose or some robot's part pose).|
|
||||
|[`geometry_msgs/TwistStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/TwistStamped.html)|Linear and angular velocity of an object in a given coordinate system and a time stamp.|
|
||||
|[`sensor_msgs/Image`](https://docs.ros.org/api/sensor_msgs/html/msg/Image.html)|Image (see the [article on working with the camera](camera.md)).|
|
||||
|
||||
> **Info** See the rest of standard message types in packages: [`common_msgs`](http://wiki.ros.org/common_msgs), [`std_msgs`](https://wiki.ros.org/std_msgs), [`geometry_msgs`](https://wiki.ros.org/geometry_msgs), [`sensor_msgs`](https://wiki.ros.org/sensor_msgs), and others.
|
||||
|
||||
Example of publishing a message of type [`String`]((https://docs.ros.org/api/std_msgs/html/msg/String.html)) in a topic `/foo` in Python:
|
||||
|
||||
```python
|
||||
from std_msgs.msg import String
|
||||
|
||||
# ...
|
||||
rospy.init_node('my_ros_node')
|
||||
|
||||
foo_pub = rospy.Publisher('/foo', String, queue_size=1) # creating a Publisher
|
||||
|
||||
# ...
|
||||
|
||||
foo_pub.publish(data='Hello, world!') # posting the message
|
||||
foo_pub.publish(data='Hello, world!') # publishing the message
|
||||
```
|
||||
|
||||
An example of subscription to topic `/foo`:
|
||||
Example of subscription to a topic `/foo`:
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from std_msgs.msg import String
|
||||
|
||||
rospy.init_node('my_ros_node')
|
||||
|
||||
def foo_callback(msg):
|
||||
print(msg.data)
|
||||
|
||||
@@ -69,7 +84,13 @@ def foo_callback(msg):
|
||||
rospy.Subscriber('/foo', String, foo_callback)
|
||||
```
|
||||
|
||||
You can also work with topics using the the `rostopic` utility. For example, using the following command, you can view messages published in topic `/mavros/state`:
|
||||
You can read a topic message once, using `wait_for_message` function:
|
||||
|
||||
```python
|
||||
msg = rospy.wait_for_message('/foo', String, timeout=3) # wait for a message in /foo topic with timeout of 3 seconds
|
||||
```
|
||||
|
||||
You can also work with topics using the `rostopic` utility. For example, using the following command, you can view messages published in topic `/mavros/state`:
|
||||
|
||||
```bash
|
||||
rostopic echo /mavros/state
|
||||
@@ -77,36 +98,87 @@ rostopic echo /mavros/state
|
||||
|
||||
The `rostopic info` command shows the type of messages in the topic, and `rostopic hz` shows frequency of published messages.
|
||||
|
||||
Also you can monitor and visualize topics using [graphical tools of ROS](rviz.md).
|
||||
|
||||
### Services
|
||||
|
||||
Main article: http://wiki.ros.org/Services
|
||||
Main article: https://wiki.ros.org/Services
|
||||
|
||||
A service can be assimilated to the a function that can be called from one node, and processed in another one. The service has a name that is similar to the name of the topic, and 2 message types: request type and response type.
|
||||
|
||||
An example ROS service invoking from Python:
|
||||
Thus, ROS services implement [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call) pattern.
|
||||
|
||||
Example of invoking a ROS service in Python:
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from clover.srv import GetTelemetry
|
||||
|
||||
# ...
|
||||
rospy.init_node('my_ros_node')
|
||||
|
||||
# Creating a wrapper for the get_telemetry service of the clover package with the GetTelemetry type:
|
||||
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
|
||||
|
||||
# Invoking the service, and receiving the quadcopter telemetry:
|
||||
# Invoking the service, and getting the quadcopter telemetry:
|
||||
telemetry = get_telemetry()
|
||||
```
|
||||
|
||||
You can also work with the services using the `rosservice` utility. For instance, you can call service `/get_telemetry` from the command line:
|
||||
|
||||
```(bash)
|
||||
```bash
|
||||
rosservice call /get_telemetry "{frame_id: ''}"
|
||||
```
|
||||
|
||||
More examples of using the services for Clover quadcopter autonomous flights are available in the [documentation for node simple_offboard](simple_offboard.md).
|
||||
|
||||
Working on several PCs
|
||||
---
|
||||
### Names
|
||||
|
||||
Main article: https://wiki.ros.org/Names.
|
||||
|
||||
Any topic, service or a parameter is identified with a unique name. A ROS name is hierarchical structure with a `/` symbol as a separator (which is close to a file name in a file system).
|
||||
|
||||
Examples of ROS names:
|
||||
|
||||
* `/` (global namespace)
|
||||
* `/foo`
|
||||
* `/stanford/robot/name`
|
||||
* `/wg/node1`
|
||||
|
||||
This names are global (close to global names in a file system). In practice, it's recommended to use *private* or *relative* names.
|
||||
|
||||
#### Private name
|
||||
|
||||
Each node can use its own private namespace (corresponding its name) for its resources. For example, `aruco_detect` node may publish such topics:
|
||||
|
||||
* `/aruco_detect/markers`
|
||||
* `/aruco_detect/visualization`
|
||||
* `/aruco_detect/debug`
|
||||
|
||||
When a node is referring its private resource, instead of `/aruco_detect/` namespace it may use `~` symbol:
|
||||
|
||||
* `~markers`
|
||||
* `~visualization`
|
||||
* `~debug`
|
||||
|
||||
Thus, creating a `foo` topic and the private namespace would look like this:
|
||||
|
||||
```python
|
||||
private_foo_pub = rospy.Publisher('~foo', String, queue_size=1)
|
||||
```
|
||||
|
||||
#### Relative name
|
||||
|
||||
Several nodes may group into a common namespace (for example, when there are several robots in the network). For referring topics and services in the current namespace, the opening `/` symbol is omitted.
|
||||
|
||||
Example of create a `foo` topic in the current namespace:
|
||||
|
||||
```python
|
||||
relative_foo_pub = rospy.Publisher('foo', String, queue_size=1)
|
||||
```
|
||||
|
||||
> **Hint** Generally, it's recommended to use private or relative names instead of global ones.
|
||||
|
||||
### Working on several PCs
|
||||
|
||||
Main article: http://wiki.ros.org/ROS/Tutorials/MultipleMachines.
|
||||
|
||||
|
||||
136
docs/ru/ros.md
136
docs/ru/ros.md
@@ -1,33 +1,28 @@
|
||||
ROS
|
||||
===
|
||||
# ROS
|
||||
|
||||
Основная статья: http://wiki.ros.org
|
||||
<img src="../assets/ros.svg" width="200" align="right">
|
||||
|
||||
ROS – это широко используемый фреймворк для создания сложных и распределенных робототехнических систем.
|
||||
Основная документация: https://wiki.ros.org.
|
||||
|
||||
Установка
|
||||
---
|
||||
**ROS** – это широко используемый фреймворк для создания сложных, распределенных робототехнических систем. На ROS основана [программная платформа Клевера](programming.md).
|
||||
|
||||
Основная статья: http://wiki.ros.org/melodic/Installation/Ubuntu
|
||||
## Установка
|
||||
|
||||
ROS уже установлен на [образе для RPi](image.md).
|
||||
ROS уже установлен на [образе для RPi для Клевера](image.md).
|
||||
|
||||
Для использования ROS на компьютере рекомендуется ОС Ubuntu Linux (либо виртуальная машина, например [Parallels Desktop Lite](https://itunes.apple.com/ru/app/parallels-desktop-lite/id1085114709?mt=12) или [VirtualBox](https://www.virtualbox.org)).
|
||||
Для установки инструментов ROS на компьютере вы можете обратиться к [официальной документации](https://wiki.ros.org/noetic/Installation/Ubuntu) по установке. Для быстрого старта рекомендуется воспользоваться [образом виртуальной машины с ROS и симулятором Клевера](simulation_vm.md).
|
||||
|
||||
> **Note** Для дистрибутива ROS Melodic рекомендуется Ubuntu версии 18.04.
|
||||
|
||||
Концепции
|
||||
---
|
||||
## Концепции
|
||||
|
||||
### Ноды
|
||||
|
||||
Основная статья: http://wiki.ros.org/Nodes
|
||||
Основная статья: https://wiki.ros.org/Nodes.
|
||||
|
||||
ROS-нода – это специальная программа (обычно написанная на Python или C++), которая взаимодействует с другими нодами посредством ROS-топиков и ROS-сервисов. Разделение сложных робототехнических систем на изолированные ноды дает определенные преимущества: понижается связанность кода, повышается переиспользуемость и надежность.
|
||||
ROS-нода[^1] – это специальная программа (обычно написанная на Python или C++), которая взаимодействует с другими нодами посредством ROS-топиков и ROS-сервисов. Разделение сложных робототехнических систем на изолированные ноды дает определенные преимущества: понижается связанность кода, повышается переиспользуемость и надежность.
|
||||
|
||||
Очень многие робототехнические библиотеки и драйвера выполнены именно в виде ROS-нод.
|
||||
|
||||
Для того, чтобы превратить обычную программу в ROS-ноду, необходимо подключить к ней библиотеку `rospy` или `roscpp` и добавить инициализирующий код.
|
||||
Для того, чтобы превратить обычную программу в ROS-ноду, необходимо подключить к ней библиотеку `rospy` (Python) или `roscpp` (C++) и добавить инициализирующий код.
|
||||
|
||||
Пример ROS-ноды на языке Python:
|
||||
|
||||
@@ -39,22 +34,36 @@ rospy.init_node('my_ros_node') # имя ROS-ноды
|
||||
rospy.spin() # входим в бесконечный цикл...
|
||||
```
|
||||
|
||||
> **Info** Любая [программа для автономного полета Клевера](programming.md) является ROS-нодой.
|
||||
|
||||
### Топики
|
||||
|
||||
Основная статья: http://wiki.ros.org/Topics
|
||||
Основная статья: https://wiki.ros.org/Topics.
|
||||
|
||||
Топик – это именованная шина данных, по которой ноды обмениваются сообщениями. Любая нода может *опубликовать* сообщение в произвольный топик, а также *подписаться* на произвольный топик.
|
||||
|
||||
Пример публикации сообщения типа [`std_msgs/String`](http://docs.ros.org/api/std_msgs/html/msg/String.html) (строка) в топик `/foo` на языке Python:
|
||||
Для каждого созданного топика должен быть задан тип сообщений, которые по нему передаются. ROS включает в себя большое количество стандартных типов сообщений, покрывающих различные аспекты робототехники, но при необходимости возможно создание собственных типов сообщений. Примеры стандартных типов сообщений:
|
||||
|
||||
|Тип сообщения|Описание|
|
||||
|-|-|
|
||||
|[`std_msgs/Int64`](https://docs.ros.org/api/std_msgs/html/msg/Int64.html)|Целое число.|
|
||||
|[`std_msgs/Float64`](https://docs.ros.org/api/std_msgs/html/msg/Float64.html)|Число с плавающей точкой (дробное) двойной точности.|
|
||||
|[`std_msgs/String`](https://docs.ros.org/api/std_msgs/html/msg/String.html)|Строка.|
|
||||
|[`geometry_msgs/PoseStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/PoseStamped.html)|Позиция и ориентация объекта с заданной [системой координат](frames.md) и временной меткой (широко используется для передачи текущей позиции робота и его частей).|
|
||||
|[`geometry_msgs/TwistStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/TwistStamped.html)|Линейная и угловая скорость объекта с заданной системой координат и временной меткой.|
|
||||
|[`sensor_msgs/Image`](https://docs.ros.org/api/sensor_msgs/html/msg/Image.html)|Изображение (см. [статью о работе с камерой](camera.md))|
|
||||
|
||||
> **Info** Смотрите остальные стандартные типы сообщений в пакетах [`common_msgs`](http://wiki.ros.org/common_msgs), [`std_msgs`](https://wiki.ros.org/std_msgs), [`geometry_msgs`](https://wiki.ros.org/geometry_msgs), [`sensor_msgs`](https://wiki.ros.org/sensor_msgs) и других.
|
||||
|
||||
Пример публикации сообщения типа [`std_msgs/String`](https://docs.ros.org/api/std_msgs/html/msg/String.html) (строка) в топик `/foo` на языке Python:
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from std_msgs.msg import String
|
||||
|
||||
# ...
|
||||
rospy.init_node('my_ros_node')
|
||||
|
||||
foo_pub = rospy.Publisher('/foo', String, queue_size=1) # создаем Publisher'а
|
||||
|
||||
# ...
|
||||
foo_pub = rospy.Publisher('/foo', String, queue_size=1) # создаем Publisher
|
||||
|
||||
foo_pub.publish(data='Hello, world!') # публикуем сообщение
|
||||
```
|
||||
@@ -62,14 +71,27 @@ foo_pub.publish(data='Hello, world!') # публикуем сообщение
|
||||
Пример подписки на топик `/foo`:
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from std_msgs.msg import String
|
||||
|
||||
rospy.init_node('my_ros_node')
|
||||
|
||||
def foo_callback(msg):
|
||||
print(msg.data)
|
||||
|
||||
# Подписываемся. При получении сообщения в топик /foo будет вызвана функция foo_callback.
|
||||
rospy.Subscriber('/foo', String, foo_callback)
|
||||
|
||||
rospy.spin() # входим в бесконечный цикл, чтобы программа не завершила работу
|
||||
```
|
||||
|
||||
Также, существует возможность работы с топиками с помощью утилиты `rostopic`. Например, с помощью следующей команды можно просматривать сообщения, публикуемые в топик `/mavros/state`:
|
||||
Вы можете прочитать данные из топика однократно, используя функцию `wait_for_message`:
|
||||
|
||||
```python
|
||||
msg = rospy.wait_for_message('/foo', String, timeout=3) # ждать сообщения в топике /foo в таймаутом 3 с
|
||||
```
|
||||
|
||||
Также существует возможность работы с топиками с помощью утилиты `rostopic`. Например, с помощью следующей команды можно просматривать сообщения, публикуемые в топик `/mavros/state`:
|
||||
|
||||
```bash
|
||||
rostopic echo /mavros/state
|
||||
@@ -77,18 +99,23 @@ rostopic echo /mavros/state
|
||||
|
||||
Команда `rostopic info` позволяет узнать тип сообщений в топике, команда `rostopic hz` — частоту публикуемых в топике сообщений.
|
||||
|
||||
Также данные в топиках можно визуализировать и в [графических инструментах ROS](rviz.md).
|
||||
|
||||
### Сервисы
|
||||
|
||||
Основная статья: http://wiki.ros.org/Services
|
||||
Основная статья: https://wiki.ros.org/Services.
|
||||
|
||||
Сервис – это некоторый аналог функции, которая может быть вызвана из одной ноды, а обработана в другой. У сервиса есть имя, аналогичное имени топика, и 2 типа сообщений: тип запроса и тип ответа.
|
||||
|
||||
Таким образом, сервисы реализуют паттерн [*удаленного вызова процедур*](https://ru.wikipedia.org/wiki/Удалённый_вызов_процедур).
|
||||
|
||||
Пример вызова ROS-сервиса из языка Python:
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from clover.srv import GetTelemetry
|
||||
|
||||
# ...
|
||||
rospy.init_node('my_ros_node')
|
||||
|
||||
# Создаем обертку над сервисом get_telemetry пакета clover с типом GetTelemetry:
|
||||
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
|
||||
@@ -105,9 +132,62 @@ rosservice call /get_telemetry "{frame_id: ''}"
|
||||
|
||||
Больше примеров использования сервисов для автономных полетов квадрокоптера Клевер можно посмотреть в [документации ноды simple_offboard](simple_offboard.md).
|
||||
|
||||
Работа на нескольких машинах
|
||||
---
|
||||
### Имена
|
||||
|
||||
Основная статья: http://wiki.ros.org/ROS/Tutorials/MultipleMachines.
|
||||
Основная статья: https://wiki.ros.org/Names.
|
||||
|
||||
Любой топик, сервис или параметр идентифицируется с помощью уникального имени. ROS-имя представляет собой иерархическую структуру с символом `/` в качестве разделителя (сходно с именами в файловой системе).
|
||||
|
||||
Примеры ROS-имен:
|
||||
|
||||
* `/` (глобальное пространство имен)
|
||||
* `/foo`
|
||||
* `/stanford/robot/name`
|
||||
* `/wg/node1`
|
||||
|
||||
Эти имена является глобальными (аналогично полному пути в файлу в файловой системе). На практике рекомендуется использование *приватных* или *относительных* имен.
|
||||
|
||||
#### Приватное имя
|
||||
|
||||
Каждая нода может использовать собственное приватное пространство имен (соответствующее имени ноды) для своих ресурсов. Например, нода `aruco_detect` может публиковать такие топики:
|
||||
|
||||
* `/aruco_detect/markers`
|
||||
* `/aruco_detect/visualization`
|
||||
* `/aruco_detect/debug`
|
||||
|
||||
Когда нода ссылается на свой приватный ресурс, вместо пространства имен (`/aruco_detect/`) используется символ `~`, например:
|
||||
|
||||
* `~markers`
|
||||
* `~visualization`
|
||||
* `~debug`
|
||||
|
||||
Таким образом, создание топика `foo` в приватном пространство имен из Python будет выглядеть так:
|
||||
|
||||
```python
|
||||
private_foo_pub = rospy.Publisher('~foo', String, queue_size=1)
|
||||
```
|
||||
|
||||
#### Относительное имя
|
||||
|
||||
Несколько нод также могут объединяться в общее пространство имен (например, при одновременной работе нескольких роботов). Для того, чтобы ссылаться на топики с учетом общего пространства имен, в названии ресурса опускается начальный символ `/`.
|
||||
|
||||
Пример создание топика `foo` с учетом общего пространства имен:
|
||||
|
||||
```python
|
||||
relative_foo_pub = rospy.Publisher('foo', String, queue_size=1)
|
||||
```
|
||||
|
||||
> **Hint** В общем случае всегда рекомендуется использовать приватные или относительные имена ресурсов и никогда не использовать глобальные.
|
||||
|
||||
## Работа на нескольких машинах
|
||||
|
||||
Основная статья: https://wiki.ros.org/ROS/Tutorials/MultipleMachines.
|
||||
|
||||
Преимуществом использования ROS является возможность распределения нод на несколько машин в сети. Например, ноду, осуществляющую распознавание образом на изображении можно запустить на более мощном компьютере; ноду, управляющую коптером можно запустить непосредственно на Raspberry Pi, подключенном к полетному контроллеру и т. д.
|
||||
|
||||
## Дополнительные материалы
|
||||
|
||||
* Учебник по ROS от Voltbro - http://docs.voltbro.ru/starting-ros/.
|
||||
* Другие книги по ROS - https://wiki.ros.org/Books.
|
||||
|
||||
[^1]: Также встречается перевод "узел".
|
||||
|
||||
Reference in New Issue
Block a user