Compare commits

...

35 Commits

Author SHA1 Message Date
sfalexrog
c8bcede60a Merge branch 'master' into nti2019 2019-04-09 10:32:30 +03:00
sfalexrog
1d591965a3 init_rpi: Fix typo in sed command 2019-04-09 10:31:12 +03:00
sfalexrog
c589235984 Merge remote-tracking branch 'origin/master' into nti2019 2019-04-08 23:30:51 +03:00
Oleg Kalachev
8bb3f751ca Set correct camera frame by default for nti 2019-04-08 20:34:58 +03:00
Oleg Kalachev
d4ab87ad9e docs: small fix for markdownlint 2019-04-08 20:34:54 +03:00
sfalexrog
7519958698 init: Automatically set Clever hostname 2019-04-08 20:16:48 +03:00
Oleg Kalachev
f90c1a6329 Change some default for NTI 2019 2019-04-08 17:23:52 +03:00
Oleg Kalachev
c63e4265d6 aruco_map: add nti_novgorod map 2019-04-08 17:22:14 +03:00
Oleg Kalachev
60c97d2318 Merge branch 'master' into nti2019 2019-04-08 17:21:11 +03:00
Oleg Kalachev
be7624b309 docs: edit nti article 2019-04-08 16:11:09 +03:00
sfalexrog
e9e8c84ddf aruco_pose: Try to draw as much of axes as possible 2019-04-07 22:46:38 +03:00
Oleg Kalachev
6535943cc8 docs: fix 2019-04-07 19:15:05 +03:00
Oleg Kalachev
375b19146c docs: changes 2019-04-07 19:14:34 +03:00
Oleg Kalachev
77602021ae Merge branch 'master' of github.com:CopterExpress/clever 2019-04-07 19:12:40 +03:00
sfalexrog
8dec500702 builder: Add ros_ws281x package 2019-04-07 17:50:31 +03:00
sfalexrog
0df66a8df7 Add annotated MQTT sample 2019-04-07 17:28:42 +03:00
Oleg Kalachev
ae9302bfc2 Remove +x flag from main_camera.launch 2019-04-07 16:35:29 +03:00
Oleg Kalachev
993cc50276 docs: edit nti.md 2019-04-07 16:12:02 +03:00
sfalexrog
09a8f702a7 docs: Add note about LED strip 2019-04-06 23:57:21 +03:00
sfalexrog
bcefb03f04 builder: Install paho-mqtt system-wide 2019-04-06 23:23:04 +03:00
sfalexrog
bc1ceb2fa0 Add annotated MQTT sample 2019-04-06 23:20:35 +03:00
Oleg Kalachev
06bf2d5b56 docs: add some info on using clever for NTI 2019 2019-04-06 19:54:26 +03:00
Oleg Kalachev
db03222a19 docs: add some info on nti 2019 2019-04-04 22:14:24 +03:00
sfalexrog
fea6992964 builder: Fix kernel version 2019-04-04 20:54:42 +03:00
Oleg Kalachev
67ddfa6c5e docs: NTI olympics 2019 page stub created 2019-04-04 19:50:04 +03:00
sfalexrog
9e77a11cf5 builder: Update kernel version 2019-04-03 14:14:20 +03:00
Oleg Kalachev
928d2e38d4 gitbook: remove yandex webmaster validation 2019-04-03 00:01:46 +03:00
Oleg Kalachev
eb9b621662 gitbook: fix for yandex webmaster 2019-04-02 23:33:40 +03:00
Oleg Kalachev
dfd6736fb0 gitbook: remove redirect for a while 2019-04-02 23:29:37 +03:00
Oleg Kalachev
08ea466232 Yandex.Webmaster verification 2019-04-02 23:26:11 +03:00
sfalexrog
07b6dcde51 builder: Update base image 2019-04-02 20:47:33 +03:00
sfalexrog
66aa4729ad docs: Minor px4flow article fix 2019-04-02 18:07:39 +03:00
Oleg Kalachev
bb825c3c30 docs: edit px4flow article a little 2019-03-29 18:24:17 +03:00
sfalexrog
32635def32 PX4FLOW article (#113)
* px4flow: Start writing documentation

* px4flow: Add more information

* docs/px4flow: Pixracer connection and configuration

* docs/px4flow: Lint fixes
2019-03-29 18:21:25 +03:00
Alamoris
0342e7da39 Small fix 2019-03-29 17:23:22 +03:00
27 changed files with 385 additions and 34 deletions

View File

@@ -0,0 +1,6 @@
34 0.33 0 0 0 0 0 0
37 0.33 0.74 0 0 0 0 0
25 0.33 0 0.54 0 0 0 0
28 0.33 0.74 0.54 0 0 0 0
32 0.33 2.79 -0.15 1.20 0 0 0
29 0.33 2.46 0.65 1.20 0 0 0

View File

@@ -102,6 +102,42 @@ void _drawPlanarBoard(Board *_board, Size outSize, OutputArray _img, int marginS
}
}
/* Draw a (potentially partially visible) line. */
static void linePartial(InputOutputArray image, Point3f p1, Point3f p2, const Scalar& color,
int thickness = 1, int lineType = LINE_8, int shift = 0)
{
// If both points are behind the screen, don't draw anything
if (p1.z <= 0 && p2.z <= 0)
{
return;
}
Point2f p1p{p1.x, p1.y};
Point2f p2p{p2.x, p2.y};
// If points are on the different sides of the plane, compute intersection point
if (p1.z * p2.z < 0)
{
// Compute intersection point with the screen
// We denote alpha as such:
// xi = (1 - alpha) * x1 + alpha * x2
// yi = (1 - alpha) * y1 + alpha * y2
// zi = (1 - alpha) * z1 + alpha * z2 = 0
// Thus, alpha can be expressed as
// alpha = z1 / (z1 - z2)
float alpha = p1.z / (p1.z - p2.z);
Point2f pi{(1 - alpha) * p1.x + alpha * p2.x, (1 - alpha) * p1.y + alpha * p2.y};
// Now, if z1 is negative, we draw the line from (xi, yi) to (x2, y2), else we draw from (x1, y1) to (xi, yi)
if (p1.z < 0)
{
p1p = pi;
}
else
{
p2p = pi;
}
}
line(image, p1p, p2p, color, thickness, lineType, shift);
}
void _drawAxis(InputOutputArray _image, InputArray _cameraMatrix, InputArray _distCoeffs,
InputArray _rvec, InputArray _tvec, float length) {
@@ -118,26 +154,10 @@ void _drawAxis(InputOutputArray _image, InputArray _cameraMatrix, InputArray _di
std::vector< Point3f > imagePointsZ;
_projectPoints(axisPoints, _rvec, _tvec, _cameraMatrix, _distCoeffs, imagePointsZ);
if (imagePointsZ[0].z < 0 ||
imagePointsZ[1].z < 0 ||
imagePointsZ[2].z < 0 ||
imagePointsZ[3].z < 0)
{
// Any axis point is behind screen plane -> don't draw anything
return;
}
// Intersect axis lines with screen plane (they may be outside)
std::vector<Point2f> imagePoints(4);
imagePoints[0] = Point2f{imagePointsZ[0].x, imagePointsZ[0].y};
imagePoints[1] = Point2f{imagePointsZ[1].x, imagePointsZ[1].y};
imagePoints[2] = Point2f{imagePointsZ[2].x, imagePointsZ[2].y};
imagePoints[3] = Point2f{imagePointsZ[3].x, imagePointsZ[3].y};
// draw axis lines
line(_image, imagePoints[0], imagePoints[1], Scalar(0, 0, 255), 3);
line(_image, imagePoints[0], imagePoints[2], Scalar(0, 255, 0), 3);
line(_image, imagePoints[0], imagePoints[3], Scalar(255, 0, 0), 3);
linePartial(_image, imagePointsZ[0], imagePointsZ[1], Scalar(0, 0, 255), 3);
linePartial(_image, imagePointsZ[0], imagePointsZ[2], Scalar(0, 255, 0), 3);
linePartial(_image, imagePointsZ[0], imagePointsZ[3], Scalar(255, 0, 0), 3);
}
static CvMat _cvMat(const cv::Mat& m)

35
builder/assets/clever_rename Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Set Clever hostname to the specified value
set -e
NEW_NAME_OPT=$1
if [[ -z ${NEW_NAME_OPT} ]]; then
echo "Please specify new name for this Clever"
exit 1
fi
NEW_NAME=$(echo ${NEW_NAME_OPT} | tr '[:upper:]' '[:lower:]')
echo "Setting name to ${NEW_NAME}"
echo "Backing up /etc/hostname"
cp /etc/hostname /etc/hostname.bak
echo "Writing new /etc/hostname"
echo ${NEW_NAME} > /etc/hostname
echo "Backing up /etc/hosts"
cp /etc/hosts /etc/hosts.bak
echo "Rewriting /etc/hosts with new values"
sed -i 's/127\.0\.1\.1.*/127.0.1.1\t'${NEW_NAME}'/g' /etc/hosts
echo "Changing hostname in /lib/systemd/system/roscore.env"
sed -i 's/ROS_HOSTNAME=.*/ROS_HOSTNAME='${NEW_NAME}'.local/g' /lib/systemd/system/roscore.env
echo "Changing hostname in .bashrc"
sed -i 's/export ROS_HOSTNAME=.*/export ROS_HOSTNAME='${NEW_NAME}'.local/g' /home/pi/.bashrc
echo "Done, reboot your Clever to see the results"

View File

@@ -32,7 +32,9 @@ echo_stamp() {
}
echo_stamp "Rename SSID"
sudo sed -i.OLD "s/CLEVER/CLEVER-$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e 's/[^0-9]//g' | cut -c 1-4)/g" /etc/wpa_supplicant/wpa_supplicant.conf
NEW_SSID='CLEVER-'$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e "s/[^0-9]//g" | cut -c 1-4)
sudo sed -i.OLD "s/CLEVER/${NEW_SSID}/" /etc/wpa_supplicant/wpa_supplicant.conf
clever_rename ${NEW_SSID}
echo_stamp "Harware setup"
/root/hardware_setup.sh

