mirror of
https://github.com/CopterExpress/clover.git
synced 2026-06-01 07:29:32 +00:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
492430e994 | ||
|
|
924a6c60da | ||
|
|
8ca24ea293 | ||
|
|
c4e6280ea9 | ||
|
|
d46bfabb65 | ||
|
|
66dd9e61c6 | ||
|
|
dcecb03cd5 | ||
|
|
687041d571 | ||
|
|
449364bffb | ||
|
|
1b313b4c5d | ||
|
|
58ec56895f | ||
|
|
28e89704e6 | ||
|
|
23da41247f | ||
|
|
1e45ec143c | ||
|
|
26ec42f1e6 | ||
|
|
3edb2f48e0 | ||
|
|
3a08085c69 | ||
|
|
4e4dfc1f07 | ||
|
|
6b0ed144e3 | ||
|
|
91bb9d6e38 | ||
|
|
e1ff92ee1f | ||
|
|
4d2b685b06 | ||
|
|
14c41b21b6 | ||
|
|
70439f172d | ||
|
|
dacaa8ebde | ||
|
|
a5309765f1 | ||
|
|
2e86ed199a | ||
|
|
ad14822684 | ||
|
|
936efa985d | ||
|
|
c55e0cb7e1 | ||
|
|
b8344dbb84 | ||
|
|
3b7242f3d6 | ||
|
|
cfeff0c74d | ||
|
|
7d022a5af1 | ||
|
|
ebd9c03251 | ||
|
|
5755300d3a | ||
|
|
8c5551b00b | ||
|
|
42c26aa645 | ||
|
|
f91dc4df71 | ||
|
|
e31b69a790 | ||
|
|
7251a76315 | ||
|
|
921e09c392 | ||
|
|
9e69bdb01b | ||
|
|
50495a9de9 | ||
|
|
12ccd919a2 | ||
|
|
f0eacfc0f7 | ||
|
|
742d0535c3 | ||
|
|
af1b993e64 | ||
|
|
d3bda9df48 | ||
|
|
939086362a | ||
|
|
7cf14373b0 | ||
|
|
f428dfdb50 | ||
|
|
76982dc198 | ||
|
|
29f01c25e0 | ||
|
|
7ca0ede1d7 | ||
|
|
c3d87b1608 | ||
|
|
47901dcff2 | ||
|
|
9404d4be6d | ||
|
|
ad51d86464 |
7
.github/workflows/build-image.yaml
vendored
7
.github/workflows/build-image.yaml
vendored
@@ -7,23 +7,24 @@ on:
|
||||
branches: [ master ]
|
||||
release:
|
||||
types: [ created ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- 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
|
||||
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 . && zip -9 $(echo *_*).zip *_* && ls -l . && unzip -l *_*.zip
|
||||
- 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 }}
|
||||
|
||||
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@@ -5,12 +5,13 @@ on:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# melodic:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Native Melodic build
|
||||
# run: |
|
||||
# docker run --rm -v $(pwd):/root/catkin_ws/src/clover ros:melodic-ros-base /root/catkin_ws/src/clover/builder/standalone-install.sh
|
||||
@@ -22,7 +23,7 @@ jobs:
|
||||
working-directory: catkin_ws
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: catkin_ws/src/clover
|
||||
- name: Install requirements
|
||||
@@ -44,7 +45,7 @@ jobs:
|
||||
fakeroot debian/rules binary
|
||||
cd -
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debian-packages
|
||||
path: catkin_ws/src/clover/*.deb
|
||||
|
||||
15
.github/workflows/docs.yml
vendored
15
.github/workflows/docs.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -19,9 +20,9 @@ jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v4
|
||||
with: { node-version: '10' }
|
||||
- name: Setup tools
|
||||
run: |
|
||||
@@ -56,16 +57,16 @@ jobs:
|
||||
rm _book/clover_ru.pdf && mv _book/clover_ru_compressed.pdf _book/clover_ru.pdf
|
||||
rm _book/clover_en.pdf && mv _book/clover_en_compressed.pdf _book/clover_en.pdf
|
||||
ls -lah _book/clover*.pdf
|
||||
echo '::set-output name=GITBOOK_PDF_OK::1'
|
||||
echo 'GITBOOK_PDF_OK=1' >> "$GITHUB_OUTPUT"
|
||||
- name: Download older PDFs
|
||||
if: ${{ !steps.generate-pdf.outputs.GITBOOK_PDF_OK }}
|
||||
run: |
|
||||
rm -f _book/clover*.pdf
|
||||
wget --no-verbose https://clover.coex.tech/clover_ru.pdf -P _book/
|
||||
wget --no-verbose https://clover.coex.tech/clover_en.pdf -P _book/
|
||||
wget --no-verbose https://clovercoex.tech/clover_ru.pdf -P _book/
|
||||
wget --no-verbose https://clovercoex.tech/clover_en.pdf -P _book/
|
||||
- name: Upload artifact
|
||||
# if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: _book
|
||||
|
||||
@@ -85,4 +86,4 @@ jobs:
|
||||
FREEZE_DOCS: ${{ secrets.FREEZE_DOCS }}
|
||||
if: ${{ !env.FREEZE_DOCS }}
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
5
.github/workflows/editorconfig.yaml
vendored
5
.github/workflows/editorconfig.yaml
vendored
@@ -5,14 +5,15 @@ on:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
editorconfig:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: .editorconfig Linter
|
||||
run: |
|
||||
wget --no-verbose https://github.com/okalachev/editorconfig-checker/releases/download/1.2.1-disable-spaces-amount/ec-linux-amd64
|
||||
chmod +x ec-linux-amd64
|
||||
./ec-linux-amd64 -spaces-after-tabs -e "roslib.js|ros3d.js|eventemitter2.js|json-to-pretty-yaml.js|draw.cpp|BinUtils.swift|\.idea|apps/android/app|blockly/|clover_blocks/programs/|highlight/|python.js|Assets.xcassets|test_parser_pass.txt|test_node_failure.txt|aruco_pose/vendor|\.stl|\.dxf|\.dae|\.material"
|
||||
./ec-linux-amd64 -spaces-after-tabs -e "roslib.js|ros3d.js|eventemitter2.js|yaml.js|draw.cpp|BinUtils.swift|\.idea|apps/android/app|blockly/|clover_blocks/programs/|highlight/|python.js|Assets.xcassets|test_parser_pass.txt|test_node_failure.txt|aruco_pose/vendor|\.stl|\.dxf|\.dae|\.material"
|
||||
|
||||
@@ -113,7 +113,9 @@
|
||||
"VMware",
|
||||
"DuoCam"
|
||||
],
|
||||
"code_blocks": false
|
||||
"code_blocks": false,
|
||||
"html_elements": false
|
||||
},
|
||||
"MD045": false
|
||||
"MD045": false,
|
||||
"MD051": false
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ Clover is an open source [ROS](https://www.ros.org)-based framework, providing u
|
||||
|
||||
COEX Clover Drone is an educational programmable drone kit, suited perfectly for running clover software. The kit is shipped unassembled and includes Pixracer-compatible autopilot running PX4 firmware, Raspberry Pi 4 as a companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices. Batteries included.
|
||||
|
||||
The main documentation is available at [https://clover.coex.tech](https://clover.coex.tech/). Official website: [coex.tech/clover](https://coex.tech/clover).
|
||||
The main documentation is available at [https://clovercoex.tech](https://clovercoex.tech/).
|
||||
|
||||
[__Support us on Kickstarter!__](https://www.kickstarter.com/projects/copterexpress/cloverdrone)
|
||||
|
||||
@@ -30,11 +30,11 @@ Image features:
|
||||
* Configured networking
|
||||
* OpenCV
|
||||
* [`mavros`](http://wiki.ros.org/mavros)
|
||||
* Periphery drivers for ROS ([GPIO](https://clover.coex.tech/en/gpio.html), [LED strip](https://clover.coex.tech/en/leds.html), etc)
|
||||
* Periphery drivers for ROS ([GPIO](https://clovercoex.tech/en/gpio.html), [LED strip](https://clovercoex.tech/en/leds.html), etc)
|
||||
* `aruco_pose` package for marker-assisted navigation
|
||||
* `clover` package for autonomous drone control
|
||||
|
||||
API description for autonomous flights is available [on GitBook](https://clover.coex.tech/en/simple_offboard.html).
|
||||
API description for autonomous flights is available [on GitBook](https://clovercoex.tech/en/simple_offboard.html).
|
||||
|
||||
For manual package installation and running see [`clover` package documentation](clover/README.md).
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ PACKAGE = "aruco_pose"
|
||||
from dynamic_reconfigure.parameter_generator_catkin import *
|
||||
import cv2.aruco
|
||||
|
||||
p = cv2.aruco.DetectorParameters_create()
|
||||
try:
|
||||
p = cv2.aruco.DetectorParameters_create()
|
||||
except AttributeError:
|
||||
p = cv2.aruco.DetectorParameters()
|
||||
|
||||
gen = ParameterGenerator()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="3">
|
||||
<name>aruco_pose</name>
|
||||
<version>0.24.0</version>
|
||||
<version>0.25.0</version>
|
||||
<description>Positioning with ArUco markers</description>
|
||||
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"blank": true
|
||||
},
|
||||
"sitemap": {
|
||||
"hostname": "https://clover.coex.tech"
|
||||
"hostname": "https://clovercoex.tech"
|
||||
},
|
||||
"toolbar": {
|
||||
"buttons":
|
||||
|
||||
@@ -736,3 +736,6 @@ realsense2_camera:
|
||||
realsense2_description:
|
||||
debian:
|
||||
buster: [ros-noetic-realsense2-description]
|
||||
geographiclib:
|
||||
debian:
|
||||
buster: [libgeographic-dev]
|
||||
|
||||
@@ -72,7 +72,7 @@ my_travis_retry() {
|
||||
echo_stamp "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 "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"
|
||||
@@ -125,11 +125,12 @@ cd /home/pi/catkin_ws/src/clover
|
||||
builder/assets/install_gitbook.sh
|
||||
gitbook install
|
||||
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
|
||||
|
||||
echo_stamp "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 \
|
||||
@@ -138,7 +139,10 @@ my_travis_retry apt-get install -y --no-install-recommends \
|
||||
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}-vision-msgs \
|
||||
ros-${ROS_DISTRO}-angles
|
||||
|
||||
# TODO move GeographicLib datasets to Mavros debian package
|
||||
echo_stamp "Install GeographicLib datasets (needed for mavros)" \
|
||||
|
||||
@@ -122,7 +122,7 @@ 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/3.7/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
|
||||
|
||||
@@ -6,6 +6,10 @@ import os
|
||||
import rospy
|
||||
from geometry_msgs.msg import PoseStamped
|
||||
from sensor_msgs.msg import Range, BatteryState
|
||||
from vision_msgs.msg import BoundingBox2D, BoundingBox2DArray, BoundingBox3D, BoundingBox3DArray, \
|
||||
Classification2D, Classification3D, Detection2D, Detection2DArray, Detection3D, Detection3DArray, \
|
||||
ObjectHypothesis, ObjectHypothesisWithPose, VisionInfo
|
||||
import angles
|
||||
|
||||
import cv2
|
||||
import cv2.aruco
|
||||
|
||||
@@ -60,6 +60,9 @@ rosversion cv_camera
|
||||
rosversion web_video_server
|
||||
rosversion nodelet
|
||||
rosversion image_view
|
||||
rosversion stereo_msgs
|
||||
rosversion vision_msgs
|
||||
rosversion angles
|
||||
|
||||
[[ $(rosversion ws281x) == "0.0.13" ]]
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ EXCLUDE = 'rviz.png', 'ssid.png', 'sitl_docker_demo.png', 'qgc-params.png', 'but
|
||||
'qgc-battery.png', 'qgc-radio.png', 'qgc-cal-acc.png', 'qgc-esc.png', 'qgc-cal-compass.png', \
|
||||
'qgc.png', 'qgc-parameters.png', 'clever4-front-white-large.png', 'qgc-modes.png', \
|
||||
'qgc-requires-setup.png', 'clever4-front-white.png', 'clever4-kit-white.png', '26_1.png', 'battery_holder.stl', \
|
||||
'camera_case.stl', 'camera_mount.stl'
|
||||
'camera_case.stl', 'camera_mount.stl', 'grip_right.stl', 'grip_left.stl'
|
||||
|
||||
code = 0
|
||||
|
||||
|
||||
@@ -2,6 +2,52 @@
|
||||
Changelog for package clover
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
0.25 (2024-07-28)
|
||||
-----------------
|
||||
* Optimize displaying newlines in the topic viewer, add width and indent parameters.
|
||||
* Link assets instead of copying in documentation to save space.
|
||||
* Install image_geometry and dynamic_reconfigure as clover dependencies.
|
||||
* Add dictionary parameter to aruco.launch.
|
||||
* Solve the issue with aruco_detect not running when aruco_map is not enabled.
|
||||
* Documentation improvements.
|
||||
* Rest changes.
|
||||
|
||||
0.24 (2023-10-11)
|
||||
-----------------
|
||||
* Significant update to autonomous flights API.
|
||||
* Updates to selfcheck.py.
|
||||
* Support PX4 v1.14 parameters.
|
||||
* Added scripts for automatic testing of autonomous flights.
|
||||
* Added new examples for working with the camera, including a red circle model and its recognition and following.
|
||||
* Implemented long_callback Python decorator to address the issue #218.
|
||||
* Implemented optical_flow/enabled dynamic parameter.
|
||||
* Updated LED strip native library to support RPi 4 rev. 1.5.
|
||||
* Show number of messages received in web topic viewer.
|
||||
* Run main_camera/image_raw_throttled topic by default.
|
||||
* Added rectify argument to main_camera.launch
|
||||
* Added udev rules for all supported autopilots by PX4.
|
||||
* Various changes.
|
||||
|
||||
0.23 (2022-02-10)
|
||||
-----------------
|
||||
* Web tool for topics monitoring.
|
||||
* Publish optical flow when local position is not available.
|
||||
* Force estimator init.
|
||||
* Web viewer for Clover logs.
|
||||
* selfcheck.py improvements.
|
||||
* Various changes.
|
||||
|
||||
0.22 (2021-06-07)
|
||||
-----------------
|
||||
* Move to ROS Noetic and Python 3.
|
||||
* aruco.launch: add placement, length and map arguments.
|
||||
* Web: add link for viewing the error log.
|
||||
* LED: add error/ignore parameter to not flash on some errors.
|
||||
* Wait for FC and camera devices before launching mavros and camera driver.
|
||||
* clover.launch: disable rc node by default.
|
||||
* optical_flow: publish debug image even when calc_flow_gyro failed.
|
||||
* Various changes.
|
||||
|
||||
0.21.1 (2020-11-17)
|
||||
-------------------
|
||||
* First release of clover package to ROS
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -50,6 +50,6 @@ To start connection to the flight controller, use:
|
||||
roslaunch clover clover.launch
|
||||
```
|
||||
|
||||
For the simulation information see the [corresponding article](https://clover.coex.tech/en/simulation.html).
|
||||
For the simulation information see the [corresponding article](https://clovercoex.tech/en/simulation.html).
|
||||
|
||||
> Note that the package is configured to connect to `/dev/px4fmu` by default (see [previous section](#manual-installation)). Install udev rules or specify path to your FCU device in `mavros.launch`.
|
||||
|
||||
@@ -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)
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/camera
|
||||
# Information: https://clovercoex.tech/camera
|
||||
|
||||
# Example on basic working with the camera and image processing:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/programming
|
||||
# Information: https://clovercoex.tech/programming
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/aruco
|
||||
# Information: https://clovercoex.tech/aruco
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/en/simple_offboard.html#gettelemetry
|
||||
# Information: https://clovercoex.tech/en/simple_offboard.html#gettelemetry
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/en/simple_offboard.html#navigateglobal
|
||||
# Information: https://clovercoex.tech/en/simple_offboard.html#navigateglobal
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
@@ -16,7 +16,7 @@ set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
|
||||
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
||||
land = rospy.ServiceProxy('land', Trigger)
|
||||
|
||||
# https://clover.coex.tech/en/snippets.html#wait_arrival
|
||||
# https://clovercoex.tech/en/snippets.html#wait_arrival
|
||||
def wait_arrival(tolerance=0.2):
|
||||
while not rospy.is_shutdown():
|
||||
telem = get_telemetry(frame_id='navigate_target')
|
||||
@@ -27,7 +27,7 @@ def wait_arrival(tolerance=0.2):
|
||||
start = get_telemetry()
|
||||
|
||||
if math.isnan(start.lat):
|
||||
raise Exception('No global position, install and configure GPS sensor: https://clover.coex.tech/gps')
|
||||
raise Exception('No global position, install and configure GPS sensor: https://clovercoex.tech/gps')
|
||||
|
||||
print('Start point global position: lat={}, lon={}'.format(start.lat, start.lon))
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/led
|
||||
# Information: https://clovercoex.tech/led
|
||||
|
||||
import rospy
|
||||
from clover.srv import SetLEDEffect
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/en/snippets.html#navigate_wait
|
||||
# Information: https://clovercoex.tech/en/snippets.html#navigate_wait
|
||||
|
||||
import math
|
||||
import rospy
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This example makes the drone find and follow the red circle.
|
||||
# To test in the simulator, place 'Red Circle' model on the floor.
|
||||
# More information: https://clover.coex.tech/red_circle
|
||||
# More information: https://clovercoex.tech/red_circle
|
||||
|
||||
# Input topic: main_camera/image_raw (camera image)
|
||||
# Output topics:
|
||||
@@ -17,6 +17,7 @@ from cv_bridge import CvBridge
|
||||
from clover import long_callback, srv
|
||||
import tf2_ros
|
||||
import tf2_geometry_msgs
|
||||
import image_geometry
|
||||
|
||||
rospy.init_node('cv', disable_signals=True) # disable signals to allow interrupting with ctrl+c
|
||||
|
||||
@@ -32,21 +33,14 @@ mask_pub = rospy.Publisher('~mask', Image, queue_size=1)
|
||||
point_pub = rospy.Publisher('~red_circle', PointStamped, queue_size=1)
|
||||
|
||||
# read camera info
|
||||
camera_info = rospy.wait_for_message('main_camera/camera_info', CameraInfo)
|
||||
camera_matrix = np.float64(camera_info.K).reshape(3, 3)
|
||||
distortion = np.float64(camera_info.D).flatten()
|
||||
camera_model = image_geometry.PinholeCameraModel()
|
||||
camera_model.fromCameraInfo(rospy.wait_for_message('main_camera/camera_info', CameraInfo))
|
||||
|
||||
|
||||
def img_xy_to_point(xy, dist):
|
||||
xy = cv2.undistortPoints(xy, camera_matrix, distortion, P=camera_matrix)[0][0]
|
||||
|
||||
# Shift points to center
|
||||
xy -= camera_info.width // 2, camera_info.height // 2
|
||||
|
||||
fx = camera_matrix[0, 0]
|
||||
fy = camera_matrix[1, 1]
|
||||
|
||||
return Point(x=xy[0] * dist / fx, y=xy[1] * dist / fy, z=dist)
|
||||
xy_rect = camera_model.rectifyPoint(xy)
|
||||
ray = camera_model.projectPixelTo3dRay(xy_rect)
|
||||
return Point(x=ray[0] * dist, y=ray[1] * dist, z=dist)
|
||||
|
||||
def get_center_of_mass(mask):
|
||||
M = cv2.moments(mask)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/en/laser.html
|
||||
# Information: https://clovercoex.tech/en/laser.html
|
||||
|
||||
import rospy
|
||||
from sensor_msgs.msg import Range
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<arg name="length" default="0.22"/> <!-- not-in-map markers length, m -->
|
||||
<arg name="map" default="map.txt"/> <!-- markers map file name -->
|
||||
|
||||
<!-- For additional help go to https://clover.coex.tech/aruco -->
|
||||
<!-- For additional help go to https://clovercoex.tech/aruco -->
|
||||
|
||||
<arg name="force_init" default="false"/>
|
||||
<arg name="disable" default="false"/> <!-- only force init -->
|
||||
@@ -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)"/>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<arg name="simulator" default="false"/>
|
||||
|
||||
<!-- For additional help go to https://clover.coex.tech/led -->
|
||||
<!-- For additional help go to https://clovercoex.tech/led -->
|
||||
|
||||
<!-- ws281x led strip driver -->
|
||||
<node pkg="ws281x" name="led" type="ws281x_node" clear_params="true" output="screen" if="$(eval ws281x and not simulator)">
|
||||
@@ -21,7 +21,8 @@
|
||||
</node>
|
||||
|
||||
<!-- high level led effects control, events notification with leds -->
|
||||
<node pkg="clover" name="led_effect" type="led" ns="led" clear_params="true" output="screen" if="$(arg led_effect)">
|
||||
<node pkg="clover" name="led_effect" type="led" clear_params="true" output="screen" if="$(arg led_effect)">
|
||||
<param name="led" value="led"/>
|
||||
<param name="blink_rate" value="2"/>
|
||||
<param name="fade_period" value="0.5"/>
|
||||
<param name="rainbow_period" value="5"/>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<launch>
|
||||
<!-- article about camera setup: https://clover.coex.tech/camera_setup -->
|
||||
<!-- article about camera setup: https://clovercoex.tech/camera_setup -->
|
||||
|
||||
<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="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 -->
|
||||
<arg name="simulator" default="false"/>
|
||||
|
||||
<node if="$(eval direction_z == 'down' and direction_y == 'backward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
||||
@@ -49,4 +50,11 @@
|
||||
<!-- image topic throttled -->
|
||||
<node pkg="topic_tools" name="main_camera_throttle" type="throttle" ns="main_camera"
|
||||
args="messages image_raw $(arg throttled_topic_rate) image_raw_throttled" if="$(arg throttled_topic)"/>
|
||||
|
||||
<!-- rectified image topic -->
|
||||
<node pkg="nodelet" type="nodelet" name="rectify" args="load image_proc/rectify main_camera_nodelet_manager" if="$(arg rectify)">
|
||||
<remap from="image_mono" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<remap from="image_rect" to="main_camera/image_rect"/>
|
||||
</node>
|
||||
</launch>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="3">
|
||||
<name>clover</name>
|
||||
<version>0.24.0</version>
|
||||
<version>0.25.0</version>
|
||||
<description>The Clover package</description>
|
||||
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
<license>MIT</license>
|
||||
|
||||
<url type="website">https://clover.coex.tech/</url>
|
||||
<url type="website">https://clovercoex.tech/</url>
|
||||
<author email="okalachev@gmail.com">Oleg Kalachev</author>
|
||||
<author email="urpylka@gmail.com">Artem Smirnov</author>
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
<depend condition="$ROS_PYTHON_VERSION == 2">python-lxml</depend>
|
||||
<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>
|
||||
|
||||
|
||||
@@ -309,15 +309,19 @@ int main(int argc, char **argv)
|
||||
nh_priv.param("notify/low_battery/threshold", low_battery_threshold, 3.7);
|
||||
nh_priv.param("notify/error/ignore", error_ignore, {});
|
||||
|
||||
ros::service::waitForService("set_leds"); // cannot work without set_leds service
|
||||
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true);
|
||||
std::string led; // led namespace
|
||||
nh_priv.param("led", led, std::string("led"));
|
||||
if (!led.empty()) led += "/";
|
||||
|
||||
ros::service::waitForService(led + "set_leds"); // cannot work without set_leds service
|
||||
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>(led + "set_leds", true);
|
||||
|
||||
// wait for leds count info
|
||||
handleState(*ros::topic::waitForMessage<led_msgs::LEDStateArray>("state", nh));
|
||||
handleState(*ros::topic::waitForMessage<led_msgs::LEDStateArray>(led + "state", nh));
|
||||
|
||||
auto state_sub = nh.subscribe("state", 1, &handleState);
|
||||
auto state_sub = nh.subscribe(led + "state", 1, &handleState);
|
||||
|
||||
auto set_effect = nh.advertiseService("set_effect", &setEffect);
|
||||
auto set_effect = nh.advertiseService(led + "set_effect", &setEffect);
|
||||
|
||||
auto mavros_state_sub = nh.subscribe("mavros/state", 1, &handleMavrosState);
|
||||
auto battery_sub = nh.subscribe("mavros/battery", 1, &handleBattery);
|
||||
|
||||
@@ -107,7 +107,7 @@ def ff(value, precision=2):
|
||||
param_get = rospy.ServiceProxy('mavros/param/get', ParamGet)
|
||||
|
||||
|
||||
def get_param(name, default=None):
|
||||
def get_param(name, default=None, strict=True):
|
||||
try:
|
||||
res = param_get(param_id=name)
|
||||
except rospy.ServiceException as e:
|
||||
@@ -115,7 +115,8 @@ def get_param(name, default=None):
|
||||
return None
|
||||
|
||||
if not res.success:
|
||||
failure('unable to retrieve PX4 parameter %s', name)
|
||||
if strict:
|
||||
failure('unable to retrieve PX4 parameter %s', name)
|
||||
return default
|
||||
else:
|
||||
if res.value.integer != 0:
|
||||
@@ -258,12 +259,12 @@ def check_fcu():
|
||||
info(line[len('HW arch: '):])
|
||||
|
||||
if not clover_fw:
|
||||
info('not Clover PX4 firmware, check https://clover.coex.tech/firmware')
|
||||
info('not Clover PX4 firmware, check https://clovercoex.tech/firmware')
|
||||
|
||||
est = get_param('SYS_MC_EST_GROUP')
|
||||
if est == 1:
|
||||
info('selected estimator: LPE')
|
||||
fuse = get_param('LPE_FUSION')
|
||||
fuse = int(get_param('LPE_FUSION'))
|
||||
if fuse & (1 << 4):
|
||||
info('LPE_FUSION: land detector fusion is enabled')
|
||||
else:
|
||||
@@ -299,11 +300,19 @@ def check_fcu():
|
||||
try:
|
||||
battery = rospy.wait_for_message('mavros/battery', BatteryState, timeout=3)
|
||||
if not battery.cell_voltage:
|
||||
failure('cell voltage is not available, https://clover.coex.tech/power')
|
||||
failure('cell voltage is not available, https://clovercoex.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)
|
||||
failure('incorrect cell voltage: %.2f V, https://clovercoex.tech/power', cell)
|
||||
elif cell < 3.7:
|
||||
failure('critically low cell voltage: %.2f V, recharge battery', cell)
|
||||
except rospy.ROSException:
|
||||
@@ -316,7 +325,13 @@ def check_fcu():
|
||||
failure('cannot read time sync offset')
|
||||
|
||||
except rospy.ROSException:
|
||||
failure('no MAVROS state (check wiring)')
|
||||
failure('no MAVROS state')
|
||||
fcu_url = rospy.get_param('mavros/fcu_url', '?')
|
||||
if fcu_url == '/dev/px4fmu':
|
||||
if not os.path.exists('/lib/udev/rules.d/99-px4fmu.rules'):
|
||||
info('udev rules are not installed, install udev rules or change usb_device to /dev/ttyACM0 in mavros.launch')
|
||||
else:
|
||||
info('udev did\'t recognize px4fmu device, check wiring or change usb_device to /dev/ttyACM0 in mavros.launch')
|
||||
info('fcu_url = %s', rospy.get_param('mavros/fcu_url', '?'))
|
||||
|
||||
|
||||
@@ -487,7 +502,7 @@ def check_vpe():
|
||||
failure('vision yaw weight is zero, change ATT_W_EXT_HDG parameter')
|
||||
else:
|
||||
info('vision yaw weight: %s', ff(vision_yaw_w))
|
||||
fuse = get_param('LPE_FUSION')
|
||||
fuse = int(get_param('LPE_FUSION'))
|
||||
if not fuse & (1 << 2):
|
||||
failure('vision position fusion is disabled, change LPE_FUSION parameter')
|
||||
delay = get_param('LPE_VIS_DELAY')
|
||||
@@ -495,11 +510,22 @@ def check_vpe():
|
||||
failure('LPE_VIS_DELAY = %s, but it should be zero', delay)
|
||||
info('LPE_VIS_XY = %s m, LPE_VIS_Z = %s m', get_paramf('LPE_VIS_XY'), get_paramf('LPE_VIS_Z'))
|
||||
elif est == 2:
|
||||
fuse = get_param('EKF2_AID_MASK')
|
||||
if not fuse & (1 << 3):
|
||||
failure('vision position fusion is disabled, change EKF2_AID_MASK parameter')
|
||||
if not fuse & (1 << 4):
|
||||
failure('vision yaw fusion is disabled, change EKF2_AID_MASK parameter')
|
||||
ev_ctrl = get_param('EKF2_EV_CTRL', strict=False)
|
||||
if ev_ctrl is not None: # PX4 after v1.14
|
||||
ev_ctrl = int(ev_ctrl)
|
||||
if not ev_ctrl & (1 << 0):
|
||||
failure('vision horizontal position fusion is disabled, change EKF2_EV_CTRL parameter')
|
||||
if not ev_ctrl & (1 << 1):
|
||||
failure('vision vertical position fusion is disabled, change EKF2_EV_CTRL parameter')
|
||||
if not ev_ctrl & (1 << 3):
|
||||
failure('vision yaw fusion is disabled, change EKF2_EV_CTRL parameter')
|
||||
else: # PX4 before v1.14
|
||||
fuse = int(get_param('EKF2_AID_MASK'))
|
||||
if not fuse & (1 << 3):
|
||||
failure('vision position fusion is disabled, change EKF2_AID_MASK parameter')
|
||||
if not fuse & (1 << 4):
|
||||
failure('vision yaw fusion is disabled, change EKF2_AID_MASK parameter')
|
||||
|
||||
delay = get_param('EKF2_EV_DELAY')
|
||||
if delay != 0:
|
||||
failure('EKF2_EV_DELAY = %.2f, but it should be zero', delay)
|
||||
@@ -606,8 +632,14 @@ def check_global_position():
|
||||
rospy.wait_for_message('mavros/global_position/global', NavSatFix, timeout=0.8)
|
||||
except rospy.ROSException:
|
||||
info('no global position')
|
||||
if get_param('SYS_MC_EST_GROUP') == 2 and (get_param('EKF2_AID_MASK', 0) & (1 << 0)):
|
||||
failure('enabled GPS fusion may suppress vision position aiding')
|
||||
if get_param('SYS_MC_EST_GROUP') == 2:
|
||||
gps_ctrl = get_param('EKF2_GPS_CTRL', strict=False)
|
||||
if gps_ctrl is not None: # PX4 after v1.14
|
||||
if int(gps_ctrl) & (1 << 0):
|
||||
failure('GPS fusion enabled may suppress vision position aiding, change EKF2_GPS_CTRL')
|
||||
else: # PX4 before v1.14
|
||||
if int(get_param('EKF2_AID_MASK', 0)) & (1 << 0):
|
||||
failure('GPS fusion enabled may suppress vision position aiding, change EKF2_AID_MASK')
|
||||
|
||||
|
||||
@check('Optical flow')
|
||||
@@ -626,7 +658,7 @@ def check_optical_flow():
|
||||
failure('SENS_FLOW_ROT = %s, but it should be zero', rot)
|
||||
est = get_param('SYS_MC_EST_GROUP')
|
||||
if est == 1:
|
||||
fuse = get_param('LPE_FUSION')
|
||||
fuse = int(get_param('LPE_FUSION'))
|
||||
if not fuse & (1 << 1):
|
||||
failure('optical flow fusion is disabled, change LPE_FUSION parameter')
|
||||
if not fuse & (1 << 1):
|
||||
@@ -640,9 +672,14 @@ def check_optical_flow():
|
||||
get_paramf('LPE_FLW_R', 4),
|
||||
get_paramf('LPE_FLW_RR', 4))
|
||||
elif est == 2:
|
||||
fuse = get_param('EKF2_AID_MASK', 0)
|
||||
if not fuse & (1 << 1):
|
||||
failure('optical flow fusion is disabled, change EKF2_AID_MASK parameter')
|
||||
of_ctrl = get_param('EKF2_OF_CTRL', strict=False)
|
||||
if of_ctrl is not None: # PX4 after v1.14
|
||||
if of_ctrl == 0:
|
||||
failure('optical flow fusion is disabled, change EKF2_OF_CTRL')
|
||||
else: # PX4 before v1.14
|
||||
fuse = int(get_param('EKF2_AID_MASK', 0))
|
||||
if not fuse & (1 << 1):
|
||||
failure('optical flow fusion is disabled, change EKF2_AID_MASK parameter')
|
||||
delay = get_param('EKF2_OF_DELAY', 0)
|
||||
if delay != 0:
|
||||
failure('EKF2_OF_DELAY = %.2f, but it should be zero', delay)
|
||||
@@ -684,23 +721,26 @@ def check_rangefinder():
|
||||
|
||||
est = get_param('SYS_MC_EST_GROUP')
|
||||
if est == 1:
|
||||
fuse = get_param('LPE_FUSION', 0)
|
||||
fuse = int(get_param('LPE_FUSION', 0))
|
||||
if not fuse & (1 << 5):
|
||||
info('"pub agl as lpos down" in LPE_FUSION is disabled, NOT operating over flat surface')
|
||||
else:
|
||||
info('"pub agl as lpos down" in LPE_FUSION is enabled, operating over flat surface')
|
||||
|
||||
elif est == 2:
|
||||
hgt = get_param('EKF2_HGT_MODE')
|
||||
hgt = get_param('EKF2_HGT_REF', strict=False)
|
||||
if hgt is None: # PX4 before v1.14
|
||||
hgt = get_param('EKF2_HGT_MODE')
|
||||
if hgt != 2:
|
||||
info('EKF2_HGT_MODE != Range sensor, NOT operating over flat surface')
|
||||
else:
|
||||
info('EKF2_HGT_MODE = Range sensor, operating over flat surface')
|
||||
aid = get_param('EKF2_RNG_AID')
|
||||
if aid != 1:
|
||||
info('EKF2_RNG_AID != 1, range sensor aiding disabled')
|
||||
else:
|
||||
info('EKF2_RNG_AID = 1, range sensor aiding enabled')
|
||||
aid = get_param('EKF2_RNG_AID', strict=False)
|
||||
if aid is not None: # PX4 before v1.14
|
||||
if aid != 1:
|
||||
info('EKF2_RNG_AID != 1, range sensor aiding disabled')
|
||||
else:
|
||||
info('EKF2_RNG_AID = 1, range sensor aiding enabled')
|
||||
|
||||
|
||||
@check('Boot duration')
|
||||
@@ -841,7 +881,7 @@ def check_network():
|
||||
if ros_hostname in parts:
|
||||
break
|
||||
else:
|
||||
failure('not found %s in /etc/hosts, ROS will malfunction if network interfaces are down, https://clover.coex.tech/hostname', ros_hostname)
|
||||
failure('not found %s in /etc/hosts, ROS will malfunction if network interfaces are down, https://clovercoex.tech/hostname', ros_hostname)
|
||||
|
||||
|
||||
@check('RPi health')
|
||||
|
||||
@@ -646,7 +646,7 @@ inline void checkState()
|
||||
throw std::runtime_error("State timeout, check mavros settings");
|
||||
|
||||
if (!state.connected)
|
||||
throw std::runtime_error("No connection to FCU, https://clover.coex.tech/connection");
|
||||
throw std::runtime_error("No connection to FCU, https://clovercoex.tech/connection");
|
||||
}
|
||||
|
||||
void publishState()
|
||||
|
||||
@@ -40,6 +40,16 @@
|
||||
<node pkg="topic_tools" name="main_camera_throttle" type="throttle" ns="main_camera"
|
||||
args="messages image_raw 5.0 image_raw_throttled" required="true"/>
|
||||
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera_nodelet_manager" args="manager" output="screen" required="true">
|
||||
<param name="num_worker_threads" value="2"/>
|
||||
</node>
|
||||
|
||||
<node pkg="nodelet" type="nodelet" name="rectify" args="load image_proc/rectify main_camera_nodelet_manager" required="true">
|
||||
<remap from="image_mono" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<remap from="image_rect" to="main_camera/image_rect"/>
|
||||
</node>
|
||||
|
||||
<param name="test_module" value="$(find clover)/test/basic.py"/>
|
||||
<test test-name="basic_test" pkg="ros_pytest" type="ros_pytest_runner"/>
|
||||
</launch>
|
||||
|
||||
@@ -1,17 +1,54 @@
|
||||
# PixHawk (px4fmu-v2), px4fmu-v3
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0011", ATTRS{product}=="PX4 FMU v2.x", SYMLINK+="px4fmu"
|
||||
# PixRacer (px4fmu-v4)
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0012", ATTRS{product}=="PX4 FMU v4.x", SYMLINK+="px4fmu"
|
||||
# px4fmu-v5
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0032", ATTRS{product}=="PX4 FMU v5.x", SYMLINK+="px4fmu"
|
||||
# auav
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0021", ATTRS{product}=="PX4 AUAV x2.1", SYMLINK+="px4fmu"
|
||||
# crazyflie
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0016", ATTRS{product}=="PX4 Crazyflie v2.0", SYMLINK+="px4fmu"
|
||||
# px4fmu-v4pro
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0013", ATTRS{product}=="PX4 FMU v4.x PRO", SYMLINK+="px4fmu"
|
||||
# Omnibus
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0001", ATTRS{product}=="PX4 OmnibusF4SD", SYMLINK+="px4fmu"
|
||||
# CUAV X7 Pro
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3163", ATTRS{idProduct}=="004c", ATTRS{product}=="PX4 CUAV X7Pro", SYMLINK+="px4fmu"
|
||||
# Source files: PX4-Autopilot/boards/**/nuttx-config/nsh/defconfig
|
||||
|
||||
# Additional info:
|
||||
# https://docs.px4.io/main/en/flight_controller/
|
||||
# https://github.com/mavlink/qgroundcontrol/blob/master/src/comm/USBBoardInfo.json
|
||||
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0001", ATTRS{product}=="PX4 GNF405", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0001", ATTRS{product}=="PX4 OmnibusF4SD", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0016", ATTRS{product}=="PX4 Crazyflie v2.0", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1FC9", ATTRS{idProduct}=="001c", ATTRS{product}=="PX4 FMUK66 v3.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1FC9", ATTRS{idProduct}=="001c", ATTRS{product}=="PX4 FMUK66 E", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1FC9", ATTRS{idProduct}=="001d", ATTRS{product}=="PX4 FMURT1062 v1.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0001", ATTRS{product}=="DiatoneMambaF405 MK2", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a32f", ATTRS{product}=="PX4 FMU ModalAI FCv1", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a330", ATTRS{product}=="PX4 FMU ModalAI FCv2", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0012", ATTRS{product}=="PX4 FMU UVify Core", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3162", ATTRS{idProduct}=="0050", ATTRS{product}=="PX4 KakuteH7", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3162", ATTRS{idProduct}=="0050", ATTRS{product}=="PX4 KakuteH7v2", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3162", ATTRS{idProduct}=="004b", ATTRS{product}=="PX4 DurandalV1", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0050", ATTRS{product}=="PX4 KakuteF7", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3162", ATTRS{idProduct}=="0050", ATTRS{product}=="PX4 KakuteH7Mini-nand", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3162", ATTRS{idProduct}=="004E", ATTRS{product}=="PX4 PIX32V5", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0061", ATTRS{product}=="PX4 ATL Mantis-EDU", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3163", ATTRS{idProduct}=="004c", ATTRS{product}=="PX4 CUAV Nora", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3163", ATTRS{idProduct}=="004c", ATTRS{product}=="PX4 CUAV X7Pro", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1B8C", ATTRS{idProduct}=="0036", ATTRS{product}=="MatekH743-mini", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1B8C", ATTRS{idProduct}=="0036", ATTRS{product}=="MatekH743", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="120A", ATTRS{idProduct}=="1004", ATTRS{product}=="Matekgnssm9nf4", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="1013", ATTRS{product}=="MatekH743", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="0037", ATTRS{product}=="PX4 FMU SmartAP AIRLink", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="2DAE", ATTRS{idProduct}=="1058", ATTRS{product}=="CubeOrange+", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="2DAE", ATTRS{idProduct}=="1012", ATTRS{product}=="CubeYellow", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="2DAE", ATTRS{idProduct}=="1016", ATTRS{product}=="CubeOrange", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3185", ATTRS{idProduct}=="0035", ATTRS{product}=="PX4 FMU v6X.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3185", ATTRS{idProduct}=="0038", ATTRS{product}=="PX4 FMU v6C.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3185", ATTRS{idProduct}=="0033", ATTRS{product}=="PX4 FMU v5X.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1B8C", ATTRS{idProduct}=="0036", ATTRS{product}=="PX4 FMU v6U.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0013", ATTRS{product}=="PX4 FMU v4.x PRO", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0011", ATTRS{product}=="PX4 FMU v2.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0012", ATTRS{product}=="PX4 FMU v4.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0032", ATTRS{product}=="PX4 FMU v5.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3162", ATTRS{idProduct}=="004b", ATTRS{product}=="PX4 SP RACING H7 EXTREME", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0030", ATTRS{product}=="MindPX FMU v2.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3185", ATTRS{idProduct}=="0039", ATTRS{product}=="ARK FMU v6X.x", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0016", ATTRS{product}=="PX4 FreeFly RTK GPS", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="1024", ATTRS{product}=="mRoControlZeroH7 OEM", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="1017", ATTRS{product}=="mRoPixracerPro", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="1023", ATTRS{product}=="mRoControlZeroH7", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="008D", ATTRS{product}=="mRoControlZeroF7", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0021", ATTRS{product}=="PX4 AUAV X2.1", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="1022", ATTRS{product}=="mRoControlZero Classic", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0088", ATTRS{product}=="mRo x2.1-777", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="35a7", ATTRS{idProduct}=="0002", ATTRS{product}=="FCC-R1", SYMLINK+="px4fmu"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="35a7", ATTRS{idProduct}=="0001", ATTRS{product}=="FCC-K1", SYMLINK+="px4fmu"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<h1>Clover Drone Kit Tools</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="docs">View documentation</a> (snapshot of <a href="https://clover.coex.tech">clover.coex.tech</a>)</li>
|
||||
<li><a href="docs">View documentation</a> (snapshot of <a href="https://clovercoex.tech">clovercoex.tech</a>)</li>
|
||||
<li><a href="topics.html">View topics</a></li>
|
||||
<li><a href="" id="wvs">View image topics</a> (<code>web_video_server</code>)</li>
|
||||
<li><a href="" id="butterfly">Open web terminal</a> (<code>Butterfly</code>)</li>
|
||||
|
||||
236
clover/www/js/json-to-pretty-yaml.js
vendored
236
clover/www/js/json-to-pretty-yaml.js
vendored
@@ -1,236 +0,0 @@
|
||||
// Browserified https://www.npmjs.com/package/json-to-pretty-yaml module
|
||||
|
||||
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var typeOf = require('remedial').typeOf;
|
||||
var trimWhitespace = require('remove-trailing-spaces');
|
||||
|
||||
function stringify(data) {
|
||||
var handlers, indentLevel = '';
|
||||
|
||||
handlers = {
|
||||
"undefined": function() {
|
||||
// objects will not have `undefined` converted to `null`
|
||||
// as this may have unintended consequences
|
||||
// For arrays, however, this behavior seems appropriate
|
||||
return 'null';
|
||||
},
|
||||
"null": function() {
|
||||
return 'null';
|
||||
},
|
||||
"number": function(x) {
|
||||
return x;
|
||||
},
|
||||
"boolean": function(x) {
|
||||
return x ? 'true' : 'false';
|
||||
},
|
||||
"string": function(x) {
|
||||
// to avoid the string "true" being confused with the
|
||||
// the literal `true`, we always wrap strings in quotes
|
||||
return JSON.stringify(x);
|
||||
},
|
||||
"array": function(x) {
|
||||
var output = '';
|
||||
|
||||
if (0 === x.length) {
|
||||
output += '[]';
|
||||
return output;
|
||||
}
|
||||
|
||||
indentLevel = indentLevel.replace(/$/, ' ');
|
||||
x.forEach(function(y, i) {
|
||||
// TODO how should `undefined` be handled?
|
||||
var handler = handlers[typeOf(y)];
|
||||
|
||||
if (!handler) {
|
||||
throw new Error('what the crap: ' + typeOf(y));
|
||||
}
|
||||
|
||||
output += '\n' + indentLevel + '- ' + handler(y, true);
|
||||
|
||||
});
|
||||
indentLevel = indentLevel.replace(/ /, '');
|
||||
|
||||
return output;
|
||||
},
|
||||
"object": function(x, inArray, rootNode) {
|
||||
var output = '';
|
||||
|
||||
if (0 === Object.keys(x).length) {
|
||||
output += '{}';
|
||||
return output;
|
||||
}
|
||||
|
||||
if (!rootNode) {
|
||||
indentLevel = indentLevel.replace(/$/, ' ');
|
||||
}
|
||||
|
||||
Object.keys(x).forEach(function(k, i) {
|
||||
var val = x[k],
|
||||
handler = handlers[typeOf(val)];
|
||||
|
||||
if ('undefined' === typeof val) {
|
||||
// the user should do
|
||||
// delete obj.key
|
||||
// and not
|
||||
// obj.key = undefined
|
||||
// but we'll error on the side of caution
|
||||
return;
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
throw new Error('what the crap: ' + typeOf(val));
|
||||
}
|
||||
|
||||
if (!(inArray && i === 0)) {
|
||||
output += '\n' + indentLevel;
|
||||
}
|
||||
|
||||
output += k + ': ' + handler(val);
|
||||
});
|
||||
indentLevel = indentLevel.replace(/ /, '');
|
||||
|
||||
return output;
|
||||
},
|
||||
"function": function() {
|
||||
// TODO this should throw or otherwise be ignored
|
||||
return '[object Function]';
|
||||
}
|
||||
};
|
||||
return trimWhitespace(handlers[typeOf(data)](data, true, true) + '\n');
|
||||
|
||||
}
|
||||
|
||||
window.yamlStringify = stringify;
|
||||
module.exports.stringify = stringify;
|
||||
}());
|
||||
|
||||
},{"remedial":2,"remove-trailing-spaces":3}],2:[function(require,module,exports){
|
||||
/*jslint onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true */
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var global = Function('return this')()
|
||||
, classes = "Boolean Number String Function Array Date RegExp Object".split(" ")
|
||||
, i
|
||||
, name
|
||||
, class2type = {}
|
||||
;
|
||||
|
||||
for (i in classes) {
|
||||
if (classes.hasOwnProperty(i)) {
|
||||
name = classes[i];
|
||||
class2type["[object " + name + "]"] = name.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
function typeOf(obj) {
|
||||
return (null === obj || undefined === obj) ? String(obj) : class2type[Object.prototype.toString.call(obj)] || "object";
|
||||
}
|
||||
|
||||
function isEmpty(o) {
|
||||
var i, v;
|
||||
if (typeOf(o) === 'object') {
|
||||
for (i in o) { // fails jslint
|
||||
v = o[i];
|
||||
if (v !== undefined && typeOf(v) !== 'function') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!String.prototype.entityify) {
|
||||
String.prototype.entityify = function () {
|
||||
return this.replace(/&/g, "&").replace(/</g,
|
||||
"<").replace(/>/g, ">");
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.quote) {
|
||||
String.prototype.quote = function () {
|
||||
var c, i, l = this.length, o = '"';
|
||||
for (i = 0; i < l; i += 1) {
|
||||
c = this.charAt(i);
|
||||
if (c >= ' ') {
|
||||
if (c === '\\' || c === '"') {
|
||||
o += '\\';
|
||||
}
|
||||
o += c;
|
||||
} else {
|
||||
switch (c) {
|
||||
case '\b':
|
||||
o += '\\b';
|
||||
break;
|
||||
case '\f':
|
||||
o += '\\f';
|
||||
break;
|
||||
case '\n':
|
||||
o += '\\n';
|
||||
break;
|
||||
case '\r':
|
||||
o += '\\r';
|
||||
break;
|
||||
case '\t':
|
||||
o += '\\t';
|
||||
break;
|
||||
default:
|
||||
c = c.charCodeAt();
|
||||
o += '\\u00' + Math.floor(c / 16).toString(16) +
|
||||
(c % 16).toString(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
return o + '"';
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.supplant) {
|
||||
String.prototype.supplant = function (o) {
|
||||
return this.replace(/{([^{}]*)}/g,
|
||||
function (a, b) {
|
||||
var r = o[b];
|
||||
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.trim) {
|
||||
String.prototype.trim = function () {
|
||||
return this.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, "$1");
|
||||
};
|
||||
}
|
||||
|
||||
// CommonJS / npm / Ender.JS
|
||||
module.exports = {
|
||||
typeOf: typeOf,
|
||||
isEmpty: isEmpty
|
||||
};
|
||||
global.typeOf = global.typeOf || typeOf;
|
||||
global.isEmpty = global.isEmpty || isEmpty;
|
||||
}());
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* removeTrailingSpaces
|
||||
* Remove the trailing spaces from a string.
|
||||
*
|
||||
* @name removeTrailingSpaces
|
||||
* @function
|
||||
* @param {String} input The input string.
|
||||
* @returns {String} The output string.
|
||||
*/
|
||||
|
||||
module.exports = function removeTrailingSpaces(input) {
|
||||
// TODO If possible, use a regex
|
||||
return input.split("\n").map(function (x) {
|
||||
return x.trimRight();
|
||||
}).join("\n");
|
||||
};
|
||||
},{}]},{},[1]);
|
||||
@@ -64,8 +64,11 @@ function viewTopic(topic) {
|
||||
}
|
||||
}
|
||||
|
||||
let txt = `<div class=counter>${counter} received</div>${yamlStringify(msg)}`; // JSON.stringify(msg, null, 4);
|
||||
topicMessage.innerHTML = txt;
|
||||
let width = Number(params.width) || 100;
|
||||
let indent = Number(params.indent) || 2;
|
||||
let txt = YAML.stringify(msg, { lineWidth: width, indent: indent });
|
||||
let html = `<div class=counter>${counter} received</div>${txt}`; // JSON.stringify(msg, null, 4);
|
||||
topicMessage.innerHTML = html;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
19
clover/www/js/yaml.js
Normal file
19
clover/www/js/yaml.js
Normal file
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
<script src="js/roslib.js"></script>
|
||||
<link rel="icon" href="data:,"> <!-- make chrome don't request icon -->
|
||||
<script type="module" src="js/topics.js"></script>
|
||||
<script src="js/json-to-pretty-yaml.js"></script>
|
||||
<script src="js/yaml.js"></script>
|
||||
<style>
|
||||
#topics { line-height: 1.2em; }
|
||||
#topic-view {
|
||||
|
||||
@@ -4,7 +4,7 @@ Blockly programming support for Clover.
|
||||
|
||||
<img src="screenshot.png" width=700>
|
||||
|
||||
See user documentation at the [main Clover documentation site](https://clover.coex.tech/en/blocks.html).
|
||||
See user documentation at the [main Clover documentation site](https://clovercoex.tech/en/blocks.html).
|
||||
|
||||
Internal package documentation is given below.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>clover_blocks</name>
|
||||
<version>0.24.0</version>
|
||||
<version>0.25.0</version>
|
||||
<description>Blockly programming support for Clover</description>
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
<license>MIT</license>
|
||||
|
||||
@@ -166,7 +166,7 @@ def load(req):
|
||||
return {'names': [], 'programs': [], 'message': str(e)}
|
||||
|
||||
|
||||
name_regexp = re.compile(r'^[a-zA-Z-_.]{0,20}$')
|
||||
name_regexp = re.compile(r'^[a-zA-Z1-9-_.]{0,30}$')
|
||||
|
||||
def store(req):
|
||||
if not name_regexp.match(req.name):
|
||||
|
||||
@@ -12,7 +12,7 @@ const COLOR_FLIGHT = 293;
|
||||
const COLOR_STATE = 36;
|
||||
const COLOR_LED = 143;
|
||||
const COLOR_GPIO = 200;
|
||||
const DOCS_URL = 'https://clover.coex.tech/en/blocks.html';
|
||||
const DOCS_URL = 'https://clovercoex.tech/en/blocks.html';
|
||||
|
||||
var frameIds = [["body", "BODY"], ["markers map", "ARUCO_MAP"], ["marker", "ARUCO"], ["last navigate target", "NAVIGATE_TARGET"], ["map", "MAP"]];
|
||||
var frameIdsWithTerrain = frameIds.concat([["terrain", "TERRAIN"]]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<package format="2">
|
||||
<name>clover_description</name>
|
||||
<version>0.24.0</version>
|
||||
<version>0.25.0</version>
|
||||
<description>The clover_description package provides URDF models of the Clover series of quadcopters.</description>
|
||||
|
||||
<maintainer email="sfalexrog@gmail.com">Alexey Rogachevskiy</maintainer>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<package format="3">
|
||||
<name>clover_simulation</name>
|
||||
<version>0.24.0</version>
|
||||
<version>0.25.0</version>
|
||||
<description>The clover_simulation package provides worlds and launch files for Gazebo.</description>
|
||||
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
|
||||
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 |
BIN
docs/assets/stl/grip_left.stl
Normal file
BIN
docs/assets/stl/grip_left.stl
Normal file
Binary file not shown.
BIN
docs/assets/stl/grip_right.stl
Normal file
BIN
docs/assets/stl/grip_right.stl
Normal file
Binary file not shown.
@@ -12,4 +12,4 @@ If you have studied the documentation but have not found an answer to your quest
|
||||
|
||||
We also have a chat for programmers coding for PX4, autonomous navigation indoors, and drone swarms: [@DroneCode](tg://resolve?domain=DroneCode).
|
||||
|
||||
You can download [PDF-version](https://clover.coex.tech/clover_en.pdf) of this documentation.
|
||||
You can download [PDF-version](https://clovercoex.tech/clover_en.pdf) of this documentation.
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Main documentation: http://wiki.ros.org/roslaunch.
|
||||
|
||||
The list of nodes / programs declared for running is specified in file `/home/pi/catkin_ws/src/clover/clover/launch/clover.launch`.
|
||||
|
||||
You can add your own node to the list of automatically launched ones. To do this, place your executable file (e.g. `my_program.py`) into folder `/home/pi/catkin_ws/src/clover/clover/src`. Then add the start of your node to `clover.launch`, for example:
|
||||
You can add your own node to the list of automatically launched ones. To do this, place your executable file (e.g. `my_program.py`) into folder `/home/pi/catkin_ws/src/clover/clover`. Then add the start of your node to `clover.launch`, for example:
|
||||
|
||||
```xml
|
||||
<node name="my_program" pkg="clover" type="my_program.py" output="screen"/>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -91,7 +91,7 @@ Prepare your article and send it as a pull request to the [Clover repository](ht
|
||||
<img src="../assets/github-pull-request-create.png" alt="GitHub Create Pull">
|
||||
|
||||
10. Wait for the review, be ready to make changes if needed.
|
||||
11. Look at your new and useful article at https://clover.coex.tech !
|
||||
11. Look at your new and useful article at https://clovercoex.tech !
|
||||
|
||||
## Easy way
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ See all points by criteria in the [full table](https://docs.google.com/spreadshe
|
||||
Teams are welcome to dive into the development of the following company cases:
|
||||
|
||||
1. Develop the Pixhawk FMUv6U flight controller board with the dimensions 55x40 mm and the compatibility of a Raspberry Pi CM 4 installation.
|
||||
2. Cloud platform for the [Clover simulator](https://clover.coex.tech/ru/simulation.html) similar as to/based on [ROS Development Studio](https://app.theconstructsim.com/).
|
||||
2. Cloud platform for the [Clover simulator](https://clovercoex.tech/ru/simulation.html) similar as to/based on [ROS Development Studio](https://app.theconstructsim.com/).
|
||||
|
||||
The list of cases may be expanded in future.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ The main goal of the contest is aerial robotics popularization and community de
|
||||
### Lecture requirements
|
||||
|
||||
* The topic of the lecture is of free choice. Programmable quadcopter kit COEX Clover 4 and/or The Clover simulation environment should be used as the main tool in the lecture.
|
||||
> **Note** *The version of COEX Clover is not earlier than [version 4](https://clover.coex.tech/en/assemble_4.html). The virtual machine image is not earlier than [version 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
> **Note** *The version of COEX Clover is not earlier than [version 4](https://clovercoex.tech/en/assemble_4.html). The virtual machine image is not earlier than [version 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
* The video is uploaded on YouTube or another public platform and is public accessible.
|
||||
* The language of the lecture is any. The video contains subtitles in English in case the language is made neither of English nor Russian.
|
||||
* The duration of the lecture is limited from 15 min. to 3 hours.
|
||||
@@ -47,7 +47,7 @@ The main goal of the contest is aerial robotics popularization and community de
|
||||
### Lesson requirements
|
||||
|
||||
* Programmable quadcopter kit COEX Clover 4 should be used as the main tool for the lesson.
|
||||
> **Note** *The version of COEX Clover is not earlier than [version 4](https://clover.coex.tech/en/assemble_4.html).
|
||||
> **Note** *The version of COEX Clover is not earlier than [version 4](https://clovercoex.tech/en/assemble_4.html).
|
||||
* Integration of the quadcopter into any of the general education disciplines (physics, mathematics, computer science, etc.).
|
||||
* Practical use of the main tool in the lesson.
|
||||
* Grade - no restrictions (primary, high school).
|
||||
@@ -88,7 +88,7 @@ The course is evaluated according to a separate, publicly available lesson submi
|
||||
|
||||
* The course is related to the direction of Aerial robotics.
|
||||
* Programmable quadcopter kit COEX Clover 4 and/or The Clover simulation environment should be used as the main tool in the course;
|
||||
> **Note** *The version of COEX Clover is not earlier than [version 4](https://clover.coex.tech/en/assemble_4.html). The virtual machine image is not earlier than [version 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
> **Note** *The version of COEX Clover is not earlier than [version 4](https://clovercoex.tech/en/assemble_4.html). The virtual machine image is not earlier than [version 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
* The course is located on a public platform (e.g., Coursera).
|
||||
* The course can be either paid or free of charge. One public lesson from the course is submitted for the competition;
|
||||
* The lesson submitted for the contest should be publicly accessible.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -9,6 +9,7 @@ Main frames in the `clover` package:
|
||||
* `base_link` is rigidly bound to the drone. It is shown by the simplified drone model on the image above;
|
||||
* `body` is bound to the drone, but its Z axis points up regardless of the drone's pitch and roll. It is shown by the red, blue and green lines in the illustration;
|
||||
* <a name="navigate_target"></a>`navigate_target` is bound to the current navigation target (as set by the [navigate](simple_offboard.md#navigate) service);
|
||||
* `terrain` is bound to the floor at the current drone position (see the [set_altitude](simple_offboard.md#set_altitude) service);
|
||||
* `setpoint` is current position setpoint;
|
||||
* `main_camera_optical` is the coordinate system, [linked to the main camera](camera_setup.md#frame);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Before you test it you need to install on your laptop:
|
||||
- Install Nodejs from [here](https://nodejs.org/en/download/). For [Ubuntu installation](https://tecadmin.net/install-latest-nodejs-npm-on-ubuntu/)
|
||||
- Install Yarn package manager from [here](https://yarnpkg.com/lang/en/docs/install/). [Usual problem](https://github.com/yarnpkg/yarn/issues/3189) while installing and using yarn with Ubuntu.
|
||||
- Have an experience in manual control on the drone in case of any weird behavior happen.
|
||||
- Worked before with COEX drones, if this is your first time to work with COEX drones check [this](https://clover.coex.tech/en/).
|
||||
- Worked before with COEX drones, if this is your first time to work with COEX drones check [this](https://clovercoex.tech/en/).
|
||||
|
||||
and you are ready to build and use the required codes.
|
||||
|
||||
@@ -145,7 +145,7 @@ Animation is created by [this](https://justsketchme.web.app/)
|
||||
## References
|
||||
|
||||
- [Human pose estimation guide](https://blog.nanonets.com/human-pose-estimation-2d-guide/)
|
||||
- [Clover drones tutorials](https://clover.coex.tech/en/)
|
||||
- [Clover drones tutorials](https://clovercoex.tech/en/)
|
||||
- [Posenet GitHub repo](https://github.com/tensorflow/tfjs-models/tree/master/posenet)
|
||||
- [Posenet meduim article](https://medium.com/tensorflow/real-time-human-pose-estimation-in-the-browser-with-tensorflow-js-7dd0bc881cd5)
|
||||
- [Tensorflow.js demos](https://www.tensorflow.org/js/demos)
|
||||
|
||||
@@ -198,6 +198,15 @@ This page contains models and drawings of some of the drone parts. They can be u
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### 3D print
|
||||
|
||||
#### Mechanical gripper
|
||||
|
||||
* **Left claw**: [`grip_left.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/stl/grip_left.stl).
|
||||
* **Right claw**: [`grip_right.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/stl/grip_right.stl).
|
||||
|
||||
Material: SBS Glass. Infill: 100%. Quantity: 1 pcs.
|
||||
|
||||
## Clover 4
|
||||
|
||||
### 3D print
|
||||
|
||||
@@ -166,7 +166,7 @@ network={
|
||||
}
|
||||
```
|
||||
|
||||
Inside the config file, general `wpa_supplicant` settings, and the settings for the adapter configuration are specified. The configuration file also contains `network` section with the basic settings of the Wi-Fi network, such as network SSID, password, adapter operating mode. There may be several `network` sections, but only the first valid one is used. For example, if the first section contains a connection to an unavailable network, the adapter will be configured according to a next valid section, if there is one. Read more about the syntax of `wpa_supplicant.conf` [TODO WIKI].
|
||||
Inside the config file, general `wpa_supplicant` settings, and the settings for the adapter configuration are specified. The configuration file also contains `network` section with the basic settings of the Wi-Fi network, such as network SSID, password, adapter operating mode. There may be several `network` sections, but only the first valid one is used. For example, if the first section contains a connection to an unavailable network, the adapter will be configured according to a next valid section, if there is one. Read more about the syntax of `wpa_supplicant.conf` in the [Debian manual page](https://manpages.debian.org/buster/wpasupplicant/wpa_supplicant.conf.5.en.html).
|
||||
|
||||
#### wpa_passphrase
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ The list of team members:
|
||||
|
||||
<img src="https://github.com/den250400/potential-fields-obstacle-avoidance/raw/main/assets/avoidance_sim_demo.gif" class="center"/>
|
||||
|
||||
[This](https://github.com/den250400/potential-fields-obstacle-avoidance) repository contains obstacle avoidance system for quadcopters with Raspberry Pi 4 onboard computer. The code in this repository is designed to work with [Clover Raspberry Pi image](https://clover.coex.tech/en/image.html) and [special PX4-based firmware](https://clover.coex.tech/en/firmware.html) modified for easier communication with Raspberry Pi.
|
||||
[This](https://github.com/den250400/potential-fields-obstacle-avoidance) repository contains obstacle avoidance system for quadcopters with Raspberry Pi 4 onboard computer. The code in this repository is designed to work with [Clover Raspberry Pi image](https://clovercoex.tech/en/image.html) and [special PX4-based firmware](https://clovercoex.tech/en/firmware.html) modified for easier communication with Raspberry Pi.
|
||||
|
||||
Artificial potential fields method is based on considering quadcopter, obstacles and target point as electric-charged points. Quadcopter and obstacles have positive charge, and target point is assigned with negative charge. This results in quadcopter "attracting" itself to the target point, while being repelled by the same-signed charges of obstacles. Using this analogy, you can compute a safe, collision-free trajectory, which can be executed by the vehicle.
|
||||
|
||||
@@ -26,7 +26,7 @@ It's obvious that you need some sort of geometrical information about the surrou
|
||||
|
||||
This guide is intended to be used on Ubuntu 20.04. Python version is 3.8.10, but it's very likely that it will work on other versions like 3.7, 3.9, 3.10 without any changes.
|
||||
|
||||
1. Install the [Clover simulator](https://clover.coex.tech/en/simulation.html).
|
||||
1. Install the [Clover simulator](https://clovercoex.tech/en/simulation.html).
|
||||
2. Install [realsense_gazebo_plugin](https://github.com/issaiass/realsense_gazebo_plugin) and [realsense2_description](https://github.com/issaiass/realsense2_description):
|
||||
|
||||
```bash
|
||||
|
||||
@@ -66,11 +66,11 @@ Flying forward for 1m:
|
||||
navigate(x=1.5, frame_id='body')
|
||||
```
|
||||
|
||||
[Navigation using ArUco-markers](aruco_marker.md) and [using VPE] are available when using Optical Flow.
|
||||
[Navigation using ArUco-markers](aruco_marker.md) and [using VPE](aruco_map.md) are available when using Optical Flow.
|
||||
|
||||
## Additional settings
|
||||
|
||||
<!-- TODO: статья по пидам -->
|
||||
For additional background on PID tuning, see the [PID tuning guide](calibratePID.md).
|
||||
|
||||
If the copter has an unstable position, try to increase the *P* coefficient of speed PID controller - parameters are `MPC_XY_VEL_P` and `MPC_Z_VEL_P`.
|
||||
|
||||
|
||||
@@ -39,17 +39,28 @@ In case of using EKF2 (official firmware):
|
||||
|
||||
|Parameter|Value|Comment|
|
||||
|-|-|-|
|
||||
|`EKF2_AID_MASK`|26|Checkboxes: *flow* + *vision position* + *vision yaw*.<br>Details: [Optical Flow](optical_flow.md), [ArUco markers](aruco_map.md), [GPS](gps.md).|
|
||||
|`EKF2_AID_MASK`\*|26|Checkboxes: *flow* + *vision position* + *vision yaw*.<br>Details: [Optical Flow](optical_flow.md), [ArUco markers](aruco_map.md), [GPS](gps.md).|
|
||||
|`EKF2_OF_DELAY`|0||
|
||||
|`EKF2_OF_QMIN`|10||
|
||||
|`EKF2_OF_N_MIN`|0.05||
|
||||
|`EKF2_OF_N_MAX`|0.2||
|
||||
|`EKF2_HGT_MODE`|3 (*Vision*)|If the [rangefinder](laser.md) is present and flying over horizontal floor – 2 (*Range sensor*)|
|
||||
|`EKF2_EVA_NOISE`|0.1||
|
||||
|`EKF2_HGT_MODE`\*|3 (*Vision*)|If the [rangefinder](laser.md) is present and flying over horizontal floor – 2 (*Range sensor*)|
|
||||
|`EKF2_EVA_NOISE`|0.1 rad or 5 deg||
|
||||
|`EKF2_EVP_NOISE`|0.1||
|
||||
|`EKF2_EV_DELAY`|0||
|
||||
|`EKF2_MAG_TYPE`|5 (*None*)|Disabling usage of the magnetometer (when navigating indoor)|
|
||||
|
||||
\* — starting from PX4 version 1.14, the parameters marked with an asterisk are replaced with the following:
|
||||
|
||||
|Parameter|Value|Comment|
|
||||
|-|-|-|
|
||||
|`EKF2_EV_CTRL`|11|Checkboxes: *Horizontal position* + *Vertical position* + *Yaw*|
|
||||
|`EKF2_GPS_CTRL`|0|All checkboxes are disabled|
|
||||
|`EKF2_BARO_CTRL`|0 (*Disabled*)|Barometer is disabled|
|
||||
|`EKF2_OF_CTRL`|1 (*Enabled*)|Optical flow is enabled|
|
||||
|`EKF2_HGT_REF`|3 (*Vision*)|If the [rangefinder](laser.md) is present and flying over horizontal floor – 2 (*Range sensor*)|
|
||||
|`EKF2_RNG_CTRL`|2 (*Enabled*)|Range sensor is enabled|
|
||||
|
||||
<!-- markdownlint-enable MD031 -->
|
||||
|
||||
> **Info** See also: list of default parameters of the [Clover simulator](simulation.md): https://github.com/CopterExpress/clover/blob/master/clover_simulation/airframes/4500_clover.
|
||||
|
||||
@@ -51,6 +51,6 @@ The sticks on the screen of the application work just like real sticks. To arm t
|
||||
Malfunctions
|
||||
---
|
||||
|
||||
* If the interface of the transmitter displays a surely incorrect voltage (e.g., > 5 V), check that the value of PX4 parameter `BAT_N_CELLS` matches the actual number of battery cells. If the displayed voltage is still incorrect, calibrate the battery (TODO: link).
|
||||
* If the interface of the transmitter displays a surely incorrect voltage (e.g., > 5 V), check that the value of PX4 parameter `BAT_N_CELLS` matches the actual number of battery cells. If the displayed voltage is still incorrect, calibrate the [power sensor](power.md).
|
||||
|
||||
* If instead of mode PX4, text "DISCONNECTED FROM FCU" is displayed, check [Raspberry Pi connection to Pixhawk](connection.md).
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ Press the *Save* button to save the changed value to the flight controller. Chan
|
||||
* `MC_ROLLRATE_I` = 0.050
|
||||
* `MC_ROLLRATE_D` = 0.0025
|
||||
|
||||
> **Hint** Note that you should fine-tune the PID parameters for each drone individually. <!-- TODO: add PID article link -->
|
||||
> **Hint** Note that you should fine-tune the PID parameters for each drone individually. See the [PID tuning guide](calibratePID.md).
|
||||
|
||||
#### Circuit breaker parameters
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Autonomous flight
|
||||
|
||||
> **Note** The following applies to the [image version **0.24**](https://github.com/CopterExpress/clover/releases/tag/v0.24), which is not yet released. Older documentation is still available for [for version **0.23**](https://github.com/CopterExpress/clover/blob/f78a03ec8943b596d5a99b893188a159d5319888/docs/en/simple_offboard.md).
|
||||
> **Note** The following applies to [image versions](image.md) **0.24** and up. Older documentation is available for [for version **0.23**](https://github.com/CopterExpress/clover/blob/v0.23/docs/en/simple_offboard.md).
|
||||
|
||||
The `simple_offboard` module of the `clover` package is intended for simplified programming of the autonomous drone flight (`OFFBOARD` [flight mode](modes.md)). It allows setting the desired flight tasks, and automatically transforms [coordinates between frames](frames.md).
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ The recommended virtual machine hypervisor is [UTM app](https://mac.getutm.app/)
|
||||
|
||||
<img src="../assets/simulation_ubuntu_account.png" width=400 class="center zoom">
|
||||
|
||||
6. Finish the installation and run the system.
|
||||
6. Finish the installation and run the system (you need to eject the virtual CD or choose *Boot from next volume* in the boot menu).
|
||||
7. Install the simulation using the [native setup manual](simulation_native.md).
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
@@ -72,7 +72,11 @@ ln -s ~/PX4-Autopilot/Tools/sitl_gazebo ~/catkin_ws/src/
|
||||
ln -s ~/PX4-Autopilot/mavlink ~/catkin_ws/src/
|
||||
```
|
||||
|
||||
> **Hint** You may use more recent PX4 version, but there would be more risk of something would not be working.
|
||||
> **Hint** You may use more recent PX4 version, but something may not work as expected in that case.
|
||||
|
||||
<!-- -->
|
||||
|
||||
> **Note** If clone fails with network error (`fatal: fetch-pack: invalid index-pack output`), set HTTP version 1.1 using `git config --global http.version HTTP/1.1` command (don't forget to return it back after clone using `git config --global http.version HTTP/2`). Alternative solution is cloning the repository and submodules through SSH using `git config --global url."git@github.com:".insteadOf https://github.com/` command (requires setting up valid SSH key in GitHub profile settings).
|
||||
|
||||
## Install PX4 prerequisites
|
||||
|
||||
@@ -115,10 +119,10 @@ Build your workspace:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws
|
||||
catkin_make
|
||||
catkin_make -j1
|
||||
```
|
||||
|
||||
> **Note** If building fails with RAM issues (`c++: fatal error: Killed signal terminated program cc1plus`), reduce the number of parallel jobs using `-j` key. For example, to use only two parallel jobs use `catkin_make -j2` command.
|
||||
> **Note** The `-j1` flag means that the build will not use parallel processes, as building with parallel processes on a virtual machine may run out of memory. If you have enough memory, you may not use this flag.
|
||||
|
||||
## Run the simulator
|
||||
|
||||
|
||||
@@ -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'
|
||||
```
|
||||
@@ -62,7 +62,7 @@ Swarm in Blocks is a CopterHack 2022 project. It's a high-level interface based
|
||||
<img width="500" src="https://raw.githubusercontent.com/Grupo-SEMEAR-USP/swarm_in_blocks/master/assets/intro/ring.gif" />
|
||||
</p>
|
||||
|
||||
For more information on our project from last year, see our final article in [Swarm in Blocks 2022](https://clover.coex.tech/en/swarm_in_blocks.html). In addition, we also recommend watching our final video from last year, [Swarm in Blocks 2022 - Final Video](https://www.youtube.com/watch?v=5C-1rRnyiE8).
|
||||
For more information on our project from last year, see our final article in [Swarm in Blocks 2022](https://clovercoex.tech/en/swarm_in_blocks.html). In addition, we also recommend watching our final video from last year, [Swarm in Blocks 2022 - Final Video](https://www.youtube.com/watch?v=5C-1rRnyiE8).
|
||||
|
||||
Even with the huge facilities that the block platform offers, we realized that this was just the *tip of the iceberg* when it comes to deploying real swarms. Several other operational and conceptual problems in validating a real swarm still haunted the general public. With that, this year's project comes precisely with the purpose of **tackling the main problems in validating a Swarm in a simple and polished way**.
|
||||
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
|
||||
Чат по разработке самой платформы Клевера и образа для RPi: [@devclover](https://t.me/devclover).
|
||||
|
||||
Вы можете скачать [PDF-версию](https://clover.coex.tech/clover_ru.pdf) этой документации. The English version of this documentation [is available](../en/).
|
||||
Вы можете скачать [PDF-версию](https://clovercoex.tech/clover_ru.pdf) этой документации. The English version of this documentation [is available](../en/).
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
Разработка симулятора для Clover с возможностью создания workspace (окружения, позволяющие легко управлять и транспортировать файлы симулятора такие как: проекты, конфигурации, установленные пакеты).
|
||||
|
||||
- Простой, быстрый и производительный способ запуска симулятора.
|
||||
- Инструментарий для создания заданий (как на [IOR2020](https://clover.coex.tech/ru/innopolis_open_L22_AERO.html)).
|
||||
- Инструментарий для создания заданий (как на [IOR2020](https://clovercoex.tech/ru/innopolis_open_L22_AERO.html)).
|
||||
- Изоляция Gazebo и чекера заданий от Workspace пользователя и clover.
|
||||
- Worker для проверки задач со степика.
|
||||
- Возможность запуска несколько коптеров каждый из которых имеет свой контейнер.
|
||||
|
||||
@@ -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 метр:
|
||||
|
||||
@@ -146,7 +146,7 @@ navigate(frame_id='aruco_5', x=0, y=0, z=1)
|
||||
|
||||
## Дополнительные настройки
|
||||
|
||||
<!-- TODO: статья по пидам -->
|
||||
Дополнительную информацию по настройке PID см. в статье [Настройка коэффициентов PID](calibratePID.md).
|
||||
|
||||
Если коптер нестабильно удерживает позицию по VPE, попробуйте увеличить коэффициенты *P* PID-регулятора по скорости – параметры `MPC_XY_VEL_P` и `MPC_Z_VEL_P`.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ roslaunch
|
||||
|
||||
Список объявленных для запуска нод / программ указывается в файле `/home/pi/catkin_ws/src/clover/clover/launch/clover.launch`.
|
||||
|
||||
Вы можете добавить собственную ноду в список автозапускаемых. Для этого разместите ваш запускаемый файл (например, `my_program.py`) в каталог `/home/pi/catkin_ws/src/clover/clover/src`. Затем добавьте запуск вашей ноды в `clover.launch`, например:
|
||||
Вы можете добавить собственную ноду в список автозапускаемых. Для этого разместите ваш запускаемый файл (например, `my_program.py`) в каталог `/home/pi/catkin_ws/src/clover/clover`. Затем добавьте запуск вашей ноды в `clover.launch`, например:
|
||||
|
||||
```xml
|
||||
<node name="my_program" pkg="clover" type="my_program.py" output="screen"/>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#### Камера направлена вверх, шлейф вперёд
|
||||
|
||||
```xml
|
||||
<arg name="direction_z" default="down"/>
|
||||
<arg name="direction_z" default="up"/>
|
||||
<arg name="direction_y" default="forward"/>
|
||||
```
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<img src="../assets/github-pull-request-create.png" alt="GitHub Create Pull">
|
||||
|
||||
10. Дождитесь комментариев на свою статью, сделайте правки, если потребуется.
|
||||
11. Порадуйтесь своей новой полезной статье, опубликованной на https://clover.coex.tech !
|
||||
11. Порадуйтесь своей новой полезной статье, опубликованной на https://clovercoex.tech !
|
||||
|
||||
## Простой способ
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ CopterHack 2022 — это международный конкурс по ра
|
||||
Команды приглашаются принять участие в работе над следующими кейсами компании:
|
||||
|
||||
1. Разработка платы полетного контроллера Pixhawk FMUv6U размером 55*40 мм и возможностью установки Raspberry Pi CM4.
|
||||
2. Облачная платформа для [симулятора Клевера](https://clover.coex.tech/ru/simulation.html) по аналогии или на основе [ROS Development Studio](https://app.theconstructsim.com/).
|
||||
2. Облачная платформа для [симулятора Клевера](https://clovercoex.tech/ru/simulation.html) по аналогии или на основе [ROS Development Studio](https://app.theconstructsim.com/).
|
||||
|
||||
Список кейсов может быть расширен.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
* Тематика лекции - открытая, на выбор участника (пример: сборка, настройка, программирование, лекция интегрированная в школьную программу и т.п.).
|
||||
* Основной инструмент лекции - «Конструктор программируемого квадрокоптера «COEX Клевер 4» и/или «Симуляционная среда программируемого квадрокоптера Клевер».
|
||||
> **Note** *Версия «COEX Клевер» не ранее [4 версии](https://clover.coex.tech/ru/assemble_4.html). «Симуляционная среда программируемого квадрокоптера Клевер» - не ранее [версии 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
> **Note** *Версия «COEX Клевер» не ранее [4 версии](https://clovercoex.tech/ru/assemble_4.html). «Симуляционная среда программируемого квадрокоптера Клевер» - не ранее [версии 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
* Видео загружено на YouTube или иную общедоступную платформу, и находится в открытом доступе для любых пользователей;
|
||||
* Язык лекции - на выбор участника. Если язык лекции не русский/английский - наличие субтитров к видео на английском языке.
|
||||
* Продолжительность лекции - от 15 мин. до 3 часов.
|
||||
@@ -47,7 +47,7 @@
|
||||
### Требования к уроку
|
||||
|
||||
* Основной инструмент урока - «Конструктор программируемого квадрокоптера «COEX Клевер 4».
|
||||
> **Note** *Версия «COEX Клевер» не ранее [4 версии](https://clover.coex.tech/ru/assemble_4.html).
|
||||
> **Note** *Версия «COEX Клевер» не ранее [4 версии](https://clovercoex.tech/ru/assemble_4.html).
|
||||
* Интеграция квадрокоптера в любую из общеобразовательных дисциплин (физика, математика, информатика, урок технологии и т.д.).
|
||||
* Практическое использование основного инструмента на уроке.
|
||||
* Класс - без ограничений (начальная, основная школа).
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
* Направление курса - «Летающая робототехника».
|
||||
* Основной инструмент курса - «Конструктор программируемого квадрокоптера «COEX Клевер 4» и/или «Симуляционная среда программируемого квадрокоптера Клевер».
|
||||
> **Note** *Версия «COEX Клевер» не ранее [4 версии](https://clover.coex.tech/ru/assemble_4.html). «Симуляционная среда программируемого квадрокоптера Клевер» - не ранее [версии 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
> **Note** *Версия «COEX Клевер» не ранее [4 версии](https://clovercoex.tech/ru/assemble_4.html). «Симуляционная среда программируемого квадрокоптера Клевер» - не ранее [версии 1.0](https://github.com/CopterExpress/clover_vm/releases/tag/v1.0).
|
||||
* Курс расположен на общедоступной платформе (Stepik, Coursera и т.п.).
|
||||
* Доступ к курсу может быть как платный, так и бесплатный, на конкурс принимается один бесплатный и общедоступный урок заявленного курса.
|
||||
* Заявленный на конкурс урок должен быть в открытом доступе.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* `base_link` — координаты относительно квадрокоптера: схематичное изображение квадрокоптера на иллюстрации;
|
||||
* `body` — координаты относительно квадрокоптера без учета наклонов по тангажу и крену: красная, синяя и зеленая линии на иллюстрации;
|
||||
* <a name="navigate_target"></a>`navigate_target` – координаты точки, в которую сейчас летит дрон (с использованием [navigate](simple_offboard.md#navigate));
|
||||
* `terrain` – координаты относительно пола в текущей позиции коптера (см. сервис [set_altitude](simple_offboard.md#set_altitude))
|
||||
* `setpoint` – текущий setpoint по позиции;
|
||||
* `main_camera_optical` – система координат, [связанная с основной камерой](camera_setup.md#frame).
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
## Ссылки на литературу
|
||||
|
||||
- [Руководство по оценке позы человека](https://blog.nanonets.com/human-pose-estimation-2d-guide/)
|
||||
- [Умные беспилотники учебники](https://clover.coex.tech/en/)
|
||||
- [Умные беспилотники учебники](https://clovercoex.tech/en/)
|
||||
- [Posnet GitHub РЕПО](https://github.com/tensorflow/tfjs-models/tree/master/posenet)
|
||||
- [Posnet Medium артикул](https://medium.com/tensorflow/real-time-human-pose-estimation-in-the-browser-with-tensorflow-js-7dd0bc881cd5)
|
||||
- [Tensorflow.js Демонстрация](https://www.tensorflow.org/js/demos)
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
* [Инструкция по сборке.](assemble_3.md)
|
||||
* [Инструкция по настройке.](setup.md)
|
||||
* [Проверочные задания.](tests.md)
|
||||
* Информационные материалы на сайте https://clover.coex.tech.
|
||||
* Информационные материалы на сайте https://clovercoex.tech.
|
||||
|
||||
## Промежуточный контроль
|
||||
|
||||
|
||||
@@ -200,13 +200,20 @@
|
||||
|
||||
### 3D печать
|
||||
|
||||
#### Механический захват
|
||||
|
||||
* **Левая клешня**: [`grip_left.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/stl/grip_left.stl).
|
||||
* **Правая клешня**: [`grip_right.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/stl/grip_right.stl).
|
||||
|
||||
Материал: SBS Glass. Заполнение 100%. Количество: 1 шт.
|
||||
|
||||
#### Груз для магнитного захвата
|
||||
|
||||
* Груз для магнитного захвата: [`load_for_magnetic_grip.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/grip_load/load_for_magnetic_grip.stl)
|
||||
* Дополнение-для-подставки-груза: [`add-on_for_load_support.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/grip_load/add-on_for_load_support.stl)
|
||||
* Подставка под теннисный мяч для магнитного захвата: [`tennis_ball_stand_for_magnetic_grip.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/grip_load/tennis_ball_stand_for_magnetic_grip.stl).
|
||||
* **Груз для магнитного захвата**: [`load_for_magnetic_grip.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/grip_load/load_for_magnetic_grip.stl).
|
||||
* **Дополнение для подставки груза**: [`add-on_for_load_support.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/grip_load/add-on_for_load_support.stl).
|
||||
* **Подставка под теннисный мяч для магнитного захвата**: [`tennis_ball_stand_for_magnetic_grip.stl`](https://github.com/CopterExpress/clover/raw/master/docs/assets/grip_load/tennis_ball_stand_for_magnetic_grip.stl).
|
||||
|
||||
Материал: PETG. Заполнение 100%. Количество: 1шт.
|
||||
Материал: PETG. Заполнение 100%. Количество: 1 шт.
|
||||
|
||||
## Клевер 4
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ network={
|
||||
}
|
||||
```
|
||||
|
||||
Внутри конфига указываются общие настройки `wpa_supplicant` и параметры для настройки адаптера. Также конфигурационный файл содержит секции `network` – основные настройки Wi-Fi сети такие как SSID сети, пароль, режим работы адаптера. Таких блоков может быть несколько, но используется первый рабочий. Например, если вы указали в первом блоке подключение к некоторой недоступной сети, то адаптер будет настроен следующей удачной секцией, если такая есть. Подробнее о синтаксисе `wpa_supplicant.conf` [TODO WIKI].
|
||||
Внутри конфига указываются общие настройки `wpa_supplicant` и параметры для настройки адаптера. Также конфигурационный файл содержит секции `network` – основные настройки Wi-Fi сети такие как SSID сети, пароль, режим работы адаптера. Таких блоков может быть несколько, но используется первый рабочий. Например, если вы указали в первом блоке подключение к некоторой недоступной сети, то адаптер будет настроен следующей удачной секцией, если такая есть. Подробнее о синтаксисе `wpa_supplicant.conf` см. в [man-странице Debian](https://manpages.debian.org/buster/wpasupplicant/wpa_supplicant.conf.5.en.html).
|
||||
|
||||
#### wpa_passphrase
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ navigate(x=-1, frame_id='navigate_target')
|
||||
|
||||
## Дополнительные настройки
|
||||
|
||||
<!-- TODO: статья по пидам -->
|
||||
Дополнительную информацию по настройке PID см. в статье [Настройка коэффициентов PID](calibratePID.md).
|
||||
|
||||
Если коптер нестабильно удерживает позицию, попробуйте увеличить коэффициенты *P* PID-регулятора по скорости – параметры `MPC_XY_VEL_P` и `MPC_Z_VEL_P`.
|
||||
|
||||
|
||||
@@ -39,17 +39,28 @@
|
||||
|
||||
|Параметр|Значение|Примечание|
|
||||
|-|-|-|
|
||||
|`EKF2_AID_MASK`|26|Чекбоксы: *flow* + *vision position* + *vision yaw*.<br>Подробнее: [Optical Flow](optical_flow.md), [ArUco-маркеры](aruco_map.md), [GPS](gps.md).|
|
||||
|`EKF2_AID_MASK`\*|26|Чекбоксы: *flow* + *vision position* + *vision yaw*.<br>Подробнее: [Optical Flow](optical_flow.md), [ArUco-маркеры](aruco_map.md), [GPS](gps.md).|
|
||||
|`EKF2_OF_DELAY`|0||
|
||||
|`EKF2_OF_QMIN`|10||
|
||||
|`EKF2_OF_N_MIN`|0.05||
|
||||
|`EKF2_OF_N_MAX`|0.2||
|
||||
|`EKF2_HGT_MODE`|3 (*Vision*)|При наличии [дальномера](laser.md) и полете над ровным полом — 2 (*Range sensor*)|
|
||||
|`EKF2_EVA_NOISE`|0.1||
|
||||
|`EKF2_HGT_MODE`\*|3 (*Vision*)|При наличии [дальномера](laser.md) и полете над ровным полом — 2 (*Range sensor*)|
|
||||
|`EKF2_EVA_NOISE`|0.1 rad или 5 deg||
|
||||
|`EKF2_EVP_NOISE`|0.1||
|
||||
|`EKF2_EV_DELAY`|0||
|
||||
|`EKF2_MAG_TYPE`|5 (*None*)|Выключение магнитометра (при навигации внутри помещения)|
|
||||
|
||||
\* — начиная с версии PX4 1.14 помеченные звездочкой параметры заменены на следующие:
|
||||
|
||||
|Параметр|Значение|Примечание|
|
||||
|-|-|-|
|
||||
|`EKF2_EV_CTRL`|11|Чекбоксы: *Horizontal position* + *Vertical position* + *Yaw*|
|
||||
|`EKF2_GPS_CTRL`|0|Все чекбоксы сняты|
|
||||
|`EKF2_BARO_CTRL`|0 (*Disabled*)|Барометр отключен|
|
||||
|`EKF2_OF_CTRL`|1 (*Enabled*)|Optical flow включен|
|
||||
|`EKF2_HGT_REF`|3 (*Vision*)|При наличии [дальномера](laser.md) и полете над ровным полом — 2 (*Range sensor*)|
|
||||
|`EKF2_RNG_CTRL`|2 (*Enabled*)|Дальномер включен|
|
||||
|
||||
<!-- markdownlint-enable MD031 -->
|
||||
|
||||
> **Info** См. также: список параметров по умолчанию в [симуляторе](simulation.md): https://github.com/CopterExpress/clover/blob/master/clover_simulation/airframes/4500_clover.
|
||||
|
||||
@@ -51,6 +51,6 @@ sudo systemctl restart clover
|
||||
Неисправности
|
||||
---
|
||||
|
||||
* Если интерфейс пульта отображает явно неправильное напряжение (напр. > 5 V), проверьте, что значение PX4-параметра `BAT_N_CELLS` соответствует реальному количество элементов батареи. Если отображаемое напряжение все равно неверно, откалибруйте батарею (TODO: ссылка).
|
||||
* Если интерфейс пульта отображает явно неправильное напряжение (напр. > 5 V), проверьте, что значение PX4-параметра `BAT_N_CELLS` соответствует реальному количеству элементов батареи. Если отображаемое напряжение все равно неверно, откалибруйте [датчик питания](power.md).
|
||||
|
||||
* Если вместо режима PX4 отображается текст "DISCONNECTED FROM FCU", проверьте [подключение Raspberry Pi к Pixhawk](connection.md).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user