Merge branch 'master' into master
BIN
docs/assets/Mikhail.jpg
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
docs/assets/Mikhail_output.jpg
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
docs/assets/Timofey.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
docs/assets/Timofey_output.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
docs/assets/calibration.jpg
Normal file
|
After Width: | Height: | Size: 234 KiB |
BIN
docs/assets/calibresult.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
docs/assets/calibresult1.jpg
Normal file
|
After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 419 KiB After Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 423 KiB After Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 379 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 152 KiB |
BIN
docs/assets/chessboard.jpg
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
docs/assets/google_play.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
docs/assets/img1.jpg
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
docs/assets/img2.jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
docs/assets/misha_calib.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
docs/assets/pty1.jpg
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
docs/assets/pty2.jpg
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
docs/assets/pty3.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
docs/assets/rqt_image_view.jpg
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
docs/assets/rqt_image_view_dyn_rec.jpg
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
docs/assets/screen.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
docs/assets/tim_calib.jpg
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
docs/assets/wcp1.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
docs/assets/wcp2.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
docs/assets/web_interface.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
@@ -6,7 +6,7 @@ Appropriate phase wires and their control signal (Fig. 1b) are marked with the s
|
||||
|
||||
For example, orange color -> bottom-right motor -> S1 - orange wire.
|
||||
|
||||
## PixRacer flight controller pin-out
|
||||
## Pixracer flight controller pin-out
|
||||
|
||||
Fig. 2a shows the pin-out of the terminal strip:
|
||||
|
||||
@@ -15,7 +15,7 @@ Fig. 2a shows the pin-out of the terminal strip:
|
||||
* 1, 2, 3, 4 are ports for connecting ESCs.
|
||||
* 1, 2 are ports for expanding the output PWM signal (can be setup in QGroundControl, can also can be used to control the hexacopter).
|
||||
|
||||
Fig. 2b shows motor numbering of the PixRacer flight controller.
|
||||
Fig. 2b shows motor numbering of the Pixracer flight controller.
|
||||
|
||||
* The arrow is the flight controller orientation.
|
||||
* Black M3, M4 are the motors that rotate clockwise.
|
||||
@@ -23,8 +23,8 @@ Fig. 2a shows the pin-out of the terminal strip:
|
||||
|
||||
## Picture of the connection, based on the current orientation of the 4 in 1 ESC board
|
||||
|
||||
Using Fig. 1a, 1b, 2a, 2b, map its own control signal to each motor, and connect in accordance with the PixRacer motor numbering order.
|
||||
Using Fig. 1a, 1b, 2a, 2b, map its own control signal to each motor, and connect in accordance with the Pixracer motor numbering order.
|
||||
|
||||
For example, motor M3 that rotates counter-clockwise (top left corner) is controlled by signal S4 (green wire). It is connected to port 3.
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -24,11 +24,11 @@ The image includes:
|
||||
|
||||
* Raspbian Stretch
|
||||
* ROS Kinetic
|
||||
* Configured [networking] (network.md)
|
||||
* Configured [networking](network.md)
|
||||
* OpenCV
|
||||
* mavros
|
||||
* A software set for working with Clever
|
||||
|
||||
[API description](simple_offboard.md) for autonomous flights.
|
||||
|
||||
The source code of the collector of the image and only can be found at [GitHub](https://github.com/CopterExpress/clever).
|
||||
The source code of the collector of the image and only can be found at [GitHub](https://github.com/CopterExpress/clever).
|
||||
|
||||
@@ -26,7 +26,7 @@ Clever 2 construction kit assembly instruction
|
||||
* EFEST Luc V4 Li-lon Charger ×1.
|
||||
* Regulators protective case ×4.
|
||||
* Legs attachment ×8.
|
||||
* PixHawk flight controller ×1.
|
||||
* Pixhawk flight controller ×1.
|
||||
* FlySky i6 radio receiver×1.
|
||||
* FlySky i6 radio transmitter ×1.
|
||||
* EFEST LUC V4 Charger ×1.
|
||||
@@ -292,7 +292,7 @@ IMPORTANT NOTE about polarity
|
||||
|
||||

|
||||
|
||||
[Radio equipment troubleshooting manual ](radioerrors.md)
|
||||
[Radio equipment troubleshooting manual](radioerrors.md)
|
||||
|
||||
### Checking the motors rotation direction
|
||||
|
||||
@@ -322,13 +322,13 @@ IMPORTANT NOTE about polarity
|
||||
|
||||

|
||||
|
||||
#### Installation of the PixHawk flight controller
|
||||
#### Installation of the Pixhawk flight controller
|
||||
|
||||
1. Stick the two-sided adhesive tape in the corners of the flight controller. 
|
||||
> **IMPORTANT** When the motors rotate, vibrations occur, which affect sensors of the PixHawk flight controller. To avoid this effect, the number of double-sided tape layers
|
||||
> **IMPORTANT** When the motors rotate, vibrations occur, which affect sensors of the Pixhawk flight controller. To avoid this effect, the number of double-sided tape layers
|
||||
should be increased up to 4 – 5.
|
||||
2. Install the flight controller in the center of the frame. 
|
||||
> **IMPORTANT** The arrows on the frame and PixHawk should point in the same direction
|
||||
> **IMPORTANT** The arrows on the frame and Pixhawk should point in the same direction
|
||||
|
||||
#### Connecting the flight controller according to the circuit diagram
|
||||
|
||||
@@ -385,4 +385,4 @@ The copter is ready for configuration!
|
||||
2. When connecting (disconnecting) batteries, hold only the connectors, never pull or tug the wires.
|
||||
3. If you see open connectors, violation of insulation or battery compartment integrity, do not touch it, and immediately inform the instructor.
|
||||
|
||||
See article [safety precautions when soldering and during copter flight operation](safety.md)
|
||||
See article [safety precautions when soldering and during copter flight operation](safety.md)
|
||||
|
||||
@@ -95,7 +95,7 @@ TODO
|
||||
|
||||

|
||||
|
||||
## Installation of the 4 in 1 ESC board and the PDB power-board
|
||||
## Installation of the 4 in 1 ESC board and the PDB power-board
|
||||
|
||||
1. Install the 4 in 1 ESC circuit-board as shown in the picture.
|
||||
|
||||
@@ -188,7 +188,7 @@ article [remote faults](radioerrors.md).
|
||||
|
||||

|
||||
|
||||
## Installation of Arduino and the FlySky radio receiver
|
||||
## Installation of Arduino and the FlySky radio receiver
|
||||
|
||||
1. Mount the pins of the Arduino Nano micro-controller using soldering.
|
||||
2. Install the micro-controller into a special mount, and attach to the lower deck using М3х16 screws (4 pcs).
|
||||
|
||||
@@ -25,4 +25,4 @@ This connector may be used together with a buzzer (beeper) for monitoring batter
|
||||
There is a great variety of Gold bullet pin connectors. Connectors of this type may have different diameters and size. The most widespread connectors are those with the diameter of 2 mm, 3 mm, and 4 mm.
|
||||
They are often used for solderless connections on PDB and motors.
|
||||
|
||||
<img src="../assets/Banana.jpg" alt="Banana" width=200>
|
||||
<img src="../assets/Banana.jpg" alt="Banana" width=200>
|
||||
|
||||
@@ -19,13 +19,13 @@ Pixhawk, Ardupilot, Naze32, CC3D.
|
||||
|
||||
An electric motor that rotates propellers of the multicopter. Usually, brushless motors are used. These motors are connected to ESC.
|
||||
|
||||
## ESC / motor controller / "regul"
|
||||
## ESC / motor controller
|
||||
|
||||
An Electronic Speed Controller. A specialized circuit-board that controls the speed of the brushless motor. It is controlled by a flight controller using pulse width modulation (PWM).
|
||||
|
||||
ESC has the firmware that determines the characteristics of its operation.
|
||||
|
||||
## Remote control / radio control equipment/ "appa"
|
||||
## Remote control / radio control equipment
|
||||
|
||||
A radio-operated quadcopter remote control. Operation of the remote control requires connecting a receiver to the flight controller.
|
||||
|
||||
@@ -67,4 +67,4 @@ A library that is a link between the aircraft operating using the MAVLink protoc
|
||||
|
||||
## UART
|
||||
|
||||
A serial asynchronous data transfer interface used in many devices. For example, GPS antennas, Wi-Fi routers, or Pixhawk.
|
||||
A serial asynchronous data transfer interface used in many devices. For example, GPS antennas, Wi-Fi routers, or Pixhawk.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Main documentation: [http://wiki.ros.org/mavros](http://wiki.ros.org/mavros)
|
||||
|
||||
MAVROS \(MAVLink + ROS\) is a package for ROS that provides the possibility of controlling drones via the [MAVLink] protocol (mavlink.md). MAVROS supports flight stacks PX4 and APM. Communication is established via UART, USB, TCP or UDP.
|
||||
MAVROS \(MAVLink + ROS\) is a package for ROS that provides the possibility of controlling drones via the [MAVLink](mavlink.md) protocol. MAVROS supports flight stacks PX4 and APM. Communication is established via UART, USB, TCP or UDP.
|
||||
|
||||
MAVROS subscribes to certain ROS topics while waiting for commands, publishes telemetry to other topics, and provides services.
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ In manual mode, the pilot controls the drone directly. GPS, computer vision data
|
||||
|
||||
In the automatic flight mode, the quadcopter ignores the control signals from the transmitter.
|
||||
|
||||
* **AUTO.MISSION** – PX4 completes the mission pre-loaded into the drone (the mission is downloaded using the QGroundControl, or from [MAVLink] (mavlink.md) using [MAVROS](mavros.md).
|
||||
* **AUTO.MISSION** – PX4 completes the mission pre-loaded into the drone (the mission is downloaded using the QGroundControl, or from [MAVLink](mavlink.md) using [MAVROS](mavros.md).
|
||||
* **AUTO.RTL** – the copter automatically returns to the takeoff point.
|
||||
* **AUTO.LAND** – the copter lands automatically.
|
||||
|
||||
@@ -44,4 +44,4 @@ The main used MAVLink packages are:
|
||||
* [SET_POSITION_TARGET_LOCAL_NED](https://mavlink.io/en/messages/common.html#SET_POSITION_TARGET_LOCAL_NED)
|
||||
* [SET_ATTITUDE_TARGET](https://mavlink.io/en/messages/common.html#SET_ATTITUDE_TARGET)
|
||||
|
||||
See: [autonomous flying the quadcopter in the OFFBOARD mode](simple_offboard.md).
|
||||
See: [autonomous flying the quadcopter in the OFFBOARD mode](simple_offboard.md).
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
The Raspberry Pi Wi-Fi adapter of has two main operating modes:
|
||||
|
||||
1. **Client mode** – RPi connects to an existing Wi-Fi network.
|
||||
|
||||
1. **Client mode** – RPi connects to an existing Wi-Fi network.
|
||||
|
||||
2. **Access point mode** – RPi creates a Wi-Fi network that you can connect to.
|
||||
|
||||
When using [the RPi image](microsd_images.md), the Wi-Fi adapter works in the [access point mode] by default (Wi-Fi.md).
|
||||
|
||||
@@ -35,7 +35,7 @@ If anyone says the opposite – don't believe him, he is trying to misguide you:
|
||||
Flying
|
||||
------
|
||||
|
||||
### Safety during preparation to flying
|
||||
### Safety during pre-flight preparations
|
||||
|
||||
* Make sure that the Li-ion batteries are charged.
|
||||
* Make sure the batteries in the control equipment are charged.
|
||||
@@ -88,4 +88,4 @@ After a scheduled landing, do the following:
|
||||
|
||||
1. Disarm (Move the left stick left-down for 3 seconds)
|
||||
2. Disconnect the Li-ion battery on the copter.
|
||||
3. Turn off the remote.
|
||||
3. Turn off the remote.
|
||||
|
||||
@@ -146,7 +146,6 @@ Start the calibration procedure
|
||||
|
||||

|
||||
|
||||
|
||||
> *Warning* During calibration, the drone should remain in position, be stable, etc.
|
||||
|
||||
## Flight modes
|
||||
|
||||
@@ -269,7 +269,6 @@ set_velocity(vx=0.4, vy=0.0, vz=0, yaw=float('nan'), yaw_rate=0.4, frame_id='bod
|
||||
|
||||
Setting pitch, roll, yaw and throttle level (approximate analogue to control in [the `STABILIZED` mode](modes.md)). This service may be used for lower level monitoring of the copter behavior or controlling the copter, if no reliable data about its position are available.
|
||||
|
||||
|
||||
Parameters:
|
||||
|
||||
* `pitch`, `roll`, `yaw` – required pitch, roll, and yaw angle *(radians)*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Viewing images from cameras
|
||||
|
||||
To view images from cameras (or other Ros topics), you can use [rviz](rviz.md), rqt, or watch them in a browser using web\_video\_server.
|
||||
To view images from cameras (or other ROS topics), you can use [rviz](rviz.md), rqt, or watch them in a browser using web\_video\_server.
|
||||
|
||||
See read more about [using rqt](rviz.md).
|
||||
|
||||
|
||||
@@ -21,4 +21,4 @@ Blanching a wire means doing the following:
|
||||
3. Apply flux to the twisted stripped wires
|
||||
4. Apply a layer of solder.
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -50,13 +50,16 @@
|
||||
* [3G-модем](3g.md)
|
||||
* Проекты на базе Клевера
|
||||
* [Шаровая защита коптера](shield.md)
|
||||
* [Распознавание лиц](face_recognition.md)
|
||||
* [Пульт на Андроид](android.md)
|
||||
* [CopterHack-2018](copterhack2018.md)
|
||||
* [CopterHack-2017](copterhack2017.md)
|
||||
* Дополнительные материалы
|
||||
* [Вклад в Клевер](contributing.md)
|
||||
* [Прошивка ESC контроллеров с помощью Arduino](esc_firmware.md)
|
||||
* [Прошивка ESC контроллеров](esc_firmware.md)
|
||||
* [Протокол MAVLink](mavlink.md)
|
||||
* [Работа с логами PX4](flight_logs.md)
|
||||
* [Калибровка камеры](calibration.md)
|
||||
* Учебник
|
||||
* [Теория и видеоуроки](lessons.md)
|
||||
* [Учебно-методическое пособие](metod.md)
|
||||
|
||||
142
docs/ru/android.md
Normal file
@@ -0,0 +1,142 @@
|
||||
|
||||
# Пульт на Android
|
||||
|
||||
Все владельцы мобильных устройств фирмы *Apple* ещё морозным январем 2018го обзавелись приятным приложением под *iOS* для пилотирования квадрокоптеров с помощью **WiFi**. И вот, спустя год вышло такое же приложение но уже для другой операционной системы. Актуальную версию вы можете скачать [**тут**](https://vk.com/away.php?to=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dexpress.copter.cleverrc&cc_key=) .
|
||||
|
||||
## Введение
|
||||
|
||||
В данной статье я расскажу вам о том, как можно написать свой или доработать уже имеющийся пульт для Андроид своими руками. Для работы будем использовать модный язык *Kotlin*, а в качестве среды разработки возьмем *Android Studio*. Для тех кто ни разу ей не пользовался рекомендую к ознакомлению следующие [*материалы*](https://www.google.com/search?ei=xQxDXMH0C8OOmgW4mYigDQ&q=%D0%A7%D1%82%D0%BE+%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C+%D0%B5%D1%81%D0%BB%D0%B8+%D1%8F+%D0%BD%D0%B5+%D1%83%D0%BC%D0%B5%D1%8E+%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C+%D0%BF%D0%BE%D0%B4+%D0%B0%D0%BD%D0%B4%D1%80%D0%BE%D0%B8%D0%B4%3F&oq=%D0%A7%D1%82%D0%BE+%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C+%D0%B5%D1%81%D0%BB%D0%B8+%D1%8F+%D0%BD%D0%B5+%D1%83%D0%BC%D0%B5%D1%8E+%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C+%D0%BF%D0%BE%D0%B4+%D0%B0%D0%BD%D0%B4%D1%80%D0%BE%D0%B8%D0%B4%3F&gs_l=psy-ab.3...4413.17423..17726...9.0..2.442.4577.45j5j1j0j1....2..0....1..gws-wiz.....6..0i71j35i39j0i131j0j0i67j0i131i67j0i22i30j33i22i29i30j33i21j33i160.0bZz-WGxoHY). Весь код приложения можно найти [**тут**](https://github.com/Tennessium/android). Если вы хотите сразу получить приложение с целью дальнейшей доработки, выполните следующую команду:
|
||||
|
||||
```Bash
|
||||
git clone https://github.com/Tennessium/android
|
||||
```
|
||||
|
||||
Однако чтобы вы смогли полностью понять устройство приложения, я расскажу вам о каждом этапе создания проекта, как если бы вы делали его с нуля.
|
||||
|
||||
## Обертка
|
||||
|
||||
Начнем с самого простого - внешнего вида нашего приложения. На [**гитхабе**](https://github.com/CopterExpress/clever/tree/master/apps/android/app/src/main/assets) вы можете найти *HTML*, *CSS* и *JavaScript* файлы, это и есть веб страница с которой будет происходить управление коптером. Чтобы эта страница отображалась у нас в приложении надо:
|
||||
|
||||
1. Создать папку **assets** в главной папке приложения **app**
|
||||
|
||||
2. Добавить в нее файлы все файлы [отсюда](https://github.com/CopterExpress/clever/tree/master/apps/android/app/src/main/assets)
|
||||
|
||||
Если вы дошли до этого этапа то у вас уже есть необходимая веб страница, поздравляю! Теперь нам надо её как-то отобразить в приложении. Для этого в классе вашего *activity* в методе **onCreate** необходимо написать следующий код:
|
||||
|
||||
```Kotlin
|
||||
main_web.loadUrl("file:///android_asset/index.html")
|
||||
```
|
||||
|
||||
Где *main_web* - id вашего *WebView*, который должен находится в *xml* файле выбранного вами *activity*.
|
||||
|
||||
К сожалению, пульт для управления коптером требует всего экрана устройства, а элементы интерфейса системы мешают полноценному использованию программы. Для этого надо в начале метода **onCreate** вызвать следующую функцию:
|
||||
|
||||
```Kotlin
|
||||
private fun fullScreenCall() {
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||
if (Build.VERSION.SDK_INT < 19) {
|
||||
val v = this.window.decorView
|
||||
v.systemUiVisibility = View.GONE
|
||||
} else {
|
||||
//for higher api versions.
|
||||
val decorView = window.decorView
|
||||
val uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
decorView.systemUiVisibility = uiOptions
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Данная функция позволяет избавиться от элементов интерфейса системы. Идем дальше.
|
||||
|
||||
Вот так выглядит пульт на этом этапе:
|
||||
|
||||
<img src="../assets/IMG_4397.PNG" width="50%">
|
||||
|
||||
Если вы запустите приложение, то заметите что стики не работают. Это происходит по тому, что на нашей странице отключен *JavaScript*. чтобы его включить надо прописать следующее:
|
||||
|
||||
```Kotlin
|
||||
main_web.settings.apply {
|
||||
domStorageEnabled = true
|
||||
javaScriptEnabled = true
|
||||
loadWithOverviewMode = true
|
||||
useWideViewPort = true
|
||||
setSupportZoom(false)
|
||||
}
|
||||
```
|
||||
|
||||
Этим куском кода мы разрешаем странице использовать *JavaScript* и заодно готовимся к следующему этапу - **логике**.
|
||||
|
||||
## Прием данных с веб страницы
|
||||
|
||||
Чтобы телефон мог принимать данные с *HTML страницы*, надо создать класс для взаимодействия с веб интерфейсом
|
||||
|
||||
```Kotlin
|
||||
class WebAppInterface(c: Context) {
|
||||
@JavascriptInterface
|
||||
public fun postMessage(message: String) {
|
||||
val data = JSONObject(message)
|
||||
send("255.255.255.255", 35602, pack(
|
||||
data.getInt("x").toShort(),
|
||||
data.getInt("y").toShort(),
|
||||
data.getInt("z").toShort(),
|
||||
data.getInt("r").toShort()))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Данный класс будет получать сообщение с веб страницы отправленное методом *postMessage*, где аргумент *message* - сообщение от страницы.
|
||||
|
||||
Теперь надо связать классы **WebAppInterface** и **MainActivity**. Для этого надо всего лишь добавить одну строку в метод **onCreate**:
|
||||
|
||||
```Kotlin
|
||||
main_web.addJavascriptInterface(WebAppInterface(this), "appInterface")
|
||||
```
|
||||
|
||||
## Отправка данных на коптер
|
||||
|
||||
**Важно!**
|
||||
Для любой работы с интернетом на платформе *Android* в файле **AndroidManifest.xml** внутри тега *manifest* необходимо добавить такую строку:
|
||||
|
||||
```XML
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
```
|
||||
|
||||
Она дает вашему приложению доступ в интернет и возможность передавать данные по средствам **WiFi**. А как это делать, мы с вами сейчас и узнаем. Идём дальше!
|
||||
|
||||
Вы наверное заметили функцию *send* в классе **WebAppInterface**. Именно она отправляет данные на коптер. Давайте объявим ее **вне классов**:
|
||||
|
||||
```Kotlin
|
||||
fun send(host: String, port: Int, data: ByteArray, senderPort: Int = 0): Boolean {
|
||||
var ret = false
|
||||
var socket: DatagramSocket? = null
|
||||
try {
|
||||
socket = DatagramSocket(senderPort)
|
||||
val address = InetAddress.getByName(host)
|
||||
val packet = DatagramPacket(data, data.size, address, port)
|
||||
socket.send(packet)
|
||||
ret = true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
socket?.close()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
Данная функция отправляет данные при помощи [*протокола пользовательских датаграмм*](https://www.google.com/search?q=udp+%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB&oq=udp+&aqs=chrome.0.69i59j69i57j35i39j0l3.1434j1j7&sourceid=chrome&ie=UTF-8) на коптер. Программа отправляет **байты**, поэтому неплохо бы было объявить функцию для создания массива **байтов** из четырех переменных:
|
||||
|
||||
```Kotlin
|
||||
fun pack(x: Short, y: Short, z: Short, r: Short): ByteArray {
|
||||
val pump_on_buf: ByteBuffer = ByteBuffer.allocate(8)
|
||||
pump_on_buf.putShort(r)
|
||||
pump_on_buf.putShort(z)
|
||||
pump_on_buf.putShort(y)
|
||||
pump_on_buf.putShort(x)
|
||||
return pump_on_buf.array().reversedArray()
|
||||
}
|
||||
```
|
||||
|
||||
## Итог
|
||||
|
||||
Теперь ваше приложение имеет полный функционал аналога под **iOS**. Можете кастомизировать его как пожелаете. По любым вопросам о приложении можете обращаться в Телеграм @Tenessinum.
|
||||
@@ -110,7 +110,7 @@ void setup()
|
||||
nav_req.x = 0;
|
||||
nav_req.y = 0;
|
||||
nav_req.z = 2;
|
||||
nav_req.frame_id = "fcu_horiz";
|
||||
nav_req.frame_id = "body";
|
||||
nav_req.speed = 0.5;
|
||||
navigate.call(nav_req, nav_res);
|
||||
|
||||
@@ -128,7 +128,7 @@ void setup()
|
||||
nav_req.x = 3;
|
||||
nav_req.y = 0;
|
||||
nav_req.z = 0;
|
||||
nav_req.frame_id = "fcu_horiz";
|
||||
nav_req.frame_id = "body";
|
||||
nav_req.speed = 0.8;
|
||||
navigate.call(nav_req, nav_res);
|
||||
|
||||
@@ -145,7 +145,6 @@ void setup()
|
||||
nav_req.y = 0;
|
||||
nav_req.z = 2;
|
||||
nav_req.frame_id = "aruco_map";
|
||||
nav_req.update_frame = true;
|
||||
nav_req.speed = 0.8;
|
||||
navigate.call(nav_req, nav_res);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Навигация с использованием ArUco-маркеров
|
||||
|
||||
> **Note** Документация для версий [образа](microsd_images.md), начиная с **0.15**. Для более ранних версий см. [документацию для версии **0.14**](https://github.com/CopterExpress/clever/blob/v0.14/docs/ru/aruco.md).
|
||||
|
||||
[ArUco-маркеры](https://docs.opencv.org/3.2.0/d5/dae/tutorial_aruco_detection.html) — это популярная технология для позиционирования
|
||||
роботехнических систем с использованием компьютерного зрения.
|
||||
|
||||
@@ -141,12 +143,12 @@ _Примечание_: указанное выше определение пр
|
||||
```python
|
||||
# Вначале необходимо взлететь, чтобы коптер увидел карту меток
|
||||
# и появился фрейм aruco_map:
|
||||
navigate(0, 0, 2, frame_id='fcu_horiz', speed=0.5, auto_arm=True) # взлет на 2 метра
|
||||
navigate(0, 0, 2, frame_id='body', speed=0.5, auto_arm=True) # взлет на 2 метра
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
# Полет в координату 2:2 маркерного поля, высота 2 метра
|
||||
navigate(2, 2, 2, speed=1, frame_id='aruco_map', update_frame=True) # полет в координату 2:2, высота 3 метра
|
||||
navigate(2, 2, 2, speed=1, frame_id='aruco_map') # полет в координату 2:2, высота 3 метра
|
||||
```
|
||||
|
||||
См. [другие функции](simple_offboard.md) simple_offboard.
|
||||
@@ -160,7 +162,7 @@ navigate(2, 2, 2, speed=1, frame_id='aruco_map', update_frame=True) # поле
|
||||
Чтобы задавать карту маркеров в "перевернутой" системе координат, необходимо изменить параметр `aruco_orientation` в файле `~/catkin_ws/src/clever/clever/aruco.launch`:
|
||||
|
||||
```xml
|
||||
<param name="aruco_orientation" value="local_origin_upside_down"/>
|
||||
<param name="aruco_orientation" value="map_upside_down"/>
|
||||
```
|
||||
|
||||
При задании вышеуказанного параметра фрейм aruco\_map также окажется "перевернутым". Таким образом, для полета на высоту 2 метра ниже потолка, аргумент `z` нужно устанавливать в 2:
|
||||
|
||||
227
docs/ru/calibration.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Калибровка камеры
|
||||
|
||||
Компьютерное зрение получает все более широкое распространение. Зачастую, алгоритмы компьютерного зрения работают неточно, получая искаженное изображение с камеры, что особенно характерно для fisheye-камер.
|
||||
|
||||

|
||||
|
||||
> Изображение "скруглено" ближе к краям.
|
||||
|
||||
Какой-либо алгоритм компьютерного зрения будет воспринимать информацию с этой картинки неправильно. Для устранения подобных искажений камера, получающая изображения, должна быть откалибрована в соответствии со своими особенностями.
|
||||
|
||||
## Установка скрипта
|
||||
|
||||
Для начала, необходимо установить необходимые библиотеки:
|
||||
|
||||
```
|
||||
pip install numpy
|
||||
pip install opencv-python
|
||||
pip install glob
|
||||
pip install pyyaml
|
||||
pip install urllib.request
|
||||
```
|
||||
|
||||
Затем скачиваем скрипт из репозитория:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/tinderad/clever_cam_calibration.git
|
||||
```
|
||||
|
||||
Переходим в скачанную папку и устанавливаем скрипт:
|
||||
|
||||
```bash
|
||||
cd clever_cam_calibration
|
||||
sudo python setup.py build
|
||||
sudo python setup.py install
|
||||
```
|
||||
|
||||
Если вы используете Windows, тогда скачайте архив из [репозитория](https://github.com/tinderad/clever_cam_calibration/archive/master.zip), распакуйте его и установите:
|
||||
|
||||
```bash
|
||||
cd path\to\archive\clever_cam_calibration\
|
||||
python setup.py build
|
||||
python setup.py install
|
||||
```
|
||||
|
||||
> path\to\archive - путь до распакованного архива.
|
||||
|
||||
## Подготовка к калибровке
|
||||
|
||||
Вам необходимо подготовить калибровочную мишень. Она представляет собой «шахматную доску». Файл можно взять [отсюда](https://www.oreilly.com/library/view/learning-opencv-3/9781491937983/assets/lcv3_ac01.png).
|
||||
Наклейте распечатанную мишень на любую твердую поверхность. Посчитайте количество пересечений в длину и в ширину доски, измерьте размер клетки (в мм).
|
||||
|
||||

|
||||
|
||||
Включите Клевер и подключитесь к его Wifi.
|
||||
|
||||
> Перейдите на 192.168.11.1:8080 и проверьте, получает ли компьютер изображения из топика image_raw.
|
||||
|
||||
## Калибровка
|
||||
|
||||
Запустите скрипт **_calibrate_cam_**:
|
||||
|
||||
**Windows:**
|
||||
|
||||
```bash
|
||||
>path\to\python\Scripts\calibrate_cam.exe
|
||||
```
|
||||
|
||||
> path\to\Python - путь до директории Python
|
||||
|
||||
**Linux:**
|
||||
|
||||
```bash
|
||||
>calibrate_cam
|
||||
```
|
||||
|
||||
Задайте параметры доски:
|
||||
|
||||
```bash
|
||||
>calibrate_cam
|
||||
Chessboard width: # Перекрестий в ширину
|
||||
Chessboard height: # Перекрестий в длину
|
||||
Square size: # Длина ребра клетки (в мм)
|
||||
Saving mode (YES - on): # Режим сохранения
|
||||
```
|
||||
|
||||
> Режим сохранения: если включен, то все полученные фотографии будут сохраняться в нынешней директории.
|
||||
|
||||
Скрипт начнет свою работу:
|
||||
|
||||
...
|
||||
Calibration started!
|
||||
Commands:
|
||||
help, catch (key: Enter), delete, restart, stop, finish
|
||||
|
||||
Чтобы откалибровать камеру, вам требуется сделать как минимум 25 фото шахматной доски с различных ракурсов.
|
||||
|
||||

|
||||
|
||||
Чтобы сделать фото, введите команду **_catch_**.
|
||||
|
||||
```bash
|
||||
>catch
|
||||
```
|
||||
|
||||
Программа будет информировать вас о состоянии калибровки.
|
||||
|
||||
```bash
|
||||
...
|
||||
Chessboard not found, now 0 (25 required)
|
||||
> # Enter
|
||||
---
|
||||
Image added, now 1 (25 required)
|
||||
```
|
||||
|
||||
> Вместо того, чтобы каждый раз вводить команду **_catch_**, Вы можете просто нажимать клавишу **_Enter_** (вводить пустую строку).
|
||||
|
||||
После того, как будет набрано достаточное количество изображений, введите команду **_finish_**.
|
||||
|
||||
```bash
|
||||
...
|
||||
>finish
|
||||
Calibration successful!
|
||||
```
|
||||
|
||||
**Калибровка по существующим изображениям:**
|
||||
|
||||
Если же у вас уже есть изображения, то вы можете откалибровать камеру по ним при помощи скрипта **_calibrate_cam_ex_**.
|
||||
|
||||
```bash
|
||||
>calibrate_cam_ex
|
||||
```
|
||||
|
||||
Указываем характеристики мишени, а так же путь до папки с изображениями:
|
||||
|
||||
```bash
|
||||
>calibrate_cam_ex
|
||||
Chessboard width: # Перекрестий в ширину
|
||||
Chessboard height: # Перекрестий в длину
|
||||
Square size: # Длина ребра клетки (в мм)
|
||||
Path: # Путь до папки с изображениями
|
||||
```
|
||||
|
||||
В остальном этот скрипт работает аналогично **_calibrate_cam_**.
|
||||
|
||||
Программа обработает все полученные фотографии, и создаст файл **_camera_info_****_._****_yaml_** в нынешней директории. При помощи этого файла можно будет выравнивать искажения на изображениях, полученных с этой камеры.
|
||||
|
||||
> Если вы поменяете разрешение получаемого изображения, вам нужно будет снова калибровать камеру.
|
||||
|
||||
## Исправление искажений
|
||||
|
||||
За получение исправленного изображения отвечает функция **_get_undistorted_image(cv2_image, camera_info)_**:
|
||||
|
||||
* **_cv2_image_**: Закодированное в массив cv2 изображение.
|
||||
* **_camera_****___****_info_**: Путь до файла калибровки.
|
||||
|
||||
Функция возвращает массив cv2, в котором закодировано исправленное изображение.
|
||||
|
||||
> Если вы используете fisheye-камеру, поставляемую вместе с Клевером, то для обработки изображений разрешением 320x240 или 640x480 вы можете использовать уже существующие параметры калибровки. Для этого в качестве аргумента **_camera_info_** передайте параметры **_clever_cam_calibration.clevercamcalib.CLEVER_FISHEYE_CAM_320_** или **_clever_cam_calibration.clevercamcalib.CLEVER_FISHEYE_CAM_640_** соответственно.
|
||||
|
||||
## Примеры работы
|
||||
|
||||
Изначальные изображения:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Иcправленные изображения:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Пример использования
|
||||
|
||||
**Обработка потока изображений с камеры**.
|
||||
|
||||
Данная программа получает изображения с камеры Клевера и выводит их на экран в исправленном виде, используя существующий калибровочный файл.
|
||||
|
||||
```python
|
||||
import clevercamcalib.clevercamcalib as ccc
|
||||
import cv2
|
||||
import urllib.request
|
||||
import numpy as np
|
||||
while True:
|
||||
req = urllib.request.urlopen('http://192.168.11.1:8080/snapshot?topic=/main_camera/image_raw')
|
||||
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
|
||||
image = cv2.imdecode(arr, -1)
|
||||
undistorted_img = ccc.get_undistorted_image(image, ccc.CLEVER_FISHEYE_CAM_640)
|
||||
cv2.imshow("undistort", undistorted_img)
|
||||
cv2.waitKey(33)
|
||||
cv2.destroyAllWindows()
|
||||
```
|
||||
|
||||
## Использование для ArUco
|
||||
|
||||
Чтобы применить параметры калибровки к системе ArUco-навигации, требуется перенести калибровочный .yaml файл на Raspberry Pi Клевера и инициализировать его.
|
||||
|
||||
> Не забудьте подключиться к WiFI Клевера.
|
||||
|
||||
Для передачи файла используется протокол SFTP. В данном примере используется программа WinSCP.
|
||||
|
||||
Подключимся к Raspberry Pi по SFTP:
|
||||
|
||||
> Пароль: _**raspberry**_
|
||||
|
||||

|
||||
|
||||
Нажимаем “Войти”. Переходим в _**/home/pi/catkin_ws/src/clever/clever/camera_info/**_ и копируем туда калибровочный .yaml файл:
|
||||
|
||||

|
||||
|
||||
Теперь мы должны выбрать этот файл в конфигурации ArUco. Для этого используется связь по протоколу SSH. В данном примере используется программа PuTTY.
|
||||
|
||||
Подключимся к Raspberry Pi по SSH:
|
||||
|
||||

|
||||
|
||||
Войдем под логином _**pi**_ и паролем _**raspberry**_, перейдем в директорию _**/home/pi/catkin_ws/src/clever/clever/launch**_ и начнем редактировать конфигурацию _**main_camera.launch**_:
|
||||
|
||||

|
||||
|
||||
В строке _**camera node**_ заменим параметр _**camera_info**_ на _**camera_info.yaml**_:
|
||||
|
||||

|
||||
|
||||
> Не забудьте изменить разрешение камеры.
|
||||
@@ -1,12 +1,14 @@
|
||||
# Настройка расположения основной камеры
|
||||
|
||||
> **Note** Документация для версий [образа](microsd_images.md), начиная с **0.15**. Для более ранних версий см. [документацию для версии **0.14**](https://github.com/CopterExpress/clever/blob/v0.14/docs/ru/camera_frame.md).
|
||||
|
||||
Расположение и ориентация основной камеры задается в файле `~/catkin_ws/src/clever/clever/launch/main_camera.launch`:
|
||||
|
||||
```xml
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0 0 -0.07 -1.5707963 0 3.1415926 fcu main_camera_optical"/>
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
||||
```
|
||||
|
||||
Эта строка задает статическую трансформацию между фреймом `fcu` ([соответствует корпусу полетного контроллера](frames.md)) и камерой (`main_camera_optical`) в формате:
|
||||
Эта строка задает статическую трансформацию между фреймом `base_link` ([соответствует корпусу полетного контроллера](frames.md)) и камерой (`main_camera_optical`) в формате:
|
||||
|
||||
```txt
|
||||
сдвиг_x сдвиг_y сдвиг_z угол_рысканье угол_тангаж угол_крен
|
||||
@@ -22,40 +24,40 @@
|
||||
|
||||
## Настройки для Клевера
|
||||
|
||||
> Первое изображение - как выглядит модель коптера в Rviz при указанных настройках, второе - как выглядит Клевер при тех же настройках.
|
||||
Первое изображение – как выглядит модель коптера в rviz при указанных настройках, второе – как выглядит Клевер при тех же настройках.
|
||||
|
||||
### 1. Камера направлена вниз, шлейф назад
|
||||
|
||||
```xml
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 fcu main_camera_optical"/>
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
||||
```
|
||||
|
||||

|
||||

|
||||
<img src="../assets/camera_option_1_rviz.png" width=400>
|
||||
<img src="../assets/camera_option_1_clever.jpg" width=400>
|
||||
|
||||
### 2. Камера направлена вниз, шлейф вперёд
|
||||
|
||||
```xml
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 1.5707963 0 3.1415926 fcu main_camera_optical"/>
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
||||
```
|
||||
|
||||

|
||||

|
||||
<img src="../assets/camera_option_2_rviz.png" width=400>
|
||||
<img src="../assets/camera_option_2_clever.jpg" width=400>
|
||||
|
||||
### 3. Камера направлена вверх, шлейф назад
|
||||
|
||||
```xml
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 1.5707963 0 0 fcu main_camera_optical"/>
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 1.5707963 0 0 base_link main_camera_optical"/>
|
||||
```
|
||||
|
||||

|
||||

|
||||
<img src="../assets/camera_option_3_rviz.png" width=400>
|
||||
<img src="../assets/camera_option_3_clever.jpg" width=400>
|
||||
|
||||
### 4. Камера направлена вверх, шлейф вперёд
|
||||
|
||||
```xml
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 -1.5707963 0 0 fcu main_camera_optical"/>
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 -1.5707963 0 0 base_link main_camera_optical"/>
|
||||
```
|
||||
|
||||

|
||||

|
||||
<img src="../assets/camera_option_4_rviz.png" width=400>
|
||||
<img src="../assets/camera_option_4_clever.jpg" width=400>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Комплектация
|
||||
|
||||
В составе набора имеется 4 дополнительных рамы (поз. 2).
|
||||
Они абсолютно одинаковые.
|
||||
Поэтому для дальнейшего удобства понимания инструкции условно разделим их на верхнюю и нижнюю дополнительные рамы
|
||||
|
||||
163
docs/ru/face_recognition.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Система распознавания лиц
|
||||
|
||||
## Введение
|
||||
|
||||
В последнее время системы распознавания лиц используются все шире, область применения этой технологии поистине огромна: от обычных селфи-дронов до дронов-полицейских. Ее интеграция в различные устройства проводится повсеместно. Сам процесс распознавания реально завораживает, и это сподвигло меня сделать проект связанный именно с этим. Целью моего стажерского проекта является создание простой open source-ной системы распознавания лиц с квадрокоптера Клевер. Данная программа берет изображения с камеры квадрокоптера, а его обработка происходит уже на компьютере. Поэтому все оставшиеся инструкции выполняются на ПК.
|
||||
|
||||
## Разработка
|
||||
|
||||
Первой задачей было найти алгоритм самого распознавания. В качестве пути решения проблемы было выбрано использовать [готовое API для Python](https://github.com/ageitgey/face_recognition). Данное API сочетает в себе ряд преимуществ: скорость и точность распознавания, а также простота использования.
|
||||
|
||||
## Установка
|
||||
|
||||
Для начала нужно установить все необходимые библиотеки:
|
||||
|
||||
```bash
|
||||
pip install face_recognition
|
||||
pip install opencv-python
|
||||
```
|
||||
|
||||
Затем скачать сам скрипт из репозитория:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mmkuznecov/face_recognition_from_clever.git
|
||||
```
|
||||
|
||||
## Объяснение кода
|
||||
|
||||
Подключаем библиотеки:
|
||||
|
||||
```python
|
||||
import face_recognition
|
||||
import cv2
|
||||
import os
|
||||
import urllib.request
|
||||
import numpy as np
|
||||
```
|
||||
|
||||
***Данный кусок кода предназначен для Python 3. В Python 2.7 подключаем urllib2 вместо urllib:***
|
||||
|
||||
```python
|
||||
import urllib2
|
||||
```
|
||||
|
||||
Создаем список кодировок изображений и список имен:
|
||||
|
||||
```python
|
||||
faces_images=[]
|
||||
for i in os.listdir('faces/'):
|
||||
faces_images.append(face_recognition.load_image_file('faces/'+i))
|
||||
known_face_encodings=[]
|
||||
for i in faces_images:
|
||||
known_face_encodings.append(face_recognition.face_encodings(i)[0])
|
||||
known_face_names=[]url
|
||||
for i in os.listdir('faces/'):
|
||||
i=i.split('.')[0]
|
||||
known_face_names.append(i)
|
||||
```
|
||||
|
||||
***Дополнение: все изображения хранятся в папке faces в формате name.jpg***
|
||||
|
||||
<img src="../assets/screen.jpg" width="50%">
|
||||
|
||||
<img src="../assets/Mikhail.jpg" width="30%">
|
||||
|
||||
<img src="../assets/Timofey.jpg" width="30%">
|
||||
|
||||
Инициализируем некоторые переменные:
|
||||
|
||||
```python
|
||||
face_locations = []
|
||||
face_encodings = []
|
||||
face_names = []
|
||||
process_this_frame = True
|
||||
```
|
||||
|
||||
Берем изображение с сервера и преобразуем его в cv2 формат:
|
||||
|
||||
```python
|
||||
req = urllib.request.urlopen('http://192.168.11.1:8080/snapshot?topic=/main_camera/image_raw')
|
||||
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
|
||||
frame = cv2.imdecode(arr, -1)
|
||||
```
|
||||
|
||||
***Для Python 2.7:***
|
||||
|
||||
```python
|
||||
req = urllib2.urlopen('http://192.168.11.1:8080/snapshot?topic=/main_camera/image_raw')
|
||||
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
|
||||
frame = cv2.imdecode(arr, -1)
|
||||
```
|
||||
|
||||
Объяснение дальнейшего кода можно найти на github’е используемого API в комментариях к [следующему скрипту](https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam_faster.py)
|
||||
|
||||
## Использование
|
||||
|
||||
Достаточно подключиться к "Клеверу" через Wi-Fi и проверить, корректно ли работает видеострим с камеры.
|
||||
|
||||
Затем просто запускаем скрипт:
|
||||
|
||||
```bash
|
||||
python recog.py
|
||||
```
|
||||
|
||||
И на выходе:
|
||||
|
||||
<img src="../assets/Mikhail_output.jpg" width="50%">
|
||||
|
||||
<img src="../assets/Timofey_output.jpg" width="50%">
|
||||
|
||||
## Возможные трудности
|
||||
|
||||
При запуске скрипта может выскочить следующая ошибка:
|
||||
|
||||
```python
|
||||
known_face_encodings.append(face_recognition.face_encodings(i)[0])
|
||||
IndexError: list index out of range
|
||||
```
|
||||
|
||||
В этом случае постарайтесь переделать изображения в папке faces, возможно из-за плохого качества программа не распознает лиц на изображениях.
|
||||
|
||||
## Использование калибровки
|
||||
|
||||
Для повышения точности распознавания можно использовать калибровку камеры. Модуль для калибровки можно установить, используя [специальный пакет](https://github.com/tinderad/clever_cam_calibration). Инструкцию по установке и использованию можно найти в файле calibration.md. Программа с использованием калибровочного пакета называется recog_undist.py
|
||||
|
||||
**Краткое пояснение кода:**
|
||||
|
||||
Подключаем установленный пакет:
|
||||
|
||||
```python
|
||||
import clever_cam_calibration.clevercamcalib as ccc
|
||||
```
|
||||
|
||||
Добавляем следующие строки:
|
||||
|
||||
```python
|
||||
height_or, width_or, depth_or = frame.shape
|
||||
```
|
||||
|
||||
Таким образом получаем информацию о размере изображения, где height_or-это высота оригинального изображения в пикселях, а width_or-ширина.
|
||||
Затем исправляем искажения оригинального изображения и получаем уже его параметры:
|
||||
|
||||
```python
|
||||
if height_or==240 and width_or==320:
|
||||
frame=ccc.get_undistorted_image(frame,ccc.CLEVER_FISHEYE_CAM_320)
|
||||
elif height_or==480 and width_or==640:
|
||||
frame=ccc.get_undistorted_image(frame,ccc.CLEVER_FISHEYE_CAM_640)
|
||||
else:
|
||||
frame=ccc.get_undistorted_image(frame,input("Input your path to the .yaml file: "))
|
||||
height_unz, width_unz, depth_unz = frame.shape
|
||||
```
|
||||
|
||||
***В данном случае мы передаем аргумент ссс.CLEVER_FISHEYE_CAM_640, т.к. разрешение изображения в приведенном примере составляет 640x480, также можно использовать ссс.CLEVER_FISHEYE_CAM_320 для разрешения 320x240, в противном случае необходимо в качестве второго аргумента передать путь до калибровочного .yaml файла.***
|
||||
|
||||
И, наконец, возвращаем изображение к изначальному размеру:
|
||||
|
||||
```python
|
||||
frame=cv2.resize(frame,(0,0), fx=(width_or/width_unz),fy=(height_or/height_unz))
|
||||
```
|
||||
|
||||
Благодаря этому можно значительно повысить точность распознавания, т.к. обрабатываемое изображение будет уже не так сильно искажено.
|
||||
|
||||
<img src="../assets/misha_calib.jpg" width="50%">
|
||||
<img src="../assets/tim_calib.jpg" width="50%">
|
||||
@@ -1,13 +1,15 @@
|
||||
Системы координат (фреймы)
|
||||
===
|
||||
|
||||
> **Note** Документация для версий [образа](microsd_images.md), начиная с **0.15**. Для более ранних версий см. [документацию для версии **0.14**](https://github.com/CopterExpress/clever/blob/v0.14/docs/ru/frames.md).
|
||||
|
||||

|
||||
|
||||
Основные фреймы в пакете `clever`:
|
||||
|
||||
* `local_origin` — координаты относительно точки инициализации полетного контроллера: белая сетка на иллюстрации;
|
||||
* `fcu` — координаты относительно квадрокоптера: схематичное изображение квадрокоптера на иллюстрации;
|
||||
* `fcu_horiz` — координаты относительно квадрокоптера без учета наклонов по тангажу и крену: красная, синия и зеленая линии на иллюстрации.
|
||||
* `map` — координаты относительно точки инициализации полетного контроллера: белая сетка на иллюстрации;
|
||||
* `base_link` — координаты относительно квадрокоптера: схематичное изображение квадрокоптера на иллюстрации;
|
||||
* `body` — координаты относительно квадрокоптера без учета наклонов по тангажу и крену: красная, синия и зеленая линии на иллюстрации.
|
||||
|
||||
> **Hint** В соответствии с [соглашением](http://www.ros.org/reps/rep-0103.html), для фреймов, связанных с коптером, ось X направлена вперед, Y – налево и Z – вверх.
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# Теория
|
||||
|
||||
[**Урок №1** «Знакомство. Принципы проектирования и строение мультикоптеров»](https://github.com/CopterExpress/clever/blob/master/docs/lesson1.md)
|
||||
[**Урок №1** «Знакомство. Принципы проектирования и строение мультикоптеров»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson1.md)
|
||||
|
||||
[**Урок №2** «Основы электричества»](https://github.com/CopterExpress/clever/blob/master/docs/lesson2.md)
|
||||
[**Урок №2** «Основы электричества»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson2.md)
|
||||
|
||||
[**Урок №3** «Теория пайки»](https://github.com/CopterExpress/clever/blob/master/docs/lesson3.md)
|
||||
[**Урок №3** «Теория пайки»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson3.md)
|
||||
|
||||
[**Урок №4** «Аэродинамика полета. Пропеллер»](https://github.com/CopterExpress/clever/blob/master/docs/lesson4.md)
|
||||
[**Урок №4** «Аэродинамика полета. Пропеллер»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson4.md)
|
||||
|
||||
[**Урок №5** «Бесколлекторные двигатели и регуляторы их хода»](https://github.com/CopterExpress/clever/blob/master/docs/lesson5.md)
|
||||
[**Урок №5** «Бесколлекторные двигатели и регуляторы их хода»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson5.md)
|
||||
|
||||
[**Урок №6** «Основы электромагнетизма. Типы двигателей»](https://github.com/CopterExpress/clever/blob/master/docs/lesson6.md)
|
||||
[**Урок №6** «Основы электромагнетизма. Типы двигателей»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson6.md)
|
||||
|
||||
[**Урок №7** «Принцип работы, типы и устройство аккумуляторов»](https://github.com/CopterExpress/clever/blob/master/docs/lesson7.md)
|
||||
[**Урок №7** «Принцип работы, типы и устройство аккумуляторов»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson7.md)
|
||||
|
||||
[**Урок №8** «Управление полётом мультикоптера. Принцип функционирования полётного контроллера. ПИД регуляторы»](https://github.com/CopterExpress/clever/blob/master/docs/lesson8.md)
|
||||
[**Урок №8** «Управление полётом мультикоптера. Принцип функционирования полётного контроллера. ПИД регуляторы»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson8.md)
|
||||
|
||||
[**Урок №9** «Основы радиосвязи. Принцип работы радиоаппаратуры управления»](https://github.com/CopterExpress/clever/blob/master/docs/lesson9.md)
|
||||
[**Урок №9** «Основы радиосвязи. Принцип работы радиоаппаратуры управления»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson9.md)
|
||||
|
||||
[**Урок №10** «Аналоговая и цифровая видеотрансляция. Применяемые камеры, радиопередатчики иприёмники»](https://github.com/CopterExpress/clever/blob/master/docs/lesson10.md)
|
||||
[**Урок №10** «Аналоговая и цифровая видеотрансляция. Применяемые камеры, радиопередатчики иприёмники»](https://github.com/CopterExpress/clever/blob/master/docs/ru/lesson10.md)
|
||||
|
||||
## Видеоуроки
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
[](https://etcher.io)
|
||||
|
||||
После записи образа на SD-карту, вы можете подключаться к [Клеверу по Wi-Fi](wifi.md), получать [доступ по SSH](ssh.md) и использовать остальные функции.
|
||||
|
||||
## Версия образа
|
||||
|
||||
Версию установленного образа можно узнать в файле `/etc/clever_version`:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Управление Клевером со смартфона
|
||||
===
|
||||
|
||||
<a href="https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8"><img src="../assets/appstore.svg"></a>
|
||||
<a href="https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8"><img src="../assets/appstore.svg"></a><a href="https://play.google.com/store/apps/details?id=express.copter.cleverrc"><img src="../assets/google_play.png" width="15%"></a>
|
||||
|
||||
Для управления Клевером со смартфона через Wi-Fi необходимо установить приложение – [iOS](https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8), Android (*work-in-progress*).
|
||||
Для управления Клевером со смартфона через Wi-Fi необходимо установить приложение – [iOS](https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8), [Android](https://play.google.com/store/apps/details?id=express.copter.cleverrc).
|
||||
|
||||

|
||||
|
||||
@@ -46,7 +46,7 @@ sudo systemctl restart clever
|
||||
|
||||
Подключите смартфон к [Wi-Fi](wifi.md) сети Клевера (`CLEVER-xxxx`). Приложение должно подключиться с коптеру автоматически. При успешном подключении должны отобразиться текущий [режим](modes.md) и заряд батареи.
|
||||
|
||||
Стики на экране приложения работают так же, как и реальные стики. Для арма коптера подержите левый стик в правом нижнем углу на протяжении нескольких секунд. Для дизарма – в левом нижнем углу.
|
||||
Стики на экране приложения работают так же, как и реальные стики. Для арма коптера подержите левый стик в правом нижнем углу на протяжении нескольких секунд. Для дизарма – в левом нижнем углу.
|
||||
|
||||
Неисправности
|
||||
---
|
||||
|
||||
@@ -31,7 +31,7 @@ export ROS_IP=192.168.11.1
|
||||
|
||||
### Визуализация положения коптера
|
||||
|
||||
В качестве reference frame рекомендуется установить фрейм `local_origin`. Для визуализации коптера добавьте визуализационные маркеры из топика `/vehicle_markers`. Для визуализации камеры коптера добавьте визуализационные маркеры из топика `/main_camera/camera_markers`.
|
||||
В качестве reference frame рекомендуется установить фрейм `map`. Для визуализации коптера добавьте визуализационные маркеры из топика `/vehicle_markers`. Для визуализации камеры коптера добавьте визуализационные маркеры из топика `/main_camera/camera_markers`.
|
||||
|
||||
Результат визуализации коптера и камеры представлен ниже:
|
||||
|
||||
@@ -43,6 +43,14 @@ export ROS_IP=192.168.11.1
|
||||
|
||||
Axis или Grid настроенный на фрейм `aruco_map` будут визуализировать расположение [карты ArUco-меток](aruco.md).
|
||||
|
||||
### jsk_rviz_plugins
|
||||
|
||||
Рекомендуется также установка набора дополнительных полезных плагинов для rviz [jsk_rviz_plugins](https://jsk-docs.readthedocs.io/en/latest/jsk_visualization/doc/jsk_rviz_plugins/index.html). Это набор позволяет визуализировать топики типа `TwistStamped` (скорость), `CameraInfo`, `PolygonArray` и многое другое. Для установки используйте команду:
|
||||
|
||||
```bash
|
||||
sudo apt-get install ros-kinetic-jsk-visualization
|
||||
```
|
||||
|
||||
Запуск инструментов rqt
|
||||
---
|
||||
|
||||
@@ -60,11 +68,8 @@ ROS_MASTER_URI=http://192.168.11.1:11311 rqt
|
||||
ROS_MASTER_URI=http://192.168.11.1:11311 rqt_image_view
|
||||
```
|
||||
|
||||
jsk_rviz_plugins
|
||||
---
|
||||
Краткое описание полезных rqt-плагинов:
|
||||
|
||||
Рекомендуется также установка набора дополнительных полезных плагинов для rviz [jsk_rviz_plugins](https://jsk-docs.readthedocs.io/en/latest/jsk_visualization/doc/jsk_rviz_plugins/index.html). Это набор позволяет визуализировать топики типа `TwistStamped` (скорость), `CameraInfo`, `PolygonArray` и многое другое. Для установки используйте команду:
|
||||
|
||||
```bash
|
||||
sudo apt-get install ros-kinetic-jsk-visualization
|
||||
```
|
||||
* `rqt_image_view` – просмотр изображений из топиков типа `sensor_msgs/Image`;
|
||||
* `rqt_multiplot` – построение графиков по данным из произвольным топиков (установка: `sudo apt-get install ros-kinetic-rqt-multiplot`);
|
||||
* Bag – работа с [Bag-файлами](http://wiki.ros.org/rosbag).
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
2. Устанавливаем БПЛА на ровную поверхность и кликаем OK.
|
||||
3. Ждем окончания калибровки.
|
||||
|
||||

|
||||

|
||||
|
||||
> *Warning* Во время калибровки БПЛА не должен менять своего положения, шататься и т.д.
|
||||
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
Simple offboard
|
||||
===
|
||||
|
||||
> **Note** Документация для версий [образа](microsd_images.md), начиная с **0.15**. Для более ранних версий см. [документацию для версии **0.14**](https://github.com/CopterExpress/clever/blob/v0.14/docs/ru/simple_offboard.md).
|
||||
|
||||
Модуль `simple_offboard` пакета `clever` предназначен для упрощенного программирования автономного дрона ([режим](modes.md) `OFFBOARD`). Он позволяет устанавливать желаемые полетные задачи и автоматически трансформирует [систему координат](frames.md).
|
||||
|
||||
`simple_offboard` является высокоуровневым способом взаимодействия с полетным контроллером. Для более низкоуровневой работы см. [mavros](mavros.md).
|
||||
|
||||
Основные сервисы – `get_telemetry` (получение всей телеметрии), `navigate` (полет в заданную точку по прямой), `navigate_global` (полет в глобальную точку по прямой), `land` (переход в режим посадки).
|
||||
|
||||
Общие для сервисов параметры:
|
||||
|
||||
* `auto_arm` = `true`/`false` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
* `frame_id` — система координат в TF2, в которой заданы координаты и рысканье (yaw), [описание систем координат](frames.md);
|
||||
* `update_frame` — считать ли систему координат изменяющейся (например, `false` для `local_origin`, `fcu`, `fcu_horiz`, `true` для `marker_map`);
|
||||
* `x`, `y` – горизонтальные координаты в системе координат `frame_id` *(м)*;
|
||||
* `z` — высота в системе координат `frame_id` *(м)*;
|
||||
* `lat`, `lon` – широта и долгота *(градусы)*;
|
||||
* `yaw` — рысканье в радианах в системе координат `frame_id` (0 – коптер смотрит по оси X);
|
||||
* `yaw_rate` — угловая скорость по рысканью в радианах в секунду (против часовой), `yaw` должен быть установлен в NaN;
|
||||
* `thrust` — уровень газа от 0 (нет газа) до 1 (полный газ).
|
||||
|
||||
> **Warning** API модуля `simple_offboard` на данный момент нестабилен и может измениться.
|
||||
|
||||
Использование из языка Python
|
||||
---
|
||||
|
||||
@@ -59,11 +47,11 @@ release = rospy.ServiceProxy('release', Trigger)
|
||||
|
||||
Параметры:
|
||||
|
||||
* `frame_id` – [фрейм](frames.md) для значений `x`, `y`, `z`, `vx`, `vy`, `vz`. Пример: `local_origin`, `fcu_horiz`, `aruco_map`.
|
||||
* `frame_id` – [система координат](frames.md) для значений `x`, `y`, `z`, `vx`, `vy`, `vz`. Пример: `map`, `body`, `aruco_map`. Значение по умолчанию: `map`.
|
||||
|
||||
Формат ответа:
|
||||
|
||||
* `frame_id` – фрейм;
|
||||
* `frame_id` – система координат;
|
||||
* `connected` – есть ли подключение к <abbr title="Flight Control Unit, полетный контроллер">FCU</abbr>;
|
||||
* `armed` – состояние `armed` винтов (винты включены, если true);
|
||||
* `mode` – текущий [полетный режим](modes.md);
|
||||
@@ -73,7 +61,7 @@ release = rospy.ServiceProxy('release', Trigger)
|
||||
* `vx, vy, vz` – скорость коптера *(м/с)*;
|
||||
* `pitch` – угол по тангажу *(радианы)*;
|
||||
* `roll` – угол по крену *(радианы)*;
|
||||
* `yaw` – угол по рысканью в фрейме `frame_id`;
|
||||
* `yaw` – угол по рысканью *(радианы)*;
|
||||
* `pitch_rate` – угловая скорость по тангажу *(рад/с)*;
|
||||
* `roll_rate` – угловая скорость по крену *(рад/с)*;
|
||||
* `yaw_rate` – угловая скорость по рысканью *(рад/с)*;
|
||||
@@ -118,19 +106,19 @@ rosservice call /get_telemetry "{frame_id: ''}"
|
||||
|
||||
Параметры:
|
||||
|
||||
* `x`, `y`, `z` – координаты в системе `frame_id` *(м)*;
|
||||
* `x`, `y`, `z` – координаты *(м)*;
|
||||
* `yaw` – угол по рысканью *(радианы)*;
|
||||
* `yaw_rate` – угловая скорость по рысканью (применяется при установке yaw в `NaN`) *(рад/с)*;
|
||||
* `speed` – скорость полета (скорость движения setpoint) *(м/с)*;
|
||||
* `auto_arm` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
* `frame_id`, `update_frame`.
|
||||
* `frame_id` – [система координат](frames.md), в которой заданы `x`, `y`, `z` и `yaw` (по умолчанию: `map`).
|
||||
|
||||
> **Note** Для полета без изменения угла по рыскаью достаточно установить `yaw` в `NaN` (значение угловой скорости по-умолчанию – 0).
|
||||
|
||||
Взлет на высоту 1.5 м со скоростью взлета 0.5 м/с:
|
||||
|
||||
```python
|
||||
navigate(x=0, y=0, z=1.5, speed=0.5, frame_id='fcu_horiz', auto_arm=True)
|
||||
navigate(x=0, y=0, z=1.5, speed=0.5, frame_id='body', auto_arm=True)
|
||||
```
|
||||
|
||||
Полет по прямой в точку 5:0 (высота 2) в локальной системе координат со скоростью 0.8 м/с (рысканье установится в 0):
|
||||
@@ -148,37 +136,37 @@ navigate(x=5, y=0, z=3, speed=0.8, yaw=float('nan'))
|
||||
Полет вправо относительно коптера на 3 м:
|
||||
|
||||
```python
|
||||
navigate(x=0, y=-3, z=0, speed=1, frame_id='fcu_horiz')
|
||||
navigate(x=0, y=-3, z=0, speed=1, frame_id='body')
|
||||
```
|
||||
|
||||
Повернуться на 90 градусов против часовой:
|
||||
|
||||
```python
|
||||
navigate(yaw=math.radians(-90), frame_id='fcu_horiz')
|
||||
navigate(yaw=math.radians(-90), frame_id='body')
|
||||
```
|
||||
|
||||
Полет в точку 3:2 (высота 2) в системе координат [маркерного поля](aruco.md) со скоростью 1 м/с:
|
||||
|
||||
```python
|
||||
navigate(x=3, y=2, z=2, speed=1, frame_id='aruco_map', update_frame=True)
|
||||
navigate(x=3, y=2, z=2, speed=1, frame_id='aruco_map')
|
||||
```
|
||||
|
||||
Вращение на месте со скоростью 0.5 рад/c (против часовой):
|
||||
|
||||
```python
|
||||
navigate(x=0, y=0, z=0, yaw=float('nan'), yaw_rate=0.5, frame_id='fcu_horiz')
|
||||
navigate(x=0, y=0, z=0, yaw=float('nan'), yaw_rate=0.5, frame_id='body')
|
||||
```
|
||||
|
||||
Полет вперед 3 метра со скоростью 0.5 м/с, вращаясь по рысканью со скоростью 0.2 рад/с:
|
||||
|
||||
```python
|
||||
navigate(x=3, y=0, z=0, speed=0.5, yaw=float('nan'), yaw_rate=0.2, frame_id='fcu_horiz')
|
||||
navigate(x=3, y=0, z=0, speed=0.5, yaw=float('nan'), yaw_rate=0.2, frame_id='body')
|
||||
```
|
||||
|
||||
Взлет на высоту 2 м (командная строка):
|
||||
|
||||
```bash
|
||||
rosservice call /navigate "{x: 0.0, y: 0.0, z: 2, yaw: 0.0, yaw_rate: 0.0, speed: 0.5, frame_id: 'fcu_horiz', update_frame: false, auto_arm: true}"
|
||||
rosservice call /navigate "{x: 0.0, y: 0.0, z: 2, yaw: 0.0, yaw_rate: 0.0, speed: 0.5, frame_id: 'body', auto_arm: true}"
|
||||
```
|
||||
|
||||
### navigate_global
|
||||
@@ -188,31 +176,31 @@ rosservice call /navigate "{x: 0.0, y: 0.0, z: 2, yaw: 0.0, yaw_rate: 0.0, speed
|
||||
Параметры:
|
||||
|
||||
* `lat`, `lon` – широта и долгота *(градусы)*;
|
||||
* `z` – высота в системе координат `frame_id` *(м)*;
|
||||
* `z` – высота *(м)*;
|
||||
* `yaw` – угол по рысканью *(радианы)*;
|
||||
* `yaw_rate` – угловая скорость по рысканью (при установке yaw в `NaN`) *(рад/с)*;
|
||||
* `speed` – скорость полета (скорость движения setpoint) *(м/с)*;
|
||||
* `auto_arm` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
* `frame_id`, `update_frame`.
|
||||
* `frame_id` – [система координат](frames.md), в которой заданы `z` и `yaw` (по умолчанию: `map`).
|
||||
|
||||
> **Note** Для полета без изменения угла по рыскаью достаточно установить `yaw` в `NaN` (значение угловой скорости по-умолчанию – 0).
|
||||
|
||||
Полет в глобальную точку со скоростью 5 м/с, оставаясь на текущей высоте (`yaw` установится в 0, коптер сориентируется передом на восток):
|
||||
|
||||
```python
|
||||
navigate_global(lat=55.707033, lon=37.725010, z=0, speed=5, frame_id='fcu_horiz')
|
||||
navigate_global(lat=55.707033, lon=37.725010, z=0, speed=5, frame_id='body')
|
||||
```
|
||||
|
||||
Полет в глобальную точку без изменения угла по рысканью (`yaw` = `NaN`, `yaw_rate` = 0):
|
||||
|
||||
```python
|
||||
navigate_global(lat=55.707033, lon=37.725010, z=0, speed=5, yaw=float('nan'), frame_id='fcu_horiz')
|
||||
navigate_global(lat=55.707033, lon=37.725010, z=0, speed=5, yaw=float('nan'), frame_id='body')
|
||||
```
|
||||
|
||||
Полет в глобальную точку (командная строка):
|
||||
|
||||
```bash
|
||||
rosservice call /navigate_global "{lat: 55.707033, lon: 37.725010, z: 0.0, yaw: 0.0, yaw_rate: 0.0, speed: 5.0, frame_id: 'fcu_horiz', update_frame: false, auto_arm: false}"
|
||||
rosservice call /navigate_global "{lat: 55.707033, lon: 37.725010, z: 0.0, yaw: 0.0, yaw_rate: 0.0, speed: 5.0, frame_id: 'body', auto_arm: false}"
|
||||
```
|
||||
|
||||
### set_position
|
||||
@@ -223,34 +211,34 @@ rosservice call /navigate_global "{lat: 55.707033, lon: 37.725010, z: 0.0, yaw:
|
||||
|
||||
Параметры:
|
||||
|
||||
* `x`, `y`, `z` – координаты точки в системе координат `frame_id` *(м)*;
|
||||
* `x`, `y`, `z` – координаты точки *(м)*;
|
||||
* `yaw` – угол по рысканью *(радианы)*;
|
||||
* `yaw_rate` – угловая скорость по рысканью (при установке yaw в NaN) *(рад/с)*;
|
||||
* `auto_arm` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
* `frame_id`, `update_frame`.
|
||||
* `frame_id` – [система координат](frames.md), в которой заданы `x`, `y`, `z` и `yaw` (по умолчанию: `map`).
|
||||
|
||||
Зависнуть на месте:
|
||||
|
||||
```python
|
||||
set_position(frame_id='fcu_horiz')
|
||||
set_position(frame_id='body')
|
||||
```
|
||||
|
||||
Назначить целевую точку на 3 м выше текущей позиции:
|
||||
|
||||
```python
|
||||
set_position(x=0, y=0, z=3, frame_id='fcu_horiz')
|
||||
set_position(x=0, y=0, z=3, frame_id='body')
|
||||
```
|
||||
|
||||
Назначить целевую точку на 1 м впереди текущей позиции:
|
||||
|
||||
```python
|
||||
set_position(x=1, y=0, z=0, frame_id='fcu_horiz')
|
||||
set_position(x=1, y=0, z=0, frame_id='body')
|
||||
```
|
||||
|
||||
Вращение на месте со скоростью 0.5 рад/c:
|
||||
|
||||
```python
|
||||
set_position(x=0, y=0, z=0, frame_id='fcu_horiz', yaw=float('nan'), yaw_rate=0.5)
|
||||
set_position(x=0, y=0, z=0, frame_id='body', yaw=float('nan'), yaw_rate=0.5)
|
||||
```
|
||||
|
||||
### set_velocity
|
||||
@@ -261,34 +249,32 @@ set_position(x=0, y=0, z=0, frame_id='fcu_horiz', yaw=float('nan'), yaw_rate=0.5
|
||||
* `yaw` – угол по рысканью *(радианы)*;
|
||||
* `yaw_rate` – угловая скорость по рысканью (при установке yaw в NaN) *(рад/с)*;
|
||||
* `auto_arm` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
* `frame_id`, `update_frame`.
|
||||
* `frame_id` – [система координат](frames.md), в которой заданы `vx`, `vy`, `vz` и `yaw` (по умолчанию: `map`).
|
||||
|
||||
> **Note** Параметр `frame_id` определяет только ориентацию результирующего вектора скорости, но не его длину.
|
||||
|
||||
Полет вперед (относительно коптера) со скоростью 1 м/с:
|
||||
|
||||
```python
|
||||
set_velocity(vx=1, vy=0.0, vz=0, frame_id='fcu_horiz')
|
||||
set_velocity(vx=1, vy=0.0, vz=0, frame_id='body')
|
||||
```
|
||||
|
||||
Один из вариантов полета по кругу:
|
||||
|
||||
```python
|
||||
set_velocity(vx=0.4, vy=0.0, vz=0, yaw=float('nan'), yaw_rate=0.4, frame_id='fcu_horiz', update_frame=True)
|
||||
set_velocity(vx=0.4, vy=0.0, vz=0, yaw=float('nan'), yaw_rate=0.4, frame_id='body')
|
||||
```
|
||||
|
||||
### set_attitude
|
||||
|
||||
Установить тангаж, крен, рысканье и уровень газа (примерный аналог управления в [режиме `STABILIZED`](modes.md)). Данный сервис может быть использован для более низкоуровнего контроля поведения коптера либо для управления коптером при отсутствии источника достоверных данных о его позиции.
|
||||
|
||||
> **Note** Параметр `frame_id` определяет только систему координат, в которой задается рысканье (`yaw`).
|
||||
|
||||
Параметры:
|
||||
|
||||
* `pitch`, `roll`, `yaw` – необходимый угол по тангажу, крену и рысканью *(радианы)*;
|
||||
* `thrust` – уровень газа от 0 (нет газа) до 1 (полный газ);
|
||||
* `thrust` – уровень газа от 0 (нет газа, пропеллеры остановлены) до 1 (полный газ);
|
||||
* `auto_arm` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
* `frame_id`, `update_frame`.
|
||||
* `frame_id` – [система координат](frames.md), в которой задан `yaw` (по умолчанию: `map`).
|
||||
|
||||
### set_rates
|
||||
|
||||
@@ -297,14 +283,14 @@ set_velocity(vx=0.4, vy=0.0, vz=0, yaw=float('nan'), yaw_rate=0.4, frame_id='fcu
|
||||
Параметры:
|
||||
|
||||
* `pitch_rate`, `roll_rate`, `yaw_rate` – угловая скорость по танажу, крену и рыканью *(рад/с)*;
|
||||
* `thrust` – уровень газа от 0 (нет газа) до 1 (полный газ).
|
||||
* `thrust` – уровень газа от 0 (нет газа, пропеллеры остановлены) до 1 (полный газ).
|
||||
* `auto_arm` – перевести коптер в `OFFBOARD` и заармить автоматически (**коптер взлетит**);
|
||||
|
||||
### land
|
||||
|
||||
Перевести коптер в [режим](modes.md) посадки (`AUTO.LAND` или аналогичный).
|
||||
|
||||
> **Note** Для автоматического отключения винтов после посадки PX4-параметр `COM_DISARM_LAND` должен быть установлен в значение > 0.
|
||||
> **Note** Для автоматического отключения винтов после посадки [параметр PX4](px4_parameters.md) `COM_DISARM_LAND` должен быть установлен в значение > 0.
|
||||
|
||||
Посадка коптера:
|
||||
|
||||
@@ -321,9 +307,11 @@ if res.success:
|
||||
rosservice call /land "{}"
|
||||
```
|
||||
|
||||
<!--
|
||||
### release
|
||||
|
||||
Перестать публиковать setpoint'ы коптеру (отпустить управление). Необходим для продолжения контроля средствами [MAVROS](mavros.md).
|
||||
-->
|
||||
|
||||
Дополнительные материалы
|
||||
------------------------
|
||||
|
||||
@@ -39,7 +39,7 @@ tolerance = 0.2 # точность проверки высоты (м)
|
||||
start = get_telemetry()
|
||||
|
||||
# Взлетаем на 2 м
|
||||
print navigate(z=z, speed=0.5, frame_id='fcu_horiz', auto_arm=True)
|
||||
print navigate(z=z, speed=0.5, frame_id='body', auto_arm=True)
|
||||
|
||||
# Ожидаем взлета
|
||||
while True:
|
||||
@@ -100,14 +100,14 @@ tf_listener = tf2_ros.TransformListener(tf_buffer)
|
||||
|
||||
# Создаем объект PoseStamped (либо получаем из топика):
|
||||
pose = PoseStamped()
|
||||
pose.header.frame_id = 'local_origin' # фрейм, в котором задана позиция
|
||||
pose.header.frame_id = 'map' # фрейм, в котором задана позиция
|
||||
pose.header.stamp = rospy.get_rostime() # момент времени, для которого задана позиция (текущее время)
|
||||
pose.pose.position.x = 1
|
||||
pose.pose.position.y = 2
|
||||
pose.pose.position.z = 3
|
||||
pose.pose.orientation.w = 1
|
||||
|
||||
frame_id = 'fcu' # целевой фрейм
|
||||
frame_id = 'base_link' # целевой фрейм
|
||||
transform_timeout = rospy.Duration(0.2) # таймаут ожидания транформации
|
||||
|
||||
# Преобразовываем позицию из старого фрейма в новый:
|
||||
@@ -252,6 +252,22 @@ rospy.Subscriber('mavros/rc/in', RCIn, rc_callback)
|
||||
rospy.spin()
|
||||
```
|
||||
|
||||
### # {#set_mode}
|
||||
|
||||
Сменить [режим полета](modes.md) на произвольный:
|
||||
|
||||
```python
|
||||
from mavros_msgs.srv import SetMode
|
||||
|
||||
# ...
|
||||
|
||||
set_mode = rospy.ServiceProxy('mavros/set_mode', SetMode)
|
||||
|
||||
# ...
|
||||
|
||||
set_mode(custom_mode='STABILIZED')
|
||||
```
|
||||
|
||||
### # {#flip}
|
||||
|
||||
Флип:
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
# Работа с ультразвуковым дальномером
|
||||
|
||||
Ультразвуковой дальномер (*«сонар»*) — это датчик расстояния, принцип действия которого основан на измерении времени распространения звуковой волны (с частотой около 40 Гц) до препятствия и обратно. Сонар может измерять расстояние до 1,5–3 м с точностью до нескольких сантиметров.
|
||||
Ультразвуковой дальномер (*«сонар»*) — это датчик расстояния, принцип действия которого основан на измерении времени распространения звуковой волны (с частотой около 40 кГц) до препятствия и обратно. Сонар может измерять расстояние до 1,5–3 м с точностью до нескольких сантиметров.
|
||||
|
||||
## HC-SR04
|
||||
## Дальномер HC-SR04
|
||||
|
||||
<img src="../assets/hc-sr04.jpg" alt="hc-sr04" width=200>
|
||||
|
||||
## Установка
|
||||
|
||||
Дальномер закрепляется к корпусу с помощью двухстороннего скотча. Для получения приемлемых результатов необходимо использование виброразвязки. В качестве виброразвязки можно использовать кусок поролона.
|
||||
|
||||
### Подключение
|
||||
|
||||
Подключите HC-SR04 к Raspberry Pi согласно схеме подключения. Используйте резисторы на 1,0 и 2,2 кОм и любые свободные GPIO-пины, например 23 и 24:
|
||||
@@ -20,7 +24,7 @@
|
||||
|
||||
### Чтение данных
|
||||
|
||||
Чтобы считать данных с дальномера HC-SR04 используется библиотека для работы с <abbr title="General-Purpose Input/Output – пины ввода/вывода общего назначения">GPIO</abbr> – [`pigpio`](http://abyz.me.uk/rpi/pigpio/index.html). Эта библиотека предустановлена на [образе Клевера](microsd_images.md), начиная с версии **v0.14**. Для более старых версий образа используйте [инструкцию по установке](http://abyz.me.uk/rpi/pigpio/download.html).
|
||||
Чтобы считать данные с дальномера HC-SR04, используется библиотека для работы с <abbr title="General-Purpose Input/Output – пины ввода/вывода общего назначения">GPIO</abbr> – [`pigpio`](http://abyz.me.uk/rpi/pigpio/index.html). Эта библиотека предустановлена на [образе Клевера](microsd_images.md), начиная с версии **v0.14**. Для более старых версий образа используйте [инструкцию по установке](http://abyz.me.uk/rpi/pigpio/download.html).
|
||||
|
||||
Для работы с `pigpio` необходимо запустить соответствующий демон:
|
||||
|
||||
@@ -108,7 +112,7 @@ while True:
|
||||
|
||||
Исходный код ROS-ноды, использовавшейся для построения графика можно найти [на Gist](https://gist.github.com/okalachev/feb2d7235f5c9636802c3cda43add253).
|
||||
|
||||
## RCW-0001
|
||||
## Дальномер RCW-0001
|
||||
|
||||
<img src="../assets/rcw-0001.jpg" width=200>
|
||||
|
||||
@@ -119,11 +123,11 @@ while True:
|
||||
Пример полетной программы с использованием [simple_offboard](simple_offboard.md), которая заставляет коптер лететь вперед, пока подключенный ультразвуковой дальномер не задетектирует препятствие:
|
||||
|
||||
```python
|
||||
set_velocity(x=0.5, frame_id='fcu_horiz', auto_arm=True) # полет вперед со скоростью 0.5 мс
|
||||
set_velocity(x=0.5, frame_id='body', auto_arm=True) # полет вперед со скоростью 0.5 мс
|
||||
|
||||
while True:
|
||||
if read_distance_filtered() < 1:
|
||||
# если препятствие ближе, чем в 1 м, зависаем в точке
|
||||
set_position(x=0, y=0, z=0, frame_id='fcu_horiz')
|
||||
set_position(x=0, y=0, z=0, frame_id='body')
|
||||
rospy.sleep(0.1)
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Просмотр изображений с камер
|
||||
|
||||
Для просмотра изображений с камер можно воспользовться [rviz](rviz.md), rqt, или смотреть их через браузер, используя web\_video\_server.
|
||||
Для просмотра изображений с камер (или других ROS-топиков) можно воспользовться [rviz](rviz.md), rqt, или смотреть их через браузер, используя web\_video\_server.
|
||||
|
||||
См. подробнее про [использование rqt](rviz.md).
|
||||
|
||||
@@ -22,7 +22,7 @@ sudo systemctl restart clever
|
||||
|
||||
### Просмотр
|
||||
|
||||
Для просмотра видеострима нужно [подключиться к Wi-Fi](wifi.md) Клевера \(`CLEVER-xxxx`\), перейти на страницу [http://192.168.11.1:8080/](http://192.168.11.1:8080/) и выбрать топик камеры.
|
||||
Для просмотра видеострима нужно [подключиться к Wi-Fi](wifi.md) Клевера \(`CLEVER-xxxx`\), перейти на страницу [http://192.168.11.1:8080/](http://192.168.11.1:8080/) и выбрать топик.
|
||||
|
||||

|
||||
|
||||
@@ -33,3 +33,25 @@ http://192.168.11.1:8080/stream_viewer?topic=/main_camera/image_raw&quality=1
|
||||
По URL выше будет доступен стрим с основной камеры в минимальном возможном качестве.
|
||||
|
||||
Также доступны параметры `width`, `height` и другие. Подробнее о `web_video_server`: http://wiki.ros.org/web_video_server.
|
||||
|
||||
## Просмотр через rqt_image_view
|
||||
|
||||
Для просмотра изображений через инструменты rqt необходим компьютер с установленной Ubuntu 16.04 и [ROS Kinetic](http://wiki.ros.org/kinetic/Installation/Ubuntu).
|
||||
|
||||
[Подключитесь к Wi-Fi сети Клевера](wifi.md) и запустите `rqt_image_view` с указанием его IP-адреса:
|
||||
|
||||
```bash
|
||||
ROS_MASTER_URI=http://192.168.11.1:11311 rqt_image_view
|
||||
```
|
||||
|
||||
Выберите топик для просмотра, например `/main_camera/image_raw`:
|
||||
|
||||

|
||||
|
||||
Для снижения нагрузки на сеть и уменьшения задержки используйте сжатый вариант топика – `/main_camera/image_raw/compressed`.
|
||||
|
||||
Для изменения настроек сжатия используйте rqt-плагин Dynamic Reconfigure:
|
||||
|
||||

|
||||
|
||||
См. [подробнее об rviz и rqt](rviz.md).
|
||||
|
||||
@@ -8,3 +8,9 @@
|
||||
<img src="../assets/ssid.png" width="300px" alt="Wi-Fi SSID">
|
||||
|
||||
Для изменения настроек Wi-Fi или получения более детальной информации о устройстве сети на Raspberry Pi прочитайте эту [статью](network.md).
|
||||
|
||||
## Веб-интерфейс
|
||||
|
||||
После подключения к Клеверу по адресу http://192.168.11.1 будет доступен веб-интерфейс. В нем доступны основные веб-инструменты Клевера: просмотр топиков с изображениями, веб-терминал (Butterfly) а также полная копия данной документации.
|
||||
|
||||

|
||||
|
||||