mirror of
https://github.com/CopterExpress/clover.git
synced 2026-06-01 15:39:32 +00:00
Compare commits
255 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
621b70711d | ||
|
|
2a2fbe3bed | ||
|
|
add15ac2fe | ||
|
|
abe6f5cf0f | ||
|
|
b04d8311bd | ||
|
|
b7e8acefb4 | ||
|
|
caa974b71c | ||
|
|
3f00001d9a | ||
|
|
1a9e689b8c | ||
|
|
1e2f92f165 | ||
|
|
d087d1c953 | ||
|
|
01c495597b | ||
|
|
8c8fdcda54 | ||
|
|
fbe353b767 | ||
|
|
4748d34fa2 | ||
|
|
afe46ab7e5 | ||
|
|
d7e8d22bf6 | ||
|
|
ee4165ea26 | ||
|
|
0a265db50e | ||
|
|
04d4dcaa1c | ||
|
|
6adfc038a2 | ||
|
|
5877235e9a | ||
|
|
b70c4387f7 | ||
|
|
00fb98c0c2 | ||
|
|
249800bc87 | ||
|
|
465bdd743b | ||
|
|
028d1ecd82 | ||
|
|
70439f172d | ||
|
|
dacaa8ebde | ||
|
|
a5309765f1 | ||
|
|
2e86ed199a | ||
|
|
ad14822684 | ||
|
|
4517cdf595 | ||
|
|
dc2293e960 | ||
|
|
1b191d9cf0 | ||
|
|
41b6311d9e | ||
|
|
b39fa10ba9 | ||
|
|
2c62fa3583 | ||
|
|
8dcdae1259 | ||
|
|
be27a6d3a3 | ||
|
|
d8c26c114e | ||
|
|
ef43b04a8b | ||
|
|
960a105cba | ||
|
|
4fcd0eaf2f | ||
|
|
f9026fa0e3 | ||
|
|
cd5a9d1176 | ||
|
|
cfe430676b | ||
|
|
3bccfd8c06 | ||
|
|
fef8a3299e | ||
|
|
63deabe01d | ||
|
|
b021afff7e | ||
|
|
b3d28723d7 | ||
|
|
22c9d238d4 | ||
|
|
eb1a6f4349 | ||
|
|
a41004d294 | ||
|
|
e788bf3d4d | ||
|
|
6e8a0d14b3 | ||
|
|
78465fc93f | ||
|
|
bf8482a6ce | ||
|
|
4659772d40 | ||
|
|
62cade7404 | ||
|
|
fa7a05bdb1 | ||
|
|
936efa985d | ||
|
|
5580bd754c | ||
|
|
50c295ed3e | ||
|
|
0f76999214 | ||
|
|
f7ae2c21a4 | ||
|
|
c55e0cb7e1 | ||
|
|
b8344dbb84 | ||
|
|
fae431c890 | ||
|
|
fdbd989d0e | ||
|
|
649e596479 | ||
|
|
d9d85f5979 | ||
|
|
bcf355acf9 | ||
|
|
89912c67b8 | ||
|
|
05c773b297 | ||
|
|
51d6d78b3d | ||
|
|
dd5dff7922 | ||
|
|
94c102b5e0 | ||
|
|
70026fef74 | ||
|
|
41f81f35e6 | ||
|
|
e7ae321b54 | ||
|
|
5b35df41b1 | ||
|
|
51af09bde8 | ||
|
|
3d17433ba8 | ||
|
|
2e174b2bc0 | ||
|
|
9bff8b47dc | ||
|
|
cceb62cfc4 | ||
|
|
4e111fa299 | ||
|
|
ba7f15b1d7 | ||
|
|
30e9d111ec | ||
|
|
8087bb26c9 | ||
|
|
3ef0065ab2 | ||
|
|
d0fa541d13 | ||
|
|
31dde130b4 | ||
|
|
bced762f77 | ||
|
|
2d8ac74f8d | ||
|
|
0e2f1b9ac1 | ||
|
|
f4733e7209 | ||
|
|
2cfdf36768 | ||
|
|
24961393a5 | ||
|
|
f16273c1ae | ||
|
|
9f20448831 | ||
|
|
343a09a242 | ||
|
|
9355790333 | ||
|
|
d07a55334f | ||
|
|
72197392fa | ||
|
|
c91da69552 | ||
|
|
8e09a1243a | ||
|
|
f6594dee62 | ||
|
|
a3fad60aae | ||
|
|
e548cade90 | ||
|
|
407ab40614 | ||
|
|
90d447734d | ||
|
|
f5a7dc2b94 | ||
|
|
2085b68cec | ||
|
|
c5bf88d858 | ||
|
|
5cf42ee650 | ||
|
|
a5a87f8590 | ||
|
|
8c119b8bc9 | ||
|
|
b1f36bf966 | ||
|
|
100eca7210 | ||
|
|
3a53b86707 | ||
|
|
ed623c2e97 | ||
|
|
956490b9bc | ||
|
|
5790d4de01 | ||
|
|
bea3149ac5 | ||
|
|
8c56da44fd | ||
|
|
26bff21253 | ||
|
|
eedb028232 | ||
|
|
c1a7fc7765 | ||
|
|
4ccd5003ad | ||
|
|
9dde4d0c51 | ||
|
|
23c795f21f | ||
|
|
05fc8ff626 | ||
|
|
380b395c72 | ||
|
|
b01f090453 | ||
|
|
3b7242f3d6 | ||
|
|
f1e9e50617 | ||
|
|
f0048f804a | ||
|
|
857d134919 | ||
|
|
8f47a26a1b | ||
|
|
77b195c203 | ||
|
|
cfeff0c74d | ||
|
|
bd99923f6b | ||
|
|
521c248c90 | ||
|
|
7a4f611e47 | ||
|
|
39cd8d5827 | ||
|
|
7d022a5af1 | ||
|
|
6fa9442963 | ||
|
|
ce4d84d8c1 | ||
|
|
ebd9c03251 | ||
|
|
0356133ab7 | ||
|
|
5755300d3a | ||
|
|
147d6238d5 | ||
|
|
9576141376 | ||
|
|
39f0be296e | ||
|
|
8c5551b00b | ||
|
|
42c26aa645 | ||
|
|
f91dc4df71 | ||
|
|
cf6f8f3488 | ||
|
|
4b059f3145 | ||
|
|
ce3b6c0cc7 | ||
|
|
9d0499159a | ||
|
|
3906bc0318 | ||
|
|
ee9b3d8fe7 | ||
|
|
aac5b25c60 | ||
|
|
5211630542 | ||
|
|
bb2afd5e9d | ||
|
|
88668897f9 | ||
|
|
36daaddfb2 | ||
|
|
b5e2073007 | ||
|
|
1154969af2 | ||
|
|
225d8e85ff | ||
|
|
bf29e87cea | ||
|
|
24c15f6e65 | ||
|
|
d6acb0a202 | ||
|
|
6defbea453 | ||
|
|
e31b69a790 | ||
|
|
9e8470a3cb | ||
|
|
e9cd3d917c | ||
|
|
373cefb01c | ||
|
|
d0039ea23f | ||
|
|
bd25818aa7 | ||
|
|
a73457c5c5 | ||
|
|
c8a4d49577 | ||
|
|
123379b60e | ||
|
|
71d3144691 | ||
|
|
d306a9d96d | ||
|
|
1d514cf5ca | ||
|
|
96adadeae9 | ||
|
|
a1061ff32c | ||
|
|
e9d13b865c | ||
|
|
b655a4274e | ||
|
|
d58a59afab | ||
|
|
d0fabd8b3e | ||
|
|
b50207e5e9 | ||
|
|
97797a9178 | ||
|
|
1e8569b664 | ||
|
|
21cc47eecb | ||
|
|
4c56adafb2 | ||
|
|
8a524a8aa5 | ||
|
|
5493445747 | ||
|
|
0ef26334dc | ||
|
|
8d83e8faa3 | ||
|
|
9b90214d9d | ||
|
|
224f6cee27 | ||
|
|
ff04b2fb75 | ||
|
|
473444ae33 | ||
|
|
168734ad8c | ||
|
|
4e7b2e379a | ||
|
|
ad1d51fd9e | ||
|
|
57c415db22 | ||
|
|
568386a758 | ||
|
|
55f8f4fa1a | ||
|
|
dd0dd6b5c1 | ||
|
|
4c40bea226 | ||
|
|
6b3f5c3690 | ||
|
|
63067823ee | ||
|
|
880f67c3bc | ||
|
|
839aeb6a26 | ||
|
|
b123585756 | ||
|
|
fa4757a4c8 | ||
|
|
28d77aea33 | ||
|
|
0425e1da24 | ||
|
|
692d424a0b | ||
|
|
1c9fd7b126 | ||
|
|
a1752c1642 | ||
|
|
0dbd2d1048 | ||
|
|
79408861a2 | ||
|
|
063f2c3c13 | ||
|
|
68819bbd34 | ||
|
|
3a5c3d5bb4 | ||
|
|
032eb52a88 | ||
|
|
7dc24437cf | ||
|
|
1ccb756931 | ||
|
|
b5268a7b62 | ||
|
|
a0663d6b36 | ||
|
|
26f2c966ff | ||
|
|
4517186862 | ||
|
|
5236afe035 | ||
|
|
fe1707d0c3 | ||
|
|
03854d2589 | ||
|
|
28339e65af | ||
|
|
e11f0cf054 | ||
|
|
c1045cd11e | ||
|
|
aa3373da58 | ||
|
|
a4ad408228 | ||
|
|
0d436637cd | ||
|
|
18daff1044 | ||
|
|
b96d17a746 | ||
|
|
1506d3fd96 | ||
|
|
eec0833707 | ||
|
|
f9883baa87 | ||
|
|
3bebecf91e |
17
.github/workflows/build-image.yaml
vendored
17
.github/workflows/build-image.yaml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
branches: [ master ]
|
||||
release:
|
||||
types: [ created ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -16,14 +17,24 @@ jobs:
|
||||
- name: Build image
|
||||
run: |
|
||||
docker run --privileged --rm -v /dev:/dev -v $(pwd):/builder/repo -e TRAVIS_TAG="${{ github.event.release.tag_name }}" sfalexrog/img-tool:qemu-update
|
||||
- name: Compress image
|
||||
# - name: Compress image
|
||||
# run: |
|
||||
# cd images && sudo chmod -R 777 . && zip -9 $(echo clover_*).zip clover_* && ls -lh . && unzip -l clover_*.zip
|
||||
- name: Compress image using 7-Zip
|
||||
run: |
|
||||
cd images && sudo chmod -R 777 . && zip -9 $(echo clover_*).zip clover_* && ls -l . && unzip -l clover_*.zip
|
||||
cd images && sudo chmod -R 777 . && 7z a -mx=9 $(echo *_*).7z *_* && ls -lh . && 7z l *_*.7z
|
||||
- name: Upload image
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
with:
|
||||
files: images/clover_*.zip
|
||||
files: images/*_*.zip
|
||||
prerelease: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload image to artifacts
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.ref != 'refs/heads/master' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: image
|
||||
path: images/*_*.7z
|
||||
retention-days: 1
|
||||
|
||||
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# melodic:
|
||||
|
||||
1
.github/workflows/docs.yml
vendored
1
.github/workflows/docs.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
1
.github/workflows/editorconfig.yaml
vendored
1
.github/workflows/editorconfig.yaml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
editorconfig:
|
||||
|
||||
@@ -113,7 +113,9 @@
|
||||
"VMware",
|
||||
"DuoCam"
|
||||
],
|
||||
"code_blocks": false
|
||||
"code_blocks": false,
|
||||
"html_elements": false
|
||||
},
|
||||
"MD045": false
|
||||
"MD045": false,
|
||||
"MD051": false
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<depend>sensor_msgs</depend>
|
||||
<depend>rostest</depend>
|
||||
<depend>dynamic_reconfigure</depend>
|
||||
<depend>pluginlib</depend>
|
||||
<depend condition="$ROS_PYTHON_VERSION == 2">python-docopt</depend>
|
||||
<depend condition="$ROS_PYTHON_VERSION == 3">python3-docopt</depend>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Requires=roscore.service
|
||||
[Service]
|
||||
User=pi
|
||||
ExecStart=/bin/bash -c ". /home/pi/catkin_ws/devel/setup.sh; \
|
||||
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clover clover.launch --wait --screen --skip-log-check \
|
||||
ROS_HOSTNAME=`hostname`.local ROS_OS_OVERRIDE=debian:bookworm exec stdbuf -o L roslaunch clover clover.launch --wait --screen --skip-log-check \
|
||||
2> >(tee /tmp/clover.err)"
|
||||
|
||||
ExecStartPre=+rm /var/log/clover.log
|
||||
|
||||
@@ -13,70 +13,38 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m$TEXT\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
# https://www.raspberrypi.com/documentation/computers/configuration.html
|
||||
|
||||
##################################################
|
||||
# Configure hardware interfaces
|
||||
##################################################
|
||||
|
||||
# 1. Enable sshd
|
||||
echo_stamp "#1 Turn on sshd"
|
||||
touch /boot/ssh
|
||||
# /usr/bin/raspi-config nonint do_ssh 0
|
||||
echo "--- Enable sshd"
|
||||
/usr/bin/raspi-config nonint do_ssh 0
|
||||
|
||||
# 2. Enable GPIO
|
||||
echo_stamp "#2 GPIO enabled by default"
|
||||
echo "--- GPIO enabled by default"
|
||||
|
||||
# 3. Enable I2C
|
||||
echo_stamp "#3 Turn on I2C"
|
||||
echo "--- Enable I2C"
|
||||
/usr/bin/raspi-config nonint do_i2c 0
|
||||
|
||||
# 4. Enable SPI
|
||||
echo_stamp "#4 Turn on SPI"
|
||||
echo "--- Enable SPI"
|
||||
/usr/bin/raspi-config nonint do_spi 0
|
||||
|
||||
# 5. Enable raspicam
|
||||
echo_stamp "#5 Turn on raspicam"
|
||||
echo "--- Enable raspicam"
|
||||
/usr/bin/raspi-config nonint do_camera 0
|
||||
|
||||
# 6. Enable hardware UART
|
||||
echo_stamp "#6 Turn on UART"
|
||||
echo "--- Setup UART"
|
||||
# Temporary solution
|
||||
# https://github.com/RPi-Distro/raspi-config/pull/75
|
||||
/usr/bin/raspi-config nonint do_serial 1
|
||||
/usr/bin/raspi-config nonint set_config_var enable_uart 1 /boot/config.txt
|
||||
echo dtoverlay=pi3-disable-bt >> /boot/config.txt
|
||||
/usr/bin/raspi-config nonint do_serial_hw 0
|
||||
/usr/bin/raspi-config nonint do_serial_cons 1
|
||||
|
||||
echo dtoverlay=pi3-disable-bt >> /boot/firmware/config.txt
|
||||
systemctl disable hciuart.service
|
||||
|
||||
# After adding to Raspbian OS
|
||||
# https://github.com/RPi-Distro/raspi-config/commit/d6d9ecc0d9cbe4aaa9744ae733b9cb239e79c116
|
||||
#/usr/bin/raspi-config nonint do_serial 2
|
||||
|
||||
# 7. Enable V4L driver http://robocraft.ru/blog/electronics/3158.html
|
||||
echo "--- Enable v4l2 driver"
|
||||
# http://robocraft.ru/blog/electronics/3158.html
|
||||
#echo "bcm2835-v4l2" >> /etc/modules
|
||||
echo_stamp "#7 Turn on v4l2 driver"
|
||||
if ! grep -q "^bcm2835-v4l2" /etc/modules;
|
||||
then printf "bcm2835-v4l2\n" >> /etc/modules
|
||||
fi
|
||||
|
||||
echo_stamp "#8 End of configure hardware interfaces"
|
||||
|
||||
@@ -13,63 +13,31 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m$TEXT\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
echo "--- Fix home directory permissions"
|
||||
chmod +rx /home/pi
|
||||
|
||||
NEW_SSID='clover-'$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e "s/[^0-9]//g" | cut -c 1-4)
|
||||
echo_stamp "Setting SSID to ${NEW_SSID}"
|
||||
# TODO: Use wpa_cli insted direct file edit
|
||||
# FIXME: We rely on raspberrypi-net-mods to copy our file to /etc/wpa_supplicant.
|
||||
# This is not very reliable, but seems to fix our rfkill problem.
|
||||
cat << EOF >> /boot/wpa_supplicant.conf
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
|
||||
update_config=1
|
||||
country=GB
|
||||
network={
|
||||
ssid="${NEW_SSID}"
|
||||
psk="cloverwifi"
|
||||
mode=2
|
||||
proto=WPA RSN
|
||||
key_mgmt=WPA-PSK
|
||||
pairwise=CCMP
|
||||
group=CCMP
|
||||
auth_alg=OPEN
|
||||
}
|
||||
EOF
|
||||
echo "--- Creating Wi-Fi AP with SSID=${NEW_SSID}"
|
||||
nmcli con add type wifi ifname wlan0 mode ap con-name clover ssid $NEW_SSID autoconnect true \
|
||||
&& nmcli con modify clover 802-11-wireless.band bg \
|
||||
&& nmcli con modify clover ipv4.method shared ipv4.address 192.168.11.1/24 \
|
||||
&& nmcli con modify clover ipv6.method disabled \
|
||||
&& nmcli con modify clover wifi-sec.key-mgmt wpa-psk \
|
||||
&& nmcli con modify clover wifi-sec.psk "cloverwifi" \
|
||||
&& systemctl disable dnsmasq # disable dnsmasq to avoid conflicts with NetworkManager's dnsmasq
|
||||
|
||||
NEW_HOSTNAME=$(echo ${NEW_SSID} | tr '[:upper:]' '[:lower:]')
|
||||
echo_stamp "Setting hostname to $NEW_HOSTNAME"
|
||||
hostnamectl set-hostname $NEW_HOSTNAME
|
||||
sed -i 's/127\.0\.1\.1.*/127.0.1.1\t'${NEW_HOSTNAME}' '${NEW_HOSTNAME}'.local/g' /etc/hosts
|
||||
echo "--- Setting hostname to $NEW_HOSTNAME"
|
||||
hostnamectl set-hostname $NEW_HOSTNAME \
|
||||
&& sed -i 's/127\.0\.1\.1.*/127.0.1.1\t'${NEW_HOSTNAME}' '${NEW_HOSTNAME}'.local/g' /etc/hosts
|
||||
# .local (mdns) hostname added to make it accesable when wlan and ethernet interfaces are down
|
||||
|
||||
echo_stamp "Enable ROS services"
|
||||
echo "--- Enable ROS services"
|
||||
systemctl enable roscore
|
||||
systemctl enable clover
|
||||
|
||||
echo_stamp "Harware setup"
|
||||
echo "--- Harware setup"
|
||||
/root/hardware_setup.sh
|
||||
|
||||
echo_stamp "Remove init scripts"
|
||||
echo "--- Remove init scripts"
|
||||
rm /root/init_rpi.sh /root/hardware_setup.sh
|
||||
|
||||
echo_stamp "End of initialization of the image"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
122
builder/image-build-ros.sh
Executable file
122
builder/image-build-ros.sh
Executable file
@@ -0,0 +1,122 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
#
|
||||
# Script for building ROS packages from scratch
|
||||
#
|
||||
# Copyright (C) 2022 Copter Express Technologies
|
||||
#
|
||||
# Author: Oleg Kalachev <okalachev@gmail.com>
|
||||
#
|
||||
# Distributed under MIT License (available at https://opensource.org/licenses/MIT).
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
# http://wiki.ros.org/Installation/Source
|
||||
|
||||
export ROS_DISTRO=noetic
|
||||
. /etc/os-release # set $VERSION_CODENAME to Debian release code name
|
||||
export ROS_OS_OVERRIDE=debian:$VERSION_CODENAME
|
||||
export ROS_PYTHON_VERSION=3
|
||||
export CLOVER_DEPS="tf tf2 tf2_ros tf2_geometry_msgs geometry_msgs sensor_msgs visualization_msgs libgeographiclib-dev mavros mavros_extras cv_camera cv_bridge rosbridge_server web_video_server tf2_web_republisher libxml2 libxslt python3-lxml dynamic_reconfigure image_transport image_proc image_geometry python-pymavlink ros_pytest"
|
||||
export CLOVER_DEPS="$CLOVER_DEPS rostest python3-docopt image_publisher"
|
||||
|
||||
echo "=== Building ROS from scratch"
|
||||
|
||||
#echo "--- Adding sources"
|
||||
# echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list
|
||||
# curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
|
||||
|
||||
#cp /etc/apt/trusted.gpg /etc/apt/trusted.gpg.d # https://askubuntu.com/a/1408456
|
||||
apt-get update
|
||||
apt-get install -y python3-distutils build-essential cmake git python3-pip python3-rosinstall-generator python3-vcstools python3-empy libpoco-dev
|
||||
|
||||
# install vcstool using pip
|
||||
# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && python3 get-pip.py && rm get-pip.py
|
||||
pip3 install -U --break-system-packages vcstool rosdep rosinstall-generator catkin-pkg future
|
||||
|
||||
# sudo rosdep init
|
||||
# rm /etc/ros/rosdep/sources.list.d/20-default.list
|
||||
rosdep init
|
||||
rosdep update --os=debian:bullseye
|
||||
|
||||
# rm /etc/ros/rosdep/sources.list.d/20-default.list && rosdep init
|
||||
# rosdep --os=debian:$VERSION_CODENAME update
|
||||
|
||||
echo "--- Create Catkin workspace to build ROS package"
|
||||
mkdir ~/ros_catkin_ws
|
||||
cd ~/ros_catkin_ws
|
||||
|
||||
echo "--- Download ROS sources"
|
||||
rosinstall_generator ros_base $CLOVER_DEPS --rosdistro $ROS_DISTRO --deps --tar > noetic.rosinstall
|
||||
mkdir ./src
|
||||
vcs import --input noetic.rosinstall ./src
|
||||
|
||||
# https://answers.ros.org/question/343367/catkin-package-dependencies-issue-when-installing-ros-melodic-on-raspberry-pi-4/
|
||||
#sudo apt remove python-rospkg
|
||||
#sudo apt remove python-catkin-pkg
|
||||
##sudo apt --fix-broken install
|
||||
#sudo apt-get autoremove
|
||||
|
||||
#echo "--- Install catkin_pkg"
|
||||
#cd
|
||||
#git clone https://github.com/ros-infrastructure/catkin_pkg.git
|
||||
#cd catkin_pkg
|
||||
#python3 setup.py install
|
||||
#cd ~/ros_catkin_ws
|
||||
|
||||
echo "--- Resolve dependencies"
|
||||
rosdep install --from-paths ./src --ignore-packages-from-source --rosdistro $ROS_DISTRO -y --os=debian:bullseye --skip-keys="python3-catkin-pkg-modules libboost-thread python3-rosdep-modules" || true
|
||||
|
||||
echo "--- Install missing dependencies"
|
||||
apt-get install -y liborocos-kdl1.5 geographiclib-tools libgeographiclib-dev
|
||||
|
||||
echo "-- Install geographiclib datasets"
|
||||
wget https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh
|
||||
chmod +x install_geographiclib_datasets.sh
|
||||
./install_geographiclib_datasets.sh
|
||||
|
||||
echo "--- Apply patches"
|
||||
wget https://github.com/ros/rosconsole/pull/58.patch
|
||||
patch -p1 -d src/rosconsole < 58.patch
|
||||
|
||||
wget https://github.com/ros/ros_comm/pull/2353.patch
|
||||
patch -p2 -d src/ros_comm < 2353.patch
|
||||
|
||||
wget https://github.com/AJahueyM/web_video_server/commit/5b722eb0822bcc3fe45fefe7b393b87bfe004417.patch
|
||||
patch -p1 -d src/web_video_server < 5b722eb0822bcc3fe45fefe7b393b87bfe004417.patch
|
||||
|
||||
echo "--- Build ROS"
|
||||
# https://github.com/ros/catkin/issues/863#issuecomment-290392074
|
||||
./src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release
|
||||
# -DSETUPTOOLS_DEB_LAYOUT=OFF \
|
||||
# --install-space=/opt/ros/$ROS_DISTRO
|
||||
|
||||
# source ~/ros_catkin_ws/install_isolated/setup.bash
|
||||
#source /opt/ros/$ROS_DISTRO/setup.bash
|
||||
#
|
||||
#echo "--- List built ROS packages"
|
||||
#set +x
|
||||
#rospack list-names | while read line; do echo $line `rosversion $line`; done
|
||||
#set -x
|
||||
#
|
||||
#echo "--- Build Debian packages"
|
||||
#apt-get install -y python3-bloom debhelper dpkg-dev libtinyxml-dev
|
||||
#
|
||||
## add rosdep file to help bloom-generate resolve missing bookworm dependencies
|
||||
#echo "yaml file:///etc/ros/rosdep/noetic-rosdep-clover.yaml" >> /etc/ros/rosdep/sources.list.d/20-default.list
|
||||
#rosdep update
|
||||
#
|
||||
#pip3 install setuptools==45.2.0 # https://github.com/ros/catkin/issues/863#issuecomment-1000446018
|
||||
#
|
||||
#for file in `find . -name "package.xml" -not -path "*/debian/*"`; do
|
||||
# cd $(dirname ${file})
|
||||
# rm -rf debian
|
||||
# bloom-generate rosdebian --os-name debian --os-version $VERSION_CODENAME --ros-distro $ROS_DISTRO --debug
|
||||
# debian/rules binary # fakeroot is not needed as we are root
|
||||
# cd -
|
||||
#done
|
||||
|
||||
ls
|
||||
@@ -13,42 +13,22 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
# https://www.raspberrypi.org/software/operating-systems/#raspberry-pi-os-32-bit
|
||||
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip"
|
||||
SOURCE_IMAGE="https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-03-15/2024-03-15-raspios-bookworm-armhf-lite.img.xz"
|
||||
|
||||
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
|
||||
export LANG=${LANG:='C.UTF-8'}
|
||||
export LC_ALL=${LC_ALL:='C.UTF-8'}
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m$TEXT\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
BUILDER_DIR="/builder"
|
||||
REPO_DIR="${BUILDER_DIR}/repo"
|
||||
SCRIPTS_DIR="${REPO_DIR}/builder"
|
||||
IMAGES_DIR="${REPO_DIR}/images"
|
||||
|
||||
[[ ! -d ${SCRIPTS_DIR} ]] && (echo_stamp "Directory ${SCRIPTS_DIR} doesn't exist" "ERROR"; exit 1)
|
||||
[[ ! -d ${IMAGES_DIR} ]] && mkdir ${IMAGES_DIR} && echo_stamp "Directory ${IMAGES_DIR} was created successful" "SUCCESS"
|
||||
[[ ! -d ${SCRIPTS_DIR} ]] && (echo "Error: directory ${SCRIPTS_DIR} doesn't exist"; exit 1)
|
||||
[[ ! -d ${IMAGES_DIR} ]] && mkdir ${IMAGES_DIR} && echo "Directory ${IMAGES_DIR} was created successful"
|
||||
|
||||
if [[ -z ${TRAVIS_TAG} ]]; then IMAGE_VERSION="$(cd ${REPO_DIR}; git log --format=%h -1)"; else IMAGE_VERSION="${TRAVIS_TAG}"; fi
|
||||
# IMAGE_VERSION="${TRAVIS_TAG:=$(cd ${REPO_DIR}; git log --format=%h -1)}"
|
||||
@@ -64,15 +44,17 @@ get_image() {
|
||||
local RPI_IMAGE_NAME=$(echo ${RPI_ZIP_NAME} | sed 's/zip/img/')
|
||||
|
||||
if [ ! -e "${BUILD_DIR}/${RPI_ZIP_NAME}" ]; then
|
||||
echo_stamp "Downloading original Linux distribution"
|
||||
echo "--- Downloading original Linux distribution"
|
||||
wget --progress=dot:giga -O ${BUILD_DIR}/${RPI_ZIP_NAME} $2
|
||||
echo_stamp "Downloading complete" "SUCCESS" \
|
||||
else echo_stamp "Linux distribution already donwloaded"; fi
|
||||
echo "--- Downloading complete" "SUCCESS"
|
||||
else
|
||||
echo "Linux distribution already downloaded"
|
||||
fi
|
||||
|
||||
echo_stamp "Unzipping Linux distribution image" \
|
||||
&& unzip -p ${BUILD_DIR}/${RPI_ZIP_NAME} ${RPI_IMAGE_NAME} > $1 \
|
||||
&& echo_stamp "Unzipping complete" "SUCCESS" \
|
||||
|| (echo_stamp "Unzipping was failed!" "ERROR"; exit 1)
|
||||
echo "--- Unzipping Linux distribution image"
|
||||
apt-get update --allow-releaseinfo-change
|
||||
apt-get install -y xz-utils
|
||||
unxz --stdout ${BUILD_DIR}/${RPI_ZIP_NAME} > $1
|
||||
}
|
||||
|
||||
get_image ${IMAGE_PATH} ${SOURCE_IMAGE}
|
||||
@@ -120,6 +102,7 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/launch.
|
||||
# ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/kinetic-ros-clover.rosinstall' '/home/pi/ros_catkin_ws/'
|
||||
# Add rename script
|
||||
${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-build-ros.sh'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-validate.sh'
|
||||
|
||||
${BUILDER_DIR}/image-resize.sh ${IMAGE_PATH}
|
||||
|
||||
@@ -12,50 +12,33 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
echo "--- Move /etc/ld.so.preload out of the way"
|
||||
mv /etc/ld.so.preload /etc/ld.so.preload.disabled-for-build
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m$TEXT\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
echo_stamp "Write Clover information"
|
||||
echo "--- Create pi user"
|
||||
echo 'pi:$6$c70VpvPsVNCG0YR5$l5vWWLsLko9Kj65gcQ8qvMkuOoRkEagI90qi3F/Y7rm8eNYZHW8CY6BOIKwMH7a3YYzZYL90zf304cAHLFaZE0' > /boot/userconf.txt
|
||||
|
||||
echo "--- Write Clover information"
|
||||
# Clover image version
|
||||
echo "$1" >> /etc/clover_version
|
||||
# Origin image file name
|
||||
echo "${2%.*}" >> /etc/clover_origin
|
||||
|
||||
echo_stamp "Write magic script to /etc/rc.local"
|
||||
echo "--- Write magic script to /etc/rc.local"
|
||||
MAGIC_SCRIPT="sudo /root/init_rpi.sh; sudo sed -i '/sudo \\\/root\\\/init_rpi.sh/d' /etc/rc.local && sudo reboot"
|
||||
sed -i "19a${MAGIC_SCRIPT}" /etc/rc.local
|
||||
# TODO: remake to oneshot systemd service
|
||||
|
||||
# It needs for autosizer.sh & maybe that is correct
|
||||
echo_stamp "Change boot partition"
|
||||
echo "--- Change boot partition"
|
||||
sed -i 's/root=[^ ]*/root=\/dev\/mmcblk0p2/' /boot/cmdline.txt
|
||||
sed -i 's/.* \/boot vfat defaults 0 2$/\/dev\/mmcblk0p1 \/boot vfat defaults 0 2/' /etc/fstab
|
||||
sed -i 's/.* \/boot\/firmware vfat defaults 0 2$/\/dev\/mmcblk0p1 \/boot\/firmware vfat defaults 0 2/' /etc/fstab
|
||||
sed -i 's/.* \/ ext4 defaults,noatime 0 1$/\/dev\/mmcblk0p2 \/ ext4 defaults,noatime 0 1/' /etc/fstab
|
||||
cat /boot/cmdline.txt
|
||||
cat /etc/fstab
|
||||
|
||||
echo_stamp "Set max space for syslogs"
|
||||
echo "--- Set max space for syslogs"
|
||||
# https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl
|
||||
sed -i 's/#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf
|
||||
|
||||
echo_stamp "Move /etc/ld.so.preload out of the way"
|
||||
mv /etc/ld.so.preload /etc/ld.so.preload.disabled-for-build
|
||||
|
||||
echo_stamp "End of init image"
|
||||
|
||||
@@ -12,43 +12,20 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m$TEXT\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
echo_stamp "#1 Write STATIC to /etc/dhcpcd.conf"
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
echo "--- Write static to /etc/dhcpcd.conf"
|
||||
cat << EOF >> /etc/dhcpcd.conf
|
||||
interface wlan0
|
||||
static ip_address=192.168.11.1/24
|
||||
EOF
|
||||
|
||||
echo_stamp "#2 Set wpa_supplicant country"
|
||||
|
||||
echo "--- Set wpa_supplicant country"
|
||||
cat << EOF >> /etc/wpa_supplicant/wpa_supplicant.conf
|
||||
country=GB
|
||||
EOF
|
||||
|
||||
echo_stamp "#3 Write dhcp-config to /etc/dnsmasq.conf"
|
||||
|
||||
echo "--- Write dhcp-config to /etc/dnsmasq.conf"
|
||||
cat << EOF >> /etc/dnsmasq.conf
|
||||
interface=wlan0
|
||||
address=/clover/coex/192.168.11.1
|
||||
@@ -59,5 +36,3 @@ bogus-priv
|
||||
domain-needed
|
||||
quiet-dhcp6
|
||||
EOF
|
||||
|
||||
echo_stamp "#4 End of network installation"
|
||||
|
||||
@@ -15,34 +15,10 @@
|
||||
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
REPO=$1
|
||||
REF=$2
|
||||
INSTALL_ROS_PACK_SOURCES=$3
|
||||
DISCOVER_ROS_PACK=$4
|
||||
NUMBER_THREADS=$5
|
||||
|
||||
# Current ROS distribution
|
||||
ROS_DISTRO=noetic
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m$TEXT\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
. /etc/os-release # set $VERSION_CODENAME to Debian release code name
|
||||
export ROS_OS_OVERRIDE=debian:$VERSION_CODENAME
|
||||
|
||||
# https://gist.github.com/letmaik/caa0f6cc4375cbfcc1ff26bd4530c2a3
|
||||
# https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/templates/header.sh
|
||||
@@ -52,7 +28,7 @@ my_travis_retry() {
|
||||
local max_count=5
|
||||
while [ $count -le $max_count ]; do
|
||||
[ $result -ne 0 ] && {
|
||||
echo -e "\nThe command \"$@\" failed. Retrying, $count of $max_count.\n" >&2
|
||||
echo -e "\nThe command \"$*\" failed. Retrying, $count of $max_count.\n" >&2
|
||||
}
|
||||
# ! { } ignores set -e, see https://stackoverflow.com/a/4073372
|
||||
! { "$@"; result=$?; }
|
||||
@@ -62,65 +38,66 @@ my_travis_retry() {
|
||||
done
|
||||
|
||||
[ $count -gt $max_count ] && {
|
||||
echo -e "\nThe command \"$@\" failed $max_count times.\n" >&2
|
||||
echo -e "\nThe command \"$*\" failed $max_count times.\n" >&2
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
echo "--- Install rosdep"
|
||||
my_travis_retry pip3 install -U rosdep
|
||||
|
||||
# TODO: 'kinetic-rosdep-clover.yaml' should add only if we use our repo?
|
||||
echo_stamp "Init rosdep"
|
||||
echo "--- Init rosdep"
|
||||
my_travis_retry rosdep init
|
||||
# FIXME: Re-add this after missing packages are built
|
||||
echo "yaml file:///etc/ros/rosdep/${ROS_DISTRO}-rosdep-clover.yaml" >> /etc/ros/rosdep/sources.list.d/20-default.list
|
||||
|
||||
echo "--- Update rosdep"
|
||||
echo "yaml file:///etc/ros/rosdep/${ROS_DISTRO}-rosdep-clover.yaml" >> /etc/ros/rosdep/sources.list.d/10-clover.list
|
||||
my_travis_retry rosdep update
|
||||
|
||||
echo_stamp "Populate rosdep for ROS user"
|
||||
my_travis_retry sudo -u pi rosdep update
|
||||
echo "--- Populate rosdep for ROS user"
|
||||
my_travis_retry sudo -u pi ROS_OS_OVERRIDE=debian:$VERSION_CODENAME rosdep update
|
||||
|
||||
export ROS_IP='127.0.0.1' # needed for running tests
|
||||
|
||||
# echo_stamp "Reconfiguring Clover repository for simplier unshallowing"
|
||||
# echo "Reconfiguring Clover repository for simplier unshallowing"
|
||||
cd /home/pi/catkin_ws/src/clover
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
|
||||
# This is sort of a hack to force "custom" packages to be installed - the ones built by COEX, linked against OpenCV 4.2
|
||||
# I **wish** OpenCV would not be such a mess, but, well, here we are.
|
||||
echo_stamp "Installing OpenCV 4.2-compatible ROS packages"
|
||||
apt install -y --no-install-recommends \
|
||||
ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \
|
||||
ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \
|
||||
ros-${ROS_DISTRO}-cv-camera=0.5.1-0buster \
|
||||
ros-${ROS_DISTRO}-image-publisher=1.15.3-0buster \
|
||||
ros-${ROS_DISTRO}-web-video-server=0.2.1-0buster
|
||||
apt-mark hold \
|
||||
ros-${ROS_DISTRO}-compressed-image-transport \
|
||||
ros-${ROS_DISTRO}-cv-bridge \
|
||||
ros-${ROS_DISTRO}-cv-camera \
|
||||
ros-${ROS_DISTRO}-image-publisher \
|
||||
ros-${ROS_DISTRO}-web-video-server
|
||||
# echo "--- Installing OpenCV 4.2-compatible ROS packages"
|
||||
# apt install -y --no-install-recommends \
|
||||
# ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \
|
||||
# ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \
|
||||
# ros-${ROS_DISTRO}-cv-camera=0.5.1-0buster \
|
||||
# ros-${ROS_DISTRO}-image-publisher=1.15.3-0buster \
|
||||
# ros-${ROS_DISTRO}-web-video-server=0.2.1-0buster
|
||||
# apt-mark hold \
|
||||
# ros-${ROS_DISTRO}-compressed-image-transport \
|
||||
# ros-${ROS_DISTRO}-cv-bridge \
|
||||
# ros-${ROS_DISTRO}-cv-camera \
|
||||
# ros-${ROS_DISTRO}-image-publisher \
|
||||
# ros-${ROS_DISTRO}-web-video-server
|
||||
|
||||
echo_stamp "Installing libboost-dev" # https://travis-ci.org/github/CopterExpress/clover/jobs/766318908#L6536
|
||||
my_travis_retry apt-get install -y --no-install-recommends libboost-dev libboost-all-dev
|
||||
#echo "--- Installing libboost-dev" # https://travis-ci.org/github/CopterExpress/clover/jobs/766318908#L6536
|
||||
#my_travis_retry apt-get install -y --no-install-recommends libboost-dev libboost-all-dev
|
||||
|
||||
echo_stamp "Build and install Clover"
|
||||
echo "--- Build and install Clover"
|
||||
cd /home/pi/catkin_ws
|
||||
# Don't try to install gazebo_ros
|
||||
my_travis_retry rosdep install -y --from-paths src --ignore-src --rosdistro ${ROS_DISTRO} --os=debian:buster \
|
||||
--skip-keys=gazebo_ros --skip-keys=gazebo_plugins
|
||||
my_travis_retry rosdep install -y --from-paths src --ignore-src --rosdistro ${ROS_DISTRO} --os=debian:$VERSION_CODENAME \
|
||||
--skip-keys="gazebo_ros gazebo_plugins"
|
||||
my_travis_retry pip3 install wheel
|
||||
my_travis_retry pip3 install -r /home/pi/catkin_ws/src/clover/clover/requirements.txt
|
||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||
# Don't build simulation plugins for actual drone
|
||||
catkin_make -j2 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
source devel/setup.bash
|
||||
|
||||
echo_stamp "Install clever package (for backwards compatibility)"
|
||||
echo "--- Install clever package (for backwards compatibility)"
|
||||
cd /home/pi/catkin_ws/src/clover/builder/assets/clever
|
||||
./setup.py install
|
||||
rm -rf build # remove build artifacts
|
||||
|
||||
echo_stamp "Build Clover documentation"
|
||||
echo "--- Build Clover documentation"
|
||||
cd /home/pi/catkin_ws/src/clover
|
||||
builder/assets/install_gitbook.sh
|
||||
gitbook install
|
||||
@@ -128,66 +105,69 @@ gitbook build
|
||||
# replace assets copy to assets symlink to save space
|
||||
rm -rf _book/assets && ln -s ../docs/assets _book/assets
|
||||
touch node_modules/CATKIN_IGNORE docs/CATKIN_IGNORE _book/CATKIN_IGNORE clover/www/CATKIN_IGNORE apps/CATKIN_IGNORE # ignore documentation files by catkin
|
||||
npm cache clean --force
|
||||
|
||||
echo_stamp "Installing additional ROS packages"
|
||||
echo "--- Installing additional ROS packages"
|
||||
my_travis_retry apt-get install -y --no-install-recommends \
|
||||
ros-${ROS_DISTRO}-dynamic-reconfigure \
|
||||
ros-${ROS_DISTRO}-rosbridge-suite \
|
||||
ros-${ROS_DISTRO}-rosserial \
|
||||
ros-${ROS_DISTRO}-usb-cam \
|
||||
ros-${ROS_DISTRO}-vl53l1x \
|
||||
ros-${ROS_DISTRO}-ws281x \
|
||||
ros-${ROS_DISTRO}-libcamera-ros \
|
||||
ros-${ROS_DISTRO}-rosshow \
|
||||
ros-${ROS_DISTRO}-cmake-modules \
|
||||
ros-${ROS_DISTRO}-image-view \
|
||||
ros-${ROS_DISTRO}-image-geometry \
|
||||
ros-${ROS_DISTRO}-nodelet-topic-tools \
|
||||
ros-${ROS_DISTRO}-stereo-msgs
|
||||
ros-${ROS_DISTRO}-stereo-msgs \
|
||||
ros-${ROS_DISTRO}-vision-msgs
|
||||
|
||||
# TODO move GeographicLib datasets to Mavros debian package
|
||||
echo_stamp "Install GeographicLib datasets (needed for mavros)" \
|
||||
echo "--- Install GeographicLib datasets (needed for mavros)" \
|
||||
&& wget -qO- https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh | bash
|
||||
|
||||
echo_stamp "Running tests"
|
||||
echo "--- Running tests"
|
||||
export ROS_IP='127.0.0.1' # needed for running tests
|
||||
cd /home/pi/catkin_ws
|
||||
# FIXME: Investigate failing tests
|
||||
catkin_make run_tests #&& catkin_test_results
|
||||
|
||||
echo_stamp "Change permissions for catkin_ws"
|
||||
echo "--- Change permissions for catkin_ws"
|
||||
chown -Rf pi:pi /home/pi/catkin_ws
|
||||
|
||||
echo_stamp "Update www"
|
||||
echo "--- Update www"
|
||||
sudo -u pi sh -c ". devel/setup.sh && rosrun clover www"
|
||||
|
||||
echo_stamp "Make \$HOME/examples symlink"
|
||||
echo "--- Make \$HOME/examples symlink"
|
||||
ln -s "$(catkin_find clover examples --first-only)" /home/pi
|
||||
chown -Rf pi:pi /home/pi/examples
|
||||
|
||||
echo_stamp "Make systemd services symlinks"
|
||||
echo "--- Make systemd services symlinks"
|
||||
ln -s /home/pi/catkin_ws/src/clover/builder/assets/clover.service /lib/systemd/system/
|
||||
ln -s /home/pi/catkin_ws/src/clover/builder/assets/roscore.service /lib/systemd/system/
|
||||
# validate
|
||||
[ -f /lib/systemd/system/clover.service ]
|
||||
[ -f /lib/systemd/system/roscore.service ]
|
||||
|
||||
echo_stamp "Make udev rules symlink"
|
||||
echo "--- Make udev rules symlink"
|
||||
ln -s "$(catkin_find clover udev --first-only)"/* /lib/udev/rules.d/
|
||||
|
||||
echo_stamp "Setup ROS environment"
|
||||
echo "--- Setup ROS environment"
|
||||
cat << EOF >> /home/pi/.bashrc
|
||||
LANG='C.UTF-8'
|
||||
LC_ALL='C.UTF-8'
|
||||
export ROS_HOSTNAME=\`hostname\`.local
|
||||
export ROS_OS_OVERRIDE=debian:bookworm
|
||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||
source /home/pi/catkin_ws/devel/setup.bash
|
||||
EOF
|
||||
|
||||
#echo_stamp "Removing local apt mirror"
|
||||
# Restore original sources.list
|
||||
#mv /var/sources.list.bak /etc/apt/sources.list
|
||||
# Clean apt cache
|
||||
apt-get clean -qq > /dev/null
|
||||
# Remove local mirror repository key
|
||||
#apt-key del COEX-MIRROR
|
||||
echo "--- Cleanup apt"
|
||||
apt-get autoremove --purge -y
|
||||
apt-get clean
|
||||
|
||||
echo_stamp "END of ROS INSTALLATION"
|
||||
echo "--- Cleanup pip"
|
||||
pip3 cache purge
|
||||
|
||||
echo "--- Cleanup /tmp"
|
||||
rm -rf /tmp/*
|
||||
|
||||
@@ -12,27 +12,9 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
echo_stamp() {
|
||||
# TEMPLATE: echo_stamp <TEXT> <TYPE>
|
||||
# TYPE: SUCCESS, ERROR, INFO
|
||||
|
||||
# More info there https://www.shellhacks.com/ru/bash-colors/
|
||||
|
||||
TEXT="$(date '+[%Y-%m-%d %H:%M:%S]') $1"
|
||||
TEXT="\e[1m${TEXT}\e[0m" # BOLD
|
||||
|
||||
case "$2" in
|
||||
SUCCESS)
|
||||
TEXT="\e[32m${TEXT}\e[0m";; # GREEN
|
||||
ERROR)
|
||||
TEXT="\e[31m${TEXT}\e[0m";; # RED
|
||||
*)
|
||||
TEXT="\e[34m${TEXT}\e[0m";; # BLUE
|
||||
esac
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
. /etc/os-release # set $VERSION_CODENAME to Debian release code name
|
||||
|
||||
# https://gist.github.com/letmaik/caa0f6cc4375cbfcc1ff26bd4530c2a3
|
||||
# https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/templates/header.sh
|
||||
@@ -41,7 +23,7 @@ my_travis_retry() {
|
||||
local count=1
|
||||
while [ $count -le 3 ]; do
|
||||
[ $result -ne 0 ] && {
|
||||
echo -e "\n${ANSI_RED}The command \"$@\" failed. Retrying, $count of 3.${ANSI_RESET}\n" >&2
|
||||
echo -e "\n${ANSI_RED}The command \"$*\" failed. Retrying, $count of 3.${ANSI_RESET}\n" >&2
|
||||
}
|
||||
# ! { } ignores set -e, see https://stackoverflow.com/a/4073372
|
||||
! { "$@"; result=$?; }
|
||||
@@ -51,41 +33,39 @@ my_travis_retry() {
|
||||
done
|
||||
|
||||
[ $count -gt 3 ] && {
|
||||
echo -e "\n${ANSI_RED}The command \"$@\" failed 3 times.${ANSI_RESET}\n" >&2
|
||||
echo -e "\n${ANSI_RED}The command \"$*\" failed 3 times.${ANSI_RESET}\n" >&2
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
echo_stamp "Increase apt retries"
|
||||
|
||||
echo "--- Increase apt retries"
|
||||
echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
|
||||
|
||||
echo_stamp "Install apt keys & repos"
|
||||
echo "--- Install apt keys & repos"
|
||||
|
||||
# TODO: This STDOUT consist 'OK'
|
||||
apt-get update \
|
||||
&& apt-get install --no-install-recommends -y dirmngr > /dev/null \
|
||||
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
|
||||
|
||||
echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
|
||||
# echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
|
||||
|
||||
wget -O - 'http://packages.coex.tech/key.asc' | apt-key add -
|
||||
echo 'deb http://packages.coex.tech buster main' >> /etc/apt/sources.list
|
||||
wget -O - 'http://packages.coex.tech/key.asc' | apt-key add -
|
||||
echo "deb http://packages.coex.tech $VERSION_CODENAME main" >> /etc/apt/sources.list
|
||||
|
||||
echo_stamp "Update apt cache"
|
||||
echo "--- Update apt cache"
|
||||
|
||||
# TODO: FIX ERROR: /usr/bin/apt-key: 596: /usr/bin/apt-key: cannot create /dev/null: Permission denied
|
||||
apt-get update
|
||||
# && apt upgrade -y
|
||||
|
||||
# Let's retry fetching those packages several times, just in case
|
||||
echo_stamp "Software installing"
|
||||
my_travis_retry apt-get install --no-install-recommends -y cmake-data=3.13.4-1 cmake=3.13.4-1 # FIXME: using older CMake due to https://travis-ci.org/github/CopterExpress/clover/jobs/764367665#L6984
|
||||
echo "--- Install software"
|
||||
my_travis_retry apt-get install --no-install-recommends -y cmake-data cmake
|
||||
my_travis_retry apt-get install --no-install-recommends -y \
|
||||
unzip \
|
||||
zip \
|
||||
ipython \
|
||||
ipython3 \
|
||||
screen \
|
||||
byobu \
|
||||
@@ -96,64 +76,57 @@ dnsmasq \
|
||||
tmux \
|
||||
tree \
|
||||
vim \
|
||||
libjpeg8 \
|
||||
tcpdump \
|
||||
libpoco-dev \
|
||||
libzbar0 \
|
||||
python3-rosdep \
|
||||
python3-rosinstall-generator \
|
||||
python3-wstool \
|
||||
python3-rosinstall \
|
||||
build-essential \
|
||||
libffi-dev \
|
||||
monkey \
|
||||
pigpio python-pigpio python3-pigpio \
|
||||
pigpio python3-pigpio \
|
||||
i2c-tools \
|
||||
espeak espeak-data python-espeak python3-espeak \
|
||||
espeak espeak-data python3-espeak \
|
||||
ntpdate \
|
||||
python-dev \
|
||||
python3-dev \
|
||||
python-systemd \
|
||||
mjpg-streamer \
|
||||
python3-opencv
|
||||
xxd \
|
||||
python3-dev \
|
||||
python3-systemd \
|
||||
python3-opencv \
|
||||
python3-pip
|
||||
#libjpeg8 \
|
||||
|
||||
# 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
|
||||
|
||||
echo_stamp "Installing pip"
|
||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip2.py
|
||||
python3 get-pip.py
|
||||
python get-pip2.py
|
||||
rm get-pip.py get-pip2.py
|
||||
#my_travis_retry pip install --upgrade pip
|
||||
#my_travis_retry pip3 install --upgrade pip
|
||||
|
||||
echo_stamp "Make sure both pip and pip3 are installed"
|
||||
echo "--- Make sure pip is installed"
|
||||
pip --version
|
||||
pip3 --version
|
||||
|
||||
echo_stamp "Install and enable Butterfly (web terminal)"
|
||||
echo_stamp "Workaround for tornado >= 6.0 breaking butterfly"
|
||||
echo "--- Enable installing packages with pip"
|
||||
mv /usr/lib/python3.11/EXTERNALLY-MANAGED /usr/lib/python3.11/EXTERNALLY-MANAGED.old
|
||||
|
||||
echo "--- Install and enable Butterfly (web terminal)"
|
||||
export CRYPTOGRAPHY_DONT_BUILD_RUST=1
|
||||
my_travis_retry pip3 install cryptography==3.4.6 # https://stackoverflow.com/a/68472128/6850197
|
||||
my_travis_retry pip3 install pyOpenSSL==20.0.1
|
||||
my_travis_retry pip3 install tornado==5.1.1
|
||||
#my_travis_retry pip3 install pyOpenSSL==20.0.1
|
||||
#my_travis_retry pip3 install tornado==5.1.1
|
||||
my_travis_retry pip3 install butterfly
|
||||
my_travis_retry pip3 install butterfly[systemd]
|
||||
systemctl enable butterfly.socket
|
||||
|
||||
echo_stamp "Install ws281x library"
|
||||
echo "--- Install ws281x library"
|
||||
my_travis_retry pip3 install --prefer-binary rpi_ws281x
|
||||
|
||||
echo_stamp "Setup Monkey"
|
||||
echo "--- Setup Monkey"
|
||||
mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
|
||||
mv /root/monkey /etc/monkey/sites/default
|
||||
sed -i 's/SymLink Off/SymLink On/' /etc/monkey/monkey.conf
|
||||
systemctl enable monkey.service
|
||||
|
||||
echo_stamp "Install Node.js"
|
||||
echo "--- Install Node.js"
|
||||
cd /home/pi
|
||||
wget --no-verbose https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-armv6l.tar.gz
|
||||
tar -xzf node-v10.15.0-linux-armv6l.tar.gz
|
||||
@@ -161,28 +134,24 @@ cp -R node-v10.15.0-linux-armv6l/* /usr/local/
|
||||
rm -rf node-v10.15.0-linux-armv6l/
|
||||
rm node-v10.15.0-linux-armv6l.tar.gz
|
||||
|
||||
echo_stamp "Installing ptvsd"
|
||||
my_travis_retry pip install ptvsd
|
||||
my_travis_retry pip3 install ptvsd
|
||||
echo "--- Installing debugpy"
|
||||
my_travis_retry pip3 install debugpy
|
||||
|
||||
echo_stamp "Installing pyzbar"
|
||||
my_travis_retry pip install pyzbar
|
||||
echo "--- Installing pyzbar"
|
||||
my_travis_retry pip3 install pyzbar
|
||||
|
||||
echo_stamp "Add .vimrc"
|
||||
echo "--- Add .vimrc"
|
||||
cat << EOF > /home/pi/.vimrc
|
||||
set mouse-=a
|
||||
syntax on
|
||||
autocmd BufNewFile,BufRead *.launch set syntax=xml
|
||||
EOF
|
||||
|
||||
echo_stamp "Change default keyboard layout to US"
|
||||
echo "--- Change default keyboard layout to US"
|
||||
sed -i 's/XKBLAYOUT="gb"/XKBLAYOUT="us"/g' /etc/default/keyboard
|
||||
|
||||
echo_stamp "Attempting to kill dirmngr"
|
||||
echo "--- Attempting to kill dirmngr"
|
||||
gpgconf --kill dirmngr
|
||||
# dirmngr is only used by apt-key, so we can safely kill it.
|
||||
# We ignore pkill's exit value as well.
|
||||
pkill -9 -f dirmngr || true
|
||||
|
||||
echo_stamp "End of software installation"
|
||||
|
||||
@@ -12,32 +12,33 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -ex
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
echo "Run image tests"
|
||||
|
||||
echo "--- Run image tests"
|
||||
|
||||
export ROS_DISTRO='noetic'
|
||||
export ROS_IP='127.0.0.1'
|
||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||
source /home/pi/catkin_ws/devel/setup.bash
|
||||
systemctl start roscore
|
||||
|
||||
cd /home/pi/catkin_ws/src/clover/builder/test/
|
||||
./tests.sh
|
||||
./tests.py
|
||||
./tests_py3.py
|
||||
[[ $(./test_qr.py) == "Found QRCODE with data Проверка Unicode with center at x=66.0, y=66.0" ]]
|
||||
[[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility
|
||||
|
||||
systemctl stop roscore
|
||||
|
||||
# check documented packages available
|
||||
apt-cache show gst-rtsp-launch
|
||||
apt-cache show openvpn
|
||||
|
||||
echo "Move /etc/ld.so.preload back to its original position"
|
||||
mv /etc/ld.so.preload.disabled-for-build /etc/ld.so.preload
|
||||
|
||||
echo "Largest packages installed"
|
||||
sudo -E sh -c 'apt-get install -y debian-goodies'
|
||||
dpigs -H -n 100
|
||||
|
||||
echo "Cleanup apt"
|
||||
apt-get autoremove --purge -y
|
||||
apt-get clean
|
||||
|
||||
echo "Move /etc/ld.so.preload back to its original position"
|
||||
mv /etc/ld.so.preload.disabled-for-build /etc/ld.so.preload
|
||||
|
||||
@@ -23,6 +23,10 @@ from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetV
|
||||
from led_msgs.srv import SetLEDs
|
||||
from led_msgs.msg import LEDStateArray, LEDState
|
||||
from aruco_pose.msg import Marker, MarkerArray, Point2D
|
||||
from vision_msgs.msg import BoundingBox2D, BoundingBox2DArray, BoundingBox3D, BoundingBox3DArray, \
|
||||
Classification2D, Classification3D, Detection2D, Detection2DArray, Detection3D, Detection3DArray, \
|
||||
ObjectHypothesis, ObjectHypothesisWithPose, VisionInfo
|
||||
|
||||
from clover import long_callback
|
||||
|
||||
import dynamic_reconfigure.client
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
set -ex # exit on error, echo commands
|
||||
|
||||
# TODO: validate versions
|
||||
|
||||
# validate required software is installed
|
||||
|
||||
python2 --version
|
||||
python3 --version
|
||||
ipython3 --version
|
||||
|
||||
@@ -22,30 +21,28 @@ pip --version
|
||||
pip3 --version
|
||||
tcpdump --version
|
||||
monkey --version
|
||||
# espeak --version
|
||||
espeak --version
|
||||
xxd --version
|
||||
systemctl --version
|
||||
|
||||
if [ -z $VM ]; then
|
||||
# rpi only software
|
||||
python --version
|
||||
ipython --version
|
||||
pip2 --version
|
||||
# `python` is python2 for now
|
||||
[[ $(python -c 'import sys;print(sys.version_info.major)') == "2" ]]
|
||||
[[ $(python -c 'import sys;print(sys.version_info.major)') == "3" ]]
|
||||
|
||||
# ptvsd does not have a stand-alone binary
|
||||
python -m ptvsd --version
|
||||
python3 -m ptvsd --version
|
||||
python -m debugpy --version
|
||||
python3 -m debugpy --version
|
||||
|
||||
pigpiod -v
|
||||
i2cdetect -V
|
||||
butterfly -h
|
||||
/usr/local/bin/butterfly.server.py --help
|
||||
mjpg_streamer --version
|
||||
fi
|
||||
|
||||
# ros stuff
|
||||
|
||||
roscore -h
|
||||
catkin_find
|
||||
rosversion clover
|
||||
rosversion aruco_pose
|
||||
rosversion mavros
|
||||
@@ -61,14 +58,14 @@ rosversion web_video_server
|
||||
rosversion nodelet
|
||||
rosversion image_view
|
||||
|
||||
[[ $(rosversion ws281x) == "0.0.13" ]]
|
||||
[[ $(rosversion ws281x) == "0.0.15" ]]
|
||||
|
||||
if [ -z $VM ]; then
|
||||
rosversion compressed_image_transport
|
||||
# rosversion compressed_image_transport
|
||||
rosversion rosshow
|
||||
rosversion vl53l1x
|
||||
rosversion rosserial
|
||||
[[ $(rosversion cv_camera) == "0.5.1" ]] # patched version with init fix
|
||||
[[ $(rosversion cv_camera) == "0.6.1" ]] # patched version with init fix
|
||||
fi
|
||||
|
||||
# determine user home directory
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Make sure our Python 3 software is installed
|
||||
|
||||
import cv2
|
||||
from pyzbar import pyzbar
|
||||
|
||||
print(cv2.getBuildInformation())
|
||||
@@ -30,6 +30,8 @@ find_package(catkin REQUIRED COMPONENTS
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
|
||||
# https://github.com/mavlink/mavros/blob/7f1a8/mavros/CMakeLists.txt#L42
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};/usr/share/cmake/geographiclib")
|
||||
find_package(GeographicLib REQUIRED)
|
||||
|
||||
# Workaround for OpenCV 3/4 support
|
||||
|
||||
65
clover/camera_info/fisheye_cam_1280x720.yaml
Normal file
65
clover/camera_info/fisheye_cam_1280x720.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 415.5985593268293
|
||||
- 0.0
|
||||
- 400.0
|
||||
- 0.0
|
||||
- 312.35267324512984
|
||||
- 225.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 720
|
||||
image_width: 1280
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 415.5985593268293
|
||||
- 0.0
|
||||
- 405.4752811707317
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 312.35267324512984
|
||||
- 205.91677004464282
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_1920x1080.yaml
Normal file
65
clover/camera_info/fisheye_cam_1920x1080.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1246.7956779804879
|
||||
- 0.0
|
||||
- 1200.0
|
||||
- 0.0
|
||||
- 702.7935148015422
|
||||
- 506.25
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 1080
|
||||
image_width: 1920
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 1246.7956779804879
|
||||
- 0.0
|
||||
- 1216.4258435121951
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 702.7935148015422
|
||||
- 463.31273260044634
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_2592x1944.yaml
Normal file
65
clover/camera_info/fisheye_cam_2592x1944.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 5049.522495820976
|
||||
- 0.0
|
||||
- 4860.0
|
||||
- 0.0
|
||||
- 2846.313734946246
|
||||
- 2050.3125
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 1944
|
||||
image_width: 2592
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 5049.522495820976
|
||||
- 0.0
|
||||
- 4926.52466622439
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 2846.313734946246
|
||||
- 1876.4165670318075
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_320x240.yaml
Normal file
65
clover/camera_info/fisheye_cam_320x240.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 166.23942373073172
|
||||
- 0.0
|
||||
- 160.0
|
||||
- 0.0
|
||||
- 166.5880923974026
|
||||
- 120.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 240
|
||||
image_width: 320
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 166.23942373073172
|
||||
- 0.0
|
||||
- 162.19011246829268
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 166.5880923974026
|
||||
- 109.82227735714285
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_3840x2160.yaml
Normal file
65
clover/camera_info/fisheye_cam_3840x2160.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 30297.13497492585
|
||||
- 0.0
|
||||
- 29160.0
|
||||
- 0.0
|
||||
- 12808.411807258106
|
||||
- 9226.40625
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 2160
|
||||
image_width: 3840
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 30297.13497492585
|
||||
- 0.0
|
||||
- 29559.14799734634
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 12808.411807258106
|
||||
- 8443.874551643134
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_4056x3040.yaml
Normal file
65
clover/camera_info/fisheye_cam_4056x3040.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 192008.0929035926
|
||||
- 0.0
|
||||
- 184801.5
|
||||
- 0.0
|
||||
- 81119.941445968
|
||||
- 58433.90625
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 3040
|
||||
image_width: 4056
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 192008.0929035926
|
||||
- 0.0
|
||||
- 187331.10043318244
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 81119.941445968
|
||||
- 53477.87216040651
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_640x480.yaml
Normal file
65
clover/camera_info/fisheye_cam_640x480.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 166.23942373073172
|
||||
- 0.0
|
||||
- 160.0
|
||||
- 0.0
|
||||
- 166.5880923974026
|
||||
- 120.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 480
|
||||
image_width: 640
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 166.23942373073172
|
||||
- 0.0
|
||||
- 162.19011246829268
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 166.5880923974026
|
||||
- 109.82227735714285
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
65
clover/camera_info/fisheye_cam_800x600.yaml
Normal file
65
clover/camera_info/fisheye_cam_800x600.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated from fisheye_cam.yaml by rescale_camera_info.py
|
||||
camera_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 207.79927966341464
|
||||
- 0.0
|
||||
- 200.0
|
||||
- 0.0
|
||||
- 208.23511549675322
|
||||
- 150.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
rows: 3
|
||||
camera_name: main_camera_optical
|
||||
distortion_coefficients:
|
||||
cols: 8
|
||||
data:
|
||||
- 0.215356885
|
||||
- -0.117472846
|
||||
- -0.000306197672
|
||||
- -0.000109444025
|
||||
- -0.00453657258
|
||||
- 0.573090623
|
||||
- -0.127574577
|
||||
- -0.0286125589
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
rows: 1
|
||||
distortion_model: plumb_bob
|
||||
image_height: 600
|
||||
image_width: 800
|
||||
projection_matrix:
|
||||
cols: 4
|
||||
data:
|
||||
- 207.79927966341464
|
||||
- 0.0
|
||||
- 202.73764058536585
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 208.23511549675322
|
||||
- 137.27784669642855
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 0.0
|
||||
- 1.0
|
||||
- 0.0
|
||||
rows: 3
|
||||
rectification_matrix:
|
||||
cols: 3
|
||||
data:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 1
|
||||
rows: 3
|
||||
@@ -1,18 +0,0 @@
|
||||
# taken from: https://github.com/mavlink/mavros/blob/master/libmavconn/cmake/Modules/FindGeographicLib.cmake
|
||||
|
||||
# Look for GeographicLib
|
||||
#
|
||||
# Set
|
||||
# GEOGRAPHICLIB_FOUND = TRUE
|
||||
# GeographicLib_INCLUDE_DIRS = /usr/local/include
|
||||
# GeographicLib_LIBRARIES = /usr/local/lib/libGeographic.so
|
||||
# GeographicLib_LIBRARY_DIRS = /usr/local/lib
|
||||
|
||||
find_path (GeographicLib_INCLUDE_DIRS NAMES GeographicLib/Config.h)
|
||||
|
||||
find_library (GeographicLib_LIBRARIES NAMES Geographic)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args (GeographicLib DEFAULT_MSG
|
||||
GeographicLib_LIBRARIES GeographicLib_INCLUDE_DIRS)
|
||||
mark_as_advanced (GeographicLib_LIBRARIES GeographicLib_INCLUDE_DIRS)
|
||||
@@ -16,9 +16,10 @@
|
||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<remap from="map_markers" to="aruco_map/map"/>
|
||||
<param name="dictionary" value="2"/> <!-- DICT_4X4_250 -->
|
||||
<param name="estimate_poses" value="true"/>
|
||||
<param name="send_tf" value="true"/>
|
||||
<param name="use_map_markers" value="true"/>
|
||||
<param name="use_map_markers" value="$(arg aruco_map)"/>
|
||||
<param name="known_vertical" value="map" if="$(eval placement == 'floor' or placement == 'ceiling')"/>
|
||||
<param name="flip_vertical" value="true" if="$(eval placement == 'ceiling')"/>
|
||||
<param name="length" value="$(arg length)"/>
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
|
||||
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up -->
|
||||
<arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
|
||||
<arg name="device" default="/dev/video0"/> <!-- v4l2 device -->
|
||||
<arg name="type" default="libcamera"/> <!-- camera interface: libcamera, v4l2 -->
|
||||
<arg name="camera_id" default="0"/> <!-- libcamera camera id -->
|
||||
<arg name="device" default="/dev/video0"/> <!-- v4l2 device path -->
|
||||
<arg name="width" default="320"/>
|
||||
<arg name="height" default="240"/>
|
||||
<arg name="fps" default="40"/>
|
||||
<arg name="throttled_topic" default="true"/> <!-- enable throttled image topic -->
|
||||
<arg name="throttled_topic_rate" default="5.0"/> <!-- throttled image topic rate -->
|
||||
<arg name="rectify" default="false"/> <!-- enable rectification -->
|
||||
@@ -26,20 +31,34 @@
|
||||
<param name="num_worker_threads" value="2"/>
|
||||
</node>
|
||||
|
||||
<!-- camera node -->
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet main_camera_nodelet_manager" launch-prefix="rosrun clover waitfile $(arg device)" clear_params="true" unless="$(arg simulator)" respawn="true">
|
||||
<!-- camera node using libcamera -->
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load libcamera_ros/LibcameraRos main_camera_nodelet_manager" output="screen" clear_params="true" if="$(eval not simulator and type == 'libcamera')" respawn="true">
|
||||
<param name="camera_name" value=""/>
|
||||
<param name="camera_id" value="$(arg camera_id)"/>
|
||||
<param name="frame_id" value="main_camera_optical"/>
|
||||
<param name="calib_url" type="string" value="file://$(find clover)/camera_info/fisheye_cam_$(arg width)x$(arg height).yaml"/>
|
||||
<param name="stream_role" value="still"/>
|
||||
<param name="pixel_format" value="RGB888"/>
|
||||
<param name="use_ros_time" value="true"/>
|
||||
<param name="resolution/width" value="$(arg width)"/>
|
||||
<param name="resolution/height" value="$(arg height)"/>
|
||||
|
||||
<!-- see: https://github.com/ctu-mrs/libcamera_ros/blob/b3645/config/param.yaml#L19 -->
|
||||
<param name="control/fps" value="$(arg fps)"/>
|
||||
</node>
|
||||
|
||||
<!-- old camera node for v4l2 (cv_camera) -->
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet main_camera_nodelet_manager" launch-prefix="rosrun clover waitfile $(arg device)" clear_params="true" if="$(eval not simulator and type == 'v4l2')" respawn="true">
|
||||
<param name="device_path" value="$(arg device)"/>
|
||||
<param name="frame_id" value="main_camera_optical"/>
|
||||
<param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/>
|
||||
|
||||
<param name="rate" value="100"/> <!-- poll rate -->
|
||||
<param name="cv_cap_prop_fps" value="40"/> <!-- camera FPS -->
|
||||
<param name="cv_cap_prop_fps" value="$(arg fps)"/> <!-- camera FPS -->
|
||||
<param name="capture_delay" value="0.02"/> <!-- approximate delay on frame retrieving -->
|
||||
<param name="rescale_camera_info" value="true"/> <!-- automatically rescale camera calibration info -->
|
||||
|
||||
<!-- camera resolution -->
|
||||
<param name="image_width" value="320"/>
|
||||
<param name="image_height" value="240"/>
|
||||
<param name="image_width" value="$(arg width)"/>
|
||||
<param name="image_height" value="$(arg height)"/>
|
||||
</node>
|
||||
|
||||
<!-- camera visualization markers -->
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<depend condition="$ROS_PYTHON_VERSION == 3">python3-lxml</depend>
|
||||
<depend>dynamic_reconfigure</depend>
|
||||
<depend>image_proc</depend>
|
||||
<depend>image_geometry</depend>
|
||||
<exec_depend>python-pymavlink</exec_depend>
|
||||
<test_depend>ros_pytest</test_depend>
|
||||
|
||||
|
||||
@@ -303,6 +303,14 @@ def check_fcu():
|
||||
failure('cell voltage is not available, https://clover.coex.tech/power')
|
||||
else:
|
||||
cell = battery.cell_voltage[0]
|
||||
# number of cells 1 means this is overall voltage
|
||||
if len(battery.cell_voltage) == 1:
|
||||
n_cells = get_param('BAT1_N_CELLS', strict=False)
|
||||
if n_cells is None:
|
||||
# older PX4
|
||||
n_cells = get_param('BAT_N_CELLS', strict=True)
|
||||
cell /= n_cells
|
||||
|
||||
if cell > 4.3 or cell < 3.0:
|
||||
failure('incorrect cell voltage: %.2f V, https://clover.coex.tech/power', cell)
|
||||
elif cell < 3.7:
|
||||
|
||||
68
clover/tools/rescale_camera_info.py
Executable file
68
clover/tools/rescale_camera_info.py
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2024 Copter Express Technologies
|
||||
#
|
||||
# Author: Oleg Kalachev <okalachev@gmail.com>
|
||||
#
|
||||
# Distributed under MIT License (available at https://opensource.org/licenses/MIT).
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
|
||||
"""Rescale camera info
|
||||
|
||||
Rescale camera info files for different resolutions.
|
||||
|
||||
Usage:
|
||||
rescale_camera_info.py <camera_info_file>
|
||||
rescale_camera_info.py (-h | --help)
|
||||
|
||||
Options:
|
||||
<camera_info_file> Path to the source camera info file
|
||||
|
||||
Example:
|
||||
rescale_camera_info.py camera_info.yaml
|
||||
"""
|
||||
|
||||
from docopt import docopt
|
||||
import yaml
|
||||
|
||||
arguments = docopt(__doc__)
|
||||
|
||||
camera_info = yaml.safe_load(open(arguments['<camera_info_file>']))
|
||||
RESOLUTIONS = (
|
||||
(320, 240), # QVGA
|
||||
(640, 480), # VGA
|
||||
(800, 600), # SVGA
|
||||
(1280, 720), # HD
|
||||
(1920, 1080), # FullHD
|
||||
(2592, 1944), # 5MP
|
||||
(3840, 2160), # 4K
|
||||
(4056, 3040),
|
||||
)
|
||||
# TODO: retrieve resolutions list (v4l2-ctl --list-formats-ext)
|
||||
|
||||
for resolution in RESOLUTIONS:
|
||||
width_k = resolution[0] / camera_info['image_width']
|
||||
height_k = resolution[1] / camera_info['image_height']
|
||||
|
||||
camera_info_rescaled = camera_info.copy()
|
||||
camera_info_rescaled['image_width'] = resolution[0]
|
||||
camera_info_rescaled['image_height'] = resolution[1]
|
||||
|
||||
# See http://docs.ros.org/api/sensor_msgs/html/msg/CameraInfo.html for clarification
|
||||
camera_info_rescaled['camera_matrix']['data'][0] *= width_k
|
||||
camera_info_rescaled['camera_matrix']['data'][2] *= width_k
|
||||
camera_info_rescaled['camera_matrix']['data'][4] *= height_k
|
||||
camera_info_rescaled['camera_matrix']['data'][5] *= height_k
|
||||
|
||||
camera_info_rescaled['projection_matrix']['data'][0] *= width_k
|
||||
camera_info_rescaled['projection_matrix']['data'][2] *= width_k
|
||||
camera_info_rescaled['projection_matrix']['data'][5] *= height_k
|
||||
camera_info_rescaled['projection_matrix']['data'][6] *= height_k
|
||||
|
||||
output_file = arguments['<camera_info_file>'].replace('.yaml', '_{}x{}.yaml'.format(resolution[0], resolution[1]))
|
||||
with open(output_file, 'w') as f:
|
||||
f.write('# Generated from {} by rescale_camera_info.py\n'.format(arguments['<camera_info_file>']))
|
||||
yaml.dump(camera_info_rescaled, f)
|
||||
|
||||
print('Saved {}'.format(output_file))
|
||||
BIN
docs/assets/raspberry-uart-telemetry2.png
Normal file
BIN
docs/assets/raspberry-uart-telemetry2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
BIN
docs/assets/ssh-keys-known_hosts-fingerprint.png
Normal file
BIN
docs/assets/ssh-keys-known_hosts-fingerprint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -57,6 +57,7 @@
|
||||
* [COEX Pix](coex_pix.md)
|
||||
* [COEX PDB](coex_pdb.md)
|
||||
* [COEX GPS](coex_gps.md)
|
||||
* [Using SSH keys](ssh_keys.md)
|
||||
* [Guide on autonomous flight](auto_setup.md)
|
||||
* [Hostname](hostname.md)
|
||||
* [PX4 Simulation](sitl.md)
|
||||
|
||||
@@ -136,7 +136,7 @@ navigate(x=2, y=2, z=2, speed=1, frame_id='aruco_map')
|
||||
|
||||
### Using a specific marker frame
|
||||
|
||||
Starting with the [image](image.md) version 0.18, the drone also can fly relative to a marker in the map, even if it is not currently visible. Like with [single-marker navigation](aruco_marker.md#working-with-detected-markers), this works by setting the frame_id parameter to aruco_ID, where ID is the desired marker number.
|
||||
Starting with the [image](image.md) version 0.18, the drone also can fly relative to a marker in the map, even if it is not currently visible. Like with [single-marker navigation](aruco_marker.md#working-with-detected-markers), this works by setting the frame_id parameter to `aruco_ID`, where ID is the desired marker number.
|
||||
|
||||
The following code will move the drone to the point 1 meter above the center of marker 5:
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ Most of the parameters for autonomous flight are located in the following direct
|
||||
<arg name="aruco_vpe" default="true"/>`
|
||||
```
|
||||
|
||||
- Generate the ArUco markers field. See the article [Map-based navigation with ArUco markers] (aruco_map.md # marker map settings) for details. To generate markers, you need to enter a command with specific values.
|
||||
- Generate the ArUco markers field. See the article [Map-based navigation with ArUco markers](aruco_map.md#marker-map-definition) for details. To generate markers, you need to enter a command with specific values.
|
||||
|
||||
Here is the example generating command where:
|
||||
|
||||
|
||||
@@ -30,6 +30,16 @@ Print path to the current directory:
|
||||
pwd
|
||||
```
|
||||
|
||||
Go to the user's home directory:
|
||||
|
||||
```bash
|
||||
# all three commands are equivalent, where the tilde character (~) is an abbreviated
|
||||
# path entry to the home directory, and the $HOME variable stores this path
|
||||
cd
|
||||
cd ~
|
||||
cd $HOME
|
||||
```
|
||||
|
||||
Print contents of the `file.py` file:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -6,37 +6,59 @@ In order to program [autonomous flights](simple_offboard.md), [work with Pixhawk
|
||||
|
||||
USB connection is the preferred way to connect to the flight controller.
|
||||
|
||||
<img src="../assets/assembling_clever4/usb_connection_1.png" alt="USB connection" height=400 class="zoom border center">
|
||||
|
||||
1. Connect your FCU to the Raspberry Pi using a microUSB to USB cable.
|
||||
2. [Connect to the Raspberry Pi over SSH](ssh.md).
|
||||
3. Make sure the connection is working by [running the following command on the Raspberry Pi](ssh.md):
|
||||
3. Make sure that the connection is working properly by [running the following command on the Raspberry Pi](cli.md):
|
||||
|
||||
```bash
|
||||
rostopic echo /mavros/state
|
||||
```
|
||||
|
||||
The `connected` field should have the `True` value.s
|
||||
The `connected` field should have the `True` value.
|
||||
|
||||
> **Hint** You need to set the `CBRK_USB_CHK` [parameter](parameters.md) to 197848 for the USB connection to work.
|
||||
|
||||
## UART connection
|
||||
|
||||
<!-- TODO: Connection scheme -->
|
||||
|
||||
UART connection is another way for the Raspberry Pi and FCU to communicate.
|
||||
|
||||
<img src="../assets/raspberry-uart-telemetry2.png" alt="UART connection via TELEM2" height=400 class="zoom border center">
|
||||
|
||||
If the pin marked GND is occupied, you can use any other ground pin (look at the [pinout](https://pinout.xyz) for reference).
|
||||
|
||||
1. Connect the TELEM 2 port on the flight controller using a UART cable to the Raspberry Pi pins following this instruction: the black cable (*GND*) to Ground, the green cable (*UART_RX*) to *GPIO14*, the yellow cable (*UART_TX*) to *GPIO15*. Do not connect the red cable (*5V*).
|
||||
2. Set the PX4 parameters: `MAV_1_CONFIG` to TELEM 2, `SER_TEL2_BAUND` to 921600 8N1. In PX4 of version prior to v1.10.0 the parameter `SYS_COMPANION` should be set to 921600.
|
||||
2. In PX4 of version v1.9.0 or higher, set parameter values: `MAV_1_CONFIG` to TELEM 2, `SER_TEL2_BAUND` to 921600 8N1. In PX4 of version [prior to v1.9.0](https://github.com/mavlink/qgroundcontrol/issues/6905#issuecomment-464549610) the parameter `SYS_COMPANION` should be set to `Companion Link (921600 baud, 8N1)`, to set it correctly use the old version of QGC [v3.3.1](https://github.com/mavlink/qgroundcontrol/releases/tag/v3.3.1).
|
||||
3. [Connect to the Raspberry Pi over SSH](ssh.md).
|
||||
4. Change the connection type in `~/catkin_ws/src/clover/clover/launch/clover.launch` to UART:
|
||||
4. Check the presence of the parameters `enable_uart=1` and `dtoverlay=pi 3-disable-bt` in the file `/boot/config.txt` by [running the following command on the Raspberry Pi](cli.md):
|
||||
|
||||
```bash
|
||||
cat /boot/config.txt | grep -E "^enable_uart=.|^dtoverlay=pi3-disable-bt"
|
||||
```
|
||||
|
||||
If the parameters in the file are different or missing, then edit the file and restart the Raspberry Pi.
|
||||
|
||||
5. Change the connection type from `usb` to `uart` in the Clover' launch file `~/catkin_ws/src/clover/clover/launch/clover.launch`:
|
||||
|
||||
```xml
|
||||
<arg name="fcu_conn" default="uart"/>
|
||||
```
|
||||
|
||||
Be sure to restart the `clover` service after editing the .launch file:
|
||||
If you change the launch file, you need to restart the `clover' service:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart clover
|
||||
```
|
||||
|
||||
6. Make sure that the connection is working properly by running the following command:
|
||||
|
||||
```bash
|
||||
rostopic echo -n1 /mavros/state
|
||||
```
|
||||
|
||||
The `connected` field should have the `True` value.
|
||||
|
||||
Read more in the PX4 docs: https://docs.px4.io/main/en/peripherals/serial_configuration.html.
|
||||
|
||||
**Next**: [Using QGroundControl over Wi-Fi](gcs_bridge.md)
|
||||
|
||||
@@ -17,6 +17,8 @@ It is advisable to use a specialized build of PX4 with the necessary fixes and b
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
> **Warning** If you are using the firmware version older than *v1.10* (for example, `v1.8.2-clover.13`), then in order to avoid configuration errors, use [QGroundControl version *v4.2.0*](https://github.com/mavlink/qgroundcontrol/releases/tag/v4.2.0) (or older). See [detailed information](https://docs.px4.io/v1.11/en/config/battery.html#parameter-migration-notes) about changes in the firmware parameters that cause errors in newer versions of QGroundControl.
|
||||
|
||||
<script type="text/javascript">
|
||||
// get latest release from GitHub
|
||||
fetch('https://api.github.com/repos/CopterExpress/Firmware/releases').then(function(res) {
|
||||
|
||||
@@ -67,7 +67,7 @@ Connect your receiver to the RC IN port on your flight controller:
|
||||
</div>
|
||||
|
||||
> **Hint** Double check that you're using the RC IN port on the COEX Pix:
|
||||
<img src="../assets/coexpix-bottom.jpg" width=300 class="zoom border center" alt="coex pix pinout">
|
||||
<img src="../assets/coex_pix/coexpix-bottom.jpg" width=300 class="zoom border center" alt="coex pix pinout">
|
||||
|
||||
## Binding your transmitter {#rc_bind}
|
||||
|
||||
|
||||
@@ -488,3 +488,23 @@ Check, if the code is running inside a [Gazebo simulation](simulation.md):
|
||||
```python
|
||||
is_simulation = rospy.get_param('/use_sim_time', False)
|
||||
```
|
||||
|
||||
### # {#simulator-interaction}
|
||||
|
||||
You can move a physical object (link) in Gazebo (as well as change its velocity) using the `gazebo/set_link_state` service (of the type [`SetLinkState`](http://docs.ros.org/en/api/gazebo_msgs/html/srv/SetLinkState.html)). For example, if you add a cube to the world (link `unit_box::link`), you can move it to the point (1, 2, 3):
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from geometry_msgs.msg import Point, Pose, Quaternion
|
||||
from gazebo_msgs.srv import SetLinkState
|
||||
from gazebo_msgs.msg import LinkState
|
||||
|
||||
rospy.init_node('flight')
|
||||
|
||||
set_link_state = rospy.ServiceProxy('gazebo/set_link_state', SetLinkState)
|
||||
|
||||
# Change link's position
|
||||
set_link_state(LinkState(link_name='unit_box::link', pose=Pose(position=Point(1, 2, 3), orientation=Quaternion(0, 0, 0, 1))))
|
||||
```
|
||||
|
||||
> **Info** Simple object animation in Gazebo can be implemented [using actors](http://classic.gazebosim.org/tutorials?tut=actor&cat=build_robot).
|
||||
|
||||
@@ -13,9 +13,9 @@ ssh pi@192.168.11.1
|
||||
|
||||
Password: `raspberry`.
|
||||
|
||||
For SSH access from Windows, you may use [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html).
|
||||
For SSH access from Windows, you may use [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html). You can also gain SSH access from your smartphone using the [Termius](https://www.termius.com) app.
|
||||
|
||||
You can also gain SSH access from your smart-phone using the [Termius](https://www.termius.com) app.
|
||||
> **Hint** To avoid entering the password each time you connect via SSH, see [the article on using SSH keys](ssh_keys.md).
|
||||
|
||||
Read more: https://www.raspberrypi.org/documentation/remote-access/ssh/README.md
|
||||
|
||||
|
||||
180
docs/en/ssh_keys.md
Normal file
180
docs/en/ssh_keys.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# Connecting to Raspberry Pi using SSH keys
|
||||
|
||||
*This instruction will allow you to quickly connect to the Raspberry Pi. In just one second. Without entering a password.*
|
||||
|
||||
Basic information on working with SSH can be found in the section [SSH access to Raspberry Pi](ssh.md). In this section you will find advanced information on using SSH, as well as a number of recommendations on using SSH when working with Clover.
|
||||
|
||||
## General information
|
||||
|
||||
SSH (*secure shell*) is a network protocol that allows you to remotely control the operating system on the computer you are connected to. It is similar to a protocol such as *telnet*, but allows you to encrypt network traffic during interaction. Thus, the transfer of passwords and other secret information is hidden. The Raspberry Pi operating system supports SSH communication, like many other common Linux-based systems.
|
||||
|
||||
SSH allows you not only to organize work in the command shell, but also to transfer files, as well as tunnel transmitted data from other protocols, such as information from a video camera or telemetry. In addition, SSH supports several authentication modes (that is, verification of the connecting user), with its help it is possible to connect to the Clover not only using a password, but also password-free access (authentication by a key pair, i.e. SSH keys).
|
||||
|
||||
## Password authentication
|
||||
|
||||
Authentication [by password](ssh.md) on the image of RPi for Clover is enabled by default and the password can be used to enter into the command shell of the minicomputer. On computers with Linux operating systems (and primarily on servers connected to the Internet), the ability to login with a password is usually disabled, since there is a more secure authentication method.
|
||||
|
||||
> **Hint** It is not recommended to disable logging into Clover by password, since you can completely lose access to the command shell over the network.
|
||||
|
||||
When connecting to RPi for the first time, you will see the notification with a suggestion to save a unique *fingerprint*. The stored information is accumulated on computers from which SSH login to RPi is performed, and is checked for sudden substitution.
|
||||
|
||||
On Linux and Unix (Mac OS) the first SSH-connection to the RPi looks like this:
|
||||
|
||||
```bash
|
||||
ssh pi@192.168.11.1
|
||||
# The authenticity of host '192.168.11.1 (192.168.11.1)' can't be established.
|
||||
# ED25519 key fingerprint is SHA256:4w/7MqTgrtsqPwKnVAMISpouaOJNqzUew2NkJjldMWI.
|
||||
# This key is not known by any other names
|
||||
# Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
|
||||
# Warning: Permanently added '192.168.11.1' (ED25519) to the list of known hosts.
|
||||
# pi@192.168.11.1's password: *********
|
||||
# Linux clover-3270 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l
|
||||
|
||||
whoami
|
||||
# pi
|
||||
|
||||
exit
|
||||
```
|
||||
|
||||
In graphical programs in Windows, you will periodically see window with similar warnings.
|
||||
|
||||
<img src="../assets/ssh-keys-known_hosts-fingerprint.png" alt="Сохранение отпечатка в Windows" class="border center">
|
||||
|
||||
> **Hint** Windows 10 has a built-in SSH client that can be run from the command line, see the Microsoft usage guide [at this link](https://learn.microsoft.com/ru-ru/windows-server/administration/openssh/openssh_install_firstuse).
|
||||
|
||||
## Authentication using SSH keys
|
||||
|
||||
SSH keys are a convenient, fast alternative way to connect to the Raspberry Pi, which does not require entering a password. In particular, when operating with Clover, this method is convenient because it saves time, and therefore battery power, and the time limit allocated for events in flight zones. In addition, using SSH keys opens up opportunities for convenient use of other programs that you would hardly use if you needed to type a password every time.
|
||||
|
||||
The SSH key is divided into two parts: the pair consists of a so-called *private* and *public* key. The key is generated once. One part of the key (open) is transferred once to the remote computer to which the connection will be made, the second part of the key (private) is stored on the computer that will connect, the private part of the key is not transferred anywhere.
|
||||
|
||||
> **Hint** The public key is copied once to the Raspberry Pi, and the private key is stored in the laptop as a file.
|
||||
|
||||
### Preparation
|
||||
|
||||
In order for a key pair to appear, it must be generated. In Linux and Unix (Mac OS), there is a program `ssh-keygen` with which we will get the key pair we need (**attention!** commands are executed not in Raspberry Pi, and not in the virtual machine of the Gazebo simulator, but in the command shell of the laptop from which you will connect to the Clover):
|
||||
|
||||
Before using the keys, you need to perform a number of actions to configure access rights *on the laptop*:
|
||||
|
||||
```bash
|
||||
# one-time setting of access rights to user directories
|
||||
chmod o-rwx $HOME
|
||||
mkdir ~/.ssh
|
||||
chmod g-rwx,o-rwx ~/.ssh
|
||||
touch ~/.ssh/config ~/.ssh/known_hosts
|
||||
chmod 600 ~/.ssh/config ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
> **Hint** The `.ssh` directory in the user's home folder is the standard storage location for both key pairs and SSH connection settings, so we prohibit access to it by the Others group (*outsiders*). Modern Linux distributions check access rights to files in the `.ssh` directory and may refuse authentication by key pairs.
|
||||
|
||||
### Generating an SSH key pair
|
||||
|
||||
Generating a pair of SSH keys in the `~/.ssh` directory on the laptop:
|
||||
|
||||
```bash
|
||||
ssh-keygen -f ~/.ssh/id_clover -C "SSH key for Clover" -N ""
|
||||
# Your identification has been saved in /home/galina/.ssh/id_clover
|
||||
# Your public key has been saved in /home/galina/.ssh/id_clover.pub
|
||||
|
||||
chmod 400 ~/.ssh/id_clover*
|
||||
```
|
||||
|
||||
### Copying SSH key to Raspberry Pi
|
||||
|
||||
After that [connect to Raspberry Pi via WiFi](wi fi.md) and continue to enter commands *on the laptop* to copy the key to the minicomputer:
|
||||
|
||||
```bash
|
||||
ssh-copy-id -i ~/.ssh/id_clover.pub pi@192.168.11.1
|
||||
# pi@192.168.11.1's password: *********
|
||||
```
|
||||
|
||||
As a result, the so-called *public* part of the key will be copied from the laptop to the RPi microcomputer, and the *private* part will remain on the laptop. To verify the connection without entering a password, use the command indicating the path where the SSH key is located:
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_clover pi@192.168.11.1
|
||||
```
|
||||
|
||||
If the terminal does not require you to enter a password to connect to the RPi, then you did everything correctly and the SSH key pair works. Now you can type the exit command from the SSH terminal to continue configuring the laptop:
|
||||
|
||||
```bash
|
||||
pi@clover-3270:~ $ exit
|
||||
# logout
|
||||
# Connection to 192.168.11.1 closed.
|
||||
|
||||
galina@Thinkpad-X1:~/.ssh$
|
||||
```
|
||||
|
||||
## Configuring SSH connection to Clover
|
||||
|
||||
Now let's set up the SSH terminal in such a way that you don't have to enter the path to the private key every time. This is done by editing the `~/.ssh/config` file *on a laptop*. Open the file in a text editor and add the following lines to the file (if there is already some information there, then put them at the end of the file):
|
||||
|
||||
```txt
|
||||
Host 192.168.11.1
|
||||
User pi
|
||||
IdentityFile ~/.ssh/id_clover
|
||||
PreferredAuthentications publickey,password
|
||||
PubkeyAuthentication yes
|
||||
PasswordAuthentication yes
|
||||
ConnectTimeout 1
|
||||
TCPKeepAlive yes
|
||||
ServerAliveInterval 2
|
||||
ServerAliveCountMax 3
|
||||
StrictHostKeyChecking no
|
||||
```
|
||||
|
||||
This setting:
|
||||
|
||||
* affects the operation of the SSH terminal when connected to a computer with the IP address `192.168.11.1`;
|
||||
* if the user name is not specified, the name `pi` will be used automatically;
|
||||
* the private key `~/.ssh/id_clover` will be used automatically;
|
||||
* if the key does not fit for some reason (it was replaced on one laptop, but forgot to replace it on another), then the SSH terminal will switch to password authentication (settings `PreferredAuthentications`, `PubkeyAuthentication`, `PasswordAuthentication`);
|
||||
* if communication with RPi cannot be established (WiFi is not yet connected), then the SSH connection will not hang, but will be completed quickly (setting `ConnectTimeout`);
|
||||
* if the connection with RPi is suddenly severed, the SSH connection will not hang, but will be completed quickly (settings `TCPKeepAlive`, `ServerAliveInterval`, `ServerAliveCountMax`);
|
||||
* the unique SSH *fingerprints* of the RPi microcomputers mentioned above will no longer be checked (the settings `StrictHostKeyChecking`).
|
||||
|
||||
This will solve a lot of inconveniences associated with using SSH connections.
|
||||
|
||||
> **Hint** If you have several Raspberry Pi-based drones in your laboratory, and several laptops, then you can **generate SSH keys once**, copy them to all drones and spread them across all laptops, then you can quickly access any of the drones from any laptop.
|
||||
|
||||
Now, to connect to RPi from a Linux terminal, you just need to type `ssh 1[TAB][TAB][ENTER]` and the ip address `192.168.11.1` will be automatically updated on the command line, because the command shell uses addresses from the file `~/.ssh/config` and is able to "guess" your intentions to connect to the Clover. By pressing enter, you will instantly find yourself in the RPi terminal.
|
||||
|
||||
> **Hint** Graphical programs for Windows that support working with SSH keys, which you can use: [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) and [MobaXterm](https://mobaxterm.mobatek.net/).
|
||||
|
||||
## Copying files using SSH
|
||||
|
||||
To copy a file `circle_flight.py` from the laptop to the RPi to the user's home folder `pi`, you can also use SSH. To do this, type the command in the command shell:
|
||||
|
||||
```bash
|
||||
# first we specify 'what' we copy, and then 'where'
|
||||
scp circle_flight.py 192.168.11.1
|
||||
```
|
||||
|
||||
To copy `output.avi` file from the `examples` RPi' folder to the laptop, use a similar command:
|
||||
|
||||
```bash
|
||||
# after the ':' character (colon), you can specify the path on the remote computer
|
||||
# the path specified as './' means the current folder where the file will be copied
|
||||
scp 192.168.11.1:examples/output.avi ./
|
||||
```
|
||||
|
||||
## Remote command launch via SSH
|
||||
|
||||
To run a command at laptop on the RPi (that is, remotely), you can also use SSH.
|
||||
|
||||
Raspberry shutdown command:
|
||||
|
||||
```bash
|
||||
ssh 192.168.11.1 'sudo shutdown now'
|
||||
```
|
||||
|
||||
Example of a Python script' startup command:
|
||||
|
||||
```bash
|
||||
ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && python3 examples/get_telemetry.py'
|
||||
```
|
||||
|
||||
In order to remotely start video recording, you can run the command:
|
||||
|
||||
```bash
|
||||
ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && rosrun image_view video_recorder image:=/main_camera/image_raw'
|
||||
```
|
||||
@@ -58,6 +58,7 @@
|
||||
* [COEX Pix](coex_pix.md)
|
||||
* [COEX PDB](coex_pdb.md)
|
||||
* [COEX GPS](coex_gps.md)
|
||||
* [Использование SSH-ключей](ssh_keys.md)
|
||||
* [Радио-телеметрия](radio_telemetry.md)
|
||||
* [Камера Hawk Eye](hawk_eye.md)
|
||||
* [Гид по автономному полету](auto_setup.md)
|
||||
|
||||
@@ -136,7 +136,7 @@ navigate(x=2, y=2, z=2, speed=1, frame_id='aruco_map') # полет в коор
|
||||
|
||||
### Полет в координаты по ID маркера
|
||||
|
||||
Начиная с версии [образа](image.md) 0.18, доступны также полёты относительно отдельного маркера в карте, даже если дрон его не видит. По аналогии с [навигацией по отдельным маркерам](aruco_marker.md#навигация-по-маркерам) при настройке карты маркеров дрон сможет лететь в координаты относительно отдельного маркера, используя фрейм aruco_ID с соответствующим ID маркера.
|
||||
Начиная с версии [образа](image.md) 0.18, доступны также полёты относительно отдельного маркера в карте, даже если дрон его не видит. По аналогии с [навигацией по отдельным маркерам](aruco_marker.md#навигация-по-маркерам) при настройке карты маркеров дрон сможет лететь в координаты относительно отдельного маркера, используя фрейм `aruco_ID` с соответствующим ID маркера.
|
||||
|
||||
Полет в точку над маркером 5 на высоту 1 метр:
|
||||
|
||||
|
||||
@@ -30,6 +30,16 @@ cd ..
|
||||
pwd
|
||||
```
|
||||
|
||||
Перейти в домашнюю директорию пользователя:
|
||||
|
||||
```bash
|
||||
# все три команды равнозначны, где символ тильда (~) это сокращённая запись пути
|
||||
# к домашней директории, а переменная $HOME хранит этот путь
|
||||
cd
|
||||
cd ~
|
||||
cd $HOME
|
||||
```
|
||||
|
||||
Вывести содержимое файла `file.py`:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
|
||||
Основным способом подключения является подключение по интерфейсу USB.
|
||||
|
||||
<img src="../assets/assembling_clever4/usb_connection_1.png" alt="Подключение по USB" height=400 class="zoom border center">
|
||||
|
||||
1. Соедините Raspberry Pi и полетный контроллер micro-USB to USB кабелем.
|
||||
2. [Подключитесь в Raspberry Pi по SSH](ssh.md).
|
||||
3. Убедитесь в работоспособности подключения, [выполнив на Raspberry Pi](ssh.md):
|
||||
3. Убедитесь в работоспособности подключения, [выполнив команду на Raspberry Pi](cli.md):
|
||||
|
||||
```bash
|
||||
rostopic echo /mavros/state
|
||||
@@ -20,14 +22,24 @@
|
||||
|
||||
## Подключение по UART
|
||||
|
||||
<!-- TODO схема подключения -->
|
||||
Дополнительным способом подключения является подключение по интерфейсу UART.
|
||||
|
||||
Дополнительным способом подключения является подключение подключение по интерфейсу UART.
|
||||
<img src="../assets/raspberry-uart-telemetry2.png" alt="Подключение UART через TELEM2" height=400 class="zoom border center">
|
||||
|
||||
Если обозначенный пин GND занят, можно использовать другой свободный, используя [распиновку](https://pinout.xyz).
|
||||
|
||||
1. Подключите Raspberry Pi к полетному контроллеру по UART. Для этого соедините кабелем порт TELEM 2 на полетном контроллере к пинам на Raspberry Pi следующем образом: черный провод (GND) к Ground, зеленый (*UART_RX*) к *GPIO14*, желтый (*UART_TX*) к *GPIO15*. Красный провод (*5V*) подключать не нужно.
|
||||
2. Измените значения параметров PX4: `MAV_1_CONFIG` на TELEM 2, `SER_TEL2_BAUND` на 921600 8N1. В PX4 до версии v1.10.0 необходима установка параметра `SYS_COMPANION` в значение 921600.
|
||||
2. В PX4 версии v1.9.0 и выше измените значения параметров PX4: `MAV_1_CONFIG` на TELEM 2, `SER_TEL2_BAUND` на 921600 8N1. В PX4 [до версии v1.9.0](https://github.com/mavlink/qgroundcontrol/issues/6905#issuecomment-464549610) необходима установка параметра `SYS_COMPANION` в значение `Companion Link (921600 baud, 8N1)`, для его корректной установки используйте старую версию QGC [v3.3.1](https://github.com/mavlink/qgroundcontrol/releases/tag/v3.3.1).
|
||||
3. [Подключитесь в Raspberry Pi по SSH](ssh.md).
|
||||
4. Поменяйте в launch-файле Клевера (`~/catkin_ws/src/clover/clover/launch/clover.launch`) тип подключения на UART:
|
||||
4. Проверьте наличие параметров `enable_uart=1` и `dtoverlay=pi3-disable-bt` в файле `/boot/config.txt`, [выполнив команду на Raspberry Pi](cli.md):
|
||||
|
||||
```bash
|
||||
cat /boot/config.txt | grep -E "^enable_uart=.|^dtoverlay=pi3-disable-bt"
|
||||
```
|
||||
|
||||
Если параметры в файле отличаются или отсутствуют, то отредактируйте файл и перезагрузите Raspberry Pi.
|
||||
|
||||
5. Поменяйте в launch-файле Клевера (`~/catkin_ws/src/clover/clover/launch/clover.launch`) тип подключения с `usb` на `uart`:
|
||||
|
||||
```xml
|
||||
<arg name="fcu_conn" default="uart"/>
|
||||
@@ -39,4 +51,14 @@
|
||||
sudo systemctl restart clover
|
||||
```
|
||||
|
||||
6. Убедитесь в работоспособности подключения:
|
||||
|
||||
```bash
|
||||
rostopic echo -n1 /mavros/state
|
||||
```
|
||||
|
||||
Поле `connected` должно содержать значение `True`.
|
||||
|
||||
Дополнительная информация: https://docs.px4.io/main/en/peripherals/serial_configuration.html.
|
||||
|
||||
**Далее**: [Подключение QGroundControl по Wi-Fi](gcs_bridge.md).
|
||||
|
||||
@@ -17,6 +17,8 @@ Pixhawk, Pixracer и [COEX Pix](coex_pix.md) можно прошить, испо
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
> **Warning** Если вы используете прошивку с версией ниже, чем *v1.10* (например `v1.8.2-clover.13`), то во избежание ошибок конфигурирования полётного контроллера, используйте [QGroundControl версии *v4.2.0*](https://github.com/mavlink/qgroundcontrol/releases/tag/v4.2.0) (или ниже). См. [подробную информацию](https://docs.px4.io/v1.11/en/config/battery.html#parameter-migration-notes) об изменениях в параметрах, которые вызывают ошибки в более новых версиях QGroundControl.
|
||||
|
||||
<script type="text/javascript">
|
||||
// get latest release from GitHub
|
||||
fetch('https://api.github.com/repos/CopterExpress/Firmware/releases').then(function(res) {
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
</div>
|
||||
|
||||
> **Hint** Убедитесь, что провод, идущий в COEX Pix, подключен к порту RC IN:
|
||||
<img src="../assets/coexpix-bottom.jpg" width=300 class="zoom border center" alt="coex pix pinout">
|
||||
<img src="../assets/coex_pix/coexpix-bottom.jpg" width=300 class="zoom border center" alt="coex pix pinout">
|
||||
|
||||
## Сопряжение приёмника с пультом {#rc_bind}
|
||||
|
||||
|
||||
@@ -499,3 +499,23 @@ param_set(param_id='MPC_Z_P', value=ParamValue(real=1.5))
|
||||
```python
|
||||
is_simulation = rospy.get_param('/use_sim_time', False)
|
||||
```
|
||||
|
||||
### # {#simulator-interaction}
|
||||
|
||||
Переместить физический объект (линк) в Gazebo (а также поменять его скорости) можно при помощи сервиса `gazebo/set_link_state` (тип [`SetLinkState`](http://docs.ros.org/en/api/gazebo_msgs/html/srv/SetLinkState.html)). Например, если добавить в мир объект куб (линк `unit_box::link`), то так можно переместить его в точку (1, 2, 3):
|
||||
|
||||
```python
|
||||
import rospy
|
||||
from geometry_msgs.msg import Point, Pose, Quaternion
|
||||
from gazebo_msgs.srv import SetLinkState
|
||||
from gazebo_msgs.msg import LinkState
|
||||
|
||||
rospy.init_node('flight')
|
||||
|
||||
set_link_state = rospy.ServiceProxy('gazebo/set_link_state', SetLinkState)
|
||||
|
||||
# Переместить линк в Gazebo
|
||||
set_link_state(LinkState(link_name='unit_box::link', pose=Pose(position=Point(1, 2, 3), orientation=Quaternion(0, 0, 0, 1))))
|
||||
```
|
||||
|
||||
> **Info** Простую анимацию объектов в Gazebo можно реализовать [с помощью акторов](http://classic.gazebosim.org/tutorials?tut=actor&cat=build_robot).
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
ssh pi@192.168.11.1
|
||||
```
|
||||
|
||||
Пароль: ``raspberry``.
|
||||
Пароль: `raspberry`.
|
||||
|
||||
Для доступа по SSH из Windows можно использовать [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) или веб-доступ (см. далее). Также можно получить доступ по SSH со смартфона с помощью приложения [Termius](https://www.termius.com).
|
||||
|
||||
> **Hint** Для того, чтобы не вводить пароль при каждом подключении по SSH, см. [статью об использовании SSH-ключей](ssh_keys.md).
|
||||
|
||||
Подробнее: https://www.raspberrypi.org/documentation/remote-access/ssh/README.md.
|
||||
|
||||
## Веб-доступ
|
||||
|
||||
184
docs/ru/ssh_keys.md
Normal file
184
docs/ru/ssh_keys.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Подключение к Raspberry Pi с использованием SSH-ключей
|
||||
|
||||
*Эта инструкция позволит вам быстро подключаться к Raspberry Pi. Всего за одну секунду. Без ввода пароля.*
|
||||
|
||||
Базовые сведения по работе с SSH вы можете найти в разделе [Доступ по SSH к Raspberry Pi](ssh.md). А в этом разделе вы найдёте расширенную информацию по использованию SSH, а также ряд рекомендаций по использованию SSH при работе с Клевером.
|
||||
|
||||
## Общая информация
|
||||
|
||||
SSH (англ. *secure shell* — "безопасная оболочка") - сетевой протокол, позволяющий удалённо управлять операционной системой на компьютере, к которому вы подключились. Аналогичен такому протоколу, как *telnet*, но позволяет выполнять шифрование сетевого трафика по время взаимодействия. Таким образом передача паролей и другой секретной информации оказываются скрыты. Операционная система Raspberry Pi поддерживает взаимодействие по SSH, как и многие другие распространённые системы на базе Linux.
|
||||
|
||||
SSH позволяет не только организовывать работу в командной оболочке, но и передавать файлы, а также туннелировать передаваемые данные других протоколов, например информацию с видеокамеры или телеметрию. Кроме того, SSH поддерживает несколько режимов аутентификации (то есть проверки подключающегося пользователя), с его помощью возможно подключение к Клеверу не только с использованием пароля, но и беспарольный доступ (аутентификация по ключевой паре, т.е. SSH-ключи).
|
||||
|
||||
## Аутентификация по паролю
|
||||
|
||||
Аутентификация [по паролю](ssh.md) на образе RPi для Клевера включена и пароль может быть использован для входа в командную оболочку мини-компьютера. На ЭВМ с операционными системами Linux (и в первую очередь на серверах, подключенных к интернету) возможность входа по паролю обычно отключают, поскольку есть более безопасный способ аутентификации.
|
||||
|
||||
> **Hint** Вход в Клевер по паролю отключать не рекомендуется, поскольку можно совсем утратить доступ к командной оболочке по сети.
|
||||
|
||||
При первом подключении к RPi пользователю показывается уведомление с предложением сохранить уникальный отпечаток *fingerprint*. Сохранённая информация накапливается на компьютерах с которых выполняется вход по SSH на RPi, и проверяется на внезапную подмену.
|
||||
|
||||
В ОС Linux и Unix (Mac OS) в текстовом SSH-клиенте первое подключение к RPi выглядит таким образом:
|
||||
|
||||
```bash
|
||||
ssh pi@192.168.11.1
|
||||
# The authenticity of host '192.168.11.1 (192.168.11.1)' can't be established.
|
||||
# ED25519 key fingerprint is SHA256:4w/7MqTgrtsqPwKnVAMISpouaOJNqzUew2NkJjldMWI.
|
||||
# This key is not known by any other names
|
||||
# Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
|
||||
# Warning: Permanently added '192.168.11.1' (ED25519) to the list of known hosts.
|
||||
# pi@192.168.11.1's password: *********
|
||||
# Linux clover-3270 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l
|
||||
|
||||
whoami
|
||||
# pi
|
||||
|
||||
exit
|
||||
```
|
||||
|
||||
В графических программах в Windows у вас будут периодически возникать окошки с похожими предупреждениями.
|
||||
|
||||
<img src="../assets/ssh-keys-known_hosts-fingerprint.png" alt="Сохранение отпечатка в Windows" class="border center">
|
||||
|
||||
> **Hint** В Windows 10 появился встроенный SSH-клиент, который можно запускать из командной строки, см. руководство по использованию от Microsoft [по этой ссылке](https://learn.microsoft.com/ru-ru/windows-server/administration/openssh/openssh_install_firstuse).
|
||||
|
||||
## Аутентификация с использованием SSH-ключей
|
||||
|
||||
SSH-ключи - это удобный, быстрый альтернативный способ подключения к Raspberry Pi, для которого не требуется ввод пароля. В частности, при эксплуатации Клевера такой способ удобен потому, что экономит время, а значит и заряд аккумулятора, и лимит времени отведённого на мероприятия в полётных зонах. Кроме того, использование SSH-ключей открывает возможности по удобному использованию других программ, которыми бы вы вряд-ли воспользовались бы при необходимости всякий раз набирать пароль.
|
||||
|
||||
SSH-ключ делится на две части: пара состоит из т.н. *закрытого* и *открытого* ключа. Ключ однократно генерируется. Одна часть ключа (открытая) однократно передаётся на удалённый компьютер к которому будет выполняться подключение, вторая часть ключа (закрытая) хранится на компьютере, который будет подключаться, закрытая часть ключа никуда не передаётся.
|
||||
|
||||
> **Hint** Открытый ключ однократно копируется на Raspberry Pi, а закрытый ключ сохраняется в ноутбуке в виде файла.
|
||||
|
||||
### Подготовка
|
||||
|
||||
Для того, чтобы пара ключей появилась, её необходимо сгенерировать. В ОС Linux и Unix (Mac OS) есть программа `ssh-keygen` с помощью которой мы и получим нужную нам пару ключей (**внимание!** команды выполняются не в Raspberry Pi, и не в виртуальной машине симулятора Gazebo, а в командной оболочке ноутбука с которого вы будете подключаться к Клеверу):
|
||||
|
||||
Прежде чем пользоваться ключами, необходимо выполнить ряд действий для настройки прав доступа *на ноутбуке*:
|
||||
|
||||
```bash
|
||||
# однократная настойка прав доступа к пользовательским директориям
|
||||
chmod o-rwx $HOME
|
||||
mkdir ~/.ssh
|
||||
chmod g-rwx,o-rwx ~/.ssh
|
||||
touch ~/.ssh/config ~/.ssh/known_hosts
|
||||
chmod 600 ~/.ssh/config ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
> **Hint** Директория `.ssh` в домашней папке пользователя - это стандартное место хранения и ключевых пар, и настроек подключения с использованием SSH, поэтому доступ к ней запрещаем группе Others (*посторонние*). Современные дистрибутивы Linux проверяют права доступа к файлам в директории `.ssh` и могут отказать в аутентификации по ключевым парам.
|
||||
|
||||
### Генерация пары SSH-ключей
|
||||
|
||||
Генерируем пару SSH-ключей в директории `~/.ssh` на ноутбуке:
|
||||
|
||||
<!-- TODO: в Windows начиная с версии 10 все команды перечисленные статье должны работать, - Проверить! -->
|
||||
|
||||
```bash
|
||||
ssh-keygen -f ~/.ssh/id_clover -C "SSH key for Clover" -N ""
|
||||
# Your identification has been saved in /home/galina/.ssh/id_clover
|
||||
# Your public key has been saved in /home/galina/.ssh/id_clover.pub
|
||||
|
||||
chmod 400 ~/.ssh/id_clover*
|
||||
```
|
||||
|
||||
### Копирование SSH-ключа на Raspberry Pi
|
||||
|
||||
После чего [подключаемся к Raspberry Pi по Wi-Fi](wifi.md) и продолжаем вводить команды *на ноутбуке* для копирования ключа на мини-компьютер:
|
||||
|
||||
```bash
|
||||
ssh-copy-id -i ~/.ssh/id_clover.pub pi@192.168.11.1
|
||||
# pi@192.168.11.1's password: *********
|
||||
```
|
||||
|
||||
В результате с ноутбука на микрокомпьютер RPi будет скопирована т.н. *открытая* часть ключа, а *закрытая* останется на ноутбуке. Для проверки подключения без ввода пароля используем команду с указанием пути где находится SSH-ключ:
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_clover pi@192.168.11.1
|
||||
```
|
||||
|
||||
Если терминал не потребует ввода пароля для подключения к RPi, то вы всё сделали правильно и пара SSH-ключей работает. Теперь можно набрать команду выхода из SSH-терминала, чтобы продолжить настройку ноутбука:
|
||||
|
||||
```bash
|
||||
pi@clover-3270:~ $ exit
|
||||
# logout
|
||||
# Connection to 192.168.11.1 closed.
|
||||
|
||||
galina@Thinkpad-X1:~/.ssh$
|
||||
```
|
||||
|
||||
## Настройка SSH-подключения к Клеверу
|
||||
|
||||
Теперь давайте настроим SSH-терминал таким образом, чтобы не приходилось всякий раз вписывать путь к закрытому ключу. Это делается с помощью редактирования файла `~/.ssh/config` *на ноутбуке*. Откройте файл в текстовом редакторе и добавьте в файл следующие строки (если там уже есть какая-то информация, то поместите их в конец файла):
|
||||
|
||||
```txt
|
||||
Host 192.168.11.1
|
||||
User pi
|
||||
IdentityFile ~/.ssh/id_clover
|
||||
PreferredAuthentications publickey,password
|
||||
PubkeyAuthentication yes
|
||||
PasswordAuthentication yes
|
||||
ConnectTimeout 1
|
||||
TCPKeepAlive yes
|
||||
ServerAliveInterval 2
|
||||
ServerAliveCountMax 3
|
||||
StrictHostKeyChecking no
|
||||
```
|
||||
|
||||
Эта настройка:
|
||||
|
||||
* влияет на работу SSH-терминала при подключении к компьютеру с ip-адресом `192.168.11.1`;
|
||||
* если имя пользователя не указано, то автоматически будет использоваться имя `pi`;
|
||||
* будет автоматически использоваться приватный ключ `~/.ssh/id_clover`;
|
||||
* если ключ по каким-то причинам не подойдёт (был заменён на одном ноутбуке, но забыт заменить на другом), то SSH-терминал перейдёт к аутентификации по паролю (настройки `PreferredAuthentications`, `PubkeyAuthentication`, `PasswordAuthentication`);
|
||||
* если связь с RPi не может установиться (WiFi ещё не включился), то SSH-подключение не зависнет, а быстро завершится (настройка `ConnectTimeout`);
|
||||
* если связь с RPi будет внезапно разорвана, то SSH-подключение не зависнет, а быстро завершится (настройки `TCPKeepAlive`, `ServerAliveInterval`, `ServerAliveCountMax`);
|
||||
* уникальные SSH-отпечатки RPi-микрокомпьютеров (*fingerprints*) о которых упоминалось выше, проверяться больше не будут (настройка `StrictHostKeyChecking`).
|
||||
|
||||
Таким образом будет решено множество неудобств, связанных с использованием SSH-подключений.
|
||||
|
||||
> **Hint** Если у вас в лаборатории несколько дронов на базе Raspberry Pi, и несколько ноутбуков, то можно **однократно** сгенерировать SSH-ключи, скопировать их на все дроны и разложить по всем ноутбукам, тогда с любого ноутбука можно будет быстро зайти на любой из дронов.
|
||||
|
||||
Теперь, чтобы подключиться к RPi из терминала Linux вам достаточно набрать `ssh 1[TAB][TAB][ENTER]` и ip-адрес `192.168.11.1` автоматически дополнится в командной строке, т.к. командная оболочка использует адреса из файла `~/.ssh/config` и способна "угадать" ваши намерения для подключения к Клеверу. Нажав ввод вы мгновенно окажетесь в терминале RPi.
|
||||
|
||||
> **Hint** Графические программы для Windows, которые поддерживают работу с SSH-ключами, которыми вы можете воспользоваться: [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) и [MobaXterm](https://mobaxterm.mobatek.net/).
|
||||
|
||||
## Копирование файлов при помощи SSH
|
||||
|
||||
Чтобы скопировать файл `circle_flight.py` с ноутбука на RPi в домашнюю папку пользователя `pi` можно также воспользоваться SSH. Для этого наберите в командной оболочке команду:
|
||||
|
||||
```bash
|
||||
# сначала указываем 'что' копируем, а потом 'куда'
|
||||
scp circle_flight.py 192.168.11.1
|
||||
```
|
||||
|
||||
Для того, чтобы скопировать файл `output.avi` c RPi из папки `examples` на ноутбук используем похожую команду:
|
||||
|
||||
```bash
|
||||
# после символа ':' (двоеточие) можно указать путь на удалённом компьютере
|
||||
# путь указанный как './' означает текущую папку, куда будет скопирован файл
|
||||
scp 192.168.11.1:examples/output.avi ./
|
||||
```
|
||||
|
||||
## Удалённый запуск команд по SSH
|
||||
|
||||
Чтобы запустить команду с ноутбука на RPi (то есть удалённо) можно также воспользоваться SSH.
|
||||
|
||||
Команда выключения Raspberry:
|
||||
|
||||
```bash
|
||||
ssh 192.168.11.1 'sudo shutdown now'
|
||||
```
|
||||
|
||||
Пример команды запуска Python-скрипта:
|
||||
|
||||
<!-- TODO: здесь слишком длинная команда получается, потому что-то запускать скрипты в .bashrc нехорошо (команды выполняются не только из bash) Должно быть так: ssh -t 192.168.11.1 'python3 examples/get_telemetry.py' -->
|
||||
|
||||
```bash
|
||||
ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && python3 examples/get_telemetry.py'
|
||||
```
|
||||
|
||||
Для того, чтобы удалённо запустить запись видео можно выполнить команду:
|
||||
|
||||
```bash
|
||||
ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && rosrun image_view video_recorder image:=/main_camera/image_raw'
|
||||
```
|
||||
@@ -21,6 +21,7 @@
|
||||
{ "from": "connection.html", "to": "en/connection.html" },
|
||||
{ "from": "wifi.html", "to": "ru/wifi.html" },
|
||||
{ "from": "ssh.html", "to": "ru/ssh.html" },
|
||||
{ "from": "ssh_keys.html", "to": "ru/ssh_keys.html" },
|
||||
{ "from": "network.html", "to": "ru/network.html" },
|
||||
{ "from": "gcs_bridge.html", "to": "ru/gcs_bridge.html" },
|
||||
{ "from": "rc.html", "to": "ru/rc.html" },
|
||||
|
||||
Reference in New Issue
Block a user