Compare commits

..

2 Commits

Author SHA1 Message Date
Alexey Rogachevskiy
8c70b7814a aruco_pose: Make vendored library compatible with older OpenCVs 2020-10-28 14:47:38 +03:00
Alexey Rogachevskiy
6e90c5d6fa aruco_pose: Make sure there are no undefined symbols
Also, compile in apriltag_quad_thresh.cpp - it contains some of the functions referenced
in aruco.cpp, which would otherwise be undefined.
2020-10-28 13:47:00 +03:00
561 changed files with 667 additions and 31817 deletions

View File

@@ -1,29 +0,0 @@
name: Build RPi image
on:
push:
branches: [ '*' ]
pull_request:
branches: [ master ]
release:
types: [ created ]
jobs:
build-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- 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: |
sudo chmod -R 777 images && zip -9 $(echo images/clover_*).zip images/clover_* && ls -l images
- name: Upload image
uses: softprops/action-gh-release@v1
if: ${{ github.event_name == 'release' }}
with:
files: images/clover_*.zip
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,23 +0,0 @@
name: Build
on:
push:
branches: [ '*' ]
pull_request:
branches: [ master ]
jobs:
build-melodic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- 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
build-noetic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Native Noetic build
run: |
docker run --rm -v $(pwd):/root/catkin_ws/src/clover ros:noetic-ros-base /root/catkin_ws/src/clover/builder/standalone-install.sh

View File

@@ -1,54 +0,0 @@
name: Documentation
on:
push:
branches: [ '*' ]
pull_request:
branches: [ master ]
jobs:
documentation:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with: { node-version: '10' }
- name: Setup tools
run: |
sudo sh -c "echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections"
sudo apt-get update && sudo apt-get install -y calibre msttcorefonts
npm install gitbook-cli -g
gitbook fetch 3.2.3 && npm i npm@3.10.10 --prefix=~/.gitbook/versions/3.2.3/ # fixing https://travis-ci.org/github/CopterExpress/clover/jobs/766541125#L932
npm install markdownlint-cli -g
npm install svgexport -g
gitbook -V
markdownlint -V
- name: Run markdownlint
run: markdownlint docs
- name: Check Assets
run: |
./check_assets_size.py
./check_unused_assets.py
- name: Build GitBook
run: |
gitbook install
gitbook build
- name: Generate PDF
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
run: |
for i in 1 2 3 4; do gitbook pdf ./ _book/clover.pdf && break || sleep 1; done
sudo apt-get -q install ghostscript
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/default -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages -dCompressFonts=true -r150 -sOutputFile=_book/clover_ru_compressed.pdf _book/clover_ru.pdf
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/default -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages -dCompressFonts=true -r150 -sOutputFile=_book/clover_en_compressed.pdf _book/clover_en.pdf
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
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.3
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
with:
branch: gh-pages
folder: _book
clean: true
single-commit: true # to avoid multiple copies of large pdf files

View File

@@ -1,18 +0,0 @@
name: Editorconfig lint
on:
push:
branches: [ '*' ]
pull_request:
branches: [ master ]
jobs:
editorconfig:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- 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|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"

View File

@@ -23,7 +23,6 @@
"ROS Melodic", "ROS Melodic",
"ROS Noetic", "ROS Noetic",
"OpenCV", "OpenCV",
"OpenVPN",
"Gazebo", "Gazebo",
"GitHub", "GitHub",
"FPV", "FPV",
@@ -108,9 +107,7 @@
"UDP", "UDP",
"QR", "QR",
"Li-ion", "Li-ion",
"Nvidia", "Nvidia"
"VirtualBox",
"VMware"
], ],
"code_blocks": false "code_blocks": false
}, },

125
.travis.yml Normal file
View File