View File

@@ -0,0 +1,14 @@
[Unit]
Description=ROS ws281x support
Requires=roscore.service
After=roscore.service
[Service]
EnvironmentFile=/lib/systemd/system/roscore.env
ExecStart=/opt/ros/kinetic/bin/roslaunch ros_ws281x clever4.launch --wait --screen
Restart=on-failure
RestartSec=3
TimeoutSec=infinity
[Install]
WantedBy=multi-user.target

View File

@@ -11,7 +11,7 @@
set -e # Exit immidiately on non-zero result
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2018-06-29/2018-06-27-raspbian-stretch-lite.zip"
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2018-11-15/2018-11-13-raspbian-stretch-lite.zip"
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
export LANG=${LANG:='C.UTF-8'}
@@ -112,6 +112,9 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/ros_pyt
# ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/kinetic-ros-clever.rosinstall' '/home/pi/ros_catkin_ws/'
# Add PX4 udev rules
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/99-px4fmu.rules' '/lib/udev/rules.d/'
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/rosled.service' '/lib/systemd/system/'
# Add rename script
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/clever_rename' '/usr/local/bin/clever_rename'
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-ros.sh' ${REPO_URL} ${IMAGE_VERSION} false false ${NUMBER_THREADS}
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-validate.sh'

View File

