mirror of
https://github.com/CopterExpress/clover.git
synced 2026-06-01 15:39:32 +00:00
Compare commits
58 Commits
v0.23-rc.4
...
v0.22-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9cddc81d1d | ||
|
|
ced9b56452 | ||
|
|
8bd4d3a8f8 | ||
|
|
4730dabaaf | ||
|
|
0991427878 | ||
|
|
3d4c02bc03 | ||
|
|
8a6bdccc9c | ||
|
|
f36401274d | ||
|
|
2cfd21269c | ||
|
|
81bcfef85b | ||
|
|
00412125f9 | ||
|
|
55366a1fac | ||
|
|
cc2ebb368d | ||
|
|
33500a13d0 | ||
|
|
d7d95132ab | ||
|
|
4c049ac349 | ||
|
|
fca3f52424 | ||
|
|
27c0f23ffa | ||
|
|
d6590e9a8d | ||
|
|
c93beec30d | ||
|
|
47628ba4af | ||
|
|
98e43aba49 | ||
|
|
404b42c9f9 | ||
|
|
6b831359dc | ||
|
|
10076e35f4 | ||
|
|
76a6a58a42 | ||
|
|
62069ab80a | ||
|
|
e1643a681a | ||
|
|
6f30613ce0 | ||
|
|
d539753e72 | ||
|
|
cc80f2b4c1 | ||
|
|
1893f0528b | ||
|
|
ce1f1d9db5 | ||
|
|
8b42fcfda3 | ||
|
|
60b9d1d61d | ||
|
|
61ae5d0537 | ||
|
|
7ffcbde82e | ||
|
|
ccc53f1cfb | ||
|
|
be2b447b46 | ||
|
|
b333dd8708 | ||
|
|
4b5524e467 | ||
|
|
5b970d5197 | ||
|
|
617ae0dcdd | ||
|
|
a1d2ae9a23 | ||
|
|
9372386f6b | ||
|
|
4b97f9d4af | ||
|
|
6af1fd2837 | ||
|
|
b7545830ba | ||
|
|
4796c4acb7 | ||
|
|
de3fb77db2 | ||
|
|
036d3dccd6 | ||
|
|
24cfc54c06 | ||
|
|
173c8cbe3a | ||
|
|
2d8cd0e0ab | ||
|
|
ee667257ef | ||
|
|
3c4f57cbe7 | ||
|
|
3ee598004a | ||
|
|
673cabe7ab |
29
.github/workflows/build-image.yaml
vendored
29
.github/workflows/build-image.yaml
vendored
@@ -1,29 +0,0 @@
|
||||
name: RPi image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
release:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
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: |
|
||||
cd images && sudo chmod -R 777 . && zip -9 $(echo clover_*).zip clover_* && ls -l . && unzip -l clover_*.zip
|
||||
- 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 }}
|
||||
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
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
|
||||
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
|
||||
57
.github/workflows/docs.yml
vendored
57
.github/workflows/docs.yml
vendored
@@ -1,57 +0,0 @@
|
||||
name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- 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
|
||||
builder/assets/install_gitbook.sh
|
||||
npm install markdownlint-cli@0.28.1 -g # FIXME: https://github.com/DavidAnson/markdownlint/issues/435
|
||||
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
|
||||
18
.github/workflows/editorconfig.yaml
vendored
18
.github/workflows/editorconfig.yaml
vendored
@@ -1,18 +0,0 @@
|
||||
name: Editorconfig
|
||||
|
||||
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|json-to-pretty-yaml.js|draw.cpp|BinUtils.swift|\.idea|apps/android/app|blockly/|clover_blocks/programs/|highlight/|python.js|Assets.xcassets|test_parser_pass.txt|test_node_failure.txt|aruco_pose/vendor|\.stl|\.dxf|\.dae|\.material"
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,3 @@ _book/
|
||||
package-lock.json
|
||||
clover_blocks/programs/*.*
|
||||
!clover_blocks/programs/examples/*
|
||||
/.vscode/
|
||||
|
||||
@@ -110,8 +110,7 @@
|
||||
"Li-ion",
|
||||
"Nvidia",
|
||||
"VirtualBox",
|
||||
"VMware",
|
||||
"DuoCam"
|
||||
"VMware"
|
||||
],
|
||||
"code_blocks": false
|
||||
},
|
||||
|
||||
125
.travis.yml
Normal file
125
.travis.yml
Normal 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: 25
|
||||
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 -9 ${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/
|
||||
@@ -1,6 +1,6 @@
|
||||
# clover🍀: create autonomous drones easily
|
||||
|
||||
<img src="docs/assets/clover42-main-margin.png" align="right" width="400px" alt="COEX Clover Drone">
|
||||
<img src="docs/assets/clever4-front-white.png" align="right" width="400px" alt="COEX 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.
|
||||
|
||||
@@ -20,8 +20,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).
|
||||
|
||||

|
||||

|
||||
[](https://travis-ci.org/CopterExpress/clover)
|
||||
|
||||
Image features:
|
||||
|
||||
@@ -38,10 +37,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).
|
||||
|
||||
## Support
|
||||
|
||||
[](https://t.me/COEXHelpdesk)
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# iOS-приложение для управления Клевером
|
||||
iOS-приложение для управления Клевером
|
||||
--------------------------------------
|
||||
|
||||
Для установки зависимостей необходим [CocoaPods](https://cocoapods.org):
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -119,7 +119,7 @@ generate_messages(
|
||||
|
||||
## Generate dynamic reconfigure parameters in the 'cfg' folder
|
||||
generate_dynamic_reconfigure_options(
|
||||
cfg/Detector.cfg
|
||||
cfg/DetectorParams.cfg
|
||||
)
|
||||
|
||||
###################################
|
||||
@@ -202,11 +202,11 @@ set_property(TARGET aruco_pose
|
||||
# )
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
)
|
||||
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
|
||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark cpp header files for installation
|
||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||
@@ -226,10 +226,6 @@ catkin_install_python(PROGRAMS src/genmap.py
|
||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
)
|
||||
|
||||
install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||
|
||||
install(DIRECTORY map DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
@@ -70,7 +70,7 @@ It's recommended to run it within the same nodelet manager with the camera nodel
|
||||
|
||||
* `~map` – path to text file with markers list
|
||||
* `~frame_id` – published frame id (default: `aruco_map`)
|
||||
* `~known_tilt` – known tilt (pitch and roll) of markers map as a frame
|
||||
* `~known_tilt` – debug image width
|
||||
* `~image_width` – debug image width (default: 2000)
|
||||
* `~image_height` – debug image height (default: 2000)
|
||||
* `~image_margin` – debug image margin (default: 200)
|
||||
|
||||
@@ -8,8 +8,6 @@ p = cv2.aruco.DetectorParameters_create()
|
||||
|
||||
gen = ParameterGenerator()
|
||||
|
||||
gen.add("enabled", bool_t, 0, "if detection enabled", True)
|
||||
|
||||
gen.add("adaptiveThreshConstant", double_t, 0,
|
||||
"Constant for adaptive thresholding before finding contours",
|
||||
p.adaptiveThreshConstant, 0, 100)
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>aruco_pose</name>
|
||||
<version>0.21.1</version>
|
||||
<version>0.0.1</version>
|
||||
<description>Positioning with ArUco markers</description>
|
||||
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
|
||||
@@ -62,7 +62,6 @@ private:
|
||||
std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
|
||||
std::unique_ptr<tf2_ros::TransformListener> tf_listener_;
|
||||
std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>> dyn_srv_;
|
||||
bool enabled_ = true;
|
||||
cv::Ptr<cv::aruco::Dictionary> dictionary_;
|
||||
cv::Ptr<cv::aruco::DetectorParameters> parameters_;
|
||||
image_transport::Publisher debug_pub_;
|
||||
@@ -126,8 +125,6 @@ public:
|
||||
private:
|
||||
void imageCallback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr &cinfo)
|
||||
{
|
||||
if (!enabled_) return;
|
||||
|
||||
Mat image = cv_bridge::toCvShare(msg, "bgr8")->image;
|
||||
|
||||
vector<int> ids;
|
||||
@@ -356,7 +353,6 @@ private:
|
||||
|
||||
void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level)
|
||||
{
|
||||
enabled_ = config.enabled;
|
||||
parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant;
|
||||
parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin;
|
||||
parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"yametrika",
|
||||
"anchors",
|
||||
"collapsible-menu",
|
||||
"validate-links@https://github.com/okalachev/gitbook-plugin-validate-links.git",
|
||||
"validate-links",
|
||||
"bulk-redirect@https://github.com/okalachev/gitbook-plugin-bulk-redirect.git",
|
||||
"sitemap@https://github.com/okalachev/plugin-sitemap.git",
|
||||
"toolbar@https://github.com/hamishwillee/gitbook-plugin-toolbar.git",
|
||||
|
||||
@@ -8,9 +8,5 @@ ExecStart=/bin/bash -c ". /home/pi/catkin_ws/devel/setup.sh; \
|
||||
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clover clover.launch --wait --screen --skip-log-check \
|
||||
2> >(tee /tmp/clover.err)"
|
||||
|
||||
ExecStartPre=+rm /var/log/clover.log
|
||||
StandardOutput=file:/var/log/clover.log
|
||||
StandardError=file:/var/log/clover.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -15,17 +15,17 @@ set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
|
||||
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
||||
land = rospy.ServiceProxy('land', Trigger)
|
||||
|
||||
print('Take off and hover 1 m above the ground')
|
||||
# Take off and hover 1 m above the ground
|
||||
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
||||
|
||||
# Wait for 5 seconds
|
||||
rospy.sleep(5)
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
print('Fly forward 1 m')
|
||||
# Fly forward 1 m
|
||||
navigate(x=1, y=0, z=0, frame_id='body')
|
||||
|
||||
# Wait for 5 seconds
|
||||
rospy.sleep(5)
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
print('Perform landing')
|
||||
# Perform landing
|
||||
land()
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/aruco
|
||||
# Information: https://clover.coex.tech/en/aruco.html
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
@@ -15,23 +15,23 @@ set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
|
||||
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
||||
land = rospy.ServiceProxy('land', Trigger)
|
||||
|
||||
print('Take off and hover 1 m above the ground')
|
||||
# Take off and hover 1 m above the ground
|
||||
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
||||
|
||||
# Wait for 5 seconds
|
||||
rospy.sleep(5)
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
print('Fly 1 meter above ArUco marker 0')
|
||||
# Fly 1 meter above ArUco marker 0
|
||||
navigate(x=0, y=0, z=1, frame_id='aruco_0')
|
||||
|
||||
# Wait for 5 seconds
|
||||
rospy.sleep(5)
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
print('Fly to x=1 y=1 z=1 relative to ArUco markers map')
|
||||
# Fly to x=1 y=1 z=1 relative to ArUco markers map
|
||||
navigate(x=1, y=1, z=1, frame_id='aruco_map')
|
||||
|
||||
# Wait for 5 seconds
|
||||
rospy.sleep(5)
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
print('Perform landing')
|
||||
# Perform landing
|
||||
land()
|
||||
@@ -1,4 +1,4 @@
|
||||
# Information: https://clover.coex.tech/led
|
||||
# Information: https://clover.coex.tech/en/leds.html
|
||||
|
||||
import rospy
|
||||
from clover.srv import SetLEDEffect
|
||||
@@ -31,11 +31,11 @@ def navigate_wait(x=0, y=0, z=0, yaw=float('nan'), yaw_rate=0, speed=0.5, \
|
||||
return res
|
||||
rospy.sleep(0.2)
|
||||
|
||||
print('Take off 1 meter')
|
||||
# Take off 1 meter
|
||||
navigate_wait(z=1, frame_id='body', auto_arm=True)
|
||||
|
||||
print('Fly forward 1 m')
|
||||
# Fly forward 1 m
|
||||
navigate_wait(x=1, frame_id='body')
|
||||
|
||||
print('Land')
|
||||
# Land
|
||||
land()
|
||||
@@ -65,7 +65,7 @@ echo_stamp "#6 Turn on UART"
|
||||
# https://github.com/RPi-Distro/raspi-config/pull/75
|
||||
/usr/bin/raspi-config nonint do_serial 1
|
||||
/usr/bin/raspi-config nonint set_config_var enable_uart 1 /boot/config.txt
|
||||
echo dtoverlay=pi3-disable-bt >> /boot/config.txt
|
||||
/usr/bin/raspi-config nonint set_config_var dtoverlay pi3-disable-bt /boot/config.txt
|
||||
systemctl disable hciuart.service
|
||||
|
||||
# After adding to Raspbian OS
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# GitBook CLI is deprecated, its installation is broken.
|
||||
# This script fixes it until we stop using GitBook.
|
||||
|
||||
export NPM_CONFIG_UNSAFE_PERM=1
|
||||
|
||||
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
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
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_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip"
|
||||
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2020-08-24/2020-08-20-raspios-buster-arm64-lite.zip"
|
||||
|
||||
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
|
||||
export LANG=${LANG:='C.UTF-8'}
|
||||
@@ -105,6 +104,8 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/butterf
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/monkey.service' '/lib/systemd/system/'
|
||||
# software install
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-software.sh'
|
||||
# examples
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/examples' '/home/pi/' # TODO: symlink?
|
||||
# network setup
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-network.sh'
|
||||
# avahi setup
|
||||
@@ -113,11 +114,15 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/avahi-s
|
||||
# If RPi then use a one thread to build a ROS package on RPi, else use all
|
||||
[[ $(arch) == 'armv7l' ]] && NUMBER_THREADS=1 || NUMBER_THREADS=$(nproc --all)
|
||||
# Clover
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/clover.service' '/lib/systemd/system/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/roscore.service' '/lib/systemd/system/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/noetic-rosdep-clover.yaml' '/etc/ros/rosdep/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/ros_python_paths' '/etc/sudoers.d/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/pigpiod.service' '/lib/systemd/system/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/launch.nanorc' '/usr/share/nano/'
|
||||
# ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/kinetic-ros-clover.rosinstall' '/home/pi/ros_catkin_ws/'
|
||||
# Add PX4 udev rules
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${REPO_DIR}'/clover/config/99-px4fmu.rules' '/lib/udev/rules.d/'
|
||||
# Add rename script
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-ros.sh' ${REPO_URL} ${IMAGE_VERSION} false false ${NUMBER_THREADS}
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-validate.sh'
|
||||
|
||||
@@ -55,7 +55,4 @@ echo_stamp "Set max space for syslogs"
|
||||
# https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl
|
||||
sed -i 's/#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf
|
||||
|
||||
echo_stamp "Move /etc/ld.so.preload out of the way"
|
||||
mv /etc/ld.so.preload /etc/ld.so.preload.disabled-for-build
|
||||
|
||||
echo_stamp "End of init image"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
|
||||
set -ex # exit on error, echo commands
|
||||
set -e # Exit immidiately on non-zero result
|
||||
|
||||
REPO=$1
|
||||
REF=$2
|
||||
@@ -80,7 +80,7 @@ my_travis_retry sudo -u pi rosdep update
|
||||
|
||||
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
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
|
||||
@@ -91,7 +91,7 @@ apt install -y --no-install-recommends \
|
||||
ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \
|
||||
ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \
|
||||
ros-${ROS_DISTRO}-cv-camera=0.5.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
|
||||
apt-mark hold \
|
||||
ros-${ROS_DISTRO}-compressed-image-transport \
|
||||
@@ -100,9 +100,6 @@ ros-${ROS_DISTRO}-cv-camera \
|
||||
ros-${ROS_DISTRO}-image-publisher \
|
||||
ros-${ROS_DISTRO}-web-video-server
|
||||
|
||||
echo_stamp "Installing libboost-dev" # https://travis-ci.org/github/CopterExpress/clover/jobs/766318908#L6536
|
||||
my_travis_retry apt-get install -y --no-install-recommends libboost-dev libboost-all-dev
|
||||
|
||||
echo_stamp "Build and install Clover"
|
||||
cd /home/pi/catkin_ws
|
||||
# Don't try to install gazebo_ros
|
||||
@@ -112,8 +109,7 @@ my_travis_retry pip3 install wheel
|
||||
my_travis_retry pip3 install -r /home/pi/catkin_ws/src/clover/clover/requirements.txt
|
||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||
# Don't build simulation plugins for actual drone
|
||||
catkin_make -j2 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
source devel/setup.bash
|
||||
catkin_make -j2 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCATKIN_BLACKLIST_PACKAGES=clover_gazebo_plugins
|
||||
|
||||
echo_stamp "Install clever package (for backwards compatibility)"
|
||||
cd /home/pi/catkin_ws/src/clover/builder/assets/clever
|
||||
@@ -122,8 +118,8 @@ rm -rf build # remove build artifacts
|
||||
|
||||
echo_stamp "Build Clover documentation"
|
||||
cd /home/pi/catkin_ws/src/clover
|
||||
builder/assets/install_gitbook.sh
|
||||
gitbook install
|
||||
NPM_CONFIG_UNSAFE_PERM=true npm install gitbook-cli -g
|
||||
NPM_CONFIG_UNSAFE_PERM=true gitbook install
|
||||
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
|
||||
|
||||
@@ -135,9 +131,7 @@ my_travis_retry apt-get install -y --no-install-recommends \
|
||||
ros-${ROS_DISTRO}-usb-cam \
|
||||
ros-${ROS_DISTRO}-vl53l1x \
|
||||
ros-${ROS_DISTRO}-ws281x \
|
||||
ros-${ROS_DISTRO}-rosshow \
|
||||
ros-${ROS_DISTRO}-cmake-modules \
|
||||
ros-${ROS_DISTRO}-image-view
|
||||
ros-${ROS_DISTRO}-rosshow
|
||||
|
||||
# TODO move GeographicLib datasets to Mavros debian package
|
||||
echo_stamp "Install GeographicLib datasets (needed for mavros)" \
|
||||
@@ -151,20 +145,9 @@ catkin_make run_tests #&& catkin_test_results
|
||||
echo_stamp "Change permissions for catkin_ws"
|
||||
chown -Rf pi:pi /home/pi/catkin_ws
|
||||
|
||||
echo_stamp "Make \$HOME/examples symlink"
|
||||
ln -s "$(catkin_find clover examples --first-only)" /home/pi
|
||||
echo_stamp "Change permissions for examples"
|
||||
chown -Rf pi:pi /home/pi/examples
|
||||
|
||||
echo_stamp "Make systemd services symlinks"
|
||||
ln -s /home/pi/catkin_ws/src/clover/builder/assets/clover.service /lib/systemd/system/
|
||||
ln -s /home/pi/catkin_ws/src/clover/builder/assets/roscore.service /lib/systemd/system/
|
||||
# validate
|
||||
[ -f /lib/systemd/system/clover.service ]
|
||||
[ -f /lib/systemd/system/roscore.service ]
|
||||
|
||||
echo_stamp "Make udev rules symlink"
|
||||
ln -s "$(catkin_find clover udev --first-only)"/* /lib/udev/rules.d/
|
||||
|
||||
echo_stamp "Setup ROS environment"
|
||||
cat << EOF >> /home/pi/.bashrc
|
||||
LANG='C.UTF-8'
|
||||
|
||||
@@ -64,14 +64,15 @@ echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
|
||||
echo_stamp "Install apt keys & repos"
|
||||
|
||||
# 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 install --no-install-recommends -y dirmngr > /dev/null \
|
||||
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
|
||||
|
||||
echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
|
||||
|
||||
wget -O - 'http://packages.coex.tech/key.asc' | apt-key add -
|
||||
echo 'deb http://packages.coex.tech buster main' >> /etc/apt/sources.list
|
||||
echo "deb http://deb.coex.tech/opencv4 buster main" > /etc/apt/sources.list.d/opencv3.list
|
||||
echo "deb http://deb.coex.tech/ros buster main" > /etc/apt/sources.list.d/rpi-ros-melodic.list
|
||||
echo "deb http://deb.coex.tech/clover buster main" > /etc/apt/sources.list.d/clover.list
|
||||
|
||||
echo_stamp "Update apt cache"
|
||||
|
||||
@@ -81,7 +82,6 @@ apt-get update
|
||||
|
||||
# Let's retry fetching those packages several times, just in case
|
||||
echo_stamp "Software installing"
|
||||
my_travis_retry apt-get install --no-install-recommends -y cmake-data=3.13.4-1 cmake=3.13.4-1 # FIXME: using older CMake due to https://travis-ci.org/github/CopterExpress/clover/jobs/764367665#L6984
|
||||
my_travis_retry apt-get install --no-install-recommends -y \
|
||||
unzip \
|
||||
zip \
|
||||
@@ -94,9 +94,8 @@ lsof \
|
||||
git \
|
||||
dnsmasq \
|
||||
tmux \
|
||||
tree \
|
||||
vim \
|
||||
libjpeg8 \
|
||||
cmake \
|
||||
tcpdump \
|
||||
libpoco-dev \
|
||||
libzbar0 \
|
||||
@@ -123,10 +122,9 @@ sed -i "s/updates_available//" /usr/share/byobu/status/status
|
||||
|
||||
echo_stamp "Installing pip"
|
||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip2.py
|
||||
python3 get-pip.py
|
||||
python get-pip2.py
|
||||
rm get-pip.py get-pip2.py
|
||||
python get-pip.py
|
||||
rm get-pip.py
|
||||
#my_travis_retry pip install --upgrade pip
|
||||
#my_travis_retry pip3 install --upgrade pip
|
||||
|
||||
@@ -136,8 +134,6 @@ pip3 --version
|
||||
|
||||
echo_stamp "Install and enable Butterfly (web terminal)"
|
||||
echo_stamp "Workaround for tornado >= 6.0 breaking butterfly"
|
||||
export CRYPTOGRAPHY_DONT_BUILD_RUST=1
|
||||
my_travis_retry pip3 install cryptography==3.4.6 # https://stackoverflow.com/a/68472128/6850197
|
||||
my_travis_retry pip3 install tornado==5.1.1
|
||||
my_travis_retry pip3 install butterfly
|
||||
my_travis_retry pip3 install butterfly[systemd]
|
||||
@@ -149,16 +145,15 @@ my_travis_retry pip3 install --prefer-binary rpi_ws281x
|
||||
echo_stamp "Setup Monkey"
|
||||
mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
|
||||
mv /root/monkey /etc/monkey/sites/default
|
||||
sed -i 's/SymLink Off/SymLink On/' /etc/monkey/monkey.conf
|
||||
systemctl enable monkey.service
|
||||
|
||||
echo_stamp "Install Node.js"
|
||||
cd /home/pi
|
||||
wget --no-verbose https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-armv6l.tar.gz
|
||||
tar -xzf node-v10.15.0-linux-armv6l.tar.gz
|
||||
cp -R node-v10.15.0-linux-armv6l/* /usr/local/
|
||||
rm -rf node-v10.15.0-linux-armv6l/
|
||||
rm node-v10.15.0-linux-armv6l.tar.gz
|
||||
wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-arm64.tar.gz
|
||||
tar -xzf node-v10.15.0-linux-arm64.tar.gz
|
||||
cp -R node-v10.15.0-linux-arm64/* /usr/local/
|
||||
rm -rf node-v10.15.0-linux-arm64/
|
||||
rm node-v10.15.0-linux-arm64.tar.gz
|
||||
|
||||
echo_stamp "Installing ptvsd"
|
||||
my_travis_retry pip install ptvsd
|
||||
|
||||
@@ -20,20 +20,9 @@ export ROS_DISTRO='noetic'
|
||||
export ROS_IP='127.0.0.1'
|
||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||
source /home/pi/catkin_ws/devel/setup.bash
|
||||
systemctl start roscore
|
||||
|
||||
cd /home/pi/catkin_ws/src/clover/builder/test/
|
||||
./tests.sh
|
||||
./tests.py
|
||||
./tests_py3.py
|
||||
[[ $(./test_qr.py) == "Found QRCODE with data Проверка Unicode with center at x=66.0, y=66.0" ]]
|
||||
[[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility
|
||||
|
||||
systemctl stop roscore
|
||||
|
||||
# check documented packages available
|
||||
apt-cache show gst-rtsp-launch
|
||||
apt-cache show openvpn
|
||||
|
||||
echo "Move /etc/ld.so.preload back to its original position"
|
||||
mv /etc/ld.so.preload.disabled-for-build /etc/ld.so.preload
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
# Perform a "standalone install" in a Docker container
|
||||
set -e
|
||||
# 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-get update
|
||||
apt-get install -y curl
|
||||
apt update
|
||||
apt install -y curl
|
||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||
if [ "x${ROS_PYTHON_VERSION}" = "x3" ]; then
|
||||
PYTHON=python3
|
||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||
else
|
||||
PYTHON=python
|
||||
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py
|
||||
fi
|
||||
|
||||
${PYTHON} ./get-pip.py
|
||||
|
||||
# Step 1.5: Add deb.coex.tech to apt
|
||||
@@ -41,7 +40,7 @@ ws281x:
|
||||
ubuntu:
|
||||
${CODENAME}: [ros-${ROS_DISTRO}-ws281x]
|
||||
EOF
|
||||
apt-get update
|
||||
apt update
|
||||
rosdep update
|
||||
|
||||
# Step 2: Run rosdep to install all dependencies
|
||||
@@ -61,6 +60,3 @@ ${PYTHON} -m pip install --upgrade pytest
|
||||
cd /root/catkin_ws
|
||||
source devel/setup.bash
|
||||
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 |
@@ -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()
|
||||
@@ -4,26 +4,18 @@
|
||||
|
||||
import rospy
|
||||
from geometry_msgs.msg import PoseStamped
|
||||
from sensor_msgs.msg import Range, BatteryState
|
||||
|
||||
import cv2
|
||||
import cv2.aruco
|
||||
from sensor_msgs.msg import Image
|
||||
from cv_bridge import CvBridge
|
||||
|
||||
import numpy
|
||||
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 std_srvs.srv import Trigger
|
||||
from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
||||
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_geometry_msgs
|
||||
@@ -33,7 +25,7 @@ import pymavlink
|
||||
from pymavlink import mavutil
|
||||
import rpi_ws281x
|
||||
import pigpio
|
||||
# from espeak import espeak
|
||||
from espeak import espeak
|
||||
from pyzbar import pyzbar
|
||||
|
||||
print(cv2.getBuildInformation())
|
||||
|
||||
@@ -32,9 +32,8 @@ monkey --version
|
||||
pigpiod -v
|
||||
i2cdetect -V
|
||||
butterfly -h
|
||||
# espeak --version
|
||||
espeak --version
|
||||
mjpg_streamer --version
|
||||
systemctl --version
|
||||
|
||||
# ros stuff
|
||||
|
||||
@@ -44,8 +43,6 @@ rosversion aruco_pose
|
||||
rosversion vl53l1x
|
||||
rosversion mavros
|
||||
rosversion mavros_extras
|
||||
rosversion ws281x
|
||||
rosversion led_msgs
|
||||
rosversion dynamic_reconfigure
|
||||
rosversion tf2_web_republisher
|
||||
rosversion compressed_image_transport
|
||||
@@ -55,8 +52,6 @@ rosversion usb_cam
|
||||
rosversion cv_camera
|
||||
rosversion web_video_server
|
||||
rosversion rosshow
|
||||
rosversion nodelet
|
||||
rosversion image_view
|
||||
|
||||
# validate examples are present
|
||||
[[ $(ls /home/pi/examples/*) ]]
|
||||
|
||||
@@ -4,9 +4,7 @@ import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
EXCLUDE = ('clever4-front-white.png', 'clever4-front-white-large.png', '.DS_Store',
|
||||
'clever4-front-black-large.png','clover42-black.png', 'clover42-main-margin.png')
|
||||
|
||||
EXCLUDE = ('clever4-front-white.png', '.DS_Store', 'clever4-front-black-large.png')
|
||||
code = 0
|
||||
|
||||
os.chdir('./docs')
|
||||
|
||||
@@ -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
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(clover)
|
||||
|
||||
## Compile as C++11, supported in ROS Kinetic and newer
|
||||
@@ -241,12 +241,12 @@ target_link_libraries(${PROJECT_NAME}
|
||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
# Mark executables and/or libraries for installation
|
||||
install(TARGETS simple_offboard clover_rc camera_markers vpe_publisher clover_led shell clover
|
||||
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
)
|
||||
## Mark executables and/or libraries for installation
|
||||
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
|
||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark cpp header files for installation
|
||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||
@@ -266,21 +266,13 @@ catkin_install_python(PROGRAMS src/selfcheck.py
|
||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
)
|
||||
|
||||
install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||
|
||||
install(DIRECTORY examples DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||
|
||||
install(DIRECTORY www DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||
|
||||
# TODO: install www
|
||||
|
||||
# Only install udev rules when building a Debian package
|
||||
# FIXME: Other operating systems may have other prefixes
|
||||
string(FIND ${CMAKE_INSTALL_PREFIX} "/opt/ros" _PREFIX_INDEX)
|
||||
if (${_PREFIX_INDEX} EQUAL 0)
|
||||
message(STATUS "Building as a Debian package - adding udev rules as installable files")
|
||||
install(FILES
|
||||
udev/99-px4fmu.rules
|
||||
config/99-px4fmu.rules
|
||||
DESTINATION /lib/udev/rules.d
|
||||
)
|
||||
else()
|
||||
|
||||
@@ -36,7 +36,7 @@ curl https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/inst
|
||||
You may optionally install udev rules to provide `/dev/px4fmu` symlink to your PX4-based flight controller connected over USB. Copy `99-px4fmu.rules` to your `/lib/udev/rules.d` folder:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/src/clover/clover/udev
|
||||
cd ~/catkin_ws/src/clover/clover/config
|
||||
sudo cp 99-px4fmu.rules /lib/udev/rules.d
|
||||
```
|
||||
|
||||
@@ -44,12 +44,16 @@ Alternatively you may change the `fcu_url` property in `mavros.launch` file to p
|
||||
|
||||
## Running
|
||||
|
||||
To start connection to SITL, use:
|
||||
|
||||
```bash
|
||||
roslaunch clover sitl.launch
|
||||
```
|
||||
|
||||
To start connection to the flight controller, use:
|
||||
|
||||
```bash
|
||||
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`.
|
||||
|
||||
@@ -12,6 +12,4 @@ SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0016", ATTRS{produ
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0013", ATTRS{product}=="PX4 FMU v4.x PRO", SYMLINK+="px4fmu"
|
||||
# Omnibus
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0001", ATTRS{product}=="PX4 OmnibusF4SD", SYMLINK+="px4fmu"
|
||||
# CUAV X7 Pro
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="3163", ATTRS{idProduct}=="004c", ATTRS{product}=="PX4 CUAV X7Pro", SYMLINK+="px4fmu"
|
||||
|
||||
@@ -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())
|
||||
@@ -1,47 +0,0 @@
|
||||
# Information: https://clover.coex.tech/en/simple_offboard.html#navigateglobal
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
from std_srvs.srv import Trigger
|
||||
import math
|
||||
|
||||
rospy.init_node('flight')
|
||||
|
||||
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
|
||||
navigate = rospy.ServiceProxy('navigate', srv.Navigate)
|
||||
navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal)
|
||||
set_position = rospy.ServiceProxy('set_position', srv.SetPosition)
|
||||
set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)
|
||||
set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
|
||||
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
||||
land = rospy.ServiceProxy('land', Trigger)
|
||||
|
||||
# https://clover.coex.tech/en/snippets.html#wait_arrival
|
||||
def wait_arrival(tolerance=0.2):
|
||||
while not rospy.is_shutdown():
|
||||
telem = get_telemetry(frame_id='navigate_target')
|
||||
if math.sqrt(telem.x ** 2 + telem.y ** 2 + telem.z ** 2) < tolerance:
|
||||
break
|
||||
rospy.sleep(0.2)
|
||||
|
||||
start = get_telemetry()
|
||||
|
||||
if math.isnan(start.lat):
|
||||
raise Exception('No global position, install and configure GPS sensor: https://clover.coex.tech/gps')
|
||||
|
||||
print('Start point global position: lat={}, lon={}'.format(start.lat, start.lon))
|
||||
|
||||
print('Take off 3 meters')
|
||||
navigate(x=0, y=0, z=3, frame_id='body', auto_arm=True)
|
||||
wait_arrival()
|
||||
|
||||
print('Fly 1 arcsecond to the North (approx. 30 meters)')
|
||||
navigate_global(lat=start.lat+1.0/60/60, lon=start.lon, z=start.z+3, yaw=math.inf, speed=5)
|
||||
wait_arrival()
|
||||
|
||||
print('Fly to home position')
|
||||
navigate_global(lat=start.lat, lon=start.lon, z=start.z+3, yaw=math.inf, speed=5)
|
||||
wait_arrival()
|
||||
|
||||
print('Land')
|
||||
land()
|
||||
@@ -1,15 +0,0 @@
|
||||
# Information: https://clover.coex.tech/en/laser.html
|
||||
|
||||
import rospy
|
||||
from sensor_msgs.msg import Range
|
||||
|
||||
rospy.init_node('process_rangefinder')
|
||||
|
||||
def range_callback(msg):
|
||||
# Process data from the rangefinder
|
||||
print('Rangefinder distance:', msg.range)
|
||||
|
||||
# Subscribe to laser rangefinder data
|
||||
rospy.Subscriber('rangefinder/range', Range, range_callback)
|
||||
|
||||
rospy.spin()
|
||||
@@ -3,16 +3,16 @@
|
||||
<arg name="aruco_map" default="false"/>
|
||||
<arg name="aruco_vpe" default="false"/>
|
||||
<arg name="placement" default="floor"/> <!-- markers placement: floor, ceiling, unknown -->
|
||||
<arg name="length" default="0.22"/> <!-- not-in-map markers length, m -->
|
||||
<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 -->
|
||||
|
||||
<!-- 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" respawn="true">
|
||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<remap from="map_markers" to="aruco_map/markers"/>
|
||||
<remap from="map_markers" to="aruco_map/markers" if="$(arg aruco_map)"/>
|
||||
<param name="estimate_poses" value="true"/>
|
||||
<param name="send_tf" value="true"/>
|
||||
<param name="known_tilt" value="map" if="$(eval placement == 'floor')"/>
|
||||
@@ -26,7 +26,7 @@
|
||||
</node>
|
||||
|
||||
<!-- 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" respawn="true">
|
||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<remap from="markers" to="aruco_detect/markers"/>
|
||||
@@ -45,7 +45,7 @@
|
||||
<remap from="~pose_cov" to="aruco_map/pose"/>
|
||||
<remap from="~vpe" to="mavros/vision_pose/pose"/>
|
||||
<param name="frame_id" value="aruco_map_detected"/>
|
||||
<param name="force_init" value="true"/>
|
||||
<param name="publish_zero" value="true"/>
|
||||
<param name="offset_frame_id" value="aruco_map"/>
|
||||
</node>
|
||||
</launch>
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
<arg name="rangefinder_vl53l1x" default="true"/>
|
||||
<arg name="led" default="true"/>
|
||||
<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 -->
|
||||
|
||||
@@ -36,13 +37,18 @@
|
||||
<include file="$(find clover)/launch/aruco.launch" if="$(arg aruco)"/>
|
||||
|
||||
<!-- 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" respawn="true">
|
||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<param name="calc_flow_gyro" value="true"/>
|
||||
<param name="roi_rad" value="0.8"/>
|
||||
</node>
|
||||
|
||||
<!-- main nodelet manager -->
|
||||
<node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" clear_params="true" respawn="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"/>
|
||||
|
||||
<!-- simplified offboard control -->
|
||||
@@ -85,6 +91,9 @@
|
||||
<param name="use_fake_gcs" value="false"/>
|
||||
</node>
|
||||
|
||||
<!-- Shell access through ROS service -->
|
||||
<node name="shell" pkg="clover" type="shell" output="screen" if="$(arg shell)"/>
|
||||
|
||||
<!-- Update static directory -->
|
||||
<node pkg="roswww_static" name="roswww_static" type="main.py" clear_params="true">
|
||||
<param name="default_package" value="clover"/>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
posctl: { r: 50, g: 100, b: 220 }
|
||||
offboard: { r: 220, g: 20, b: 250 }
|
||||
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>
|
||||
</node>
|
||||
</launch>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up -->
|
||||
<arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
|
||||
<arg name="device" default="/dev/video0"/> <!-- v4l2 device -->
|
||||
<arg name="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"/>
|
||||
@@ -18,14 +17,9 @@
|
||||
<!-- 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"/> -->
|
||||
|
||||
<!-- 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 -->
|
||||
<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">
|
||||
<param name="device_path" value="$(arg device)"/>
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet nodelet_manager" clear_params="true" unless="$(arg simulator)" respawn="true">
|
||||
<param name="device_path" value="/dev/video0"/> <!-- v4l2 device -->
|
||||
<param name="frame_id" value="main_camera_optical"/>
|
||||
<param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/>
|
||||
|
||||
|
||||
@@ -6,16 +6,13 @@
|
||||
<arg name="viz" default="true"/>
|
||||
<arg name="respawn" default="true"/>
|
||||
<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 -->
|
||||
<param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/>
|
||||
|
||||
<!-- 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 -->
|
||||
<param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Config file for mavros
|
||||
# Based on https://raw.githubusercontent.com/mavlink/mavros/master/mavros/launch/px4_config.yaml
|
||||
|
||||
startup_px4_usb_quirk: false
|
||||
startup_px4_usb_quirk: true
|
||||
|
||||
conn:
|
||||
heartbeat_rate: 1.0 # send hertbeat rate in Hertz
|
||||
@@ -13,7 +13,6 @@ time:
|
||||
time_ref_source: "fcu" # time_reference source
|
||||
timesync_mode: MAVLINK
|
||||
timesync_avg_alpha: 0.6 # timesync averaging factor
|
||||
publish_sim_time: false # don't publish /clock
|
||||
|
||||
global_position:
|
||||
frame_id: "map" # origin frame
|
||||
|
||||
19
clover/launch/sitl.launch
Normal file
19
clover/launch/sitl.launch
Normal 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>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="3">
|
||||
<name>clover</name>
|
||||
<version>0.21.1</version>
|
||||
<version>0.0.1</version>
|
||||
<description>The Clover package</description>
|
||||
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include <ros/ros.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <clover/SetLEDEffect.h>
|
||||
@@ -30,7 +29,6 @@ ros::Timer timer;
|
||||
ros::Time start_time;
|
||||
double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period;
|
||||
double low_battery_threshold;
|
||||
std::vector<std::string> error_ignore;
|
||||
bool blink_state;
|
||||
led_msgs::SetLEDs set_leds;
|
||||
led_msgs::LEDStateArray state, start_state;
|
||||
@@ -276,10 +274,6 @@ void handleMavrosState(const mavros_msgs::State& msg)
|
||||
void handleLog(const rosgraph_msgs::Log& log)
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -308,7 +302,6 @@ int main(int argc, char **argv)
|
||||
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/error/ignore", error_ignore, {});
|
||||
|
||||
ros::service::waitForService("set_leds"); // cannot work without set_leds service
|
||||
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true);
|
||||
|
||||
@@ -53,7 +53,6 @@ private:
|
||||
std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
|
||||
std::unique_ptr<tf2_ros::TransformListener> tf_listener_;
|
||||
bool calc_flow_gyro_;
|
||||
float flow_gyro_default_;
|
||||
|
||||
void onInit()
|
||||
{
|
||||
@@ -70,13 +69,15 @@ private:
|
||||
roi_px_ = nh_priv.param("roi", 128);
|
||||
roi_rad_ = nh_priv.param("roi_rad", 0.0);
|
||||
calc_flow_gyro_ = nh_priv.param("calc_flow_gyro", false);
|
||||
flow_gyro_default_ = nh_priv.param("flow_gyro_default", NAN);
|
||||
|
||||
img_pub_ = it_priv.advertise("debug", 1);
|
||||
flow_pub_ = nh.advertise<mavros_msgs::OpticalFlowRad>("mavros/px4flow/raw/send", 1);
|
||||
velo_pub_ = nh_priv.advertise<geometry_msgs::TwistStamped>("angular_velocity", 1);
|
||||
shift_pub_ = nh_priv.advertise<geometry_msgs::Vector3Stamped>("shift", 1);
|
||||
|
||||
flow_.integrated_xgyro = NAN; // no IMU available
|
||||
flow_.integrated_ygyro = NAN;
|
||||
flow_.integrated_zgyro = NAN;
|
||||
flow_.time_delta_distance_us = 0;
|
||||
flow_.distance = -1; // no distance sensor available
|
||||
flow_.temperature = 0;
|
||||
@@ -152,7 +153,7 @@ private:
|
||||
cv::Point2d shift = cv::phaseCorrelate(prev_, curr_, hann_, &response);
|
||||
|
||||
// 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.frame_id = msg->header.frame_id;
|
||||
shift_vec.vector.x = shift.x;
|
||||
@@ -178,8 +179,8 @@ private:
|
||||
double flow_x = atan2(points_undist[0].x, focal_length_x);
|
||||
double flow_y = atan2(points_undist[0].y, focal_length_y);
|
||||
|
||||
// Convert to FCU frame
|
||||
geometry_msgs::Vector3Stamped flow_camera, flow_fcu;
|
||||
// // Convert to FCU frame
|
||||
static geometry_msgs::Vector3Stamped flow_camera, flow_fcu;
|
||||
flow_camera.header.frame_id = msg->header.frame_id;
|
||||
flow_camera.header.stamp = msg->header.stamp;
|
||||
flow_camera.vector.x = flow_y; // +y means counter-clockwise rotation around Y axis
|
||||
@@ -195,21 +196,18 @@ private:
|
||||
ros::Duration integration_time = msg->header.stamp - prev_stamp_;
|
||||
uint32_t integration_time_us = integration_time.toSec() * 1.0e6;
|
||||
|
||||
// Calculate flow gyro
|
||||
flow_.integrated_xgyro = flow_gyro_default_;
|
||||
flow_.integrated_ygyro = flow_gyro_default_;
|
||||
flow_.integrated_zgyro = flow_gyro_default_;
|
||||
|
||||
if (calc_flow_gyro_) {
|
||||
try {
|
||||
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_);
|
||||
flow_.integrated_xgyro = flow_gyro_fcu.vector.x;
|
||||
flow_.integrated_ygyro = flow_gyro_fcu.vector.y;
|
||||
flow_.integrated_zgyro = flow_gyro_fcu.vector.z;
|
||||
} catch (const tf2::TransformException& e) {
|
||||
// Transform not available, keep NANs in flow gyro
|
||||
// Invalidate previous frame
|
||||
prev_.release();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,10 +219,6 @@ private:
|
||||
flow_.quality = (uint8_t)(response * 255);
|
||||
flow_pub_.publish(flow_);
|
||||
|
||||
prev_ = curr_.clone();
|
||||
prev_stamp_ = msg->header.stamp;
|
||||
|
||||
publish_debug:
|
||||
// Publish debug image
|
||||
if (img_pub_.getNumSubscribers() > 0) {
|
||||
// publish debug image
|
||||
@@ -238,12 +232,15 @@ publish_debug:
|
||||
}
|
||||
|
||||
// Publish estimated angular velocity
|
||||
geometry_msgs::TwistStamped velo;
|
||||
static geometry_msgs::TwistStamped velo;
|
||||
velo.header.stamp = msg->header.stamp;
|
||||
velo.header.frame_id = fcu_frame_id_;
|
||||
velo.twist.angular.x = flow_fcu.vector.x / integration_time.toSec();
|
||||
velo.twist.angular.y = flow_fcu.vector.y / integration_time.toSec();
|
||||
velo.twist.angular.x = flow_.integrated_x / integration_time.toSec();
|
||||
velo.twist.angular.y = flow_.integrated_y / integration_time.toSec();
|
||||
velo_pub_.publish(velo);
|
||||
|
||||
prev_ = curr_.clone();
|
||||
prev_stamp_ = msg->header.stamp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ from mavros import mavlink
|
||||
|
||||
rospy.init_node('selfcheck')
|
||||
|
||||
os.environ['ROSCONSOLE_FORMAT']='[${severity}]: ${message}'
|
||||
|
||||
|
||||
tf_buffer = tf2_ros.Buffer()
|
||||
tf_listener = tf2_ros.TransformListener(tf_buffer)
|
||||
@@ -201,13 +199,18 @@ def check_fcu():
|
||||
if version_str == '':
|
||||
info('no version data available from SITL')
|
||||
|
||||
for line in version_str.split('\n'):
|
||||
if line.startswith('FW version: '):
|
||||
info(line[len('FW version: '):])
|
||||
elif line.startswith('FW git tag: '):
|
||||
info(line[len('FW git tag: '):])
|
||||
elif line.startswith('HW arch: '):
|
||||
info(line[len('HW arch: '):])
|
||||
r = re.compile(r'^FW (git tag|version): (v?\d\.\d\.\d.*)$')
|
||||
is_clover_firmware = False
|
||||
for ver_line in version_str.split('\n'):
|
||||
match = r.search(ver_line)
|
||||
if match is not None:
|
||||
field, version = match.groups()
|
||||
info('firmware %s: %s' % (field, version))
|
||||
if 'clover' in version or 'clever' in version:
|
||||
is_clover_firmware = True
|
||||
|
||||
if not is_clover_firmware:
|
||||
failure('not running Clover PX4 firmware, https://clover.coex.tech/firmware')
|
||||
|
||||
est = get_param('SYS_MC_EST_GROUP')
|
||||
if est == 1:
|
||||
@@ -480,9 +483,6 @@ def check_local_position():
|
||||
failure('roll is %.2f deg; place copter horizontally or redo level horizon calib',
|
||||
math.degrees(roll))
|
||||
|
||||
if not tf_buffer.can_transform('base_link', pose.header.frame_id, rospy.get_rostime(), rospy.Duration(0.5)):
|
||||
failure('can\'t transform from %s to base_link (timeout 0.5 s): is TF enabled?', pose.header.frame_id)
|
||||
|
||||
except rospy.ROSException:
|
||||
failure('no local position')
|
||||
|
||||
@@ -612,13 +612,13 @@ def check_boot_duration():
|
||||
output = subprocess.check_output('systemd-analyze').decode()
|
||||
r = re.compile(r'([\d\.]+)s\s*$', flags=re.MULTILINE)
|
||||
duration = float(r.search(output).groups()[0])
|
||||
if duration > 20:
|
||||
if duration > 15:
|
||||
failure('long Raspbian boot duration: %ss (systemd-analyze for analyzing)', duration)
|
||||
|
||||
|
||||
@check('CPU usage')
|
||||
def check_cpu_usage():
|
||||
WHITELIST = 'nodelet', 'gzclient', 'gzserver'
|
||||
WHITELIST = 'nodelet',
|
||||
CMD = "top -n 1 -b -i | tail -n +8 | awk '{ printf(\"%-8s\\t%-8s\\t%-8s\\n\", $1, $9, $12); }'"
|
||||
output = subprocess.check_output(CMD, shell=True).decode()
|
||||
processes = output.split('\n')
|
||||
@@ -646,22 +646,13 @@ def check_clover_service():
|
||||
elif 'failed' in output:
|
||||
failure('service failed to run, check your launch-files')
|
||||
|
||||
BLACKLIST = 'Unexpected command 520', 'Time jump detected', 'different index:'
|
||||
|
||||
r = re.compile(r'^(.*)\[(FATAL|ERROR| WARN)\] \[\d+.\d+\]: (.*?)(\x1b(.*))?$')
|
||||
r = re.compile(r'^(.*)\[(FATAL|ERROR)\] \[\d+.\d+\]: (.*?)(\x1b(.*))?$')
|
||||
error_count = OrderedDict()
|
||||
try:
|
||||
for line in open('/tmp/clover.err', 'r'):
|
||||
skip = False
|
||||
for substr in BLACKLIST:
|
||||
if substr in line:
|
||||
skip = True
|
||||
if skip:
|
||||
continue
|
||||
|
||||
node_error = r.search(line)
|
||||
if node_error:
|
||||
msg = node_error.groups()[1].strip() + ': ' + node_error.groups()[2]
|
||||
msg = node_error.groups()[1] + ': ' + node_error.groups()[2]
|
||||
if msg in error_count:
|
||||
error_count[msg] += 1
|
||||
else:
|
||||
@@ -762,7 +753,7 @@ def check_rpi_health():
|
||||
# with some of the FLAGs OR'ed together
|
||||
output = subprocess.check_output(['vcgencmd', 'get_throttled']).decode()
|
||||
except OSError:
|
||||
info('could not call vcgencmd binary; not a Raspberry Pi?')
|
||||
failure('could not call vcgencmd binary; not a Raspberry Pi?')
|
||||
return
|
||||
|
||||
throttle_mask = int(output.split('=')[1], base=16)
|
||||
|
||||
@@ -181,10 +181,9 @@ inline bool waitTransform(const string& target, const string& source,
|
||||
ros::spinOnce();
|
||||
r.sleep();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define TIMEOUT(msg, timeout) (msg.header.stamp.isZero() || (ros::Time::now() - msg.header.stamp > timeout))
|
||||
#define TIMEOUT(msg, timeout) (ros::Time::now() - msg.header.stamp > timeout)
|
||||
|
||||
bool getTelemetry(GetTelemetry::Request& req, GetTelemetry::Response& res)
|
||||
{
|
||||
@@ -442,10 +441,6 @@ void publish(const ros::Time stamp)
|
||||
|
||||
// publish setpoint frame
|
||||
if (!setpoint.child_frame_id.empty()) {
|
||||
if (setpoint.header.stamp == position_msg.header.stamp) {
|
||||
return; // avoid TF_REPEATED_DATA warnings
|
||||
}
|
||||
|
||||
setpoint.transform.translation.x = position_msg.pose.position.x;
|
||||
setpoint.transform.translation.y = position_msg.pose.position.y;
|
||||
setpoint.transform.translation.z = position_msg.pose.position.z;
|
||||
@@ -717,7 +712,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
|
||||
}
|
||||
|
||||
if (sp_type == VELOCITY) {
|
||||
Vector3Stamped vel;
|
||||
static Vector3Stamped vel;
|
||||
vel.header.frame_id = frame_id;
|
||||
vel.header.stamp = stamp;
|
||||
vel.vector.x = vx;
|
||||
@@ -848,7 +843,6 @@ bool land(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
||||
busy = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
@@ -53,7 +53,7 @@ void publishZero(const ros::TimerEvent& e)
|
||||
}
|
||||
|
||||
ROS_INFO_THROTTLE(10, "publish zero");
|
||||
geometry_msgs::PoseStamped zero;
|
||||
static geometry_msgs::PoseStamped zero;
|
||||
zero.header.frame_id = local_frame_id;
|
||||
zero.header.stamp = e.current_real;
|
||||
zero.pose.orientation.w = 1;
|
||||
@@ -141,11 +141,11 @@ int main(int argc, char **argv) {
|
||||
vpe_pub = nh_priv.advertise<PoseStamped>("vpe", 1);
|
||||
//vpe_cov_pub = nh_priv_.advertise<PoseStamped>("pose_cov_pub", 1);
|
||||
|
||||
if (nh_priv.param("force_init", false) || nh_priv.param("publish_zero", false)) { // publish_zero is old name
|
||||
if (nh_priv.param("publish_zero", false)) {
|
||||
// publish zero to initialize the local position
|
||||
zero_timer = nh.createTimer(ros::Duration(0.1), &publishZero);
|
||||
publish_zero_timout = ros::Duration(nh_priv.param("force_init_timeout", 5.0));
|
||||
publish_zero_duration = ros::Duration(nh_priv.param("force_init_duration", 5.0));
|
||||
publish_zero_timout = ros::Duration(nh_priv.param("publish_zero_timout", 5.0));
|
||||
publish_zero_duration = ros::Duration(nh_priv.param("publish_zero_duration", 5.0));
|
||||
local_position_sub = nh.subscribe("mavros/local_position/pose", 1, &localPositionCallback);
|
||||
}
|
||||
|
||||
|
||||
@@ -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}"
|
||||
@@ -33,3 +33,19 @@ def test_web_video_server(node):
|
||||
# Python 3
|
||||
import urllib.request as urllib
|
||||
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 == ''
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/var/log/clover.log
|
||||
@@ -1 +0,0 @@
|
||||
/etc/clover_version
|
||||
@@ -1,36 +1,25 @@
|
||||
<title>Clover Drone Kit Tools</title>
|
||||
|
||||
<h1>Clover Drone Kit Tools</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="docs">View documentation</a> (snapshot of <a href="https://clover.coex.tech">clover.coex.tech</a>)</li>
|
||||
<li><a href="topics.html">View topics</a></li>
|
||||
<li><a href="" id="wvs">View image topics</a> (<code>web_video_server</code>)</li>
|
||||
<li><a href="" id="butterfly">Open web terminal</a> (<code>Butterfly</code>)</li>
|
||||
<li>View <a href="viz.html">View 3D visualization</a>, <a href="aruco_map.html">3D visualization for markers map</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="../clover_blocks/">Blocks programming</a> (<code>Blockly</code>)</li>
|
||||
<li><a href="clover.log">Clover console</a> (<code>/var/log/clover.log</code>)</li>
|
||||
</ul>
|
||||
|
||||
<div class="version"></div>
|
||||
|
||||
<script src="js/roslib.js"></script>
|
||||
<script type="text/javascript">
|
||||
document.querySelector("#wvs").href = location.protocol + '//' + location.hostname + ':8080';
|
||||
document.querySelector("#butterfly").href = location.protocol + '//' + location.hostname + ':57575';
|
||||
|
||||
document.querySelector("#butterfly").addEventListener('click', function(e) {
|
||||
if (location.hostname == 'localhost' || location.hostname == '127.0.0.1') {
|
||||
if (!confirm('Please use regular Terminal app on a local machine.\nClick OK to proceed to Butterfly anyway.')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Determine image version
|
||||
fetch('clover_version').then(function(response) {
|
||||
if (response.status !== 200) return;
|
||||
response.text().then(function(text) {
|
||||
document.querySelector('.version').innerHTML = 'Version: ' + text;
|
||||
});
|
||||
var ros = new ROSLIB.Ros({ url: 'ws://' + location.hostname + ':9090' });
|
||||
var exec = new ROSLIB.Service({ ros: ros, name : '/exec', serviceType : 'clover/Execute' });
|
||||
exec.callService(new ROSLIB.ServiceRequest({ cmd: 'cat /etc/clover_version' }), function(result) {
|
||||
document.querySelector('.version').innerHTML = 'Version: ' + result.output;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
// Browserified https://www.npmjs.com/package/json-to-pretty-yaml module
|
||||
|
||||
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var typeOf = require('remedial').typeOf;
|
||||
var trimWhitespace = require('remove-trailing-spaces');
|
||||
|
||||
function stringify(data) {
|
||||
var handlers, indentLevel = '';
|
||||
|
||||
handlers = {
|
||||
"undefined": function() {
|
||||
// objects will not have `undefined` converted to `null`
|
||||
// as this may have unintended consequences
|
||||
// For arrays, however, this behavior seems appropriate
|
||||
return 'null';
|
||||
},
|
||||
"null": function() {
|
||||
return 'null';
|
||||
},
|
||||
"number": function(x) {
|
||||
return x;
|
||||
},
|
||||
"boolean": function(x) {
|
||||
return x ? 'true' : 'false';
|
||||
},
|
||||
"string": function(x) {
|
||||
// to avoid the string "true" being confused with the
|
||||
// the literal `true`, we always wrap strings in quotes
|
||||
return JSON.stringify(x);
|
||||
},
|
||||
"array": function(x) {
|
||||
var output = '';
|
||||
|
||||
if (0 === x.length) {
|
||||
output += '[]';
|
||||
return output;
|
||||
}
|
||||
|
||||
indentLevel = indentLevel.replace(/$/, ' ');
|
||||
x.forEach(function(y, i) {
|
||||
// TODO how should `undefined` be handled?
|
||||
var handler = handlers[typeOf(y)];
|
||||
|
||||
if (!handler) {
|
||||
throw new Error('what the crap: ' + typeOf(y));
|
||||
}
|
||||
|
||||
output += '\n' + indentLevel + '- ' + handler(y, true);
|
||||
|
||||
});
|
||||
indentLevel = indentLevel.replace(/ /, '');
|
||||
|
||||
return output;
|
||||
},
|
||||
"object": function(x, inArray, rootNode) {
|
||||
var output = '';
|
||||
|
||||
if (0 === Object.keys(x).length) {
|
||||
output += '{}';
|
||||
return output;
|
||||
}
|
||||
|
||||
if (!rootNode) {
|
||||
indentLevel = indentLevel.replace(/$/, ' ');
|
||||
}
|
||||
|
||||
Object.keys(x).forEach(function(k, i) {
|
||||
var val = x[k],
|
||||
handler = handlers[typeOf(val)];
|
||||
|
||||
if ('undefined' === typeof val) {
|
||||
// the user should do
|
||||
// delete obj.key
|
||||
// and not
|
||||
// obj.key = undefined
|
||||
// but we'll error on the side of caution
|
||||
return;
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
throw new Error('what the crap: ' + typeOf(val));
|
||||
}
|
||||
|
||||
if (!(inArray && i === 0)) {
|
||||
output += '\n' + indentLevel;
|
||||
}
|
||||
|
||||
output += k + ': ' + handler(val);
|
||||
});
|
||||
indentLevel = indentLevel.replace(/ /, '');
|
||||
|
||||
return output;
|
||||
},
|
||||
"function": function() {
|
||||
// TODO this should throw or otherwise be ignored
|
||||
return '[object Function]';
|
||||
}
|
||||
};
|
||||
return trimWhitespace(handlers[typeOf(data)](data, true, true) + '\n');
|
||||
|
||||
}
|
||||
|
||||
window.yamlStringify = stringify;
|
||||
module.exports.stringify = stringify;
|
||||
}());
|
||||
|
||||
},{"remedial":2,"remove-trailing-spaces":3}],2:[function(require,module,exports){
|
||||
/*jslint onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true */
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var global = Function('return this')()
|
||||
, classes = "Boolean Number String Function Array Date RegExp Object".split(" ")
|
||||
, i
|
||||
, name
|
||||
, class2type = {}
|
||||
;
|
||||
|
||||
for (i in classes) {
|
||||
if (classes.hasOwnProperty(i)) {
|
||||
name = classes[i];
|
||||
class2type["[object " + name + "]"] = name.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
function typeOf(obj) {
|
||||
return (null === obj || undefined === obj) ? String(obj) : class2type[Object.prototype.toString.call(obj)] || "object";
|
||||
}
|
||||
|
||||
function isEmpty(o) {
|
||||
var i, v;
|
||||
if (typeOf(o) === 'object') {
|
||||
for (i in o) { // fails jslint
|
||||
v = o[i];
|
||||
if (v !== undefined && typeOf(v) !== 'function') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!String.prototype.entityify) {
|
||||
String.prototype.entityify = function () {
|
||||
return this.replace(/&/g, "&").replace(/</g,
|
||||
"<").replace(/>/g, ">");
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.quote) {
|
||||
String.prototype.quote = function () {
|
||||
var c, i, l = this.length, o = '"';
|
||||
for (i = 0; i < l; i += 1) {
|
||||
c = this.charAt(i);
|
||||
if (c >= ' ') {
|
||||
if (c === '\\' || c === '"') {
|
||||
o += '\\';
|
||||
}
|
||||
o += c;
|
||||
} else {
|
||||
switch (c) {
|
||||
case '\b':
|
||||
o += '\\b';
|
||||
break;
|
||||
case '\f':
|
||||
o += '\\f';
|
||||
break;
|
||||
case '\n':
|
||||
o += '\\n';
|
||||
break;
|
||||
case '\r':
|
||||
o += '\\r';
|
||||
break;
|
||||
case '\t':
|
||||
o += '\\t';
|
||||
break;
|
||||
default:
|
||||
c = c.charCodeAt();
|
||||
o += '\\u00' + Math.floor(c / 16).toString(16) +
|
||||
(c % 16).toString(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
return o + '"';
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.supplant) {
|
||||
String.prototype.supplant = function (o) {
|
||||
return this.replace(/{([^{}]*)}/g,
|
||||
function (a, b) {
|
||||
var r = o[b];
|
||||
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.trim) {
|
||||
String.prototype.trim = function () {
|
||||
return this.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, "$1");
|
||||
};
|
||||
}
|
||||
|
||||
// CommonJS / npm / Ender.JS
|
||||
module.exports = {
|
||||
typeOf: typeOf,
|
||||
isEmpty: isEmpty
|
||||
};
|
||||
global.typeOf = global.typeOf || typeOf;
|
||||
global.isEmpty = global.isEmpty || isEmpty;
|
||||
}());
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* removeTrailingSpaces
|
||||
* Remove the trailing spaces from a string.
|
||||
*
|
||||
* @name removeTrailingSpaces
|
||||
* @function
|
||||
* @param {String} input The input string.
|
||||
* @returns {String} The output string.
|
||||
*/
|
||||
|
||||
module.exports = function removeTrailingSpaces(input) {
|
||||
// TODO If possible, use a regex
|
||||
return input.split("\n").map(function (x) {
|
||||
return x.trimRight();
|
||||
}).join("\n");
|
||||
};
|
||||
},{}]},{},[1]);
|
||||
@@ -1,75 +0,0 @@
|
||||
const url = 'ws://' + location.hostname + ':9090';
|
||||
const ros = new ROSLIB.Ros({ url: url });
|
||||
|
||||
ros.on('connection', function () {
|
||||
document.body.classList.add('connected');
|
||||
document.body.classList.remove('closed');
|
||||
init();
|
||||
});
|
||||
|
||||
ros.on('close', function () {
|
||||
document.body.classList.remove('connected');
|
||||
document.body.classList.add('closed');
|
||||
setTimeout(function() {
|
||||
// reconnect
|
||||
ros.connect(url);
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
const title = document.querySelector('h1');
|
||||
const topicsList = document.querySelector('#topics');
|
||||
const topicMessage = document.querySelector('#topic-message');
|
||||
|
||||
function viewTopicsList() {
|
||||
title.innerHTML = 'Topics:';
|
||||
|
||||
ros.getTopics(function(topics) {
|
||||
topicsList.innerHTML = topics.topics.map(function(topic, i) {
|
||||
const type = topics.types[i];
|
||||
if (type == 'sensor_msgs/Image') {
|
||||
let url = `${location.protocol}//${location.hostname}:8080/stream_viewer?topic=${topic}`;
|
||||
return `<li><a href="${url}" class=topic title=${type}>${topic}</a> 🖼</li>`;
|
||||
} else {
|
||||
return `<li><a href="?topic=${topic}" class=topic title=${type}>${topic}</a></li>`;
|
||||
}
|
||||
}).join('');
|
||||
});
|
||||
}
|
||||
|
||||
let rosdistro;
|
||||
|
||||
function viewTopic(topic) {
|
||||
let index = '<a href=topics.html>Topics</a>';
|
||||
title.innerHTML = `${index}: ${topic}`;
|
||||
topicMessage.style.display = 'block';
|
||||
|
||||
ros.getTopicType(topic, function(typeStr) {
|
||||
const [pack, type] = typeStr.split('/');
|
||||
let href = `https://docs.ros.org/en/${rosdistro}/api/${pack}/html/msg/${type}.html`;
|
||||
title.innerHTML = `${index}: ${topic} <a id="topic-type" href=${href} target="_blank">${typeStr}</a>`;
|
||||
});
|
||||
|
||||
new ROSLIB.Topic({ ros: ros, name: topic }).subscribe(function(msg) {
|
||||
document.title = topic;
|
||||
if (mouseDown) return;
|
||||
topicMessage.innerHTML = yamlStringify(msg); // JSON.stringify(msg, null, 4);
|
||||
});
|
||||
}
|
||||
|
||||
let mouseDown;
|
||||
|
||||
topicMessage.addEventListener('mousedown', function() { mouseDown = true; });
|
||||
topicMessage.addEventListener('mouseup', function() { mouseDown = false; });
|
||||
|
||||
function init() {
|
||||
const params = Object.fromEntries(new URLSearchParams(window.location.search).entries());
|
||||
|
||||
if (!params.topic) {
|
||||
viewTopicsList();
|
||||
} else {
|
||||
new ROSLIB.Param({ ros: ros, name: '/rosdistro'}).get(function(value) {
|
||||
rosdistro = value.trim();
|
||||
viewTopic(params.topic);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>ROS topics</title>
|
||||
<script src="js/roslib.js"></script>
|
||||
<link rel="icon" href="data:,"> <!-- make chrome don't request icon -->
|
||||
<script type="module" src="js/topics.js"></script>
|
||||
<script src="js/json-to-pretty-yaml.js"></script>
|
||||
<style>
|
||||
#topics { line-height: 1.2em; }
|
||||
#topic-view {
|
||||
display: none;
|
||||
}
|
||||
#topic-message {
|
||||
display: none;
|
||||
white-space: pre;
|
||||
font-family: monospace;
|
||||
}
|
||||
#topic-type { font-family: monospace; font-size: 0.5em; vertical-align: super; font-weight: normal; }
|
||||
.topic { font-family: monospace; }
|
||||
body.closed { background-color: rgb(207, 207, 207); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1> </h1>
|
||||
<ul id="topics"></ul>
|
||||
<code id="topic-message" title="Hold mouse button to pause">No messages received</code>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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
|
||||
@@ -73,13 +73,6 @@ catkin_install_python(PROGRAMS src/clover_blocks
|
||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
)
|
||||
|
||||
# TODO: store programs in home directory?
|
||||
install(DIRECTORY programs
|
||||
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
)
|
||||
|
||||
install(DIRECTORY www DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
@@ -10,7 +10,7 @@ Internal package documentation is given below.
|
||||
|
||||
## Frontend
|
||||
|
||||
The frontend files are located in [`www`](./www/) subdirectory. The frontend application uses [`roslib.js`](http://wiki.ros.org/roslibjs) library for communicating with backend node and other ROS resources.
|
||||
The frontend files are located in [`www`](./www/) subdirectory. The frontend application uses [`roblib.js`](http://wiki.ros.org/roslibjs) library for communicating with backend node and other ROS resources.
|
||||
|
||||
## `clover_blocks` node
|
||||
|
||||
@@ -30,8 +30,7 @@ The frontend files are located in [`www`](./www/) subdirectory. The frontend app
|
||||
Parameters read by frontend:
|
||||
|
||||
* `~navigate_tolerance` (*float*) – distance tolerance in meters, used for navigate-like blocks (default: 0.2).
|
||||
* `~navigate_global_tolerance` (*float*) – distance tolerance for global coordinates navigation (default: 1).
|
||||
* `~yaw_tolerance` (*float*) – yaw angle tolerance in degrees, used in set_yaw block (default: 1).
|
||||
* `~yaw_tolerance` (*float*) – yaw angle tolerance in degrees, used in set_yaw block (default: 20).
|
||||
* `~sleep_time` (*float*) – duration of sleep in loop cycles, used for navigate-like blocks (default: 0.2).
|
||||
* `~confirm_run` (*bool*) – enable confirmation to run the program (default: true).
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>clover_blocks</name>
|
||||
<version>0.21.1</version>
|
||||
<version>0.0.0</version>
|
||||
<description>Blockly programming support for Clover</description>
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
<license>MIT</license>
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import rospy
|
||||
import os, sys
|
||||
import traceback
|
||||
import os
|
||||
import threading
|
||||
import re
|
||||
import uuid
|
||||
@@ -117,12 +116,7 @@ def run(req):
|
||||
rospy.loginfo('Program forced to stop')
|
||||
except Exception as e:
|
||||
rospy.logerr(str(e))
|
||||
traceback.print_exc()
|
||||
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)
|
||||
error_pub.publish(str(e))
|
||||
|
||||
rospy.loginfo('Program terminated')
|
||||
running_lock.release()
|
||||
@@ -146,7 +140,6 @@ def stop(req):
|
||||
return {'success': True}
|
||||
|
||||
|
||||
# TODO: find dir in installed package
|
||||
programs_path = rospy.get_param('~programs_dir', os.path.dirname(os.path.abspath(__file__)) + '/../programs')
|
||||
|
||||
|
||||
|
||||
@@ -31,14 +31,6 @@ function considerFrameId(e) {
|
||||
this.getInput('Y').fieldRow[0].setValue('y');
|
||||
this.getInput('Z').fieldRow[0].setValue('z');
|
||||
}
|
||||
if (this.getInput('LAT')) { // block has global coordinates
|
||||
let global = frameId.startsWith('GLOBAL');
|
||||
this.getInput('LAT').setVisible(global);
|
||||
this.getInput('LON').setVisible(global);
|
||||
this.getInput('X').setVisible(!global);
|
||||
this.getInput('Y').setVisible(!global);
|
||||
this.getInput('Z').fieldRow[0].setValue(frameId == 'GLOBAL' ? 'altitude' : 'z');
|
||||
}
|
||||
}
|
||||
if (this.getInput('ID')) { // block has marker id field
|
||||
this.getInput('ID').setVisible(frameId == 'ARUCO'); // toggle id field
|
||||
@@ -73,9 +65,6 @@ function updateSetpointBlock(e) {
|
||||
|
||||
Blockly.Blocks['navigate'] = {
|
||||
init: function () {
|
||||
let navFrameId = frameIds.slice();
|
||||
navFrameId.push(['global', 'GLOBAL_LOCAL'])
|
||||
navFrameId.push(['global, WGS 84 alt.', 'GLOBAL'])
|
||||
this.appendDummyInput()
|
||||
.appendField("navigate to point");
|
||||
this.appendValueInput("X")
|
||||
@@ -84,20 +73,12 @@ Blockly.Blocks['navigate'] = {
|
||||
this.appendValueInput("Y")
|
||||
.setCheck("Number")
|
||||
.appendField("left");
|
||||
this.appendValueInput("LAT")
|
||||
.setCheck("Number")
|
||||
.appendField("latitude")
|
||||
.setVisible(false);
|
||||
this.appendValueInput("LON")
|
||||
.setCheck("Number")
|
||||
.appendField("longitude")
|
||||
.setVisible(false)
|
||||
this.appendValueInput("Z")
|
||||
.setCheck("Number")
|
||||
.appendField("up");
|
||||
this.appendDummyInput()
|
||||
.appendField("relative to")
|
||||
.appendField(new Blockly.FieldDropdown(navFrameId), "FRAME_ID");
|
||||
.appendField(new Blockly.FieldDropdown(frameIds), "FRAME_ID");
|
||||
this.appendValueInput("ID")
|
||||
.setCheck("Number")
|
||||
.appendField("with ID")
|
||||
@@ -287,7 +268,7 @@ Blockly.Blocks['mode'] = {
|
||||
.appendField("current flight mode");
|
||||
this.setOutput(true, "String");
|
||||
this.setColour(COLOR_STATE);
|
||||
this.setTooltip("Returns current flight mode (POSCTL, OFFBOARD, etc).");
|
||||
this.setTooltip("");
|
||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||
}
|
||||
};
|
||||
@@ -394,7 +375,7 @@ Blockly.Blocks['take_off'] = {
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(COLOR_FLIGHT);
|
||||
this.setTooltip("Take off on desired altitude in meters.");
|
||||
this.setTooltip("Take off on desired altitude in meters");
|
||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||
}
|
||||
};
|
||||
@@ -410,7 +391,7 @@ Blockly.Blocks['land'] = {
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(COLOR_FLIGHT);
|
||||
this.setTooltip("Land the drone.");
|
||||
this.setTooltip("");
|
||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||
}
|
||||
};
|
||||
@@ -419,10 +400,10 @@ Blockly.Blocks['global_position'] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("current")
|
||||
.appendField(new Blockly.FieldDropdown([["latitude", "LAT"], ["longitude", "LON"], ["altitude", "ALT"]]), "FIELD");
|
||||
.appendField(new Blockly.FieldDropdown([["latitude", "LATITUDE"], ["longitude", "LONGITUDE"], ["altitude", "ALTITUDE"]]), "NAME");
|
||||
this.setOutput(true, "Number");
|
||||
this.setColour(COLOR_STATE);
|
||||
this.setTooltip("Returns current global position (latitude, longitude, altitude above the WGS 84 ellipsoid).");
|
||||
this.setColour(230);
|
||||
this.setTooltip("");
|
||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,8 +52,6 @@
|
||||
<value name="X"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
<value name="Y"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
<value name="Z"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
<value name="LAT"><shadow type="math_number"><field name="NUM">47.397503</field></shadow></value>
|
||||
<value name="LON"><shadow type="math_number"><field name="NUM">8.544945</field></shadow></value>
|
||||
<value name="SPEED"><shadow type="math_number"><field name="NUM">0.5</field></shadow></value>
|
||||
<value name="ID"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
</block>
|
||||
@@ -87,7 +85,6 @@
|
||||
<value name="ID"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
</block>
|
||||
<block type="get_attitude"></block>
|
||||
<block type="global_position"></block>
|
||||
<block type="distance">
|
||||
<value name="X"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
<value name="Y"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||
|
||||
@@ -39,8 +39,7 @@ var workspace = Blockly.inject('blockly', {
|
||||
function readParams() {
|
||||
return Promise.all([
|
||||
ros.readParam('navigate_tolerance', true, 0.2),
|
||||
ros.readParam('navigate_global_tolerance', true, 1),
|
||||
ros.readParam('yaw_tolerance', true, 1),
|
||||
ros.readParam('yaw_tolerance', true, 20),
|
||||
ros.readParam('sleep_time', true, 0.2),
|
||||
ros.readParam('confirm_run', true, true),
|
||||
]);
|
||||
@@ -211,7 +210,7 @@ function loadPrograms() {
|
||||
updateChanged();
|
||||
}, function(err) {
|
||||
document.querySelector('.backend-fail').style.display = 'inline';
|
||||
alert(`Error loading programs list.\n\nHave you enabled 'blocks' in clover.launch?`);
|
||||
alert(`Error loading programs list.\n\nHave you enabled clover_blocks in clover.launch?`);
|
||||
runButton.disabled = true;
|
||||
})
|
||||
}
|
||||
|
||||
@@ -33,18 +33,6 @@ const NAVIGATE_WAIT = () => `\ndef navigate_wait(x=0, y=0, z=0, speed=0.5, frame
|
||||
return
|
||||
rospy.sleep(${params.sleep_time})\n`;
|
||||
|
||||
const NAVIGATE_GLOBAL_WAIT = () => `\ndef navigate_global_wait(lat, lon, z, speed=0.5):
|
||||
res = navigate_global(lat=lat, lon=lon, z=z, yaw=float('inf'), speed=speed)
|
||||
|
||||
if not res.success:
|
||||
raise Exception(res.message)
|
||||
|
||||
while not rospy.is_shutdown():
|
||||
telem = get_telemetry(frame_id='navigate_target')
|
||||
if math.sqrt(telem.x ** 2 + telem.y ** 2 + telem.z ** 2) < ${params.navigate_global_tolerance}:
|
||||
return
|
||||
rospy.sleep(${params.sleep_time})\n`;
|
||||
|
||||
const LAND_WAIT = () => `\ndef land_wait():
|
||||
land()
|
||||
while get_telemetry().armed:
|
||||
@@ -80,9 +68,6 @@ function generateROSDefinitions() {
|
||||
if (rosDefinitions.offboard) {
|
||||
code += `get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)\n`;
|
||||
code += `navigate = rospy.ServiceProxy('navigate', srv.Navigate)\n`;
|
||||
if (rosDefinitions.navigateGlobal) {
|
||||
code += `navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal)\n`;
|
||||
}
|
||||
if (rosDefinitions.setVelocity) {
|
||||
code += `set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)\n`;
|
||||
}
|
||||
@@ -109,10 +94,6 @@ function generateROSDefinitions() {
|
||||
Blockly.Python.definitions_['import_math'] = 'import math';
|
||||
code += NAVIGATE_WAIT();
|
||||
}
|
||||
if (rosDefinitions.navigateGlobalWait) {
|
||||
Blockly.Python.definitions_['import_math'] = 'import math';
|
||||
code += NAVIGATE_GLOBAL_WAIT();
|
||||
}
|
||||
if (rosDefinitions.landWait) {
|
||||
code += LAND_WAIT();
|
||||
}
|
||||
@@ -180,48 +161,24 @@ Blockly.Python.navigate = function(block) {
|
||||
let x = Blockly.Python.valueToCode(block, 'X', Blockly.Python.ORDER_NONE);
|
||||
let y = Blockly.Python.valueToCode(block, 'Y', Blockly.Python.ORDER_NONE);
|
||||
let z = Blockly.Python.valueToCode(block, 'Z', Blockly.Python.ORDER_NONE);
|
||||
let lat = Blockly.Python.valueToCode(block, 'LAT', Blockly.Python.ORDER_NONE);
|
||||
let lon = Blockly.Python.valueToCode(block, 'LON', Blockly.Python.ORDER_NONE);
|
||||
let wait = block.getFieldValue('WAIT') == 'TRUE';
|
||||
let frameId = block.getFieldValue('FRAME_ID');
|
||||
let frameId = buildFrameId(block);
|
||||
let speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
|
||||
|
||||
let params = [`x=${x}`, `y=${y}`, `z=${z}`, `frame_id=${frameId}`, `speed=${speed}`];
|
||||
|
||||
simpleOffboard();
|
||||
|
||||
// global coordinates
|
||||
if (frameId.startsWith('GLOBAL')) {
|
||||
rosDefinitions.navigateGlobal = true;
|
||||
if (block.getFieldValue('WAIT') == 'TRUE') {
|
||||
rosDefinitions.navigateWait = true;
|
||||
simpleOffboard();
|
||||
|
||||
if (frameId == 'GLOBAL') {
|
||||
z = `${z} + get_telemetry().alt - get_telemetry().z`;
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
rosDefinitions.navigateGlobalWait = true;
|
||||
simpleOffboard();
|
||||
return `navigate_global_wait(lat=${lat}, lon=${lon}, z=${z}, speed=${speed})\n`;
|
||||
|
||||
} else {
|
||||
return `navigate_global(lat=${lat}, lon=${lon}, z=${z}, yaw=float('inf'), speed=${speed})\n`;
|
||||
}
|
||||
return `navigate_wait(${params.join(', ')})\n`;
|
||||
|
||||
} else {
|
||||
frameId = buildFrameId(block);
|
||||
let params = [`x=${x}`, `y=${y}`, `z=${z}`, `frame_id=${frameId}`, `speed=${speed}`];
|
||||
|
||||
if (wait) {
|
||||
rosDefinitions.navigateWait = true;
|
||||
simpleOffboard();
|
||||
|
||||
return `navigate_wait(${params.join(', ')})\n`;
|
||||
|
||||
} else {
|
||||
if (frameId != 'body') {
|
||||
params.push(`yaw=float('nan')`);
|
||||
}
|
||||
return `navigate(${params.join(', ')})\n`;
|
||||
if (frameId != 'body') {
|
||||
params.push(`yaw=float('nan')`);
|
||||
}
|
||||
return `navigate(${params.join(', ')})\n`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,12 +315,6 @@ Blockly.Python.get_attitude = function(block) {
|
||||
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
||||
}
|
||||
|
||||
Blockly.Python.global_position = function(block) {
|
||||
simpleOffboard();
|
||||
var code = `get_telemetry().${block.getFieldValue('FIELD').toLowerCase()}`;
|
||||
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
||||
}
|
||||
|
||||
Blockly.Python.distance = function(block) {
|
||||
rosDefinitions.distance = true;
|
||||
simpleOffboard();
|
||||
@@ -464,7 +415,7 @@ Blockly.Python.led_count = function(block) {
|
||||
|
||||
function pigpio() {
|
||||
Blockly.Python.definitions_['import_pigpio'] = 'import pigpio';
|
||||
Blockly.Python.definitions_['init_pigpio'] = 'pi = pigpio.pi()\nif not pi.connected: raise Exception(\'Cannot connect to pigpiod\')';
|
||||
Blockly.Python.definitions_['init_pigpio'] = 'pi = pigpio.pi()';
|
||||
}
|
||||
|
||||
const GPIO_READ = `\ndef gpio_read(pin):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,7 +14,7 @@ You may provide additional parameters for `spawn_drone.launch` as well:
|
||||
* `rangefinder` (*boolean*, default: *true*) - controls whether the drone will have a downward-facing laser rangefinder attached;
|
||||
* `led` (*boolean*, default: *true*) - controls whether the drone will have a programmable LED strip (requires plugins from `clover_simulation`);
|
||||
* `gps` (*boolean*, default: *true*) - controls whether the drone will have a simulated GPS attached (requires plugins from `sitl_gazebo`);
|
||||
* `maintain_camera_rate` (*boolean*, default: *false*) - slow down the simulation to maintain camera publishing rate (internally changes the camera plugin from `libgazebo_ros_camera.so` to `libthrottling_camera.so` from [`clover_simulation`](../clover_simulation/README.md#throttling-camera-plugin-throttling_camera)).
|
||||
* `maintain_camera_rate` (*boolean*, default: *false*) - slow down the simultion to maintain camera publishing rate (internally changes the camera plugin from `libgazebo_ros_camera.so` to `libthrottling_camera.so` from [`clover_simulation`](../clover_simulation/README.md#throttling-camera-plugin-throttling_camera)).
|
||||
|
||||
For example, in order to spawn a drone without a GPS module, you may use the following command:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<launch>
|
||||
<arg name="model" default="$(find clover_description)/urdf/clover/clover4.xacro"/>
|
||||
<arg name="model" default="$(find clover_description)/urdf/drones/clover4.xacro"/>
|
||||
|
||||
<param name="robot_description" command="xacro $(arg model)"/>
|
||||
<param name="robot_description" command="$(find xacro)/xacro.py $(arg model)"/>
|
||||
|
||||
<node name="rviz" pkg="rviz" type="rviz" required="true"/>
|
||||
</launch>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<package format="2">
|
||||
<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>
|
||||
|
||||
<maintainer email="sfalexrog@gmail.com">Alexey Rogachevskiy</maintainer>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot name="clover" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<robot name="clover_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
|
||||
<xacro:arg name="main_camera" default="true"/>
|
||||
<xacro:arg name="rangefinder" default="true"/>
|
||||
@@ -8,10 +8,10 @@
|
||||
<xacro:arg name="maintain_camera_rate" default="false"/>
|
||||
<xacro:arg name="use_clover_physics" default="false"/>
|
||||
|
||||
<xacro:include filename="clover4_base.xacro" />
|
||||
<xacro:include filename="../sensors/rpi_cam.urdf.xacro"/>
|
||||
<xacro:include filename="../sensors/distance_sensor.urdf.xacro"/>
|
||||
<xacro:include filename="../leds/led_strip.xacro"/>
|
||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_base.xacro" />
|
||||
<xacro:include filename="$(find clover_description)/urdf/sensors/rpi_cam.urdf.xacro"/>
|
||||
<xacro:include filename="$(find clover_description)/urdf/sensors/distance_sensor.urdf.xacro"/>
|
||||
<xacro:include filename="$(find clover_description)/urdf/leds/led_strip.xacro"/>
|
||||
|
||||
<!-- Create camera plugin -->
|
||||
<xacro:if value="$(arg main_camera)">
|
||||
@@ -36,17 +36,11 @@
|
||||
</xacro:if>
|
||||
|
||||
<xacro:if value="$(arg gps)">
|
||||
<gazebo>
|
||||
<include>
|
||||
<uri>model://gps</uri>
|
||||
<pose>0.1 0 0 0 0 0</pose>
|
||||
<name>gps0</name>
|
||||
</include>
|
||||
<joint name='gps0_joint' type='fixed'>
|
||||
<child>gps0::link</child>
|
||||
<parent>base_link</parent>
|
||||
</joint>
|
||||
</gazebo>
|
||||
<!-- Instantiate gps plugin. -->
|
||||
<xacro:gps_plugin_macro
|
||||
namespace="${namespace}"
|
||||
gps_noise="true"
|
||||
/>
|
||||
</xacro:if>
|
||||
|
||||
</robot>
|
||||
|
||||
@@ -1,15 +1,40 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<robot name="clover" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<!-- Properties that can be assigned at build time as arguments.
|
||||
Is there a reason not to make all properties arguments?
|
||||
-->
|
||||
<xacro:arg name='name' default='iris' />
|
||||
<xacro:arg name='mavlink_addr' default='INADDR_ANY' />
|
||||
<xacro:arg name='mavlink_udp_port' default='14560' />
|
||||
<xacro:arg name='mavlink_tcp_port' default='4560' />
|
||||
<xacro:arg name='serial_enabled' default='false' />
|
||||
<xacro:arg name='serial_device' default='/dev/ttyACM0' />
|
||||
<xacro:arg name='baudrate' default='921600' />
|
||||
<xacro:arg name='qgc_addr' default='INADDR_ANY' />
|
||||
<xacro:arg name='qgc_udp_port' default='14550' />
|
||||
<xacro:arg name='sdk_addr' default='INADDR_ANY' />
|
||||
<xacro:arg name='sdk_udp_port' default='14540' />
|
||||
<xacro:arg name='hil_mode' default='false' />
|
||||
<xacro:arg name='hil_state_level' default='false' />
|
||||
<xacro:arg name='send_vision_estimation' default='false' />
|
||||
<xacro:arg name='send_odometry' default='false' />
|
||||
<xacro:arg name='enable_lockstep' default='true' />
|
||||
<xacro:arg name='use_tcp' default='true' />
|
||||
<xacro:arg name='vehicle_is_tailsitter' default='false' />
|
||||
<xacro:arg name='visual_material' default='DarkGrey' />
|
||||
<xacro:arg name='enable_mavlink_interface' default='true' />
|
||||
<xacro:arg name='enable_wind' default='false' />
|
||||
<!-- The following causes segfault with multiple vehicles if defaults to true!!! -->
|
||||
<xacro:arg name='enable_ground_truth' default='false' />
|
||||
<xacro:arg name='enable_logging' default='false' />
|
||||
<xacro:arg name='log_file' default='clover' />
|
||||
<xacro:arg name='log_file' default='iris' />
|
||||
|
||||
<!-- macros for gazebo plugins, sensors -->
|
||||
<xacro:include filename="../component_snippets.urdf.xacro" />
|
||||
<xacro:include filename="$(find clover_description)/urdf/component_snippets.urdf.xacro" />
|
||||
|
||||
<!-- Instantiate iris "mechanics" -->
|
||||
<xacro:include filename="clover4_physics.xacro" />
|
||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_physics.xacro" />
|
||||
|
||||
<xacro:if value="$(arg enable_wind)">
|
||||
<xacro:wind_plugin_macro
|
||||
@@ -24,8 +49,126 @@
|
||||
/>
|
||||
</xacro:if>
|
||||
|
||||
<!-- Gazebo plugins -->
|
||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_gazebo.xacro" />
|
||||
<!-- Instantiate magnetometer plugin. -->
|
||||
<xacro:magnetometer_plugin_macro
|
||||
namespace="${namespace}"
|
||||
pub_rate="20"
|
||||
noise_density="0.0004"
|
||||
random_walk="0.0000064"
|
||||
bias_correlation_time="600"
|
||||
mag_topic="/mag"
|
||||
>
|
||||
</xacro:magnetometer_plugin_macro>
|
||||
|
||||
<!-- Instantiate barometer plugin. -->
|
||||
<xacro:barometer_plugin_macro
|
||||
namespace="${namespace}"
|
||||
pub_rate="10"
|
||||
baro_topic="/baro"
|
||||
>
|
||||
</xacro:barometer_plugin_macro>
|
||||
|
||||
<xacro:if value="$(arg enable_mavlink_interface)">
|
||||
<!-- Instantiate mavlink telemetry interface. -->
|
||||
<xacro:mavlink_interface_macro
|
||||
namespace="${namespace}"
|
||||
imu_sub_topic="/imu"
|
||||
gps_sub_topic="/gps"
|
||||
mag_sub_topic="/mag"
|
||||
baro_sub_topic="/baro"
|
||||
mavlink_addr="$(arg mavlink_addr)"
|
||||
mavlink_udp_port="$(arg mavlink_udp_port)"
|
||||
mavlink_tcp_port="$(arg mavlink_tcp_port)"
|
||||
serial_enabled="$(arg serial_enabled)"
|
||||
serial_device="$(arg serial_device)"
|
||||
baudrate="$(arg baudrate)"
|
||||
qgc_addr="$(arg qgc_addr)"
|
||||
qgc_udp_port="$(arg qgc_udp_port)"
|
||||
sdk_addr="$(arg sdk_addr)"
|
||||
sdk_udp_port="$(arg sdk_udp_port)"
|
||||
hil_mode="$(arg hil_mode)"
|
||||
hil_state_level="$(arg hil_state_level)"
|
||||
vehicle_is_tailsitter="$(arg vehicle_is_tailsitter)"
|
||||
send_vision_estimation="$(arg send_vision_estimation)"
|
||||
send_odometry="$(arg send_odometry)"
|
||||
enable_lockstep="$(arg enable_lockstep)"
|
||||
use_tcp="$(arg use_tcp)"
|
||||
>
|
||||
</xacro:mavlink_interface_macro>
|
||||
</xacro:if>
|
||||
|
||||
<!-- Mount an ADIS16448 IMU. -->
|
||||
<xacro:imu_plugin_macro
|
||||
namespace="${namespace}"
|
||||
imu_suffix=""
|
||||
parent_link="base_link"
|
||||
imu_topic="/imu"
|
||||
mass_imu_sensor="0.015"
|
||||
gyroscope_noise_density="0.0003394"
|
||||
gyroscopoe_random_walk="0.000038785"
|
||||
gyroscope_bias_correlation_time="1000.0"
|
||||
gyroscope_turn_on_bias_sigma="0.0087"
|
||||
accelerometer_noise_density="0.004"
|
||||
accelerometer_random_walk="0.006"
|
||||
accelerometer_bias_correlation_time="300.0"
|
||||
accelerometer_turn_on_bias_sigma="0.1960"
|
||||
>
|
||||
<inertia ixx="0.00001" ixy="0.0" ixz="0.0" iyy="0.00001" iyz="0.0" izz="0.00001" />
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
</xacro:imu_plugin_macro>
|
||||
|
||||
<xacro:if value="$(arg enable_ground_truth)">
|
||||
<!-- Mount an IMU providing ground truth. -->
|
||||
<xacro:imu_plugin_macro
|
||||
namespace="${namespace}"
|
||||
imu_suffix="gt"
|
||||
parent_link="base_link"
|
||||
imu_topic="ground_truth/imu"
|
||||
mass_imu_sensor="0.00001"
|
||||
gyroscope_noise_density="0.0"
|
||||
gyroscopoe_random_walk="0.0"
|
||||
gyroscope_bias_correlation_time="1000.0"
|
||||
gyroscope_turn_on_bias_sigma="0.0"
|
||||
accelerometer_noise_density="0.0"
|
||||
accelerometer_random_walk="0.0"
|
||||
accelerometer_bias_correlation_time="300.0"
|
||||
accelerometer_turn_on_bias_sigma="0.0"
|
||||
>
|
||||
<inertia ixx="0.00001" ixy="0.0" ixz="0.0" iyy="0.00001" iyz="0.0" izz="0.00001" />
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
</xacro:imu_plugin_macro>
|
||||
|
||||
<!-- Mount a generic odometry sensor providing ground truth. -->
|
||||
<xacro:odometry_plugin_macro
|
||||
namespace="${namespace}/ground_truth"
|
||||
odometry_sensor_suffix="gt"
|
||||
parent_link="base_link"
|
||||
pose_topic="pose"
|
||||
pose_with_covariance_topic="pose_with_covariance"
|
||||
position_topic="position"
|
||||
transform_topic="transform"
|
||||
odometry_topic="odometry"
|
||||
parent_frame_id="world"
|
||||
mass_odometry_sensor="0.00001"
|
||||
measurement_divisor="1"
|
||||
measurement_delay="0"
|
||||
unknown_delay="0.0"
|
||||
noise_normal_position="0 0 0"
|
||||
noise_normal_quaternion="0 0 0"
|
||||
noise_normal_linear_velocity="0 0 0"
|
||||
noise_normal_angular_velocity="0 0 0"
|
||||
noise_uniform_position="0 0 0"
|
||||
noise_uniform_quaternion="0 0 0"
|
||||
noise_uniform_linear_velocity="0 0 0"
|
||||
noise_uniform_angular_velocity="0 0 0"
|
||||
enable_odometry_map="false"
|
||||
odometry_map=""
|
||||
image_scale=""
|
||||
>
|
||||
<inertia ixx="0.00001" ixy="0.0" ixz="0.0" iyy="0.00001" iyz="0.0" izz="0.00001" /> <!-- [kg.m^2] [kg.m^2] [kg.m^2] [kg.m^2] [kg.m^2] [kg.m^2] -->
|
||||
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
|
||||
</xacro:odometry_plugin_macro>
|
||||
</xacro:if>
|
||||
|
||||
<xacro:if value="$(arg enable_logging)">
|
||||
<!-- Instantiate a logger -->
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- Reference: https://github.com/PX4/PX4-SITL_gazebo/blob/7505aee97d2d3112fb2bd95198946345c6fa0b07/models/iris/iris.sdf.jinja#L430 -->
|
||||
|
||||
<robot xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
|
||||
<!-- IMU link -->
|
||||
<link name="/imu_link">
|
||||
<inertial>
|
||||
<inertia ixx="0.00001" ixy="0.0" ixz="0.0" iyy="0.00001" iyz="0.0" izz="0.00001"/>
|
||||
<mass value="0.015"/>
|
||||
<!-- [kg] -->
|
||||
<origin rpy="0 0 0" xyz="0 0 0"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<!-- IMU joint -->
|
||||
<joint name="/imu_joint" type="fixed">
|
||||
<origin rpy="0 0 0" xyz="0 0 0"/>
|
||||
<parent link="base_link"/>
|
||||
<child link="/imu_link"/>
|
||||
<!-- <limit upper="0" lower="0" effort="0" velocity="0" /> -->
|
||||
</joint>
|
||||
|
||||
<gazebo reference="/imu_joint">
|
||||
<disableFixedJointLumping>true</disableFixedJointLumping>
|
||||
<preserveFixedJoint>true</preserveFixedJoint>
|
||||
</gazebo>
|
||||
|
||||
<gazebo>
|
||||
<plugin name='groundtruth_plugin' filename='libgazebo_groundtruth_plugin.so'>
|
||||
<robotNamespace/>
|
||||
</plugin>
|
||||
<plugin name='magnetometer_plugin' filename='libgazebo_magnetometer_plugin.so'>
|
||||
<robotNamespace/>
|
||||
<pubRate>100</pubRate>
|
||||
<noiseDensity>0.0004</noiseDensity>
|
||||
<randomWalk>6.4e-06</randomWalk>
|
||||
<biasCorrelationTime>600</biasCorrelationTime>
|
||||
<magTopic>/mag</magTopic>
|
||||
</plugin>
|
||||
<plugin name='barometer_plugin' filename='libgazebo_barometer_plugin.so'>
|
||||
<robotNamespace/>
|
||||
<pubRate>50</pubRate>
|
||||
<baroTopic>/baro</baroTopic>
|
||||
<baroDriftPaPerSec>0</baroDriftPaPerSec>
|
||||
</plugin>
|
||||
<plugin name='mavlink_interface' filename='libgazebo_mavlink_interface.so'>
|
||||
<robotNamespace/>
|
||||
<imuSubTopic>/imu</imuSubTopic>
|
||||
<magSubTopic>/mag</magSubTopic>
|
||||
<baroSubTopic>/baro</baroSubTopic>
|
||||
<mavlink_addr>INADDR_ANY</mavlink_addr>
|
||||
<mavlink_tcp_port>4560</mavlink_tcp_port>
|
||||
<mavlink_udp_port>14560</mavlink_udp_port>
|
||||
<serialEnabled>false</serialEnabled>
|
||||
<serialDevice>/dev/ttyACM0</serialDevice>
|
||||
<baudRate>921600</baudRate>
|
||||
<qgc_addr>INADDR_ANY</qgc_addr>
|
||||
<qgc_udp_port>14550</qgc_udp_port>
|
||||
<sdk_addr>INADDR_ANY</sdk_addr>
|
||||
<sdk_udp_port>14540</sdk_udp_port>
|
||||
<hil_mode>false</hil_mode>
|
||||
<hil_state_level>0</hil_state_level>
|
||||
<send_vision_estimation>0</send_vision_estimation>
|
||||
<send_odometry>1</send_odometry>
|
||||
<enable_lockstep>1</enable_lockstep>
|
||||
<use_tcp>1</use_tcp>
|
||||
<motorSpeedCommandPubTopic>/gazebo/command/motor_speed</motorSpeedCommandPubTopic>
|
||||
<control_channels>
|
||||
<channel name='rotor1'>
|
||||
<input_index>0</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>1000</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>100</zero_position_armed>
|
||||
<joint_control_type>velocity</joint_control_type>
|
||||
</channel>
|
||||
<channel name='rotor2'>
|
||||
<input_index>1</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>1000</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>100</zero_position_armed>
|
||||
<joint_control_type>velocity</joint_control_type>
|
||||
</channel>
|
||||
<channel name='rotor3'>
|
||||
<input_index>2</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>1000</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>100</zero_position_armed>
|
||||
<joint_control_type>velocity</joint_control_type>
|
||||
</channel>
|
||||
<channel name='rotor4'>
|
||||
<input_index>3</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>1000</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>100</zero_position_armed>
|
||||
<joint_control_type>velocity</joint_control_type>
|
||||
</channel>
|
||||
<channel name='rotor5'>
|
||||
<input_index>4</input_index>
|
||||
<input_offset>1</input_offset>
|
||||
<input_scaling>324.6</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>0</zero_position_armed>
|
||||
<joint_control_type>velocity</joint_control_type>
|
||||
<joint_control_pid>
|
||||
<p>0.1</p>
|
||||
<i>0</i>
|
||||
<d>0</d>
|
||||
<iMax>0.0</iMax>
|
||||
<iMin>0.0</iMin>
|
||||
<cmdMax>2</cmdMax>
|
||||
<cmdMin>-2</cmdMin>
|
||||
</joint_control_pid>
|
||||
<joint_name>zephyr_delta_wing::propeller_joint</joint_name>
|
||||
</channel>
|
||||
<channel name='rotor6'>
|
||||
<input_index>5</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>0.524</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>0</zero_position_armed>
|
||||
<joint_control_type>position</joint_control_type>
|
||||
<joint_name>zephyr_delta_wing::flap_left_joint</joint_name>
|
||||
<joint_control_pid>
|
||||
<p>10.0</p>
|
||||
<i>0</i>
|
||||
<d>0</d>
|
||||
<iMax>0</iMax>
|
||||
<iMin>0</iMin>
|
||||
<cmdMax>20</cmdMax>
|
||||
<cmdMin>-20</cmdMin>
|
||||
</joint_control_pid>
|
||||
</channel>
|
||||
<channel name='rotor7'>
|
||||
<input_index>6</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>0.524</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>0</zero_position_armed>
|
||||
<joint_control_type>position</joint_control_type>
|
||||
<joint_name>zephyr_delta_wing::flap_right_joint</joint_name>
|
||||
<joint_control_pid>
|
||||
<p>10.0</p>
|
||||
<i>0</i>
|
||||
<d>0</d>
|
||||
<iMax>0</iMax>
|
||||
<iMin>0</iMin>
|
||||
<cmdMax>20</cmdMax>
|
||||
<cmdMin>-20</cmdMin>
|
||||
</joint_control_pid>
|
||||
</channel>
|
||||
<channel name='rotor8'>
|
||||
<input_index>7</input_index>
|
||||
<input_offset>0</input_offset>
|
||||
<input_scaling>0.524</input_scaling>
|
||||
<zero_position_disarmed>0</zero_position_disarmed>
|
||||
<zero_position_armed>0</zero_position_armed>
|
||||
<joint_control_type>position</joint_control_type>
|
||||
</channel>
|
||||
</control_channels>
|
||||
</plugin>
|
||||
<static>0</static>
|
||||
<plugin name='rotors_gazebo_imu_plugin' filename='libgazebo_imu_plugin.so'>
|
||||
<robotNamespace/>
|
||||
<linkName>/imu_link</linkName>
|
||||
<imuTopic>/imu</imuTopic>
|
||||
<gyroscopeNoiseDensity>0.00018665</gyroscopeNoiseDensity>
|
||||
<gyroscopeRandomWalk>3.8785e-05</gyroscopeRandomWalk>
|
||||
<gyroscopeBiasCorrelationTime>1000.0</gyroscopeBiasCorrelationTime>
|
||||
<gyroscopeTurnOnBiasSigma>0.0087</gyroscopeTurnOnBiasSigma>
|
||||
<accelerometerNoiseDensity>0.00186</accelerometerNoiseDensity>
|
||||
<accelerometerRandomWalk>0.006</accelerometerRandomWalk>
|
||||
<accelerometerBiasCorrelationTime>300.0</accelerometerBiasCorrelationTime>
|
||||
<accelerometerTurnOnBiasSigma>0.196</accelerometerTurnOnBiasSigma>
|
||||
</plugin>
|
||||
</gazebo>
|
||||
|
||||
</robot>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
-->
|
||||
|
||||
<robot name="clover" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<robot name="iris" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<!-- Properties -->
|
||||
<xacro:property name="namespace" value="" />
|
||||
<xacro:property name="rotor_velocity_slowdown_sim" value="10" />
|
||||
@@ -84,7 +84,7 @@
|
||||
</xacro:unless>
|
||||
|
||||
<!-- Included URDF Files -->
|
||||
<xacro:include filename="clover4_macros.xacro" />
|
||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_macros.xacro" />
|
||||
|
||||
<!-- Instantiate multirotor_base_macro once -->
|
||||
<xacro:clover4_base_macro
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<robot name="rpi_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<xacro:include filename="../camera_sensor.urdf.xacro"/>
|
||||
<xacro:include filename="$(find clover_description)/urdf/camera_sensor.urdf.xacro"/>
|
||||
|
||||
<xacro:macro name="distance_sensor" params="name:=lidar_vl53l1x parent x:=0 y:=0 z:=0 roll:=0 pitch:=0 yaw:=0 range_min:=0.01 range_max:=4.0 resolution:=0.01 rate:=10">
|
||||
<joint name="${name}_joint" type="fixed">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<robot name="pinhole_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<xacro:include filename="../camera_sensor.urdf.xacro"/>
|
||||
<xacro:include filename="$(find clover_description)/urdf/camera_sensor.urdf.xacro"/>
|
||||
<xacro:camera_sensor name="main_camera" width="640" height="480" rate="30" horizontal_fov="${120.0*pi/180.0}"/>
|
||||
</robot>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<robot name="rpi_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<xacro:include filename="../camera_sensor.urdf.xacro"/>
|
||||
<xacro:include filename="$(find clover_description)/urdf/camera_sensor.urdf.xacro"/>
|
||||
|
||||
<xacro:macro name="rpi_cam" params="name:=rpi_cam parent x:=0 y:=0 z:=0 roll:=0 pitch:=0 yaw:=0 width:=320 height:=240 rate:=40 do_throttling:=false">
|
||||
<joint name="${name}_joint" type="fixed">
|
||||
|
||||
@@ -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
|
||||
@@ -52,7 +52,7 @@ target_compile_options(throttling_camera PRIVATE -std=c++11)
|
||||
add_dependencies(throttling_camera ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
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})
|
||||
|
||||
catkin_install_python(PROGRAMS scripts/aruco_gen
|
||||
|
||||
@@ -55,7 +55,7 @@ A visual Gazebo plugin is used for the LED strip. An example of the plugin usage
|
||||
The plugin accepts the following parameters during instantiation:
|
||||
|
||||
* `robotNamespace` (*string*, default: "") - a ROS namespace for the plugin;
|
||||
* `ledCount` (*integer*, required) - total number of LEDs in a strip.
|
||||
* `ledCount` (*integer*, required) - total numer of LEDs in a strip.
|
||||
|
||||
The plugin will provide the following service:
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# @name COEX Clover Simulator
|
||||
#
|
||||
# @type Quadrotor X
|
||||
#
|
||||
|
||||
. ${R}etc/init.d-posix/airframes/10016_iris # base on iris
|
||||
|
||||
param set ATT_W_EXT_HDG 0.5
|
||||
param set ATT_EXT_HDG_M 1
|
||||
|
||||
param set COM_DISARM_LAND 1.0
|
||||
|
||||
param set LPE_FLW_SCALE 1.0
|
||||
param set LPE_FLW_R 0.2
|
||||
param set LPE_FLW_RR 0.0
|
||||
param set LPE_FLW_QMIN 10
|
||||
param set LPE_VIS_DELAY 0.0
|
||||
param set LPE_VIS_Z 0.1
|
||||
param set LPE_FUSION 86
|
||||
|
||||
param set SENS_FLOW_ROT 0
|
||||
param set SENS_FLOW_MINHGT 0.01
|
||||
param set SENS_FLOW_MAXHGT 4.0
|
||||
param set SENS_FLOW_MAXR 10.0
|
||||
|
||||
param set EKF2_AID_MASK 27 # gps + flow + vis pos + vis yaw
|
||||
param set EKF2_OF_DELAY 0
|
||||
param set EKF2_OF_QMIN 10
|
||||
param set EKF2_OF_N_MIN 0.05
|
||||
param set EKF2_OF_N_MAX 0.2
|
||||
param set EKF2_HGT_MODE 2
|
||||
param set EKF2_EVA_NOISE 0.1
|
||||
param set EKF2_EVP_NOISE 0.1
|
||||
param set EKF2_EV_DELAY 0
|
||||
@@ -1,57 +1,41 @@
|
||||
<launch>
|
||||
<arg name="type" default="gazebo"/> <!-- gazebo, jmavsim, none (only clover packages) -->
|
||||
<arg name="mav_id" default="0"/>
|
||||
<arg name="est" default="ekf2"/> <!-- PX4 estimator: lpe, ekf2 -->
|
||||
<arg name="vehicle" default="clover"/> <!-- PX4 vehicle configuration: clover, clover_vpe -->
|
||||
<arg name="main_camera" default="true"/> <!-- Simulated vision position estimation camera (optical flow, ArUco) -->
|
||||
<arg name="maintain_camera_rate" default="false"/> <!-- Slow simulation down to maintain camera rate -->
|
||||
<arg name="rangefinder" default="true"/> <!-- Simulated downward-facing rangefinder, vl53l1x-like -->
|
||||
<arg name="led" default="true"/> <!-- Simulated LED strip, ws281x-like -->
|
||||
<arg name="gps" default="false"/> <!--Simulated GPS module -->
|
||||
<arg name="use_clover_physics" default="false"/> <!-- Use inertial parameters from CAD models -->
|
||||
<arg name="gui" default="true"/> <!-- Run Gazebo with GUI -->
|
||||
|
||||
<!-- 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 -->
|
||||
<env name="SVGA_VGPU10" value="0"/>
|
||||
<arg name="gui" value="$(arg gui)"/>
|
||||
<arg name="world_name" value="$(find clover_simulation)/resources/worlds/clover_aruco.world"/>
|
||||
<arg name="gui" value="true"/>
|
||||
<arg name="world_name" value="$(find clover_simulation)/resources/worlds/clover.world"/>
|
||||
<arg name="verbose" value="true"/>
|
||||
</include>
|
||||
|
||||
<!-- 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_ESTIMATOR" value="$(arg est)"/>
|
||||
</node>
|
||||
|
||||
<!-- 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="maintain_camera_rate" value="$(arg maintain_camera_rate)"/>
|
||||
<arg name="rangefinder" value="$(arg rangefinder)"/>
|
||||
<arg name="led" value="$(arg led)"/>
|
||||
<arg name="gps" value="$(arg gps)"/>
|
||||
<arg name="use_clover_physics" value="$(arg use_clover_physics)"/>
|
||||
</include>
|
||||
|
||||
<node name="jmavsim" pkg="px4" type="jmavsim_run.sh" output="screen" if="$(eval type == 'jmavsim')">
|
||||
<env name="HEADLESS" value="1" if="$(eval not gui)"/>
|
||||
</node>
|
||||
|
||||
<param name="use_sim_time" value="false" if="$(eval type == 'jmavsim')"/>
|
||||
|
||||
<!-- Clover services -->
|
||||
<include file="$(find clover)/launch/clover.launch">
|
||||
<arg name="simulator" value="true"/>
|
||||
<arg name="fcu_conn" value="sitl"/>
|
||||
<arg name="fcu_ip" value="127.0.0.1"/>
|
||||
<arg name="gcs_bridge" value=""/>
|
||||
<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="optical_flow" default="false" if="$(eval type == 'jmavsim')"/>
|
||||
<arg name="led" default="false" if="$(eval type == 'jmavsim')"/>
|
||||
</include>
|
||||
</launch>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<sdf version="1.5">
|
||||
<model name="aruco_100">
|
||||
<static>true</static>
|
||||
<link name="marker_100_link">
|
||||
<pose>0 0 1e-3 0 0 1.5707963267948966</pose>
|
||||
<visual name="visual_marker_100">
|
||||
<cast_shadows>false</cast_shadows>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>0.22 0.22 1e-3</size>
|
||||
</box>
|
||||
</geometry>
|
||||
<material>
|
||||
<script>
|
||||
<uri>model://aruco_100/materials/scripts</uri>
|
||||
<uri>model://aruco_100/materials/textures</uri>
|
||||
<name>aruco/marker_100</name>
|
||||
</script>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
</sdf>
|
||||
@@ -1,15 +0,0 @@
|
||||
material aruco/marker_100
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
texture_unit
|
||||
{
|
||||
texture aruco_marker_100.png
|
||||
filtering none
|
||||
scale 1.0 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 94 B |
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<model>
|
||||
<name>ArUco Marker 100</name>
|
||||
<version>1.0</version>
|
||||
<sdf version="1.5">marker_100.sdf</sdf>
|
||||
<author>
|
||||
<name>Marker Generator script</name>
|
||||
<email>marker@generator.sh</email>
|
||||
</author>
|
||||
<description>
|
||||
ArUco marker #100
|
||||
</description>
|
||||
</model>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<sdf version="1.5">
|
||||
<model name="aruco_101">
|
||||
<static>true</static>
|
||||
<link name="marker_101_link">
|
||||
<pose>0 0 1e-3 0 0 1.5707963267948966</pose>
|
||||
<visual name="visual_marker_101">
|
||||
<cast_shadows>false</cast_shadows>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>0.44 0.44 1e-3</size>
|
||||
</box>
|
||||
</geometry>
|
||||
<material>
|
||||
<script>
|
||||
<uri>model://aruco_101/materials/scripts</uri>
|
||||
<uri>model://aruco_101/materials/textures</uri>
|
||||
<name>aruco/marker_101</name>
|
||||
</script>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
</sdf>
|
||||
@@ -1,15 +0,0 @@
|
||||
material aruco/marker_101
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
texture_unit
|
||||
{
|
||||
texture aruco_marker_101.png
|
||||
filtering none
|
||||
scale 1.0 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 94 B |
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<model>
|
||||
<name>ArUco Marker 101</name>
|
||||
<version>1.0</version>
|
||||
<sdf version="1.5">marker_101.sdf</sdf>
|
||||
<author>
|
||||
<name>Marker Generator script</name>
|
||||
<email>marker@generator.sh</email>
|
||||
</author>
|
||||
<description>
|
||||
ArUco marker #101
|
||||
</description>
|
||||
</model>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<sdf version="1.5">
|
||||
<model name="aruco_102">
|
||||
<static>true</static>
|
||||
<link name="marker_102_link">
|
||||
<pose>0 0 1e-3 0 0 1.5707963267948966</pose>
|
||||
<visual name="visual_marker_102">
|
||||
<cast_shadows>false</cast_shadows>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>0.44 0.44 1e-3</size>
|
||||
</box>
|
||||
</geometry>
|
||||
<material>
|
||||
<script>
|
||||
<uri>model://aruco_102/materials/scripts</uri>
|
||||
<uri>model://aruco_102/materials/textures</uri>
|
||||
<name>aruco/marker_102</name>
|
||||
</script>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
</sdf>
|
||||
@@ -1,15 +0,0 @@
|
||||
material aruco/marker_102
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
texture_unit
|
||||
{
|
||||
texture aruco_marker_102.png
|
||||
filtering none
|
||||
scale 1.0 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 94 B |
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<model>
|
||||
<name>ArUco Marker 102</name>
|
||||
<version>1.0</version>
|
||||
<sdf version="1.5">marker_102.sdf</sdf>
|
||||
<author>
|
||||
<name>Marker Generator script</name>
|
||||
<email>marker@generator.sh</email>
|
||||
</author>
|
||||
<description>
|
||||
ArUco marker #102
|
||||
</description>
|
||||
</model>
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user