@@ -0,0 +1,125 @@
os: linux
dist: xenial
language: generic
services:
- docker
env:
global:
- DOCKER="sfalexrog/img-tool:qemu-aarch64"
- TARGET_REPO="https://github.com/${TRAVIS_REPO_SLUG}.git"
- IMAGE_VERSION=${TRAVIS_TAG:-${TRAVIS_COMMIT:0:7}}
- IMAGE_NAME="$(basename -s '.git' ${TARGET_REPO})_${IMAGE_VERSION}.img"
git:
depth: 50
jobs:
fast_finish: true
include:
- stage: Build
name: "Raspberry Pi Image Build"
cache:
directories:
- imgcache
before_script:
- docker pull ${DOCKER}
# Check if there are any cached images, copy them to our "images" directory
- if [ -n "$(ls -A imgcache/*.zip)" ]; then mkdir -p images && cp imgcache/*.zip images; fi
script:
- if [[ -z ${TRAVIS_TAG} && "${TRAVIS_PULL_REQUEST}" != "false" ]]; then
echo "Commit range is ${TRAVIS_COMMIT_RANGE}" &&
if [ $(git diff --name-only ${TRAVIS_COMMIT_RANGE} | grep -v ^"docs/" | wc -l) -eq 0 ]; then
echo " === Docs-only change; skipping build ===" &&
export SKIP_BUILD=true;
fi;
fi
- if [ -z ${SKIP_BUILD} ]; then
docker run --privileged --rm -v /dev:/dev -v $(pwd):/builder/repo -e TRAVIS_TAG="${TRAVIS_TAG}" ${DOCKER};
fi
before_cache:
- cp images/*.zip imgcache
after_success:
- sudo chmod -R 777 *
- cd images && zip ${IMAGE_NAME}.zip ${IMAGE_NAME} && stat --printf="Compressed image size:%s\n" ${IMAGE_NAME}.zip
before_deploy:
# Set up git user name and tag this commit
- git config --local user.name "goldarte"
- git config --local user.email "goldartt@gmail.com"
deploy:
provider: releases
token: ${GITHUB_OAUTH_TOKEN}
file: ${IMAGE_NAME}.zip
skip_cleanup: true
on:
tags: true
draft: true
name: ${TRAVIS_TAG}
- stage: Build
name: "Native Kinetic build"
env:
- NATIVE_DOCKER=ros:kinetic-ros-base
before_script:
- docker pull ${NATIVE_DOCKER}
script:
- docker run --rm -v $(pwd):/root/catkin_ws/src/clover ${NATIVE_DOCKER} /root/catkin_ws/src/clover/builder/standalone-install.sh
- stage: Build
name: "Native Melodic build"
env:
- NATIVE_DOCKER=ros:melodic-ros-base
before_script:
- docker pull ${NATIVE_DOCKER}
script:
- docker run --rm -v $(pwd):/root/catkin_ws/src/clover ${NATIVE_DOCKER} /root/catkin_ws/src/clover/builder/standalone-install.sh
- stage: Build
name: "Native Noetic build"
env:
- NATIVE_DOCKER=ros:noetic-ros-base
before_script:
- docker pull ${NATIVE_DOCKER}
script:
- docker run --rm -v $(pwd):/root/catkin_ws/src/clover ${NATIVE_DOCKER} /root/catkin_ws/src/clover/builder/standalone-install.sh
- stage: Build
name: "Documentation"
language: node_js
node_js:
- "10"
before_script:
- sudo sh -c "echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections"
- sudo apt update && sudo apt install -y calibre msttcorefonts
- npm install gitbook-cli -g
- npm install markdownlint-cli -g
- npm install svgexport -g
- gitbook -V
- markdownlint -V
script:
- markdownlint docs
- ./check_assets_size.py
- ./check_unused_assets.py
- gitbook install
- gitbook build
- gitbook pdf ./ _book/clover.pdf
deploy:
provider: pages
local_dir: _book
skip_cleanup: true
token: ${GITHUB_OAUTH_TOKEN}
keep_history: true
target_branch: master
repo: CopterExpress/clover.coex.tech
fqdn: clover.coex.tech
verbose: true
on:
branch: master
- stage: Build
name: Editorconfig-lint
language: generic
before_script:
- wget https://github.com/okalachev/editorconfig-checker/releases/download/1.2.1-disable-spaces-amount/ec-linux-amd64
- chmod +x ec-linux-amd64
script:
- ./ec-linux-amd64 -spaces-after-tabs -e "roslib.js|ros3d.js|eventemitter2.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"
stages:
- Build
# More info there
# https://github.com/travis-ci/travis-ci/issues/6893
# https://docs.travis-ci.com/user/customizing-the-build/
# https://docs.travis-ci.com/user/deployment/releases
# https://docs.travis-ci.com/user/environment-variables/

View File

@@ -1,14 +1,12 @@
# clover🍀: create autonomous drones easily # COEX Clover Drone Kit
<img src="docs/assets/clover42-main.png" align="right" width="400px" alt="COEX Clover Drone"> <img src="docs/assets/clever4-front-white.png" align="right" width="400px" alt="Clover Drone">
Clover is an open source [ROS](https://www.ros.org)-based framework, providing user-friendly tools to control [PX4](https://px4.io)-powered drones. Clover is available as a ROS package, but is shipped mainly as a preconfigured image for Raspberry Pi. Once you've installed Raspberry Pi on your drone and flashed the image to its microSD card, taking the drone up in the air is a matter of minutes. Clover is an educational programmable drone kit consisting of an unassembled quadcopter, open source software and documentation. The kit includes Pixracer-compatible autopilot running PX4 firmware, Raspberry Pi 4 as companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices.
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 [on Gitbook](https://clover.coex.tech/).
The main documentation is available at [https://clover.coex.tech](https://clover.coex.tech/). Official website: [coex.tech/clover](https://coex.tech/clover). Official website: <a href="https://coex.tech/clover">coex.tech/clover</a>.
[__Support us on Kickstarter!__](https://www.kickstarter.com/projects/copterexpress/cloverdrone)
## Video compilation ## Video compilation
@@ -20,8 +18,7 @@ Clover drone is used on a wide range of educational events, including [Copter Ha
Preconfigured image for Raspberry Pi with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clover/releases). Preconfigured image for Raspberry Pi with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clover/releases).
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/CopterExpress/clover/CI) [![Build Status](https://travis-ci.org/CopterExpress/clover.svg?branch=master)](https://travis-ci.org/CopterExpress/clover)
![GitHub all releases](https://img.shields.io/github/downloads/CopterExpress/clover/total)
Image features: Image features:
@@ -38,10 +35,6 @@ API description for autonomous flights is available [on GitBook](https://clover.
For manual package installation and running see [`clover` package documentation](clover/README.md). For manual package installation and running see [`clover` package documentation](clover/README.md).
## Support
[![Telegram Support Chat](https://img.shields.io/endpoint?label=Support%20Chat&url=https%3A%2F%2Ftelegram-badge-4mbpu8e0fit4.runkit.sh%2F%3Furl%3Dhttps%3A%2F%2Ft.me%2FCOEXHelpDesk)](https://t.me/COEXHelpdesk)
## License ## License
While the Clover platform source code is available under the MIT License, note, that the [documentation](docs/) is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. While the Clover platform source code is available under the MIT License, note, that the [documentation](docs/) is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

View File

@@ -1,8 +0,0 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package aruco_pose
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.21.1 (2020-11-17)
-------------------
* First release of aruco_pose package to ROS
* Contributors: Alamoris, Alexey Rogachevskiy, Arthur Golubtsov, Ilya Petrov, Oleg Kalachev

View File

@@ -24,7 +24,7 @@ find_package(catkin REQUIRED COMPONENTS
# Workaround for OpenCV 3/4 support # Workaround for OpenCV 3/4 support
set(_opencv_version 4) set(_opencv_version 4)
find_package(OpenCV ${_opencv_version} QUIET COMPONENTS core imgproc calib3d) find_package(OpenCV ${_opencv_version} QUIET)
if (NOT OpenCV_FOUND) if (NOT OpenCV_FOUND)
message(STATUS "Did not find OpenCV 4, searching for OpenCV 3") message(STATUS "Did not find OpenCV 4, searching for OpenCV 3")
set(_opencv_version 3) set(_opencv_version 3)
@@ -119,7 +119,7 @@ generate_messages(
## Generate dynamic reconfigure parameters in the 'cfg' folder ## Generate dynamic reconfigure parameters in the 'cfg' folder
generate_dynamic_reconfigure_options( generate_dynamic_reconfigure_options(
cfg/Detector.cfg cfg/DetectorParams.cfg
) )
################################### ###################################

View File

@@ -8,8 +8,6 @@ p = cv2.aruco.DetectorParameters_create()
gen = ParameterGenerator() gen = ParameterGenerator()
gen.add("enabled", bool_t, 0, "if detection enabled", True)
gen.add("adaptiveThreshConstant", double_t, 0, gen.add("adaptiveThreshConstant", double_t, 0,
"Constant for adaptive thresholding before finding contours", "Constant for adaptive thresholding before finding contours",
p.adaptiveThreshConstant, 0, 100) p.adaptiveThreshConstant, 0, 100)

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package format="2"> <package format="2">
<name>aruco_pose</name> <name>aruco_pose</name>
<version>0.21.1</version> <version>0.0.1</version>
<description>Positioning with ArUco markers</description> <description>Positioning with ArUco markers</description>
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer> <maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>

View File

@@ -62,7 +62,6 @@ private:
std::unique_ptr<tf2_ros::Buffer> tf_buffer_; std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
std::unique_ptr<tf2_ros::TransformListener> tf_listener_; std::unique_ptr<tf2_ros::TransformListener> tf_listener_;
std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>> dyn_srv_; std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>> dyn_srv_;
bool enabled_ = true;
cv::Ptr<cv::aruco::Dictionary> dictionary_; cv::Ptr<cv::aruco::Dictionary> dictionary_;
cv::Ptr<cv::aruco::DetectorParameters> parameters_; cv::Ptr<cv::aruco::DetectorParameters> parameters_;
image_transport::Publisher debug_pub_; image_transport::Publisher debug_pub_;
@@ -111,14 +110,17 @@ public:
image_transport::ImageTransport it(nh_); image_transport::ImageTransport it(nh_);
image_transport::ImageTransport it_priv(nh_priv_); image_transport::ImageTransport it_priv(nh_priv_);
dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>>(nh_priv_); map_markers_sub_ = nh_.subscribe("map_markers", 1, &ArucoDetect::mapMarkersCallback, this);
dyn_srv_->setCallback(std::bind(&ArucoDetect::paramCallback, this, std::placeholders::_1, std::placeholders::_2));
debug_pub_ = it_priv.advertise("debug", 1); debug_pub_ = it_priv.advertise("debug", 1);
markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1); markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1);
vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1); vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1);
img_sub_ = it.subscribeCamera("image_raw", 1, &ArucoDetect::imageCallback, this); img_sub_ = it.subscribeCamera("image_raw", 1, &ArucoDetect::imageCallback, this);
map_markers_sub_ = nh_.subscribe("map_markers", 1, &ArucoDetect::mapMarkersCallback, this);
dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>>(nh_priv_);
dynamic_reconfigure::Server<aruco_pose::DetectorConfig>::CallbackType cb;
cb = std::bind(&ArucoDetect::paramCallback, this, std::placeholders::_1, std::placeholders::_2);
dyn_srv_->setCallback(cb);
NODELET_INFO("ready"); NODELET_INFO("ready");
} }
@@ -126,8 +128,6 @@ public:
private: private:
void imageCallback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr &cinfo) void imageCallback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr &cinfo)
{ {
if (!enabled_) return;
Mat image = cv_bridge::toCvShare(msg, "bgr8")->image; Mat image = cv_bridge::toCvShare(msg, "bgr8")->image;
vector<int> ids; vector<int> ids;
@@ -356,7 +356,6 @@ private:
void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level) void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level)
{ {
enabled_ = config.enabled;
parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant; parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant;
parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin; parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin;
parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax; parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax;

View File

@@ -124,11 +124,6 @@ public:
vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1, true); vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1, true);
debug_pub_ = it_priv.advertise("debug", 1); debug_pub_ = it_priv.advertise("debug", 1);
publishMarkersFrames();
publishMarkers();
publishMapImage();
vis_markers_pub_.publish(vis_array_);
image_sub_.subscribe(nh_, "image_raw", 1); image_sub_.subscribe(nh_, "image_raw", 1);
info_sub_.subscribe(nh_, "camera_info", 1); info_sub_.subscribe(nh_, "camera_info", 1);
markers_sub_.subscribe(nh_, "markers", 1); markers_sub_.subscribe(nh_, "markers", 1);
@@ -136,6 +131,11 @@ public:
sync_.reset(new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(10), image_sub_, info_sub_, markers_sub_)); sync_.reset(new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(10), image_sub_, info_sub_, markers_sub_));
sync_->registerCallback(boost::bind(&ArucoMap::callback, this, _1, _2, _3)); sync_->registerCallback(boost::bind(&ArucoMap::callback, this, _1, _2, _3));
publishMarkersFrames();
publishMarkers();
publishMapImage();
vis_markers_pub_.publish(vis_array_);
NODELET_INFO("ready"); NODELET_INFO("ready");
} }

View File

@@ -13,7 +13,7 @@
Generate map file for aruco_map nodelet. Generate map file for aruco_map nodelet.
Usage: Usage:
genmap.py <length> <x> <y> <dist_x> <dist_y> [<first>] [<x0>] [<y0>] [--top-left | --bottom-left] [-o <filename>] genmap.py <length> <x> <y> <dist_x> <dist_y> [<first>] [<x0>] [<y0>] [--top-left | --bottom-left]
genmap.py (-h | --help) genmap.py (-h | --help)
Options: Options:
@@ -27,7 +27,6 @@ Options:
<y0> Y coordinate for the first marker [default: 0] <y0> Y coordinate for the first marker [default: 0]
--top-left First marker is on top-left (default) --top-left First marker is on top-left (default)
--bottom-left First marker is on bottom-left --bottom-left First marker is on bottom-left
-o <filename> Output map file name in the 'map' subdirectory of aruco_pose package
Example: Example:
rosrun aruco_pose genmap.py 0.33 2 4 1 1 0 > $(catkin_find aruco_pose map)/test_map.txt rosrun aruco_pose genmap.py 0.33 2 4 1 1 0 > $(catkin_find aruco_pose map)/test_map.txt
@@ -35,8 +34,6 @@ Example:
from __future__ import print_function from __future__ import print_function
import sys
from os import path
from docopt import docopt from docopt import docopt
@@ -52,19 +49,14 @@ dist_x = float(arguments['<dist_x>'])
dist_y = float(arguments['<dist_y>']) dist_y = float(arguments['<dist_y>'])
bottom_left = arguments['--bottom-left'] bottom_left = arguments['--bottom-left']
if arguments['-o'] is None:
output = sys.stdout
else:
output = open(path.join(path.dirname(__file__), '..', 'map', arguments['-o']), 'w')
max_y = y0 + (markers_y - 1) * dist_y max_y = y0 + (markers_y - 1) * dist_y
output.write('# id\tlength\tx\ty\tz\trot_z\trot_y\trot_x\n') print('# id\tlength\tx\ty\tz\trot_z\trot_y\trot_x')
for y in range(markers_y): for y in range(markers_y):
for x in range(markers_x): for x in range(markers_x):
pos_x = x0 + x * dist_x pos_x = x0 + x * dist_x
pos_y = y0 + y * dist_y pos_y = y0 + y * dist_y
if not bottom_left: if not bottom_left:
pos_y = max_y - pos_y pos_y = max_y - pos_y
output.write('{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n'.format(first, length, pos_x, pos_y, 0, 0, 0, 0)) print('{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}'.format(first, length, pos_x, pos_y, 0, 0, 0, 0))
first += 1 first += 1

View File

@@ -24,7 +24,7 @@ target_compile_definitions(_opencv_aruco PRIVATE
CV_OVERRIDE=override CV_OVERRIDE=override
) )
target_compile_options(_opencv_aruco PRIVATE target_compile_options(_opencv_aruco PRIVATE
-fpic -fPIC -fvisibility=hidden -fpic -fPIC
) )
target_include_directories(_opencv_aruco PUBLIC target_include_directories(_opencv_aruco PUBLIC

View File

@@ -1,4 +1,4 @@
# Information: https://clover.coex.tech/aruco # Information: https://clover.coex.tech/en/aruco.html
import rospy import rospy
from clover import srv from clover import srv

View File

@@ -1,11 +0,0 @@
# Information: https://clover.coex.tech/en/simple_offboard.html#gettelemetry
import rospy
from clover import srv
rospy.init_node('flight')
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
# Print drone's state
print(get_telemetry())

View File

@@ -1,4 +1,4 @@
# Information: https://clover.coex.tech/led # Information: https://clover.coex.tech/en/leds.html
import rospy import rospy
from clover.srv import SetLEDEffect from clover.srv import SetLEDEffect
@@ -7,25 +7,19 @@ rospy.init_node('leds')
set_effect = rospy.ServiceProxy('led/set_effect', SetLEDEffect) # define proxy to ROS-service set_effect = rospy.ServiceProxy('led/set_effect', SetLEDEffect) # define proxy to ROS-service
print('Fill red')
set_effect(r=255, g=0, b=0) # fill strip with red color set_effect(r=255, g=0, b=0) # fill strip with red color
rospy.sleep(2) rospy.sleep(2)
print('Fill green')
set_effect(r=0, g=100, b=0) # fill strip with green color set_effect(r=0, g=100, b=0) # fill strip with green color
rospy.sleep(2) rospy.sleep(2)
print('Fade to blue')
set_effect(effect='fade', r=0, g=0, b=255) # fade to blue color set_effect(effect='fade', r=0, g=0, b=255) # fade to blue color
rospy.sleep(2) rospy.sleep(2)
print('Flash red')
set_effect(effect='flash', r=255, g=0, b=0) # flash twice with red color set_effect(effect='flash', r=255, g=0, b=0) # flash twice with red color
rospy.sleep(2) rospy.sleep(5)
print('Blink white')
set_effect(effect='blink', r=255, g=255, b=255) # blink with white color set_effect(effect='blink', r=255, g=255, b=255) # blink with white color
rospy.sleep(5) rospy.sleep(5)
print('Rainbow')
set_effect(effect='rainbow') # show rainbow set_effect(effect='rainbow') # show rainbow

View File

@@ -65,7 +65,7 @@ echo_stamp "#6 Turn on UART"
# https://github.com/RPi-Distro/raspi-config/pull/75 # https://github.com/RPi-Distro/raspi-config/pull/75
/usr/bin/raspi-config nonint do_serial 1 /usr/bin/raspi-config nonint do_serial 1
/usr/bin/raspi-config nonint set_config_var enable_uart 1 /boot/config.txt /usr/bin/raspi-config nonint set_config_var enable_uart 1 /boot/config.txt
echo dtoverlay=pi3-disable-bt >> /boot/config.txt /usr/bin/raspi-config nonint set_config_var dtoverlay pi3-disable-bt /boot/config.txt
systemctl disable hciuart.service systemctl disable hciuart.service
# After adding to Raspbian OS # After adding to Raspbian OS

View File

@@ -15,8 +15,7 @@
set -e # Exit immidiately on non-zero result set -e # Exit immidiately on non-zero result
# https://www.raspberrypi.org/software/operating-systems/#raspberry-pi-os-32-bit SOURCE_IMAGE="https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2020-08-24/2020-08-20-raspios-buster-arm64-lite.zip"
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip"
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'} export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
export LANG=${LANG:='C.UTF-8'} export LANG=${LANG:='C.UTF-8'}
@@ -106,7 +105,7 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/monkey.
# software install # software install
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-software.sh' ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-software.sh'
# examples # examples
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/examples' '/home/pi/' # TODO: symlink? ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/examples' '/home/pi/'
# network setup # network setup
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-network.sh' ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-network.sh'
# avahi setup # avahi setup

View File

@@ -55,7 +55,4 @@ echo_stamp "Set max space for syslogs"
# https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl # https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl
sed -i 's/#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf sed -i 's/#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf
echo_stamp "Move /etc/ld.so.preload out of the way"
mv /etc/ld.so.preload /etc/ld.so.preload.disabled-for-build
echo_stamp "End of init image" echo_stamp "End of init image"

View File

@@ -80,7 +80,7 @@ my_travis_retry sudo -u pi rosdep update
export ROS_IP='127.0.0.1' # needed for running tests export ROS_IP='127.0.0.1' # needed for running tests
# echo_stamp "Reconfiguring Clover repository for simplier unshallowing" echo_stamp "Reconfiguring Clover repository for simplier unshallowing"
cd /home/pi/catkin_ws/src/clover cd /home/pi/catkin_ws/src/clover
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
@@ -90,8 +90,8 @@ echo_stamp "Installing OpenCV 4.2-compatible ROS packages"
apt install -y --no-install-recommends \ apt install -y --no-install-recommends \
ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \ ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \
ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \ ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \
ros-${ROS_DISTRO}-cv-camera=0.5.1-0buster \ ros-${ROS_DISTRO}-cv-camera=0.5.0-0buster \
ros-${ROS_DISTRO}-image-publisher=1.15.3-0buster \ ros-${ROS_DISTRO}-image-publisher=1.15.2-0buster \
ros-${ROS_DISTRO}-web-video-server=0.2.1-0buster ros-${ROS_DISTRO}-web-video-server=0.2.1-0buster
apt-mark hold \ apt-mark hold \
ros-${ROS_DISTRO}-compressed-image-transport \ ros-${ROS_DISTRO}-compressed-image-transport \
@@ -100,9 +100,6 @@ ros-${ROS_DISTRO}-cv-camera \
ros-${ROS_DISTRO}-image-publisher \ ros-${ROS_DISTRO}-image-publisher \
ros-${ROS_DISTRO}-web-video-server ros-${ROS_DISTRO}-web-video-server
echo_stamp "Installing libboost-dev" # https://travis-ci.org/github/CopterExpress/clover/jobs/766318908#L6536
my_travis_retry apt-get install -y --no-install-recommends libboost-dev libboost-all-dev
echo_stamp "Build and install Clover" echo_stamp "Build and install Clover"
cd /home/pi/catkin_ws cd /home/pi/catkin_ws
# Don't try to install gazebo_ros # Don't try to install gazebo_ros
@@ -112,7 +109,7 @@ my_travis_retry pip3 install wheel
my_travis_retry pip3 install -r /home/pi/catkin_ws/src/clover/clover/requirements.txt my_travis_retry pip3 install -r /home/pi/catkin_ws/src/clover/clover/requirements.txt
source /opt/ros/${ROS_DISTRO}/setup.bash source /opt/ros/${ROS_DISTRO}/setup.bash
# Don't build simulation plugins for actual drone # Don't build simulation plugins for actual drone
catkin_make -j2 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCATKIN_BLACKLIST_PACKAGES=clover_gazebo_plugins catkin_make -j2 -DCMAKE_BUILD_TYPE=Release -DCATKIN_BLACKLIST_PACKAGES=clover_gazebo_plugins
echo_stamp "Install clever package (for backwards compatibility)" echo_stamp "Install clever package (for backwards compatibility)"
cd /home/pi/catkin_ws/src/clover/builder/assets/clever cd /home/pi/catkin_ws/src/clover/builder/assets/clever
@@ -122,7 +119,6 @@ rm -rf build # remove build artifacts
echo_stamp "Build Clover documentation" echo_stamp "Build Clover documentation"
cd /home/pi/catkin_ws/src/clover cd /home/pi/catkin_ws/src/clover
NPM_CONFIG_UNSAFE_PERM=true npm install gitbook-cli -g NPM_CONFIG_UNSAFE_PERM=true npm install gitbook-cli -g
NPM_CONFIG_UNSAFE_PERM=true gitbook fetch 3.2.3 && npm i npm@3.10.10 --prefix=~/.gitbook/versions/3.2.3/ # fixing https://travis-ci.org/github/CopterExpress/clover/jobs/766541125#L932
NPM_CONFIG_UNSAFE_PERM=true gitbook install NPM_CONFIG_UNSAFE_PERM=true gitbook install
gitbook build gitbook build
touch node_modules/CATKIN_IGNORE docs/CATKIN_IGNORE _book/CATKIN_IGNORE clover/www/CATKIN_IGNORE apps/CATKIN_IGNORE # ignore documentation files by catkin touch node_modules/CATKIN_IGNORE docs/CATKIN_IGNORE _book/CATKIN_IGNORE clover/www/CATKIN_IGNORE apps/CATKIN_IGNORE # ignore documentation files by catkin
@@ -135,9 +131,7 @@ my_travis_retry apt-get install -y --no-install-recommends \
ros-${ROS_DISTRO}-usb-cam \ ros-${ROS_DISTRO}-usb-cam \
ros-${ROS_DISTRO}-vl53l1x \ ros-${ROS_DISTRO}-vl53l1x \
ros-${ROS_DISTRO}-ws281x \ ros-${ROS_DISTRO}-ws281x \
ros-${ROS_DISTRO}-rosshow \ ros-${ROS_DISTRO}-rosshow
ros-${ROS_DISTRO}-cmake-modules \
ros-${ROS_DISTRO}-image-view
# TODO move GeographicLib datasets to Mavros debian package # TODO move GeographicLib datasets to Mavros debian package
echo_stamp "Install GeographicLib datasets (needed for mavros)" \ echo_stamp "Install GeographicLib datasets (needed for mavros)" \
@@ -151,9 +145,6 @@ catkin_make run_tests #&& catkin_test_results
echo_stamp "Change permissions for catkin_ws" echo_stamp "Change permissions for catkin_ws"
chown -Rf pi:pi /home/pi/catkin_ws chown -Rf pi:pi /home/pi/catkin_ws
echo_stamp "Change permissions for examples"
chown -Rf pi:pi /home/pi/examples
echo_stamp "Setup ROS environment" echo_stamp "Setup ROS environment"
cat << EOF >> /home/pi/.bashrc cat << EOF >> /home/pi/.bashrc
LANG='C.UTF-8' LANG='C.UTF-8'

View File

@@ -64,14 +64,15 @@ echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
echo_stamp "Install apt keys & repos" echo_stamp "Install apt keys & repos"
# TODO: This STDOUT consist 'OK' # TODO: This STDOUT consist 'OK'
curl http://deb.coex.tech/aptly_repo_signing.key 2> /dev/null | apt-key add -
apt-get update \ apt-get update \
&& apt-get install --no-install-recommends -y dirmngr > /dev/null \ && apt-get install --no-install-recommends -y dirmngr > /dev/null \
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 && apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
echo "deb http://deb.coex.tech/opencv4 buster main" > /etc/apt/sources.list.d/opencv3.list
wget -O - 'http://packages.coex.tech/key.asc' | apt-key add - echo "deb http://deb.coex.tech/ros buster main" > /etc/apt/sources.list.d/rpi-ros-melodic.list
echo 'deb http://packages.coex.tech buster main' >> /etc/apt/sources.list echo "deb http://deb.coex.tech/clover buster main" > /etc/apt/sources.list.d/clover.list
echo_stamp "Update apt cache" echo_stamp "Update apt cache"
@@ -81,7 +82,6 @@ apt-get update
# Let's retry fetching those packages several times, just in case # Let's retry fetching those packages several times, just in case
echo_stamp "Software installing" echo_stamp "Software installing"
my_travis_retry apt-get install --no-install-recommends -y cmake-data=3.13.4-1 cmake=3.13.4-1 # FIXME: using older CMake due to https://travis-ci.org/github/CopterExpress/clover/jobs/764367665#L6984
my_travis_retry apt-get install --no-install-recommends -y \ my_travis_retry apt-get install --no-install-recommends -y \
unzip \ unzip \
zip \ zip \
@@ -94,9 +94,8 @@ lsof \
git \ git \
dnsmasq \ dnsmasq \
tmux \ tmux \
tree \
vim \ vim \
libjpeg8 \ cmake \
tcpdump \ tcpdump \
libpoco-dev \ libpoco-dev \
libzbar0 \ libzbar0 \
@@ -123,10 +122,9 @@ sed -i "s/updates_available//" /usr/share/byobu/status/status
echo_stamp "Installing pip" echo_stamp "Installing pip"
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip2.py
python3 get-pip.py python3 get-pip.py
python get-pip2.py python get-pip.py
rm get-pip.py get-pip2.py rm get-pip.py
#my_travis_retry pip install --upgrade pip #my_travis_retry pip install --upgrade pip
#my_travis_retry pip3 install --upgrade pip #my_travis_retry pip3 install --upgrade pip
@@ -136,7 +134,6 @@ pip3 --version
echo_stamp "Install and enable Butterfly (web terminal)" echo_stamp "Install and enable Butterfly (web terminal)"
echo_stamp "Workaround for tornado >= 6.0 breaking butterfly" echo_stamp "Workaround for tornado >= 6.0 breaking butterfly"
export CRYPTOGRAPHY_DONT_BUILD_RUST=1
my_travis_retry pip3 install tornado==5.1.1 my_travis_retry pip3 install tornado==5.1.1
my_travis_retry pip3 install butterfly my_travis_retry pip3 install butterfly
my_travis_retry pip3 install butterfly[systemd] my_travis_retry pip3 install butterfly[systemd]
@@ -148,16 +145,15 @@ my_travis_retry pip3 install --prefer-binary rpi_ws281x
echo_stamp "Setup Monkey" echo_stamp "Setup Monkey"
mv /etc/monkey/sites/default /etc/monkey/sites/default.orig mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
mv /root/monkey /etc/monkey/sites/default mv /root/monkey /etc/monkey/sites/default
sed -i 's/SymLink Off/SymLink On/' /etc/monkey/monkey.conf
systemctl enable monkey.service systemctl enable monkey.service
echo_stamp "Install Node.js" echo_stamp "Install Node.js"
cd /home/pi cd /home/pi
wget --no-verbose https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-armv6l.tar.gz wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-arm64.tar.gz
tar -xzf node-v10.15.0-linux-armv6l.tar.gz tar -xzf node-v10.15.0-linux-arm64.tar.gz
cp -R node-v10.15.0-linux-armv6l/* /usr/local/ cp -R node-v10.15.0-linux-arm64/* /usr/local/
rm -rf node-v10.15.0-linux-armv6l/ rm -rf node-v10.15.0-linux-arm64/
rm node-v10.15.0-linux-armv6l.tar.gz rm node-v10.15.0-linux-arm64.tar.gz
echo_stamp "Installing ptvsd" echo_stamp "Installing ptvsd"
my_travis_retry pip install ptvsd my_travis_retry pip install ptvsd

View File

@@ -20,16 +20,9 @@ export ROS_DISTRO='noetic'
export ROS_IP='127.0.0.1' export ROS_IP='127.0.0.1'
source /opt/ros/${ROS_DISTRO}/setup.bash source /opt/ros/${ROS_DISTRO}/setup.bash
source /home/pi/catkin_ws/devel/setup.bash source /home/pi/catkin_ws/devel/setup.bash
systemctl start roscore
cd /home/pi/catkin_ws/src/clover/builder/test/ cd /home/pi/catkin_ws/src/clover/builder/test/
./tests.sh ./tests.sh
./tests.py ./tests.py
./tests_py3.py ./tests_py3.py
[[ $(./test_qr.py) == "Found QRCODE with data Проверка Unicode with center at x=66.0, y=66.0" ]]
[[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility [[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility
systemctl stop roscore
echo "Move /etc/ld.so.preload back to its original position"
mv /etc/ld.so.preload.disabled-for-build /etc/ld.so.preload

View File

@@ -3,16 +3,15 @@
# Perform a "standalone install" in a Docker container # Perform a "standalone install" in a Docker container
set -e set -e
# Step 1: Install pip # Step 1: Install pip
apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 # https://github.com/osrf/docker_images/issues/535 apt update
apt-get update apt install -y curl
apt-get install -y curl curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
if [ "x${ROS_PYTHON_VERSION}" = "x3" ]; then if [ "x${ROS_PYTHON_VERSION}" = "x3" ]; then
PYTHON=python3 PYTHON=python3
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
else else
PYTHON=python PYTHON=python
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py
fi fi
${PYTHON} ./get-pip.py ${PYTHON} ./get-pip.py
# Step 1.5: Add deb.coex.tech to apt # Step 1.5: Add deb.coex.tech to apt
@@ -41,7 +40,7 @@ ws281x:
ubuntu: ubuntu:
${CODENAME}: [ros-${ROS_DISTRO}-ws281x] ${CODENAME}: [ros-${ROS_DISTRO}-ws281x]
EOF EOF
apt-get update apt update
rosdep update rosdep update
# Step 2: Run rosdep to install all dependencies # Step 2: Run rosdep to install all dependencies
@@ -61,6 +60,3 @@ ${PYTHON} -m pip install --upgrade pytest
cd /root/catkin_ws cd /root/catkin_ws
source devel/setup.bash source devel/setup.bash
catkin_make run_tests && catkin_test_results catkin_make run_tests && catkin_test_results
# Step 5: Install packages
catkin_make install

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,42 +0,0 @@
#!/usr/bin/env python3
# Test QG recognition example
# Should be synced with the documentation: /docs/en/camera.md, /docs/ru/camera.md
# TODO: use real ROS topics
import rospy
from pyzbar import pyzbar
from cv_bridge import CvBridge
from sensor_msgs.msg import Image
bridge = CvBridge()
# rospy.init_node('barcode_test')
# Image subscriber callback function
def image_callback(data):
cv_image = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image
barcodes = pyzbar.decode(cv_image)
for barcode in barcodes:
b_data = barcode.data.decode("utf-8")
b_type = barcode.type
(x, y, w, h) = barcode.rect
xc = x + w/2
yc = y + h/2
print("Found {} with data {} with center at x={}, y={}".format(b_type, b_data, xc, yc))
# rospy.signal_shutdown('done')
# image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback, queue_size=1)
# ==============================================================================
# Publish test image
# rospy.sleep(2)
import cv2
img = cv2.imread('qr.png')
image_callback(bridge.cv2_to_imgmsg(img, 'bgr8'))
# image_pub = rospy.Publisher('/main_camera/image_raw', Image, queue_size=1, latch=True)
# image_pub.publish(bridge.cv2_to_imgmsg(img, 'bgr8'))
# rospy.spin()

View File

@@ -4,26 +4,18 @@
import rospy import rospy
from geometry_msgs.msg import PoseStamped from geometry_msgs.msg import PoseStamped
from sensor_msgs.msg import Range, BatteryState
import cv2 import cv2
import cv2.aruco import cv2.aruco
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import numpy import numpy
import mavros import mavros
from mavros_msgs.msg import State, StatusText, ExtendedState, RCIn, Mavlink from mavros_msgs.msg import State, StatusText, ExtendedState
from mavros_msgs.srv import CommandBool, CommandLong, SetMode from mavros_msgs.srv import CommandBool, CommandLong, SetMode
from std_srvs.srv import Trigger from std_srvs.srv import Trigger
from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \ from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
SetAttitude, SetRates, SetLEDEffect SetAttitude, SetRates, SetLEDEffect
from led_msgs.srv import SetLEDs
from led_msgs.msg import LEDStateArray, LEDState
from aruco_pose.msg import Marker, MarkerArray, Point2D
import dynamic_reconfigure.client
import tf2_ros import tf2_ros
import tf2_geometry_msgs import tf2_geometry_msgs
@@ -33,7 +25,7 @@ import pymavlink
from pymavlink import mavutil from pymavlink import mavutil
import rpi_ws281x import rpi_ws281x
import pigpio import pigpio
# from espeak import espeak from espeak import espeak
from pyzbar import pyzbar from pyzbar import pyzbar
print(cv2.getBuildInformation()) print(cv2.getBuildInformation())

View File

@@ -32,7 +32,7 @@ monkey --version
pigpiod -v pigpiod -v
i2cdetect -V i2cdetect -V
butterfly -h butterfly -h
# espeak --version espeak --version
mjpg_streamer --version mjpg_streamer --version
# ros stuff # ros stuff
@@ -43,8 +43,6 @@ rosversion aruco_pose
rosversion vl53l1x rosversion vl53l1x
rosversion mavros rosversion mavros
rosversion mavros_extras rosversion mavros_extras
rosversion ws281x
rosversion led_msgs
rosversion dynamic_reconfigure rosversion dynamic_reconfigure
rosversion tf2_web_republisher rosversion tf2_web_republisher
rosversion compressed_image_transport rosversion compressed_image_transport
@@ -54,8 +52,6 @@ rosversion usb_cam
rosversion cv_camera rosversion cv_camera
rosversion web_video_server rosversion web_video_server
rosversion rosshow rosversion rosshow
rosversion nodelet
rosversion image_view
# validate examples are present # validate examples are present
[[ $(ls /home/pi/examples/*) ]] [[ $(ls /home/pi/examples/*) ]]

View File

@@ -4,9 +4,7 @@ import os
import sys import sys
import subprocess import subprocess
EXCLUDE = ('clever4-front-white.png', 'clever4-front-white-large.png', '.DS_Store', EXCLUDE = ('clever4-front-white.png', '.DS_Store', 'clever4-front-black-large.png')
'clever4-front-black-large.png','clover42-black.png')
code = 0 code = 0
os.chdir('./docs') os.chdir('./docs')

View File

@@ -1,8 +0,0 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package clover
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.21.1 (2020-11-17)
-------------------
* First release of clover package to ROS
* Contributors: Alexey Rogachevskiy, Arthur Golubtsov, Oleg Kalachev

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 2.8.3)
project(clover) project(clover)
## Compile as C++11, supported in ROS Kinetic and newer ## Compile as C++11, supported in ROS Kinetic and newer
@@ -32,7 +32,7 @@ find_package(GeographicLib REQUIRED)
# Workaround for OpenCV 3/4 support # Workaround for OpenCV 3/4 support
set(_opencv_version 4) set(_opencv_version 4)
find_package(OpenCV ${_opencv_version} QUIET COMPONENTS calib3d imgproc) find_package(OpenCV ${_opencv_version} QUIET)
if (NOT OpenCV_FOUND) if (NOT OpenCV_FOUND)
message(STATUS "Did not find OpenCV 4, searching for OpenCV 3") message(STATUS "Did not find OpenCV 4, searching for OpenCV 3")
set(_opencv_version 3) set(_opencv_version 3)

View File

@@ -44,12 +44,16 @@ Alternatively you may change the `fcu_url` property in `mavros.launch` file to p
## Running ## Running
To start connection to SITL, use:
```bash
roslaunch clover sitl.launch
```
To start connection to the flight controller, use: To start connection to the flight controller, use:
```bash ```bash
roslaunch clover clover.launch roslaunch clover clover.launch
``` ```
For the simulation information see the [corresponding article](https://clover.coex.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`. > 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`.

View File

@@ -2,37 +2,30 @@
<arg name="aruco_detect" default="true"/> <arg name="aruco_detect" default="true"/>
<arg name="aruco_map" default="false"/> <arg name="aruco_map" default="false"/>
<arg name="aruco_vpe" default="false"/> <arg name="aruco_vpe" default="false"/>
<arg name="placement" default="floor"/> <!-- markers placement: floor, ceiling, unknown -->
<arg name="length" default="0.33"/> <!-- 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://clover.coex.tech/aruco -->
<!-- aruco_detect: detect aruco markers, estimate poses --> <!-- aruco_detect: detect aruco markers, estimate poses -->
<node name="aruco_detect" pkg="nodelet" if="$(arg aruco_detect)" type="nodelet" args="load aruco_pose/aruco_detect main_camera_nodelet_manager" output="screen" clear_params="true" respawn="true"> <node name="aruco_detect" pkg="nodelet" if="$(arg aruco_detect)" type="nodelet" args="load aruco_pose/aruco_detect nodelet_manager" output="screen" clear_params="true">
<remap from="image_raw" to="main_camera/image_raw"/> <remap from="image_raw" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/> <remap from="camera_info" to="main_camera/camera_info"/>
<remap from="map_markers" to="aruco_map/markers" if="$(arg aruco_map)"/> <remap from="map_markers" to="aruco_map/markers" if="$(arg aruco_map)"/>
<param name="estimate_poses" value="true"/> <param name="estimate_poses" value="true"/>
<param name="send_tf" value="true"/> <param name="send_tf" value="true"/>
<param name="known_tilt" value="map" if="$(eval placement == 'floor')"/> <param name="known_tilt" value="map"/>
<param name="known_tilt" value="map_flipped" if="$(eval placement == 'ceiling')"/> <param name="length" value="0.33"/>
<param name="length" value="$(arg length)"/>
<!-- aruco detector parameters --> <!-- aruco detector parameters -->
<param name="cornerRefinementMethod" value="2"/> <!-- contour refinement --> <param name="cornerRefinementMethod" value="2"/> <!-- contour refinement -->
<param name="minMarkerPerimeterRate" value="0.075"/> <!-- 0.075 for 320x240, 0.0375 for 640x480 --> <param name="minMarkerPerimeterRate" value="0.075"/> <!-- 0.075 for 320x240, 0.0375 for 640x480 -->
<!-- length override example: -->
<!-- <param name="length_override/3" value="0.1"/> -->
</node> </node>
<!-- aruco_map: estimate aruco map pose --> <!-- aruco_map: estimate aruco map pose -->
<node name="aruco_map" pkg="nodelet" type="nodelet" if="$(arg aruco_map)" args="load aruco_pose/aruco_map main_camera_nodelet_manager" output="screen" clear_params="true" respawn="true"> <node name="aruco_map" pkg="nodelet" type="nodelet" if="$(arg aruco_map)" args="load aruco_pose/aruco_map nodelet_manager" output="screen" clear_params="true">
<remap from="image_raw" to="main_camera/image_raw"/> <remap from="image_raw" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/> <remap from="camera_info" to="main_camera/camera_info"/>
<remap from="markers" to="aruco_detect/markers"/> <remap from="markers" to="aruco_detect/markers"/>
<param name="map" value="$(find aruco_pose)/map/$(arg map)"/> <param name="map" value="$(find aruco_pose)/map/map.txt"/>
<param name="known_tilt" value="map" if="$(eval placement == 'floor')"/> <param name="known_tilt" value="map"/>
<param name="known_tilt" value="map_flipped" if="$(eval placement == 'ceiling')"/>
<param name="image_axis" value="true"/> <param name="image_axis" value="true"/>
<param name="frame_id" value="aruco_map_detected" if="$(arg aruco_vpe)"/> <param name="frame_id" value="aruco_map_detected" if="$(arg aruco_vpe)"/>
<param name="frame_id" value="aruco_map" unless="$(arg aruco_vpe)"/> <param name="frame_id" value="aruco_map" unless="$(arg aruco_vpe)"/>

View File

@@ -11,7 +11,8 @@
<arg name="rangefinder_vl53l1x" default="true"/> <arg name="rangefinder_vl53l1x" default="true"/>
<arg name="led" default="true"/> <arg name="led" default="true"/>
<arg name="blocks" default="false"/> <arg name="blocks" default="false"/>
<arg name="rc" default="false"/> <arg name="rc" default="true"/>
<arg name="shell" default="true"/>
<arg name="simulator" default="false"/> <!-- flag that we are operating on a simulated drone --> <arg name="simulator" default="false"/> <!-- flag that we are operating on a simulated drone -->
@@ -36,13 +37,18 @@
<include file="$(find clover)/launch/aruco.launch" if="$(arg aruco)"/> <include file="$(find clover)/launch/aruco.launch" if="$(arg aruco)"/>
<!-- optical flow --> <!-- optical flow -->
<node pkg="nodelet" type="nodelet" name="optical_flow" args="load clover/optical_flow main_camera_nodelet_manager" if="$(arg optical_flow)" clear_params="true" output="screen" respawn="true"> <node pkg="nodelet" type="nodelet" name="optical_flow" args="load clover/optical_flow nodelet_manager" if="$(arg optical_flow)" clear_params="true" output="screen">
<remap from="image_raw" to="main_camera/image_raw"/> <remap from="image_raw" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/> <remap from="camera_info" to="main_camera/camera_info"/>
<param name="calc_flow_gyro" value="true"/> <param name="calc_flow_gyro" value="true"/>
<param name="roi_rad" value="0.8"/> <param name="roi_rad" value="0.8"/>
</node> </node>
<!-- main nodelet manager -->
<node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" clear_params="true">
<param name="num_worker_threads" value="2"/>
</node>
<node pkg="tf2_ros" type="static_transform_publisher" name="map_flipped_frame" args="0 0 0 3.1415926 3.1415926 0 map map_flipped"/> <node pkg="tf2_ros" type="static_transform_publisher" name="map_flipped_frame" args="0 0 0 3.1415926 3.1415926 0 map map_flipped"/>
<!-- simplified offboard control --> <!-- simplified offboard control -->
@@ -85,6 +91,9 @@
<param name="use_fake_gcs" value="false"/> <param name="use_fake_gcs" value="false"/>
</node> </node>
<!-- Shell access through ROS service -->
<node name="shell" pkg="clover" type="shell" output="screen" if="$(arg shell)"/>
<!-- Update static directory --> <!-- Update static directory -->
<node pkg="roswww_static" name="roswww_static" type="main.py" clear_params="true"> <node pkg="roswww_static" name="roswww_static" type="main.py" clear_params="true">
<param name="default_package" value="clover"/> <param name="default_package" value="clover"/>

View File

@@ -2,7 +2,7 @@
<arg name="ws281x" default="true"/> <arg name="ws281x" default="true"/>
<arg name="led_effect" default="true"/> <arg name="led_effect" default="true"/>
<arg name="led_notify" default="true"/> <arg name="led_notify" default="true"/>
<arg name="led_count" default="72"/> <arg name="led_count" default="58"/>
<arg name="gpio_pin" default="21"/> <arg name="gpio_pin" default="21"/>
<arg name="simulator" default="false"/> <arg name="simulator" default="false"/>
@@ -36,7 +36,7 @@
posctl: { r: 50, g: 100, b: 220 } posctl: { r: 50, g: 100, b: 220 }
offboard: { r: 220, g: 20, b: 250 } offboard: { r: 220, g: 20, b: 250 }
low_battery: { threshold: 3.6, effect: blink_fast, r: 255, g: 0, b: 0 } low_battery: { threshold: 3.6, effect: blink_fast, r: 255, g: 0, b: 0 }
error: { effect: flash, r: 255, g: 0, b: 0, ignore: [ "[lpe] vision position timeout" ]} error: { effect: flash, r: 255, g: 0, b: 0 }
</rosparam> </rosparam>
</node> </node>
</launch> </launch>

View File

@@ -3,7 +3,6 @@
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up --> <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="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
<arg name="device" default="/dev/video0"/> <!-- v4l2 device -->
<arg name="simulator" default="false"/> <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"/> <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"/>
@@ -18,14 +17,9 @@
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id --> <!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
<!-- <node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/> --> <!-- <node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/> -->
<!-- camera nodelet manager -->
<node pkg="nodelet" type="nodelet" name="main_camera_nodelet_manager" args="manager" output="screen" clear_params="true" respawn="true">
<param name="num_worker_threads" value="2"/>
</node>
<!-- camera node --> <!-- camera node -->
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet main_camera_nodelet_manager" launch-prefix="rosrun clover waitfile $(arg device)" clear_params="true" unless="$(arg simulator)" respawn="true"> <node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet nodelet_manager" clear_params="true" unless="$(arg simulator)">
<param name="device_path" value="$(arg device)"/> <param name="device_path" value="/dev/video0"/> <!-- v4l2 device -->
<param name="frame_id" value="main_camera_optical"/> <param name="frame_id" value="main_camera_optical"/>
<param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/> <param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/>

View File

@@ -6,16 +6,13 @@
<arg name="viz" default="true"/> <arg name="viz" default="true"/>
<arg name="respawn" default="true"/> <arg name="respawn" default="true"/>
<arg name="distance_sensor_remap" default="rangefinder/range"/> <arg name="distance_sensor_remap" default="rangefinder/range"/>
<arg name="usb_device" default="/dev/px4fmu"/>
<arg name="prefix" default="" unless="$(eval fcu_conn == 'usb')"/>
<arg name="prefix" default="rosrun clover waitfile $(arg usb_device)" if="$(eval fcu_conn == 'usb')"/>
<node pkg="mavros" type="mavros_node" name="mavros" launch-prefix="$(arg prefix)" required="false" clear_params="true" respawn="$(arg respawn)" unless="$(eval fcu_conn == 'none')" respawn_delay="1" output="screen"> <node pkg="mavros" type="mavros_node" name="mavros" required="false" clear_params="true" respawn="$(arg respawn)" unless="$(eval fcu_conn == 'none')" respawn_delay="1" output="screen">
<!-- UART connection --> <!-- UART connection -->
<param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/> <param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/>
<!-- USB connection --> <!-- USB connection -->
<param name="fcu_url" value="$(arg usb_device)" if="$(eval fcu_conn == 'usb')"/> <param name="fcu_url" value="/dev/px4fmu" if="$(eval fcu_conn == 'usb')"/>
<!-- sitl before PX4 1.9.0 --> <!-- sitl before PX4 1.9.0 -->
<param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/> <param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/>

19
clover/launch/sitl.launch Normal file
View File

@@ -0,0 +1,19 @@
<launch>
<!-- clover configuration for testing in sitl -->
<arg name="ip" default="127.0.0.1"/>
<arg name="rosbridge" default="false"/>
<include file="$(find clover)/launch/clover.launch">
<arg name="fcu_conn" value="udp"/>
<arg name="fcu_ip" value="$(arg ip)"/>
<arg name="gcs_bridge" value="false"/>
<arg name="optical_flow" value="false"/>
<arg name="web_video_server" default="false"/>
<arg name="main_camera" default="false"/>
<arg name="rosbridge" value="$(arg rosbridge)"/>
<arg name="aruco" default="false"/>
<arg name="rangefinder_vl53l1x" default="false"/>
<arg name="led" default="false"/>
<arg name="rc" default="false"/>
</include>
</launch>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package format="3"> <package format="3">
<name>clover</name> <name>clover</name>
<version>0.21.1</version> <version>0.0.1</version>
<description>The Clover package</description> <description>The Clover package</description>
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer> <maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>

View File

@@ -12,7 +12,6 @@
#include <ros/ros.h> #include <ros/ros.h>
#include <string> #include <string>
#include <vector>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <clover/SetLEDEffect.h> #include <clover/SetLEDEffect.h>
@@ -30,7 +29,6 @@ ros::Timer timer;
ros::Time start_time; ros::Time start_time;
double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period; double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period;
double low_battery_threshold; double low_battery_threshold;
std::vector<std::string> error_ignore;
bool blink_state; bool blink_state;
led_msgs::SetLEDs set_leds; led_msgs::SetLEDs set_leds;
led_msgs::LEDStateArray state, start_state; led_msgs::LEDStateArray state, start_state;
@@ -276,10 +274,6 @@ void handleMavrosState(const mavros_msgs::State& msg)
void handleLog(const rosgraph_msgs::Log& log) void handleLog(const rosgraph_msgs::Log& log)
{ {
if (log.level >= rosgraph_msgs::Log::ERROR) { if (log.level >= rosgraph_msgs::Log::ERROR) {
// check if ignored
for (auto const& str : error_ignore) {
if (log.msg.find(str) != std::string::npos) return;
}
notify("error"); notify("error");
} }
} }
@@ -308,7 +302,6 @@ int main(int argc, char **argv)
nh_priv.param("rainbow_period", rainbow_period, 5.0); nh_priv.param("rainbow_period", rainbow_period, 5.0);
nh_priv.param("notify/low_battery/threshold", low_battery_threshold, 3.7); 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 ros::service::waitForService("set_leds"); // cannot work without set_leds service
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true); set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true);

View File

@@ -70,6 +70,7 @@ private:
roi_rad_ = nh_priv.param("roi_rad", 0.0); roi_rad_ = nh_priv.param("roi_rad", 0.0);
calc_flow_gyro_ = nh_priv.param("calc_flow_gyro", false); calc_flow_gyro_ = nh_priv.param("calc_flow_gyro", false);
img_sub_ = it.subscribeCamera("image_raw", 1, &OpticalFlow::flow, this);
img_pub_ = it_priv.advertise("debug", 1); img_pub_ = it_priv.advertise("debug", 1);
flow_pub_ = nh.advertise<mavros_msgs::OpticalFlowRad>("mavros/px4flow/raw/send", 1); flow_pub_ = nh.advertise<mavros_msgs::OpticalFlowRad>("mavros/px4flow/raw/send", 1);
velo_pub_ = nh_priv.advertise<geometry_msgs::TwistStamped>("angular_velocity", 1); velo_pub_ = nh_priv.advertise<geometry_msgs::TwistStamped>("angular_velocity", 1);
@@ -82,8 +83,6 @@ private:
flow_.distance = -1; // no distance sensor available flow_.distance = -1; // no distance sensor available
flow_.temperature = 0; flow_.temperature = 0;
img_sub_ = it.subscribeCamera("image_raw", 1, &OpticalFlow::flow, this);
NODELET_INFO("Optical Flow initialized"); NODELET_INFO("Optical Flow initialized");
} }
@@ -153,7 +152,7 @@ private:
cv::Point2d shift = cv::phaseCorrelate(prev_, curr_, hann_, &response); cv::Point2d shift = cv::phaseCorrelate(prev_, curr_, hann_, &response);
// Publish raw shift in pixels // Publish raw shift in pixels
geometry_msgs::Vector3Stamped shift_vec; static geometry_msgs::Vector3Stamped shift_vec;
shift_vec.header.stamp = msg->header.stamp; shift_vec.header.stamp = msg->header.stamp;
shift_vec.header.frame_id = msg->header.frame_id; shift_vec.header.frame_id = msg->header.frame_id;
shift_vec.vector.x = shift.x; shift_vec.vector.x = shift.x;
@@ -180,7 +179,7 @@ private:
double flow_y = atan2(points_undist[0].y, focal_length_y); double flow_y = atan2(points_undist[0].y, focal_length_y);
// // Convert to FCU frame // // Convert to FCU frame
geometry_msgs::Vector3Stamped flow_camera, flow_fcu; static geometry_msgs::Vector3Stamped flow_camera, flow_fcu;
flow_camera.header.frame_id = msg->header.frame_id; flow_camera.header.frame_id = msg->header.frame_id;
flow_camera.header.stamp = msg->header.stamp; flow_camera.header.stamp = msg->header.stamp;
flow_camera.vector.x = flow_y; // +y means counter-clockwise rotation around Y axis flow_camera.vector.x = flow_y; // +y means counter-clockwise rotation around Y axis
@@ -199,7 +198,7 @@ private:
if (calc_flow_gyro_) { if (calc_flow_gyro_) {
try { try {
auto flow_gyro_camera = calcFlowGyro(msg->header.frame_id, prev_stamp_, msg->header.stamp); auto flow_gyro_camera = calcFlowGyro(msg->header.frame_id, prev_stamp_, msg->header.stamp);
geometry_msgs::Vector3Stamped flow_gyro_fcu; static geometry_msgs::Vector3Stamped flow_gyro_fcu;
tf_buffer_->transform(flow_gyro_camera, flow_gyro_fcu, fcu_frame_id_); tf_buffer_->transform(flow_gyro_camera, flow_gyro_fcu, fcu_frame_id_);
flow_.integrated_xgyro = flow_gyro_fcu.vector.x; flow_.integrated_xgyro = flow_gyro_fcu.vector.x;
flow_.integrated_ygyro = flow_gyro_fcu.vector.y; flow_.integrated_ygyro = flow_gyro_fcu.vector.y;
@@ -207,7 +206,7 @@ private:
} catch (const tf2::TransformException& e) { } catch (const tf2::TransformException& e) {
// Invalidate previous frame // Invalidate previous frame
prev_.release(); prev_.release();
goto publish_debug; return;
} }
} }
@@ -219,10 +218,6 @@ private:
flow_.quality = (uint8_t)(response * 255); flow_.quality = (uint8_t)(response * 255);
flow_pub_.publish(flow_); flow_pub_.publish(flow_);
prev_ = curr_.clone();
prev_stamp_ = msg->header.stamp;
publish_debug:
// Publish debug image // Publish debug image
if (img_pub_.getNumSubscribers() > 0) { if (img_pub_.getNumSubscribers() > 0) {
// publish debug image // publish debug image
@@ -236,12 +231,15 @@ publish_debug:
} }
// Publish estimated angular velocity // Publish estimated angular velocity
geometry_msgs::TwistStamped velo; static geometry_msgs::TwistStamped velo;
velo.header.stamp = msg->header.stamp; velo.header.stamp = msg->header.stamp;
velo.header.frame_id = fcu_frame_id_; velo.header.frame_id = fcu_frame_id_;
velo.twist.angular.x = flow_fcu.vector.x / integration_time.toSec(); velo.twist.angular.x = flow_.integrated_x / integration_time.toSec();
velo.twist.angular.y = flow_fcu.vector.y / integration_time.toSec(); velo.twist.angular.y = flow_.integrated_y / integration_time.toSec();
velo_pub_.publish(velo); velo_pub_.publish(velo);
prev_ = curr_.clone();
prev_stamp_ = msg->header.stamp;
} }
} }

View File

@@ -73,7 +73,6 @@ ros::Duration state_timeout;
ros::Duration velocity_timeout; ros::Duration velocity_timeout;
ros::Duration global_position_timeout; ros::Duration global_position_timeout;
ros::Duration battery_timeout; ros::Duration battery_timeout;
ros::Duration manual_control_timeout;
float default_speed; float default_speed;
bool auto_release; bool auto_release;
bool land_only_in_offboard, nav_from_sp, check_kill_switch; bool land_only_in_offboard, nav_from_sp, check_kill_switch;
@@ -489,25 +488,16 @@ void publishSetpoint(const ros::TimerEvent& event)
publish(event.current_real); publish(event.current_real);
} }
inline void checkManualControl() inline void checkKillSwitch()
{ {
if (!manual_control_timeout.isZero() && TIMEOUT(manual_control, manual_control_timeout)) { if (!TIMEOUT(manual_control, state_timeout))
throw std::runtime_error("Manual control timeout, RC is switched off?"); throw std::runtime_error("Manual control timeout, can't check kill switch status");
}
if (check_kill_switch) { const int KILL_SWITCH_BIT = 12; // https://github.com/PX4/Firmware/blob/c302514a0809b1765fafd13c014d705446ae1113/src/modules/mavlink/mavlink_messages.cpp#L3975
// switch values: https://github.com/PX4/PX4-Autopilot/blob/c302514a0809b1765fafd13c014d705446ae1113/msg/manual_control_setpoint.msg#L3 bool kill_switch = manual_control.buttons & (1 << KILL_SWITCH_BIT);
const uint8_t SWITCH_POS_NONE = 0; // switch is not mapped
const uint8_t SWITCH_POS_ON = 1; // switch activated
const uint8_t SWITCH_POS_MIDDLE = 2; // middle position
const uint8_t SWITCH_POS_OFF = 3; // switch not activated
const int KILL_SWITCH_BIT = 12; // https://github.com/PX4/Firmware/blob/c302514a0809b1765fafd13c014d705446ae1113/src/modules/mavlink/mavlink_messages.cpp#L3975 if (kill_switch)
uint8_t kill_switch = (manual_control.buttons & (0b11 << KILL_SWITCH_BIT)) >> KILL_SWITCH_BIT; throw std::runtime_error("Kill switch is on");
if (kill_switch == SWITCH_POS_ON)
throw std::runtime_error("Kill switch is on");
}
} }
inline void checkState() inline void checkState()
@@ -537,8 +527,8 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
// Checks // Checks
checkState(); checkState();
if (auto_arm) { if (auto_arm && check_kill_switch) {
checkManualControl(); checkKillSwitch();
} }
// default frame is local frame // default frame is local frame
@@ -712,7 +702,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
} }
if (sp_type == VELOCITY) { if (sp_type == VELOCITY) {
Vector3Stamped vel; static Vector3Stamped vel;
vel.header.frame_id = frame_id; vel.header.frame_id = frame_id;
vel.header.stamp = stamp; vel.header.stamp = stamp;
vel.vector.x = vx; vel.vector.x = vx;
@@ -872,7 +862,6 @@ int main(int argc, char **argv)
velocity_timeout = ros::Duration(nh_priv.param("velocity_timeout", 2.0)); velocity_timeout = ros::Duration(nh_priv.param("velocity_timeout", 2.0));
global_position_timeout = ros::Duration(nh_priv.param("global_position_timeout", 10.0)); global_position_timeout = ros::Duration(nh_priv.param("global_position_timeout", 10.0));
battery_timeout = ros::Duration(nh_priv.param("battery_timeout", 2.0)); battery_timeout = ros::Duration(nh_priv.param("battery_timeout", 2.0));
manual_control_timeout = ros::Duration(nh_priv.param("manual_control_timeout", 0.0));
transform_timeout = ros::Duration(nh_priv.param("transform_timeout", 0.5)); transform_timeout = ros::Duration(nh_priv.param("transform_timeout", 0.5));
telemetry_transform_timeout = ros::Duration(nh_priv.param("telemetry_transform_timeout", 0.5)); telemetry_transform_timeout = ros::Duration(nh_priv.param("telemetry_transform_timeout", 0.5));

View File

@@ -53,7 +53,7 @@ void publishZero(const ros::TimerEvent& e)
} }
ROS_INFO_THROTTLE(10, "publish zero"); ROS_INFO_THROTTLE(10, "publish zero");
geometry_msgs::PoseStamped zero; static geometry_msgs::PoseStamped zero;
zero.header.frame_id = local_frame_id; zero.header.frame_id = local_frame_id;
zero.header.stamp = e.current_real; zero.header.stamp = e.current_real;
zero.pose.orientation.w = 1; zero.pose.orientation.w = 1;

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env bash
# $ ./waitfile <file> <command> <args...>
# wait until <file> appears and then invoke <command> with <args>
echo "wait for file $1"
while [ ! -e "$1" ]; do sleep 1; done;
echo "file $1 appeared"
exec "${@:2}"

View File

@@ -33,3 +33,19 @@ def test_web_video_server(node):
# Python 3 # Python 3
import urllib.request as urllib import urllib.request as urllib
urllib.urlopen("http://localhost:8080").read() urllib.urlopen("http://localhost:8080").read()
def test_shell(node):
execute = rospy.ServiceProxy('exec', srv.Execute)
execute.wait_for_service(5)
res = execute(cmd='echo foo')
assert res.code == 0
assert res.output == 'foo\n'
res = execute(cmd='foo')
assert res.code == 32512
assert res.output == ''
res = execute(cmd='ls foo')
assert res.code == 512
assert res.output == ''

View File

@@ -1 +0,0 @@
/tmp/clover.err

View File

@@ -1 +0,0 @@
/etc/clover_version

View File

@@ -1,5 +1,3 @@
<title>Clover Drone Kit Tools</title>
<h1>Clover Drone Kit Tools</h1> <h1>Clover Drone Kit Tools</h1>
<ul> <ul>
@@ -9,20 +7,19 @@
<li><a href="viz.html">View 3D visualization</a> (<code>ros3djs</code>)</li> <li><a href="viz.html">View 3D visualization</a> (<code>ros3djs</code>)</li>
<li><a href="aruco_map.html">3D visualization for markers map</a> (<code>ros3djs</code>)</li> <li><a href="aruco_map.html">3D visualization for markers map</a> (<code>ros3djs</code>)</li>
<li><a href="../clover_blocks/">Blocks programming</a> (<code>Blockly</code>)</li> <li><a href="../clover_blocks/">Blocks programming</a> (<code>Blockly</code>)</li>
<li><a href="clover.err">Clover console</a> (<code>/tmp/clover.err</code>)</li>
</ul> </ul>
<div class="version"></div> <div class="version"></div>
<script src="js/roslib.js"></script>
<script type="text/javascript"> <script type="text/javascript">
document.querySelector("#wvs").href = location.protocol + '//' + location.hostname + ':8080'; document.querySelector("#wvs").href = location.protocol + '//' + location.hostname + ':8080';
document.querySelector("#butterfly").href = location.protocol + '//' + location.hostname + ':57575'; document.querySelector("#butterfly").href = location.protocol + '//' + location.hostname + ':57575';
// Determine image version // Determine image version
fetch('clover_version').then(function(response) { var ros = new ROSLIB.Ros({ url: 'ws://' + location.hostname + ':9090' });
if (response.status !== 200) return; var exec = new ROSLIB.Service({ ros: ros, name : '/exec', serviceType : 'clover/Execute' });
response.text().then(function(text) { exec.callService(new ROSLIB.ServiceRequest({ cmd: 'cat /etc/clover_version' }), function(result) {
document.querySelector('.version').innerHTML = 'Version: ' + text; document.querySelector('.version').innerHTML = 'Version: ' + result.output;
});
}); });
</script> </script>

View File

@@ -1,8 +0,0 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package clover_blocks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.21.1 (2020-11-17)
-------------------
* First release of clover_blocks package to ROS
* Contributors: Oleg Kalachev

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package format="2"> <package format="2">
<name>clover_blocks</name> <name>clover_blocks</name>
<version>0.21.1</version> <version>0.0.0</version>
<description>Blockly programming support for Clover</description> <description>Blockly programming support for Clover</description>
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer> <maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
<license>MIT</license> <license>MIT</license>

View File

@@ -29,7 +29,7 @@
</value> </value>
<value name="Z"> <value name="Z">
<shadow type="math_number" id="n0ULZn64%k.:,l(,D?TZ"> <shadow type="math_number" id="n0ULZn64%k.:,l(,D?TZ">
<field name="NUM">1</field> <field name="NUM">0</field>
</shadow> </shadow>
</value> </value>
<value name="ID"> <value name="ID">

View File

@@ -1,91 +1,106 @@
<xml xmlns="https://developers.google.com/blockly/xml"> <xml xmlns="https://developers.google.com/blockly/xml">
<block type="controls_whileUntil" id="U1it{GcGuSS:=[xiwZr1" x="113" y="113"> <variables>
<field name="MODE">WHILE</field> <variable id="_{V-S5HPBUl]CcJkL1Jw">led_count</variable>
<value name="BOOL"> </variables>
<block type="logic_boolean" id="]7ZDRwde}/RqjQCX}aVW"> <block type="variables_set" id="{)^J~:UMX%D;RWvztWLN" x="113" y="87">
<field name="BOOL">TRUE</field> <field name="VAR" id="_{V-S5HPBUl]CcJkL1Jw">led_count</field>
<value name="VALUE">
<block type="math_number" id="V_W$3,VFwZjcc|?|1o`l">
<field name="NUM">58</field>
</block> </block>
</value> </value>
<statement name="DO"> <next>
<block type="set_effect" id="WI0zqOz/z3].cR/6UWHn"> <block type="controls_whileUntil" id="U1it{GcGuSS:=[xiwZr1">
<field name="EFFECT">FILL</field> <field name="MODE">WHILE</field>
<value name="COLOR"> <value name="BOOL">
<shadow type="colour_picker" id="B`6;Xv{s2TFp8Yd=ZpSD"> <block type="logic_boolean" id="]7ZDRwde}/RqjQCX}aVW">
<field name="COLOUR">#000000</field> <field name="BOOL">TRUE</field>
</shadow> </block>
</value> </value>
<next> <statement name="DO">
<block type="set_led" id="^Vcs}ki?#ctf7rAchix$"> <block type="set_effect" id="WI0zqOz/z3].cR/6UWHn">
<value name="INDEX"> <field name="EFFECT">FILL</field>
<shadow type="math_number" id="U;VWW$[*LOF7Gf,~?YR7"> <value name="COLOR">
<field name="NUM">0</field> <shadow type="colour_picker" id="B`6;Xv{s2TFp8Yd=ZpSD">
<field name="COLOUR">#000000</field>
</shadow> </shadow>
<block type="math_arithmetic" id="AI6PZBd`]_Z%_~4c-%dB"> </value>
<field name="OP">MULTIPLY</field> <next>
<value name="A"> <block type="set_led" id="^Vcs}ki?#ctf7rAchix$">
<shadow type="math_number" id="|p}X]`SedK3).F/;}NlB"> <value name="INDEX">
<field name="NUM">1</field> <shadow type="math_number" id="U;VWW$[*LOF7Gf,~?YR7">
<field name="NUM">0</field>
</shadow> </shadow>
<block type="math_arithmetic" id="-haE#:,cg{-J=NZERA;F"> <block type="math_arithmetic" id="AI6PZBd`]_Z%_~4c-%dB">
<field name="OP">DIVIDE</field> <field name="OP">MULTIPLY</field>
<value name="A"> <value name="A">
<shadow type="math_number" id="::st;ot}[r]csqceURu*"> <shadow type="math_number" id="|p}X]`SedK3).F/;}NlB">
<field name="NUM">1</field> <field name="NUM">1</field>
</shadow> </shadow>
<block type="math_arithmetic" id="a%+LN)F~=Igg+,p02[qo"> <block type="math_arithmetic" id="-haE#:,cg{-J=NZERA;F">
<field name="OP">ADD</field> <field name="OP">DIVIDE</field>
<value name="A"> <value name="A">
<shadow type="math_number" id="*yIGN((y)/^z0:f5:VDw"> <shadow type="math_number" id="::st;ot}[r]csqceURu*">
<field name="NUM">1</field> <field name="NUM">1</field>
</shadow> </shadow>
<block type="get_yaw" id="mf%77q30bEqNfc/3`Mtb"> <block type="math_arithmetic" id="a%+LN)F~=Igg+,p02[qo">
<field name="FRAME_ID">MAP</field> <field name="OP">ADD</field>
<value name="ID"> <value name="A">
<shadow type="math_number" id="xb32G.N#ip`|^Xv*MOmY"> <shadow type="math_number" id="*yIGN((y)/^z0:f5:VDw">
<field name="NUM">0</field> <field name="NUM">1</field>
</shadow>
<block type="get_yaw" id="mf%77q30bEqNfc/3`Mtb">
<field name="FRAME_ID">MAP</field>
<value name="ID">
<shadow type="math_number" id="xb32G.N#ip`|^Xv*MOmY">
<field name="NUM">0</field>
</shadow>
</value>
</block>
</value>
<value name="B">
<shadow type="math_number" id="T/fTrm;j2Azgav;gI{ZW">
<field name="NUM">180</field>
</shadow> </shadow>
</value> </value>
</block> </block>
</value> </value>
<value name="B"> <value name="B">
<shadow type="math_number" id="T/fTrm;j2Azgav;gI{ZW"> <shadow type="math_number" id="Wo1/ZCeir,u6/.e1H+BB">
<field name="NUM">180</field> <field name="NUM">360</field>
</shadow> </shadow>
</value> </value>
</block> </block>
</value> </value>
<value name="B"> <value name="B">
<shadow type="math_number" id="Wo1/ZCeir,u6/.e1H+BB"> <shadow type="math_number" id="jENTcXz0C5/=)Xpd!}LL">
<field name="NUM">360</field> <field name="NUM">1</field>
</shadow> </shadow>
<block type="variables_get" id="Ko,`n=i88FY~`YbQLA?[">
<field name="VAR" id="_{V-S5HPBUl]CcJkL1Jw">led_count</field>
</block>
</value> </value>
</block> </block>
</value> </value>
<value name="B"> <value name="COLOR">
<shadow type="math_number" id="jENTcXz0C5/=)Xpd!}LL"> <shadow type="colour_picker" id="+vw3bff.5c[=_w,Xm^C(">
<field name="NUM">1</field> <field name="COLOUR">#3366ff</field>
</shadow>
<block type="led_count" id="vM@X8s!xa]v}AaK6PWF5"></block>
</value>
</block>
</value>
<value name="COLOR">
<shadow type="colour_picker" id="+vw3bff.5c[=_w,Xm^C(">
<field name="COLOUR">#3366ff</field>
</shadow>
</value>
<next>
<block type="wait" id="DT%f$bn1*1El5zsgUW8Y">
<value name="TIME">
<shadow type="math_number" id="~Y0hNY[_^#v@aZkE-TH[">
<field name="NUM">0.1</field>
</shadow> </shadow>
</value> </value>
<next>
<block type="wait" id="DT%f$bn1*1El5zsgUW8Y">
<value name="TIME">
<shadow type="math_number" id="~Y0hNY[_^#v@aZkE-TH[">
<field name="NUM">0.1</field>
</shadow>
</value>
</block>
</next>
</block> </block>
</next> </next>
</block> </block>
</next> </statement>
</block> </block>
</statement> </next>
</block> </block>
</xml> </xml>

View File

@@ -11,8 +11,7 @@
from __future__ import print_function from __future__ import print_function
import rospy import rospy
import os, sys import os
import traceback
import threading import threading
import re import re
import uuid import uuid
@@ -117,12 +116,7 @@ def run(req):
rospy.loginfo('Program forced to stop') rospy.loginfo('Program forced to stop')
except Exception as e: except Exception as e:
rospy.logerr(str(e)) rospy.logerr(str(e))
traceback.print_exc() error_pub.publish(str(e))
etype, value, tb = sys.exc_info()
fmt = traceback.format_exception(etype, value, tb)
fmt.pop(1) # remove 'clover_blocks' file frame
exc_info = ''.join(fmt)
error_pub.publish(str(e) + '\n\n' + exc_info)
rospy.loginfo('Program terminated') rospy.loginfo('Program terminated')
running_lock.release() running_lock.release()

View File

@@ -353,17 +353,6 @@ Blockly.Blocks['set_effect'] = {
} }
}; };
Blockly.Blocks['led_count'] = {
init: function () {
this.appendDummyInput()
.appendField("LED count");
this.setOutput(true, "Number");
this.setColour(COLOR_LED);
this.setTooltip("Returns the number of LEDs (configured in led.launch).");
this.setHelpUrl(DOCS_URL + '#' + this.type);
}
};
Blockly.Blocks['take_off'] = { Blockly.Blocks['take_off'] = {
init: function () { init: function () {
this.appendValueInput("ALT") this.appendValueInput("ALT")
@@ -546,7 +535,7 @@ Blockly.Blocks['gpio_read'] = {
this.setOutput(true, "Boolean"); this.setOutput(true, "Boolean");
this.setColour(COLOR_GPIO); this.setColour(COLOR_GPIO);
this.setTooltip("Returns if there is voltage on a GPIO pin."); this.setTooltip("Returns if there is voltage on a GPIO pin.");
this.setHelpUrl(DOCS_URL + '#GPIO'); this.setHelpUrl(DOCS_URL + '#' + this.type);
} }
}; };
@@ -563,7 +552,7 @@ Blockly.Blocks['gpio_write'] = {
this.setPreviousStatement(true, null); this.setPreviousStatement(true, null);
this.setNextStatement(true, null); this.setNextStatement(true, null);
this.setTooltip("Set GPIO pin level."); this.setTooltip("Set GPIO pin level.");
this.setHelpUrl(DOCS_URL + '#GPIO'); this.setHelpUrl(DOCS_URL + '#' + this.type);
} }
}; };
@@ -579,24 +568,7 @@ Blockly.Blocks['set_servo'] = {
this.setColour(COLOR_GPIO); this.setColour(COLOR_GPIO);
this.setPreviousStatement(true, null); this.setPreviousStatement(true, null);
this.setNextStatement(true, null); this.setNextStatement(true, null);
this.setTooltip("Set PWM on a GPIO pin to control servo. PWM is specified in range of 5002500 μs."); this.setTooltip("Set PWM on a GPIO pin to control servo. PWM is specified in range of 5002500 ms.");
this.setHelpUrl(DOCS_URL + '#GPIO'); this.setHelpUrl(DOCS_URL + '#' + this.type);
}
};
Blockly.Blocks['set_duty_cycle'] = {
init: function () {
this.appendValueInput("PIN")
.setCheck("Number")
.appendField("set GPIO pin");
this.appendValueInput("DUTY_CYCLE")
.setCheck("Number")
.appendField("to duty cycle");
this.setInputsInline(true);
this.setColour(COLOR_GPIO);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip("Set PWM duty cycle on a GPIO pin (better to control LEDs, etc). Duty cycle is set in range of 01.");
this.setHelpUrl(DOCS_URL + '#GPIO');
} }
}; };

View File

@@ -106,7 +106,6 @@
<value name="INDEX"><shadow type="math_number"><field name="NUM">0</field></shadow></value> <value name="INDEX"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
<value name="COLOR"><shadow type="colour_picker"></shadow></value> <value name="COLOR"><shadow type="colour_picker"></shadow></value>
</block> </block>
<block type="led_count"></block>
</category> </category>
<category name="GPIO" colour="#5b97cc"> <category name="GPIO" colour="#5b97cc">
<block type="gpio_read"> <block type="gpio_read">
@@ -120,10 +119,6 @@
<value name="PIN"><shadow type="math_number"><field name="NUM">1</field></shadow></value> <value name="PIN"><shadow type="math_number"><field name="NUM">1</field></shadow></value>
<value name="PWM"><shadow type="math_number"><field name="NUM">1500</field></shadow></value> <value name="PWM"><shadow type="math_number"><field name="NUM">1500</field></shadow></value>
</block> </block>
<block type="set_duty_cycle">
<value name="PIN"><shadow type="math_number"><field name="NUM">1</field></shadow></value>
<value name="DUTY_CYCLE"><shadow type="math_number"><field name="NUM">0.5</field></shadow></value>
</block>
</category> </category>
<sep></sep> <sep></sep>
<category name="Logic" colour="#5b80a5"> <category name="Logic" colour="#5b80a5">

View File

@@ -15,7 +15,7 @@ Blockly.Python.addReservedWords('_b,_print');
Blockly.Python.addReservedWords('rospy,srv,Trigger,get_telemetry,navigate,set_velocity,land'); Blockly.Python.addReservedWords('rospy,srv,Trigger,get_telemetry,navigate,set_velocity,land');
Blockly.Python.addReservedWords('navigate_wait,land_wait,wait_arrival,wait_yaw,get_distance'); Blockly.Python.addReservedWords('navigate_wait,land_wait,wait_arrival,wait_yaw,get_distance');
Blockly.Python.addReservedWords('pigpio,pi,Range'); Blockly.Python.addReservedWords('pigpio,pi,Range');
Blockly.Python.addReservedWords('SetLEDEffect,set_effect,led_count,get_led_count'); Blockly.Python.addReservedWords('SetLEDEffect,set_effect');
Blockly.Python.addReservedWords('SetLEDs,LEDState,set_leds'); Blockly.Python.addReservedWords('SetLEDs,LEDState,set_leds');
const IMPORT_SRV = `from clover import srv const IMPORT_SRV = `from clover import srv
@@ -87,9 +87,6 @@ function generateROSDefinitions() {
Blockly.Python.definitions_['import_set_led'] = 'from led_msgs.srv import SetLEDs\nfrom led_msgs.msg import LEDState'; Blockly.Python.definitions_['import_set_led'] = 'from led_msgs.srv import SetLEDs\nfrom led_msgs.msg import LEDState';
code += `set_leds = rospy.ServiceProxy('led/set_leds', SetLEDs, persistent=True)\n`; code += `set_leds = rospy.ServiceProxy('led/set_leds', SetLEDs, persistent=True)\n`;
} }
if (rosDefinitions.ledStateArray) {
Blockly.Python.definitions_['import_led_state_array'] = 'from led_msgs.msg import LEDStateArray';
}
if (rosDefinitions.navigateWait) { if (rosDefinitions.navigateWait) {
Blockly.Python.definitions_['import_math'] = 'import math'; Blockly.Python.definitions_['import_math'] = 'import math';
code += NAVIGATE_WAIT(); code += NAVIGATE_WAIT();
@@ -391,48 +388,29 @@ Blockly.Python.set_led = function(block) {
if (/^'(.*)'$/.test(colorCode)) { // is simple string if (/^'(.*)'$/.test(colorCode)) { // is simple string
let color = parseColor(colorCode); let color = parseColor(colorCode);
return `set_leds([LEDState(index=int(${index}), r=${color.r}, g=${color.g}, b=${color.b})])\n`; // TODO: check for simple int return `set_leds([LEDState(index=${index}, r=${color.r}, g=${color.g}, b=${color.b})])\n`;
} else { } else {
let parseColor = Blockly.Python.provideFunction_('parse_color', [PARSE_COLOR]); let parseColor = Blockly.Python.provideFunction_('parse_color', [PARSE_COLOR]);
return `set_leds([LEDState(index=${index}, **${parseColor}(${colorCode}))])\n`; return `set_leds([LEDState(index=${index}, **${parseColor}(${colorCode})])\n`;
} }
} }
const GET_LED_COUNT = `led_count = None
def get_led_count():
global led_count
if led_count is None:
led_count = len(rospy.wait_for_message('led/state', LEDStateArray, timeout=10).leds)
return led_count\n`;
Blockly.Python.led_count = function(block) {
rosDefinitions.ledStateArray = true;
initNode();
Blockly.Python.definitions_['get_led_count'] = GET_LED_COUNT;
return [`get_led_count()`, Blockly.Python.ORDER_FUNCTION_CALL]
}
function pigpio() { function pigpio() {
Blockly.Python.definitions_['import_pigpio'] = 'import pigpio'; Blockly.Python.definitions_['import_pigpio'] = 'import pigpio';
Blockly.Python.definitions_['init_pigpio'] = 'pi = pigpio.pi()'; Blockly.Python.definitions_['init_pigpio'] = 'pi = pigpio.pi()';
} }
const GPIO_READ = `\ndef gpio_read(pin): const GPIO_READ = `\ndef gpio_read(pin):
pi.set_mode(pin, pigpio.INPUT) pi.set_mode(pin, pigpio.INPUT)
return pi.read(pin)\n`; return pi.read(pin)\n`;
const GPIO_WRITE = `\ndef gpio_write(pin, level): const GPIO_WRITE = `\ndef gpio_write(pin, level):
pi.set_mode(pin, pigpio.OUTPUT) pi.set_mode(pin, pigpio.OUTPUT)
pi.write(pin, level)\n`; pi.write(pin, level)\n`;
const SET_SERVO = `\ndef set_servo(pin, pwm): const SET_SERVO = `\ndef set_servo(pin, pwm):
pi.set_mode(pin, pigpio.OUTPUT) pi.set_mode(pin, pigpio.OUTPUT)
pi.set_servo_pulsewidth(pin, pwm)\n`; pi.set_servo_pulsewidth(pin, pwm)\n`;
const SET_DUTY_CYCLE = `\ndef set_duty_cycle(pin, duty_cycle):
pi.set_mode(pin, pigpio.OUTPUT)
pi.set_PWM_dutycycle(pin, duty_cycle * 255)\n`;
Blockly.Python.gpio_read = function(block) { Blockly.Python.gpio_read = function(block) {
pigpio(); pigpio();
@@ -456,11 +434,3 @@ Blockly.Python.set_servo = function(block) {
var pwm = Blockly.Python.valueToCode(block, 'PWM', Blockly.Python.ORDER_NONE); var pwm = Blockly.Python.valueToCode(block, 'PWM', Blockly.Python.ORDER_NONE);
return `set_servo(${pin}, ${pwm})\n`; return `set_servo(${pin}, ${pwm})\n`;
} }
Blockly.Python.set_duty_cycle = function(block) {
pigpio();
Blockly.Python.definitions_['set_duty_cycle'] = SET_DUTY_CYCLE;
var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_NONE);
var dutyCycle = Blockly.Python.valueToCode(block, 'DUTY_CYCLE', Blockly.Python.ORDER_NONE);
return `set_duty_cycle(${pin}, ${dutyCycle})\n`;
}

View File

@@ -1,9 +0,0 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package clover_description
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.21.1 (2020-11-17)
-------------------
* First release of clover_description package to ROS
* Contributors: Alexey Rogachevskiy

View File

@@ -1,6 +1,6 @@
<package format="2"> <package format="2">
<name>clover_description</name> <name>clover_description</name>
<version>0.21.1</version> <version>0.0.1</version>
<description>The clover_description package provides URDF models of the Clover series of quadcopters.</description> <description>The clover_description package provides URDF models of the Clover series of quadcopters.</description>
<maintainer email="sfalexrog@gmail.com">Alexey Rogachevskiy</maintainer> <maintainer email="sfalexrog@gmail.com">Alexey Rogachevskiy</maintainer>

View File

@@ -1,8 +0,0 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package clover_simulation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.21.1 (2020-11-17)
-------------------
* First release of clover_simulation package to ROS
* Contributors: Alexey Rogachevskiy

View File

@@ -52,7 +52,7 @@ target_compile_options(throttling_camera PRIVATE -std=c++11)
add_dependencies(throttling_camera ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) add_dependencies(throttling_camera ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
install(DIRECTORY models DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) install(DIRECTORY meshes DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
install(DIRECTORY resources DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) install(DIRECTORY resources DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
catkin_install_python(PROGRAMS scripts/aruco_gen catkin_install_python(PROGRAMS scripts/aruco_gen

View File

@@ -1,5 +1,4 @@
<launch> <launch>
<arg name="type" default="gazebo"/> <!-- gazebo, jmavsim, none (only clover packages) -->
<arg name="mav_id" default="0"/> <arg name="mav_id" default="0"/>
<arg name="est" default="ekf2"/> <!-- PX4 estimator: lpe, ekf2 --> <arg name="est" default="ekf2"/> <!-- PX4 estimator: lpe, ekf2 -->
<arg name="vehicle" default="clover"/> <!-- PX4 vehicle configuration: clover, clover_vpe --> <arg name="vehicle" default="clover"/> <!-- PX4 vehicle configuration: clover, clover_vpe -->
@@ -10,22 +9,22 @@
<arg name="use_clover_physics" default="false"/> <!-- Use inertial parameters from CAD models --> <arg name="use_clover_physics" default="false"/> <!-- Use inertial parameters from CAD models -->
<!-- Gazebo instance --> <!-- Gazebo instance -->
<include file="$(find gazebo_ros)/launch/empty_world.launch" if="$(eval type == 'gazebo')"> <include file="$(find gazebo_ros)/launch/empty_world.launch">
<!-- Workaround for crashes in VMware --> <!-- Workaround for crashes in VMware -->
<env name="SVGA_VGPU10" value="0"/> <env name="SVGA_VGPU10" value="0"/>
<arg name="gui" value="true"/> <arg name="gui" value="true"/>
<arg name="world_name" value="$(find clover_simulation)/resources/worlds/clover_aruco.world"/> <arg name="world_name" value="$(find clover_simulation)/resources/worlds/clover.world"/>
<arg name="verbose" value="true"/> <arg name="verbose" value="true"/>
</include> </include>
<!-- PX4 instance --> <!-- PX4 instance -->
<node name="sitl_$(arg mav_id)" pkg="px4" type="px4" output="screen" args="$(find px4)/ROMFS/px4fmu_common -s etc/init.d-posix/rcS -i $(arg mav_id)" unless="$(eval type == 'none')"> <node name="sitl_$(arg mav_id)" pkg="px4" type="px4" output="screen" args="$(find px4)/ROMFS/px4fmu_common -s etc/init.d-posix/rcS -i $(arg mav_id)">
<env name="PX4_SIM_MODEL" value="$(arg vehicle)"/> <env name="PX4_SIM_MODEL" value="$(arg vehicle)"/>
<env name="PX4_ESTIMATOR" value="$(arg est)"/> <env name="PX4_ESTIMATOR" value="$(arg est)"/>
</node> </node>
<!-- Clover model --> <!-- Clover model -->
<include file="$(find clover_description)/launch/spawn_drone.launch" if="$(eval type == 'gazebo')"> <include file="$(find clover_description)/launch/spawn_drone.launch">
<arg name="main_camera" value="$(arg main_camera)"/> <arg name="main_camera" value="$(arg main_camera)"/>
<arg name="rangefinder" value="$(arg rangefinder)"/> <arg name="rangefinder" value="$(arg rangefinder)"/>
<arg name="led" value="$(arg led)"/> <arg name="led" value="$(arg led)"/>
@@ -33,20 +32,10 @@
<arg name="use_clover_physics" value="$(arg use_clover_physics)"/> <arg name="use_clover_physics" value="$(arg use_clover_physics)"/>
</include> </include>
<node name="jmavsim" pkg="px4" type="jmavsim_run.sh" output="screen" if="$(eval type == 'jmavsim')"/>
<param name="use_sim_time" value="false" if="$(eval type == 'jmavsim')"/>
<!-- Clover services --> <!-- Clover services -->
<include file="$(find clover)/launch/clover.launch"> <include file="$(find clover)/launch/clover.launch">
<arg name="simulator" value="true"/> <arg name="simulator" value="true"/>
<arg name="fcu_conn" value="sitl"/> <arg name="fcu_conn" value="sitl"/>
<arg name="fcu_ip" value="127.0.0.1"/> <arg name="fcu_ip" value="127.0.0.1"/>
<arg name="gcs_bridge" value=""/>
<arg name="rc" default="false"/>
<arg name="web_video_server" default="false" if="$(eval type == 'jmavsim')"/>
<arg name="main_camera" default="false" if="$(eval type == 'jmavsim')"/>
<arg name="aruco" default="false" if="$(eval type == 'jmavsim')"/>
<arg name="led" default="false" if="$(eval type == 'jmavsim')"/>
</include> </include>
</launch> </launch>

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Some files were not shown because too many files have changed in this diff Show More