@@ -137,6 +137,10 @@ fi
export ROS_IP='127.0.0.1' # needed for running tests
echo_stamp "Adding ros_ws281x ROS package"
cd /home/pi/catkin_ws/src
git clone https://github.com/sfalexrog/ros_ws281x
echo_stamp "Installing CLEVER" \
&& cd /home/pi/catkin_ws/src/clever \
&& git status \
@@ -145,7 +149,7 @@ echo_stamp "Installing CLEVER" \
&& my_travis_retry pip install wheel \
&& my_travis_retry pip install -r /home/pi/catkin_ws/src/clever/clever/requirements.txt \
&& source /opt/ros/kinetic/setup.bash \
&& catkin_make -j2 -DCMAKE_BUILD_TYPE=Release \
&& catkin_make -j2 -DCMAKE_BUILD_TYPE=Release -DROS_WS2811_REAL_LIB=ON \
&& catkin_make run_tests \
&& catkin_test_results \
&& systemctl enable roscore \
@@ -153,6 +157,9 @@ echo_stamp "Installing CLEVER" \
&& echo_stamp "All CLEVER was installed!" "SUCCESS" \
|| (echo_stamp "CLEVER installation was failed!" "ERROR"; exit 1)
echo_stamp "Enabling ROS LED service"
systemctl enable rosled
echo_stamp "Build CLEVER documentation"
cd /home/pi/catkin_ws/src/clever
NPM_CONFIG_UNSAFE_PERM=true npm install gitbook-cli -g

View File

@@ -105,6 +105,9 @@ python3-dev \
&& echo_stamp "Everything was installed!" "SUCCESS" \
|| (echo_stamp "Some packages wasn't installed!" "ERROR"; exit 1)
echo_stamp "Updating kernel to fix camera bug"
apt-get install --no-install-recommends -y raspberrypi-kernel=1.20190215-1
# Deny byobu to check available updates
sed -i "s/updates_available//" /usr/share/byobu/status/status
# sed -i "s/updates_available//" /home/pi/.byobu/status
@@ -136,6 +139,9 @@ mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
mv /root/monkey /etc/monkey/sites/default
systemctl enable monkey.service
echo_stamp "Install paho-mqtt"
my_travis_retry pip install paho-mqtt
echo_stamp "Install Node.js"
cd /home/pi
wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-armv6l.tar.gz

View File

@@ -46,3 +46,4 @@ rosversion rosserial
rosversion usb_cam
rosversion cv_camera
rosversion web_video_server
rosversion ros_ws281x

View File

@@ -1,7 +1,7 @@
<launch>
<arg name="aruco_detect" default="true"/>
<arg name="aruco_map" default="false"/>
<arg name="aruco_vpe" default="false"/>
<arg name="aruco_map" default="true"/>
<arg name="aruco_vpe" default="true"/>
<!-- For additional help go to https://clever.copterexpress.com/aruco.html -->

View File

@@ -5,10 +5,10 @@
<arg name="web_video_server" default="true"/>
<arg name="rosbridge" default="true"/>
<arg name="main_camera" default="true"/>
<arg name="optical_flow" default="false"/>
<arg name="aruco" default="false"/>
<arg name="rc" default="true"/>
<arg name="rangefinder_vl53l1x" default="false"/>
<arg name="optical_flow" default="true"/>
<arg name="aruco" default="true"/>
<arg name="rc" default="false"/>
<arg name="rangefinder_vl53l1x" default="true"/>
<arg name="arduino" default="false"/>
<!-- mavros -->

4
clever/launch/main_camera.launch Executable file → Normal file
View File

@@ -5,10 +5,10 @@
<!-- article about camera setup: https://clever.copterexpress.com/camera_frame.html -->
<!-- camera is oriented downward, camera cable goes backward [option 1] -->
<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"/>
<!-- <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"/> -->
<!-- camera is oriented downward, camera cable goes forward [option 2] -->
<!--<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"/>-->
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="-0.04 0 -0.08 1.5707963 0 3.1415926 base_link main_camera_optical"/>
<!-- camera is oriented upward, camera cable goes backward [option 3] -->
<!--<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"/>-->

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
docs/assets/px4flow_top.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -62,12 +62,14 @@
* [CopterHack-2018](copterhack2018.md)
* [CopterHack-2017](copterhack2017.md)
* Дополнительные материалы
* [Олимпиада НТИ 2019](nti2019.md)
* [Вклад в Клевер](contributing.md)
* [Прошивка ESC контроллеров](esc_firmware.md)
* [Протокол MAVLink](mavlink.md)
* [Работа с логами PX4](flight_logs.md)
* [Калибровка камеры](calibration.md)
* [Работа с ИК датчиками](ir_sensors.md)
* [Подключение PX4FLOW](px4flow.md)
* Учебник
* [Теория и видеоуроки](lessons.md)
* [Учебно-методическое пособие](metod.md)

157
docs/ru/nti2019.md Normal file
View File

@@ -0,0 +1,157 @@
# Олимпиада НТИ 2019
## Работа с MQTT
[MQTT](https://ru.wikipedia.org/wiki/MQTT) протокол для обмена сообщениями между различными устройствами. Этот протокол используется для отправки команд дрону на Олимпиаде НТИ 2019. Для отправки сообщения оно публикуется в определенный топик; все подписчики этого топика получают это сообщение.
### Подписка на топики
В образе Клевера для Олимпиады НТИ 2019 предустановлена библиотека `paho-mqtt` для Python. Пример работы с этой библиотекой описан ниже:
```python
import paho.mqtt.client as mqtt # Импортирование библиотеки mqtt
# Callback, вызываемый при получении от сервера подтверждения о подключении
def on_connect(client, userdata, flags, rc):
print ("Connected with result code "+str(rc))
# Если подписываться на топик в on_connect, то при обрыве соединения
# и повторном подключении произойдёт автоматическое переподписание
client.subscribe("/copters/copter1")
# Callback, вызываемый при появлении сообщения в одном из топиков, на который
# подписан клиент
def on_message(client, userdata, msg):
# В объекте msg хранится топик, в который пришло сообщение (в поле topic)
# и само сообщение (в поле payload)
print(msg.topic, str(msg.payload))
# Инициализация клиента MQTT
client = mqtt.Client()
# Здесь указываются callback'и, вызываемые при подключении и получении сообщения
client.on_connect = on_connect
client.on_message = on_message
# Подключение к MQTT-брокеру. Первый параметр - имя или адрес брокера, второй - порт
# (по умолчанию 1883), третий - максимальное время между сообщениями в секундах
# (по умолчанию 60).
client.connect('192.168.11.162', 1883, 60)
# Метод loop_start создаёт поток, в котором будет производиться опрос сервера и
# вызов callback'ов.
client.loop_start()
# Далее продолжается ваша программа
```
Более подробная документация доступна на [странице библиотеки в PyPI](https://pypi.org/project/paho-mqtt/).
### Проверка
Для проверки вы можете опубликовать любое сообщение в топик с помощью команды `hbmqtt_pub`:
```bash
hbmqtt_pub --url mqtt://192.168.0.1:1883 -t /copters/copter1 -m 'сообщение'
```
Где `192.168.0.1` IP-адрес MQTT-брокера, `сообщение` – сообщение для публикации, `/copters/copter1` необходимый топик для публикации.
### Работа с MQTT
В образе Клевера предустановлена библиотека `paho-mqtt` для Python. Пример работы с этой библиотекой описан ниже:
```python
import paho.mqtt.client as mqtt # Импортирование библиотеки mqtt
# Callback, вызываемый при получении от сервера подтверждения о подключении
def on_connect(client, userdata, flags, rc):
print ("Connected with result code "+str(rc))
# Если подписываться на топик в on_connect, то при обрыве соединения
# и повторном подключении произойдёт автоматическое переподписание
client.subscribe("/copters/copter1")
# Callback, вызываемый при появлении сообщения в одном из топиков, на который
# подписан клиент
def on_message(client, userdata, msg):
# В объекте msg хранится топик, в который пришло сообщение (в поле topic)
# и само сообщение (в поле payload)
print (msg.topic+" "+str(msg.payload))
# Инициализация клиента MQTT
client = mqtt.Client()
# Здесь указываются callback'и, вызываемые при подключении и получении сообщения
client.on_connect = on_connect
client.on_message = on_message
# Подключение к MQTT-брокеру. Первый параметр - имя или адрес брокера, второй - порт
# (по умолчанию 1883), третий - максимальное время между сообщениями в секундах
# (по умолчанию 60).
client.connect("192.168.11.162", 1883, 60)
# Метод loop_start создаёт поток, в котором будет производиться опрос сервера и
# вызов callback'ов.
client.loop_start()
# Далее продолжается ваша программа
```
Более подробная документация доступна на [странице библиотеки в PyPI](https://pypi.org/project/paho-mqtt/).
## Работа с Клевером
Для выполнения команд на Клевере:
* подключитесь в Wi-Fi сети NTI;
* подключитесь к вашему Клеверу по SSH по его IP-адресу (подробнее см. [подключение по SSH](ssh.md));
Для редактирования файлов на Клевере вы можете использовать консольные редакторы `nano` или `vim`. Также вы можете загружать файлы используя PyCharm или WinSCP.
Для автономного полета используйте API модуля [simple_offboard](simple_offboard.md).
Пример программы, выполняющей взлет, полет в точку в системе координат площадки и посадку на Python:
```python
# coding: utf8
import rospy
from clever import srv
from std_srvs.srv import Trigger
rospy.init_node('flight')
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
navigate = rospy.ServiceProxy('navigate', srv.Navigate)
land = rospy.ServiceProxy('land', Trigger)
# Взлет на 1 метр со скоростью 1 метр в секунду
navigate(x=0, y=0, z=1, speed=1, frame_id='body', auto_arm=True)
# Ждем 5 секунд
rospy.sleep(5)
# Полет на координаты x=3, y=2, z=1 площадки с углом по рысканью 3.14 радиан со скоростью 0.5 метров в секунду
navigate(x=3, y=2, z=1, yaw=3.14, speed=0.5, frame_id='aruco_map')
# Ждем 5 секунд
rospy.sleep(5)
# Посадка
land()
```
Для более подробной информации и описания других команд смотрите [API simple_offboard](simple_offboard.md) и [примеры кода](snippets.md).
Пример взлета на высоту 1 метр из командной строки:
```bash
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}"
```
Для более подробной информации и описания других команд смотрите [API simple_offboard](simple_offboard.md) и [примеры кода](snippets.md).
### Работа со светодиодной лентой
В используемой версии Клевера LED-лента подключена напрямую к Raspberry Pi. При включении всех светодиодов ленты на полную мощность возможно повреждение цепей питания микрокомпьютера.
Сигнальный провод ленты подключен к GPIO-пину 18.
Подробнее про работу с LED-лентой можно прочитать [в соответствующей статье](leds.md)

98
docs/ru/px4flow.md Normal file
View File

@@ -0,0 +1,98 @@
# Смарт-камера PX4FLOW
![PX4Flow Top View](../assets/px4flow_top.jpg) ![PX4Flow Bottom View](../assets/px4flow_bottom.jpg)
[PX4FLOW](https://docs.px4.io/en/sensor/px4flow.html) смарт-камера, реализующая алгоритм вычисления "оптического потока" ([optical flow](https://docs.px4.io/en/sensor/optical_flow.html)) и способная передать полученные данные в полётный контроллер. Optical flow часто применяется для полётов коптера в помещении.
## Спецификации
Модуль PX4FLOW содержит:
* микропроцессор Cortex M4F (168 MHz, 128 + 64 KB RAM);
* светочувствительную матрицу MT9V034 (разрешение: 752x480 точек);
* трёхосевой гироскоп L3GD20.
Для светочувствительной матрицы используется объектив 16мм М12 с установленным ИК-фильтром.
Габариты модуля составляют 45.5x35x25 мм (в зависимости от настройки объектива).
Модуль использует питание 5 В и потребляет до 115 мА.
Интерфейсы:
* USB (разъём microUSB) используется для программирования и первоначальной настройки;
* I2C (разъём Hirose DF13 4 pos) используется для передачи данных на полётный контроллер;
* USART2, USART3 (разъёмы Hirose DF13 6 pos) могут использоваться для подключения к полётному контроллеру и последовательного соединения нескольких модулей.
> **Hint** Использование Optical Flow требует наличия дальномера!
На некоторых моделях PX4FLOW может быть установлен сонар Maxbotix LZ-EZ4. В этом случае его показания будут пересылаться вместе с показаниями камеры.
## Первоначальная настройка
Настройка камеры производится с помощью программы [QGroundControl](http://qgroundcontrol.com/). Запустите её и подключите модуль PX4FLOW к компьютеру по USB. Откройте режим `Vehicle setup` (иконка с шестерёнками); окно QGroundControl при этом будет выглядеть примерно так:
![QGroundContor PX4FLOW connected](../assets/px4flow_qgc_connected.png)
Если это первое включение камеры, то вам надо будет произвести [обновление её прошивки](firmware.md) по аналогии с перепрошивкой полётного контроллера.
![QGroundControl PX4FLOW firmware update](../assets/px4flow_qgc_firmware.png)
> **Info** При перепрошивке PX4FLOW следует выбрать прошивку `PX4 Pro` при использовании полётного контроллера на базе `PX4` и `ArduPilot` при использовании полётного контроллера с прошивкой `ArduPilot`.
## Фокусировка камеры
Для оптимальной работы модуля PX4FLOW следует настроить фокус его камеры на предполагаемое расстояние от пола, при котором будут осуществляться полёты. Это можно сделать в QGroundControl в режиме `Vehicle setup` во вкладке `PX4Flow`. Там вы сможете увидеть изображение с камеры:
![QGroundControl PX4FLOW camera feed](../assets/px4flow_qgc_camera_feed.png)
> **Hint** Для калибровки камеры лучше использовать специальный режим `Video only`. Для его включения зайдите во вкладку `Parameters`, найдите параметр `VIDEO_ONLY` и установите его в значение `1`
![QGroundControl PX4FLOW Video Only Parameter](../assets/px4flow_qgc_video_only_param.png)
Фокусировку следует проводить в хорошо освещённом месте, модуль камеры при этом следует закрепить. Для фокусировки рекомендуется использовать книгу или коробку с текстом. Расположите объект, на котором вы будете фокусироваться, на таком расстоянии, на котором вы предполагаете летать над полом.
> **Info** В режиме калибровки камера будет выдавать изображение большего разрешения, чем при штатной работе, но с меньшей частотой кадров.
При работе в режиме калибровки рекомендуется развернуть окно QGroundControl на весь экран, чтобы лучше видеть изображение:
![QGroundControl PX4FLOW calibration](../assets/px4flow_qgc_calibration.png)
> **Hint** Изображение с камеры будет отражено по вертикальной оси. Это является нормальным поведением и не должно быть поводом для беспокойства.
Отпустите контргайку на объективе и медленно вращайте его, пока изображение не станет резким. После этого аккуратно закрепите объектив с помощью контргайки.
> **Info** Остальные параметры в данный момент не сохраняются, поэтому настройка камеры ограничивается её фокусировкой.
## Установка и подключение
По умолчанию предполагается, что модуль PX4FLOW будет расположен так, что направление оси `y` будет совпадать со стрелкой на полётном контроллере:
![PX4FLOW alignment](../assets/px4flow_alignment.jpg)
> **Hint** Поворот модуля PX4FLOW относительно полётного контроллера указывается параметром [`SENS_FLOW_ROT`](https://docs.px4.io/en/advanced_config/parameter_reference.html#SENS_FLOW_ROT) в PX4. Его значение по умолчанию (`Yaw 270°`) соответствует размещению на иллюстрации.
### Подключение к Pixhawk
Подключите PX4FLOW с помощью поставляемых кабелей к разъёму I2C на Pixhawk:
![PX4FLOW Pixhawk connection](../assets/px4flow_pixhawk_connection.jpg)
### Подключение к Pixracer
В полётном контроллере Pixracer используется совмещённый порт [UART/I2C](https://docs.px4.io/en/flight_controller/pixracer.html#pinouts) (помечен как GPS).
> **Warning** На более ранних версиях PX4FLOW разъём I2C может быть перевёрнут; ориентируйтесь на кабель, идущий в комплекте на нём красным отмечен провод питания.
![PX4FLOW Pixracer connection](../assets/px4flow_pixracer_connection.jpg)
> **Hint** Для подключения PX4FLOW к Pixracer рекомендуется использовать [GPS/I2C сплиттер](https://store.mrobotics.io/mRo-JST-GH-GPS-Port-to-I-C-Bus-Splitter-p/mro-jstgh-gps-i2c-split-mr.htm)
## Настройка полётного контроллера
Для того, чтобы полётный контроллер использовал данные с PX4FLOW, следует установить соответствующие флаги в настройках estimator'а:
* Для **LPE** (`SYS_MC_EST_GROUP` = `local_position_estimator`): в `LPE_FUSION` включены флажки `fuse optical flow` и `flow gyro compensation`.
* Для **EKF2** (`SYS_MC_EST_GROUP` = `ekf2`): в `EKF_AID_MASK` включен флажок `use optical flow`.
> **Hint** Остальные настройки PX4FLOW описаны в [статье по Optical Flow](optical_flow.md). Значения по умолчанию должны обеспечить оптимальную работу PX4FLOW.

View File

@@ -118,7 +118,7 @@ docker run \
```
touch /tmp/.docker.xauth
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f /tmp/.docker/xauth nmerge -
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f /tmp/.docker.xauth nmerge -
docker run \
-it \

View File

@@ -784,21 +784,21 @@
### Теория FPV полетов
**1. Какой стик является основным для позиционирования при FPV полетах? **
**1. Какой стик является основным для позиционирования при FPV полетах?**
1. Roll
2. Pitch
3. Yaw
4. Throttle
**2. Каким стиком удерживается высота? **
**2. Каким стиком удерживается высота?**
1. Roll
2. Pitch
3. Yaw
4. Throttle
**3. Что такое FPV пилотирование? **
**3. Что такое FPV пилотирование?**
1. Полеты с ориентацией “от первого лица”
2. Полеты с грузом