mirror of
https://github.com/CopterExpress/clover.git
synced 2026-06-02 16:09:32 +00:00
Compare commits
326 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a72bf9cbad | ||
|
|
9dc4407afc | ||
|
|
365bd4146a | ||
|
|
fc99269404 | ||
|
|
9231679353 | ||
|
|
4defe2c7ef | ||
|
|
9f3410847f | ||
|
|
fa8da1cb33 | ||
|
|
3bb285fd35 | ||
|
|
ec1829e60c | ||
|
|
c32a412f42 | ||
|
|
810ddb4157 | ||
|
|
3656c1714a | ||
|
|
937b68aa43 | ||
|
|
bdd1b06541 | ||
|
|
dd96c91b55 | ||
|
|
8f3d64e9aa | ||
|
|
cfd413ffc1 | ||
|
|
ca054c88ba | ||
|
|
d55576bf4f | ||
|
|
470e6ff0e9 | ||
|
|
441cf7fcf7 | ||
|
|
fc5960586b | ||
|
|
4aef1e616c | ||
|
|
463c08da96 | ||
|
|
ebaaa14a7e | ||
|
|
c0d33abff6 | ||
|
|
3c4ef56b4e | ||
|
|
17e806601d | ||
|
|
3e3c5aa453 | ||
|
|
7fd463d1cb | ||
|
|
64b083b242 | ||
|
|
b2ec48f0f3 | ||
|
|
b249524828 | ||
|
|
d0dcc0e72a | ||
|
|
4c6e7029e8 | ||
|
|
613f70fd25 | ||
|
|
77832e65fa | ||
|
|
01edd129ab | ||
|
|
d03acff31b | ||
|
|
22e74febd6 | ||
|
|
989d9b66f1 | ||
|
|
f8eb8e1e67 | ||
|
|
b92ebe7d60 | ||
|
|
af51e88179 | ||
|
|
59c8debcab | ||
|
|
ec6f3089e3 | ||
|
|
2b88d21792 | ||
|
|
274b81c50f | ||
|
|
33a6dffb1f | ||
|
|
5f9b3e82db | ||
|
|
5f43367d82 | ||
|
|
7809e7ed2d | ||
|
|
1688b97091 | ||
|
|
1c6129fde8 | ||
|
|
dae9599d64 | ||
|
|
c0677f6aa3 | ||
|
|
e7bbf21700 | ||
|
|
58c10d7cb8 | ||
|
|
b6bd6bdde8 | ||
|
|
3374c7756c | ||
|
|
0dffeca55f | ||
|
|
8cb911854d | ||
|
|
a1b3efe67d | ||
|
|
6700d8728f | ||
|
|
be2e6ae198 | ||
|
|
b9eed0f3ad | ||
|
|
853a7fcf67 | ||
|
|
e342796f07 | ||
|
|
4fa70aa73a | ||
|
|
226c91c3d8 | ||
|
|
e33c9e78ea | ||
|
|
18c927469e | ||
|
|
a465afd65c | ||
|
|
a2c65d2466 | ||
|
|
ef7faa126a | ||
|
|
d0666ca9d7 | ||
|
|
b48f22cd35 | ||
|
|
731f908053 | ||
|
|
505a1efebd | ||
|
|
f1b5484e65 | ||
|
|
3343477a02 | ||
|
|
60da608191 | ||
|
|
7e383d713d | ||
|
|
c2a60380b7 | ||
|
|
7f82f8683f | ||
|
|
e28cbea8d9 | ||
|
|
27528c20dc | ||
|
|
e3503fca35 | ||
|
|
40b8941cab | ||
|
|
0a9b6fff95 | ||
|
|
4a4e539edd | ||
|
|
8d24a737ac | ||
|
|
20af13947d | ||
|
|
e91609ff61 | ||
|
|
0024372c45 | ||
|
|
b62d202a29 | ||
|
|
84d685469a | ||
|
|
3f6bb0cd68 | ||
|
|
c01a145a16 | ||
|
|
6d28bf4ef9 | ||
|
|
f6ea7209db | ||
|
|
21727ef76d | ||
|
|
9847b7a71c | ||
|
|
a5d44ff63a | ||
|
|
391a2f9af9 | ||
|
|
5918702fbd | ||
|
|
69fe288a41 | ||
|
|
5154720348 | ||
|
|
cc1694661d | ||
|
|
d5efa962d8 | ||
|
|
1195336cbc | ||
|
|
5fc67b8e65 | ||
|
|
c1409d4467 | ||
|
|
7a1f09da98 | ||
|
|
6934cc7a1a | ||
|
|
2550ffe532 | ||
|
|
9def866a30 | ||
|
|
802f8eeaa4 | ||
|
|
504aa53b1a | ||
|
|
015cf730c2 | ||
|
|
8e6ef727ce | ||
|
|
973e1f1181 | ||
|
|
275faa78a4 | ||
|
|
fc7d010881 | ||
|
|
242e35f84a | ||
|
|
3f07d28e0f | ||
|
|
613d378e66 | ||
|
|
769c421898 | ||
|
|
3830ceea04 | ||
|
|
df3a11b035 | ||
|
|
ef5700845f | ||
|
|
921084504e | ||
|
|
6550780afb | ||
|
|
2448915300 | ||
|
|
247a7917d9 | ||
|
|
37f2c78b36 | ||
|
|
e76618bd3b | ||
|
|
9fbfcfbd2e | ||
|
|
2003b4516a | ||
|
|
03985ae1b8 | ||
|
|
a47d5d1bfe | ||
|
|
20075dd40f | ||
|
|
c247c75d17 | ||
|
|
c36279e536 | ||
|
|
1471a53b3a | ||
|
|
931f50a458 | ||
|
|
118b4573fe | ||
|
|
f77843f4a5 | ||
|
|
5f62a8639a | ||
|
|
fa1db1d90b | ||
|
|
1a2e87bb6a | ||
|
|
7dbd983ec5 | ||
|
|
d2d395f1fc | ||
|
|
ff93f79c0a | ||
|
|
5deb09eb45 | ||
|
|
70b8be5c5d | ||
|
|
2a08e20b47 | ||
|
|
3328d8f4ac | ||
|
|
f7fb814894 | ||
|
|
3a3b0bbd80 | ||
|
|
ca095f3f16 | ||
|
|
baf2467939 | ||
|
|
abba3bf876 | ||
|
|
346373ed23 | ||
|
|
bb996056c9 | ||
|
|
0e0b1cdc31 | ||
|
|
eceaa0ec91 | ||
|
|
f29686b9f4 | ||
|
|
b7f1f2b391 | ||
|
|
6b0bb41564 | ||
|
|
563e5acad6 | ||
|
|
5932faa29c | ||
|
|
bcc2e86e6f | ||
|
|
e80a1cc7d6 | ||
|
|
5fd3a92c7b | ||
|
|
84b87055df | ||
|
|
7cc0f066c7 | ||
|
|
868fc728dd | ||
|
|
faa90b89f6 | ||
|
|
f4d07e2c2c | ||
|
|
fad7886012 | ||
|
|
7eb139fd22 | ||
|
|
855d13e210 | ||
|
|
781b8962be | ||
|
|
047a965f9f | ||
|
|
47060db84b | ||
|
|
2693fd4ace | ||
|
|
faa702cab0 | ||
|
|
150ecbe29d | ||
|
|
df5e83e416 | ||
|
|
1f2ba65669 | ||
|
|
27be9eb281 | ||
|
|
f8222e1028 | ||
|
|
dce0c00773 | ||
|
|
dc8c5d9db9 | ||
|
|
261faaec0e | ||
|
|
dbd9a4a238 | ||
|
|
80d446e857 | ||
|
|
609a7ab014 | ||
|
|
c0d9bd7ef0 | ||
|
|
cdd6000c58 | ||
|
|
480a9b1f0a | ||
|
|
4943cb94b0 | ||
|
|
e0ca1272bb | ||
|
|
cb88537ddc | ||
|
|
659380c575 | ||
|
|
b4a8119bd7 | ||
|
|
c72eb1b440 | ||
|
|
f825901a19 | ||
|
|
200c5dea57 | ||
|
|
0504569b0c | ||
|
|
9829ee2e72 | ||
|
|
dfdaf3aa4f | ||
|
|
63f979c2ff | ||
|
|
b8dafce816 | ||
|
|
19e0b94fda | ||
|
|
957e57692c | ||
|
|
0d49c426eb | ||
|
|
b1f104ce5e | ||
|
|
80177b3ea4 | ||
|
|
3223d3817e | ||
|
|
4612f7e9f0 | ||
|
|
a026410fdb | ||
|
|
dd1a212cd0 | ||
|
|
20b6824012 | ||
|
|
6f6933234c | ||
|
|
3edafbef97 | ||
|
|
7740a136ce | ||
|
|
380112de6a | ||
|
|
79f5c6d0e7 | ||
|
|
e207b55966 | ||
|
|
043a4ad67c | ||
|
|
dbeb2b354d | ||
|
|
6134965f2a | ||
|
|
976bb7aeea | ||
|
|
faa0e6d8d2 | ||
|
|
d02151aedd | ||
|
|
7f0606397e | ||
|
|
fb2842a0a1 | ||
|
|
9a9621ab4b | ||
|
|
171804149c | ||
|
|
0cb7494023 | ||
|
|
e0a81e0ca8 | ||
|
|
1e5e9cdc43 | ||
|
|
5e315c477e | ||
|
|
f45000f595 | ||
|
|
48a1385a1a | ||
|
|
765c470baa | ||
|
|
fd69beed7b | ||
|
|
1d4179bccf | ||
|
|
0b2095bbb8 | ||
|
|
a0436fbcc5 | ||
|
|
aee867d6bc | ||
|
|
3c078ab92f | ||
|
|
d780aedb88 | ||
|
|
a16d9d80fc | ||
|
|
10d250d96a | ||
|
|
acdcf20392 | ||
|
|
796d614f5e | ||
|
|
f8de7443d7 | ||
|
|
5c3ffdbeb6 | ||
|
|
1c732137c6 | ||
|
|
345aad9e64 | ||
|
|
02c67ea71a | ||
|
|
050e0fedb9 | ||
|
|
0e9b54934c | ||
|
|
793b614b7b | ||
|
|
62ab5c2357 | ||
|
|
181a78e4a9 | ||
|
|
c72eb0c027 | ||
|
|
5d99e44c30 | ||
|
|
5eb9b4acbe | ||
|
|
30ada8f311 | ||
|
|
e717829945 | ||
|
|
50dc17badb | ||
|
|
1dea541df2 | ||
|
|
d6b950b726 | ||
|
|
e2a1d3aaeb | ||
|
|
165e4d1a61 | ||
|
|
4f631300d4 | ||
|
|
e252a1cddc | ||
|
|
25dd17c286 | ||
|
|
b9395e3d18 | ||
|
|
a32dd7dcdd | ||
|
|
1e12e34070 | ||
|
|
3ff675d794 | ||
|
|
bb3e4befe5 | ||
|
|
fe71007ebd | ||
|
|
68cec159f7 | ||
|
|
4e8127f690 | ||
|
|
8f78f2b6e4 | ||
|
|
c8163cd38b | ||
|
|
7831992d6a | ||
|
|
873befdba9 | ||
|
|
c3cbc305c3 | ||
|
|
b71e802a2e | ||
|
|
3c5f2c958e | ||
|
|
267993aec4 | ||
|
|
86dd42c3b3 | ||
|
|
9d338d843b | ||
|
|
3e100bee91 | ||
|
|
8a29b9a37a | ||
|
|
2e80a06db1 | ||
|
|
0003985c3b | ||
|
|
f250916ede | ||
|
|
ee2944a1d3 | ||
|
|
a088524468 | ||
|
|
215fe237ca | ||
|
|
8c1b5c19d0 | ||
|
|
779dfb3f4f | ||
|
|
23d503adc5 | ||
|
|
0350ecbff7 | ||
|
|
12bed337dc | ||
|
|
6a1b609ccd | ||
|
|
3d5c51a42e | ||
|
|
3702ed0c86 | ||
|
|
741abadb54 | ||
|
|
c6dc732867 | ||
|
|
ba76e51966 | ||
|
|
7951f0e2ba | ||
|
|
cd58c03c0f | ||
|
|
ce6b2530c4 | ||
|
|
14e4af76aa | ||
|
|
f3f1557b0b | ||
|
|
18d410db24 |
29
.github/workflows/build-image.yaml
vendored
Normal file
29
.github/workflows/build-image.yaml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
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
Normal file
23
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
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
|
||||||
53
.github/workflows/docs.yml
vendored
Normal file
53
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
name: Documentation
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ '*' ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docs:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with: { node-version: '10' }
|
||||||
|
- name: Setup tools
|
||||||
|
run: |
|
||||||
|
sudo sh -c "echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections"
|
||||||
|
sudo apt-get update && sudo apt-get install -y calibre msttcorefonts
|
||||||
|
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
Normal file
18
.github/workflows/editorconfig.yaml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
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,3 +6,4 @@ _book/
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
clover_blocks/programs/*.*
|
clover_blocks/programs/*.*
|
||||||
!clover_blocks/programs/examples/*
|
!clover_blocks/programs/examples/*
|
||||||
|
/.vscode/
|
||||||
|
|||||||
@@ -110,7 +110,8 @@
|
|||||||
"Li-ion",
|
"Li-ion",
|
||||||
"Nvidia",
|
"Nvidia",
|
||||||
"VirtualBox",
|
"VirtualBox",
|
||||||
"VMware"
|
"VMware",
|
||||||
|
"DuoCam"
|
||||||
],
|
],
|
||||||
"code_blocks": false
|
"code_blocks": false
|
||||||
},
|
},
|
||||||
|
|||||||
125
.travis.yml
125
.travis.yml
@@ -1,125 +0,0 @@
|
|||||||
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
|
# clover🍀: create autonomous drones easily
|
||||||
|
|
||||||
<img src="docs/assets/clever4-front-white.png" align="right" width="400px" alt="COEX Clover Drone">
|
<img src="docs/assets/clover42-main-margin.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.
|
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,7 +20,8 @@ Clover drone is used on a wide range of educational events, including [Copter Ha
|
|||||||
|
|
||||||
Preconfigured image for Raspberry Pi with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clover/releases).
|
Preconfigured image for Raspberry Pi with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clover/releases).
|
||||||
|
|
||||||
[](https://travis-ci.org/CopterExpress/clover)
|

|
||||||
|

|
||||||
|
|
||||||
Image features:
|
Image features:
|
||||||
|
|
||||||
@@ -37,6 +38,10 @@ API description for autonomous flights is available [on GitBook](https://clover.
|
|||||||
|
|
||||||
For manual package installation and running see [`clover` package documentation](clover/README.md).
|
For manual package installation and running see [`clover` package documentation](clover/README.md).
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
[](https://t.me/COEXHelpdesk)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
While the Clover platform source code is available under the MIT License, note, that the [documentation](docs/) is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
While the Clover platform source code is available under the MIT License, note, that the [documentation](docs/) is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
iOS-приложение для управления Клевером
|
# iOS-приложение для управления Клевером
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
Для установки зависимостей необходим [CocoaPods](https://cocoapods.org):
|
Для установки зависимостей необходим [CocoaPods](https://cocoapods.org):
|
||||||
|
|
||||||
|
|||||||
8
aruco_pose/CHANGELOG.rst
Normal file
8
aruco_pose/CHANGELOG.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
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 parameters in the 'cfg' folder
|
||||||
generate_dynamic_reconfigure_options(
|
generate_dynamic_reconfigure_options(
|
||||||
cfg/DetectorParams.cfg
|
cfg/Detector.cfg
|
||||||
)
|
)
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
@@ -202,11 +202,11 @@ set_property(TARGET aruco_pose
|
|||||||
# )
|
# )
|
||||||
|
|
||||||
## Mark executables and/or libraries for installation
|
## Mark executables and/or libraries for installation
|
||||||
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
|
install(TARGETS ${PROJECT_NAME}
|
||||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||||
# )
|
)
|
||||||
|
|
||||||
## Mark cpp header files for installation
|
## Mark cpp header files for installation
|
||||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||||
@@ -226,6 +226,10 @@ catkin_install_python(PROGRAMS src/genmap.py
|
|||||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||||
|
|
||||||
|
install(DIRECTORY map DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||||
|
|
||||||
#############
|
#############
|
||||||
## Testing ##
|
## 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
|
* `~map` – path to text file with markers list
|
||||||
* `~frame_id` – published frame id (default: `aruco_map`)
|
* `~frame_id` – published frame id (default: `aruco_map`)
|
||||||
* `~known_tilt` – debug image width
|
* `~known_tilt` – known tilt (pitch and roll) of markers map as a frame
|
||||||
* `~image_width` – debug image width (default: 2000)
|
* `~image_width` – debug image width (default: 2000)
|
||||||
* `~image_height` – debug image height (default: 2000)
|
* `~image_height` – debug image height (default: 2000)
|
||||||
* `~image_margin` – debug image margin (default: 200)
|
* `~image_margin` – debug image margin (default: 200)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ p = cv2.aruco.DetectorParameters_create()
|
|||||||
|
|
||||||
gen = ParameterGenerator()
|
gen = ParameterGenerator()
|
||||||
|
|
||||||
|
gen.add("enabled", bool_t, 0, "if detection enabled", True)
|
||||||
|
|
||||||
gen.add("adaptiveThreshConstant", double_t, 0,
|
gen.add("adaptiveThreshConstant", double_t, 0,
|
||||||
"Constant for adaptive thresholding before finding contours",
|
"Constant for adaptive thresholding before finding contours",
|
||||||
p.adaptiveThreshConstant, 0, 100)
|
p.adaptiveThreshConstant, 0, 100)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<package format="2">
|
<package format="2">
|
||||||
<name>aruco_pose</name>
|
<name>aruco_pose</name>
|
||||||
<version>0.0.1</version>
|
<version>0.21.1</version>
|
||||||
<description>Positioning with ArUco markers</description>
|
<description>Positioning with ArUco markers</description>
|
||||||
|
|
||||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ private:
|
|||||||
std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
|
std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
|
||||||
std::unique_ptr<tf2_ros::TransformListener> tf_listener_;
|
std::unique_ptr<tf2_ros::TransformListener> tf_listener_;
|
||||||
std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>> dyn_srv_;
|
std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>> dyn_srv_;
|
||||||
|
bool enabled_ = true;
|
||||||
cv::Ptr<cv::aruco::Dictionary> dictionary_;
|
cv::Ptr<cv::aruco::Dictionary> dictionary_;
|
||||||
cv::Ptr<cv::aruco::DetectorParameters> parameters_;
|
cv::Ptr<cv::aruco::DetectorParameters> parameters_;
|
||||||
image_transport::Publisher debug_pub_;
|
image_transport::Publisher debug_pub_;
|
||||||
@@ -125,6 +126,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void imageCallback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr &cinfo)
|
void imageCallback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr &cinfo)
|
||||||
{
|
{
|
||||||
|
if (!enabled_) return;
|
||||||
|
|
||||||
Mat image = cv_bridge::toCvShare(msg, "bgr8")->image;
|
Mat image = cv_bridge::toCvShare(msg, "bgr8")->image;
|
||||||
|
|
||||||
vector<int> ids;
|
vector<int> ids;
|
||||||
@@ -353,6 +356,7 @@ private:
|
|||||||
|
|
||||||
void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level)
|
void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level)
|
||||||
{
|
{
|
||||||
|
enabled_ = config.enabled;
|
||||||
parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant;
|
parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant;
|
||||||
parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin;
|
parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin;
|
||||||
parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax;
|
parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"yametrika",
|
"yametrika",
|
||||||
"anchors",
|
"anchors",
|
||||||
"collapsible-menu",
|
"collapsible-menu",
|
||||||
"validate-links",
|
"validate-links@https://github.com/okalachev/gitbook-plugin-validate-links.git",
|
||||||
"bulk-redirect@https://github.com/okalachev/gitbook-plugin-bulk-redirect.git",
|
"bulk-redirect@https://github.com/okalachev/gitbook-plugin-bulk-redirect.git",
|
||||||
"sitemap@https://github.com/okalachev/plugin-sitemap.git",
|
"sitemap@https://github.com/okalachev/plugin-sitemap.git",
|
||||||
"toolbar@https://github.com/hamishwillee/gitbook-plugin-toolbar.git",
|
"toolbar@https://github.com/hamishwillee/gitbook-plugin-toolbar.git",
|
||||||
|
|||||||
@@ -8,5 +8,9 @@ ExecStart=/bin/bash -c ". /home/pi/catkin_ws/devel/setup.sh; \
|
|||||||
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clover clover.launch --wait --screen --skip-log-check \
|
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clover clover.launch --wait --screen --skip-log-check \
|
||||||
2> >(tee /tmp/clover.err)"
|
2> >(tee /tmp/clover.err)"
|
||||||
|
|
||||||
|
ExecStartPre=+rm /var/log/clover.log
|
||||||
|
StandardOutput=file:/var/log/clover.log
|
||||||
|
StandardError=file:/var/log/clover.log
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ echo_stamp "#6 Turn on UART"
|
|||||||
# https://github.com/RPi-Distro/raspi-config/pull/75
|
# https://github.com/RPi-Distro/raspi-config/pull/75
|
||||||
/usr/bin/raspi-config nonint do_serial 1
|
/usr/bin/raspi-config nonint do_serial 1
|
||||||
/usr/bin/raspi-config nonint set_config_var enable_uart 1 /boot/config.txt
|
/usr/bin/raspi-config nonint set_config_var enable_uart 1 /boot/config.txt
|
||||||
/usr/bin/raspi-config nonint set_config_var dtoverlay pi3-disable-bt /boot/config.txt
|
echo dtoverlay=pi3-disable-bt >> /boot/config.txt
|
||||||
systemctl disable hciuart.service
|
systemctl disable hciuart.service
|
||||||
|
|
||||||
# After adding to Raspbian OS
|
# After adding to Raspbian OS
|
||||||
|
|||||||
9
builder/assets/install_gitbook.sh
Executable file
9
builder/assets/install_gitbook.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/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,7 +15,8 @@
|
|||||||
|
|
||||||
set -e # Exit immidiately on non-zero result
|
set -e # Exit immidiately on non-zero result
|
||||||
|
|
||||||
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2020-08-24/2020-08-20-raspios-buster-arm64-lite.zip"
|
# 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"
|
||||||
|
|
||||||
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
|
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
|
||||||
export LANG=${LANG:='C.UTF-8'}
|
export LANG=${LANG:='C.UTF-8'}
|
||||||
@@ -104,8 +105,6 @@ ${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/'
|
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/monkey.service' '/lib/systemd/system/'
|
||||||
# software install
|
# software install
|
||||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-software.sh'
|
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-software.sh'
|
||||||
# examples
|
|
||||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/examples' '/home/pi/' # TODO: symlink?
|
|
||||||
# network setup
|
# network setup
|
||||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-network.sh'
|
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-network.sh'
|
||||||
# avahi setup
|
# avahi setup
|
||||||
@@ -114,15 +113,11 @@ ${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
|
# 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)
|
[[ $(arch) == 'armv7l' ]] && NUMBER_THREADS=1 || NUMBER_THREADS=$(nproc --all)
|
||||||
# Clover
|
# 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/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/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/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/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/'
|
# ${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
|
# 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-ros.sh' ${REPO_URL} ${IMAGE_VERSION} false false ${NUMBER_THREADS}
|
||||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-validate.sh'
|
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-validate.sh'
|
||||||
|
|||||||
@@ -55,4 +55,7 @@ echo_stamp "Set max space for syslogs"
|
|||||||
# https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl
|
# https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl
|
||||||
sed -i 's/#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf
|
sed -i 's/#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf
|
||||||
|
|
||||||
|
echo_stamp "Move /etc/ld.so.preload out of the way"
|
||||||
|
mv /etc/ld.so.preload /etc/ld.so.preload.disabled-for-build
|
||||||
|
|
||||||
echo_stamp "End of init image"
|
echo_stamp "End of init image"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
# copies or substantial portions of the Software.
|
# copies or substantial portions of the Software.
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e # Exit immidiately on non-zero result
|
set -ex # exit on error, echo commands
|
||||||
|
|
||||||
REPO=$1
|
REPO=$1
|
||||||
REF=$2
|
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
|
export ROS_IP='127.0.0.1' # needed for running tests
|
||||||
|
|
||||||
echo_stamp "Reconfiguring Clover repository for simplier unshallowing"
|
# echo_stamp "Reconfiguring Clover repository for simplier unshallowing"
|
||||||
cd /home/pi/catkin_ws/src/clover
|
cd /home/pi/catkin_ws/src/clover
|
||||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ apt install -y --no-install-recommends \
|
|||||||
ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \
|
ros-${ROS_DISTRO}-compressed-image-transport=1.14.0-0buster \
|
||||||
ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \
|
ros-${ROS_DISTRO}-cv-bridge=1.15.0-0buster \
|
||||||
ros-${ROS_DISTRO}-cv-camera=0.5.0-0buster \
|
ros-${ROS_DISTRO}-cv-camera=0.5.0-0buster \
|
||||||
ros-${ROS_DISTRO}-image-publisher=1.15.2-0buster \
|
ros-${ROS_DISTRO}-image-publisher=1.15.3-0buster \
|
||||||
ros-${ROS_DISTRO}-web-video-server=0.2.1-0buster
|
ros-${ROS_DISTRO}-web-video-server=0.2.1-0buster
|
||||||
apt-mark hold \
|
apt-mark hold \
|
||||||
ros-${ROS_DISTRO}-compressed-image-transport \
|
ros-${ROS_DISTRO}-compressed-image-transport \
|
||||||
@@ -100,6 +100,9 @@ ros-${ROS_DISTRO}-cv-camera \
|
|||||||
ros-${ROS_DISTRO}-image-publisher \
|
ros-${ROS_DISTRO}-image-publisher \
|
||||||
ros-${ROS_DISTRO}-web-video-server
|
ros-${ROS_DISTRO}-web-video-server
|
||||||
|
|
||||||
|
echo_stamp "Installing libboost-dev" # https://travis-ci.org/github/CopterExpress/clover/jobs/766318908#L6536
|
||||||
|
my_travis_retry apt-get install -y --no-install-recommends libboost-dev libboost-all-dev
|
||||||
|
|
||||||
echo_stamp "Build and install Clover"
|
echo_stamp "Build and install Clover"
|
||||||
cd /home/pi/catkin_ws
|
cd /home/pi/catkin_ws
|
||||||
# Don't try to install gazebo_ros
|
# Don't try to install gazebo_ros
|
||||||
@@ -110,6 +113,7 @@ my_travis_retry pip3 install -r /home/pi/catkin_ws/src/clover/clover/requirement
|
|||||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||||
# Don't build simulation plugins for actual drone
|
# Don't build simulation plugins for actual drone
|
||||||
catkin_make -j2 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCATKIN_BLACKLIST_PACKAGES=clover_gazebo_plugins
|
catkin_make -j2 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCATKIN_BLACKLIST_PACKAGES=clover_gazebo_plugins
|
||||||
|
source devel/setup.bash
|
||||||
|
|
||||||
echo_stamp "Install clever package (for backwards compatibility)"
|
echo_stamp "Install clever package (for backwards compatibility)"
|
||||||
cd /home/pi/catkin_ws/src/clover/builder/assets/clever
|
cd /home/pi/catkin_ws/src/clover/builder/assets/clever
|
||||||
@@ -118,8 +122,8 @@ rm -rf build # remove build artifacts
|
|||||||
|
|
||||||
echo_stamp "Build Clover documentation"
|
echo_stamp "Build Clover documentation"
|
||||||
cd /home/pi/catkin_ws/src/clover
|
cd /home/pi/catkin_ws/src/clover
|
||||||
NPM_CONFIG_UNSAFE_PERM=true npm install gitbook-cli -g
|
builder/assets/install_gitbook.sh
|
||||||
NPM_CONFIG_UNSAFE_PERM=true gitbook install
|
gitbook install
|
||||||
gitbook build
|
gitbook build
|
||||||
touch node_modules/CATKIN_IGNORE docs/CATKIN_IGNORE _book/CATKIN_IGNORE clover/www/CATKIN_IGNORE apps/CATKIN_IGNORE # ignore documentation files by catkin
|
touch node_modules/CATKIN_IGNORE docs/CATKIN_IGNORE _book/CATKIN_IGNORE clover/www/CATKIN_IGNORE apps/CATKIN_IGNORE # ignore documentation files by catkin
|
||||||
|
|
||||||
@@ -131,7 +135,9 @@ my_travis_retry apt-get install -y --no-install-recommends \
|
|||||||
ros-${ROS_DISTRO}-usb-cam \
|
ros-${ROS_DISTRO}-usb-cam \
|
||||||
ros-${ROS_DISTRO}-vl53l1x \
|
ros-${ROS_DISTRO}-vl53l1x \
|
||||||
ros-${ROS_DISTRO}-ws281x \
|
ros-${ROS_DISTRO}-ws281x \
|
||||||
ros-${ROS_DISTRO}-rosshow
|
ros-${ROS_DISTRO}-rosshow \
|
||||||
|
ros-${ROS_DISTRO}-cmake-modules \
|
||||||
|
ros-${ROS_DISTRO}-image-view
|
||||||
|
|
||||||
# TODO move GeographicLib datasets to Mavros debian package
|
# TODO move GeographicLib datasets to Mavros debian package
|
||||||
echo_stamp "Install GeographicLib datasets (needed for mavros)" \
|
echo_stamp "Install GeographicLib datasets (needed for mavros)" \
|
||||||
@@ -145,9 +151,20 @@ catkin_make run_tests #&& catkin_test_results
|
|||||||
echo_stamp "Change permissions for catkin_ws"
|
echo_stamp "Change permissions for catkin_ws"
|
||||||
chown -Rf pi:pi /home/pi/catkin_ws
|
chown -Rf pi:pi /home/pi/catkin_ws
|
||||||
|
|
||||||
echo_stamp "Change permissions for examples"
|
echo_stamp "Make \$HOME/examples symlink"
|
||||||
|
ln -s "$(catkin_find clover examples --first-only)" /home/pi
|
||||||
chown -Rf pi:pi /home/pi/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"
|
echo_stamp "Setup ROS environment"
|
||||||
cat << EOF >> /home/pi/.bashrc
|
cat << EOF >> /home/pi/.bashrc
|
||||||
LANG='C.UTF-8'
|
LANG='C.UTF-8'
|
||||||
|
|||||||
@@ -64,15 +64,14 @@ echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
|
|||||||
echo_stamp "Install apt keys & repos"
|
echo_stamp "Install apt keys & repos"
|
||||||
|
|
||||||
# TODO: This STDOUT consist 'OK'
|
# TODO: This STDOUT consist 'OK'
|
||||||
curl http://deb.coex.tech/aptly_repo_signing.key 2> /dev/null | apt-key add -
|
|
||||||
apt-get update \
|
apt-get update \
|
||||||
&& apt-get install --no-install-recommends -y dirmngr > /dev/null \
|
&& apt-get install --no-install-recommends -y dirmngr > /dev/null \
|
||||||
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
|
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
|
||||||
|
|
||||||
echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
|
echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
|
||||||
echo "deb http://deb.coex.tech/opencv4 buster main" > /etc/apt/sources.list.d/opencv3.list
|
|
||||||
echo "deb http://deb.coex.tech/ros buster main" > /etc/apt/sources.list.d/rpi-ros-melodic.list
|
wget -O - 'http://packages.coex.tech/key.asc' | apt-key add -
|
||||||
echo "deb http://deb.coex.tech/clover buster main" > /etc/apt/sources.list.d/clover.list
|
echo 'deb http://packages.coex.tech buster main' >> /etc/apt/sources.list
|
||||||
|
|
||||||
echo_stamp "Update apt cache"
|
echo_stamp "Update apt cache"
|
||||||
|
|
||||||
@@ -82,6 +81,7 @@ apt-get update
|
|||||||
|
|
||||||
# Let's retry fetching those packages several times, just in case
|
# Let's retry fetching those packages several times, just in case
|
||||||
echo_stamp "Software installing"
|
echo_stamp "Software installing"
|
||||||
|
my_travis_retry apt-get install --no-install-recommends -y cmake-data=3.13.4-1 cmake=3.13.4-1 # FIXME: using older CMake due to https://travis-ci.org/github/CopterExpress/clover/jobs/764367665#L6984
|
||||||
my_travis_retry apt-get install --no-install-recommends -y \
|
my_travis_retry apt-get install --no-install-recommends -y \
|
||||||
unzip \
|
unzip \
|
||||||
zip \
|
zip \
|
||||||
@@ -94,8 +94,9 @@ lsof \
|
|||||||
git \
|
git \
|
||||||
dnsmasq \
|
dnsmasq \
|
||||||
tmux \
|
tmux \
|
||||||
|
tree \
|
||||||
vim \
|
vim \
|
||||||
cmake \
|
libjpeg8 \
|
||||||
tcpdump \
|
tcpdump \
|
||||||
libpoco-dev \
|
libpoco-dev \
|
||||||
libzbar0 \
|
libzbar0 \
|
||||||
@@ -122,9 +123,10 @@ sed -i "s/updates_available//" /usr/share/byobu/status/status
|
|||||||
|
|
||||||
echo_stamp "Installing pip"
|
echo_stamp "Installing pip"
|
||||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||||
|
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip2.py
|
||||||
python3 get-pip.py
|
python3 get-pip.py
|
||||||
python get-pip.py
|
python get-pip2.py
|
||||||
rm get-pip.py
|
rm get-pip.py get-pip2.py
|
||||||
#my_travis_retry pip install --upgrade pip
|
#my_travis_retry pip install --upgrade pip
|
||||||
#my_travis_retry pip3 install --upgrade pip
|
#my_travis_retry pip3 install --upgrade pip
|
||||||
|
|
||||||
@@ -134,6 +136,8 @@ pip3 --version
|
|||||||
|
|
||||||
echo_stamp "Install and enable Butterfly (web terminal)"
|
echo_stamp "Install and enable Butterfly (web terminal)"
|
||||||
echo_stamp "Workaround for tornado >= 6.0 breaking butterfly"
|
echo_stamp "Workaround for tornado >= 6.0 breaking butterfly"
|
||||||
|
export CRYPTOGRAPHY_DONT_BUILD_RUST=1
|
||||||
|
my_travis_retry pip3 install cryptography==3.4.6 # https://stackoverflow.com/a/68472128/6850197
|
||||||
my_travis_retry pip3 install tornado==5.1.1
|
my_travis_retry pip3 install tornado==5.1.1
|
||||||
my_travis_retry pip3 install butterfly
|
my_travis_retry pip3 install butterfly
|
||||||
my_travis_retry pip3 install butterfly[systemd]
|
my_travis_retry pip3 install butterfly[systemd]
|
||||||
@@ -145,15 +149,16 @@ my_travis_retry pip3 install --prefer-binary rpi_ws281x
|
|||||||
echo_stamp "Setup Monkey"
|
echo_stamp "Setup Monkey"
|
||||||
mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
|
mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
|
||||||
mv /root/monkey /etc/monkey/sites/default
|
mv /root/monkey /etc/monkey/sites/default
|
||||||
|
sed -i 's/SymLink Off/SymLink On/' /etc/monkey/monkey.conf
|
||||||
systemctl enable monkey.service
|
systemctl enable monkey.service
|
||||||
|
|
||||||
echo_stamp "Install Node.js"
|
echo_stamp "Install Node.js"
|
||||||
cd /home/pi
|
cd /home/pi
|
||||||
wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-arm64.tar.gz
|
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-arm64.tar.gz
|
tar -xzf node-v10.15.0-linux-armv6l.tar.gz
|
||||||
cp -R node-v10.15.0-linux-arm64/* /usr/local/
|
cp -R node-v10.15.0-linux-armv6l/* /usr/local/
|
||||||
rm -rf node-v10.15.0-linux-arm64/
|
rm -rf node-v10.15.0-linux-armv6l/
|
||||||
rm node-v10.15.0-linux-arm64.tar.gz
|
rm node-v10.15.0-linux-armv6l.tar.gz
|
||||||
|
|
||||||
echo_stamp "Installing ptvsd"
|
echo_stamp "Installing ptvsd"
|
||||||
my_travis_retry pip install ptvsd
|
my_travis_retry pip install ptvsd
|
||||||
|
|||||||
@@ -20,9 +20,21 @@ export ROS_DISTRO='noetic'
|
|||||||
export ROS_IP='127.0.0.1'
|
export ROS_IP='127.0.0.1'
|
||||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
source /opt/ros/${ROS_DISTRO}/setup.bash
|
||||||
source /home/pi/catkin_ws/devel/setup.bash
|
source /home/pi/catkin_ws/devel/setup.bash
|
||||||
|
systemctl start roscore
|
||||||
|
|
||||||
cd /home/pi/catkin_ws/src/clover/builder/test/
|
cd /home/pi/catkin_ws/src/clover/builder/test/
|
||||||
./tests.sh
|
./tests.sh
|
||||||
./tests.py
|
./tests.py
|
||||||
./tests_py3.py
|
./tests_py3.py
|
||||||
|
./test_pigpio.py
|
||||||
|
[[ $(./test_qr.py) == "Found QRCODE with data Проверка Unicode with center at x=66.0, y=66.0" ]]
|
||||||
[[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility
|
[[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility
|
||||||
|
|
||||||
|
systemctl stop roscore
|
||||||
|
|
||||||
|
# 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,15 +3,16 @@
|
|||||||
# Perform a "standalone install" in a Docker container
|
# Perform a "standalone install" in a Docker container
|
||||||
set -e
|
set -e
|
||||||
# Step 1: Install pip
|
# Step 1: Install pip
|
||||||
apt update
|
apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 # https://github.com/osrf/docker_images/issues/535
|
||||||
apt install -y curl
|
apt-get update
|
||||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
apt-get install -y curl
|
||||||
if [ "x${ROS_PYTHON_VERSION}" = "x3" ]; then
|
if [ "x${ROS_PYTHON_VERSION}" = "x3" ]; then
|
||||||
PYTHON=python3
|
PYTHON=python3
|
||||||
|
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||||
else
|
else
|
||||||
PYTHON=python
|
PYTHON=python
|
||||||
|
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${PYTHON} ./get-pip.py
|
${PYTHON} ./get-pip.py
|
||||||
|
|
||||||
# Step 1.5: Add deb.coex.tech to apt
|
# Step 1.5: Add deb.coex.tech to apt
|
||||||
@@ -40,7 +41,7 @@ ws281x:
|
|||||||
ubuntu:
|
ubuntu:
|
||||||
${CODENAME}: [ros-${ROS_DISTRO}-ws281x]
|
${CODENAME}: [ros-${ROS_DISTRO}-ws281x]
|
||||||
EOF
|
EOF
|
||||||
apt update
|
apt-get update
|
||||||
rosdep update
|
rosdep update
|
||||||
|
|
||||||
# Step 2: Run rosdep to install all dependencies
|
# Step 2: Run rosdep to install all dependencies
|
||||||
@@ -60,3 +61,6 @@ ${PYTHON} -m pip install --upgrade pytest
|
|||||||
cd /root/catkin_ws
|
cd /root/catkin_ws
|
||||||
source devel/setup.bash
|
source devel/setup.bash
|
||||||
catkin_make run_tests && catkin_test_results
|
catkin_make run_tests && catkin_test_results
|
||||||
|
|
||||||
|
# Step 5: Install packages
|
||||||
|
catkin_make install
|
||||||
|
|||||||
BIN
builder/test/qr.png
Normal file
BIN
builder/test/qr.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
6
builder/test/test_pigpio.py
Normal file
6
builder/test/test_pigpio.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import pigpio
|
||||||
|
pi = pigpio.pi()
|
||||||
|
pi.set_mode(24, pigpio.OUTPUT)
|
||||||
|
pi.write(24, True)
|
||||||
42
builder/test/test_qr.py
Executable file
42
builder/test/test_qr.py
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/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,18 +4,26 @@
|
|||||||
|
|
||||||
import rospy
|
import rospy
|
||||||
from geometry_msgs.msg import PoseStamped
|
from geometry_msgs.msg import PoseStamped
|
||||||
|
from sensor_msgs.msg import Range, BatteryState
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import cv2.aruco
|
import cv2.aruco
|
||||||
|
from sensor_msgs.msg import Image
|
||||||
|
from cv_bridge import CvBridge
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
import mavros
|
import mavros
|
||||||
from mavros_msgs.msg import State, StatusText, ExtendedState
|
from mavros_msgs.msg import State, StatusText, ExtendedState, RCIn, Mavlink
|
||||||
from mavros_msgs.srv import CommandBool, CommandLong, SetMode
|
from mavros_msgs.srv import CommandBool, CommandLong, SetMode
|
||||||
|
|
||||||
from std_srvs.srv import Trigger
|
from std_srvs.srv import Trigger
|
||||||
from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
||||||
SetAttitude, SetRates, SetLEDEffect
|
SetAttitude, SetRates, SetLEDEffect
|
||||||
|
from led_msgs.srv import SetLEDs
|
||||||
|
from led_msgs.msg import LEDStateArray, LEDState
|
||||||
|
from aruco_pose.msg import Marker, MarkerArray, Point2D
|
||||||
|
|
||||||
|
import dynamic_reconfigure.client
|
||||||
|
|
||||||
import tf2_ros
|
import tf2_ros
|
||||||
import tf2_geometry_msgs
|
import tf2_geometry_msgs
|
||||||
@@ -25,7 +33,7 @@ import pymavlink
|
|||||||
from pymavlink import mavutil
|
from pymavlink import mavutil
|
||||||
import rpi_ws281x
|
import rpi_ws281x
|
||||||
import pigpio
|
import pigpio
|
||||||
from espeak import espeak
|
# from espeak import espeak
|
||||||
from pyzbar import pyzbar
|
from pyzbar import pyzbar
|
||||||
|
|
||||||
print(cv2.getBuildInformation())
|
print(cv2.getBuildInformation())
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ monkey --version
|
|||||||
pigpiod -v
|
pigpiod -v
|
||||||
i2cdetect -V
|
i2cdetect -V
|
||||||
butterfly -h
|
butterfly -h
|
||||||
espeak --version
|
# espeak --version
|
||||||
mjpg_streamer --version
|
mjpg_streamer --version
|
||||||
|
systemctl --version
|
||||||
|
|
||||||
# ros stuff
|
# ros stuff
|
||||||
|
|
||||||
@@ -43,6 +44,8 @@ rosversion aruco_pose
|
|||||||
rosversion vl53l1x
|
rosversion vl53l1x
|
||||||
rosversion mavros
|
rosversion mavros
|
||||||
rosversion mavros_extras
|
rosversion mavros_extras
|
||||||
|
rosversion ws281x
|
||||||
|
rosversion led_msgs
|
||||||
rosversion dynamic_reconfigure
|
rosversion dynamic_reconfigure
|
||||||
rosversion tf2_web_republisher
|
rosversion tf2_web_republisher
|
||||||
rosversion compressed_image_transport
|
rosversion compressed_image_transport
|
||||||
@@ -52,6 +55,8 @@ rosversion usb_cam
|
|||||||
rosversion cv_camera
|
rosversion cv_camera
|
||||||
rosversion web_video_server
|
rosversion web_video_server
|
||||||
rosversion rosshow
|
rosversion rosshow
|
||||||
|
rosversion nodelet
|
||||||
|
rosversion image_view
|
||||||
|
|
||||||
# validate examples are present
|
# validate examples are present
|
||||||
[[ $(ls /home/pi/examples/*) ]]
|
[[ $(ls /home/pi/examples/*) ]]
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
EXCLUDE = ('clever4-front-white.png', '.DS_Store', 'clever4-front-black-large.png')
|
EXCLUDE = ('clever4-front-white.png', 'clever4-front-white-large.png', '.DS_Store',
|
||||||
|
'clever4-front-black-large.png','clover42-black.png', 'clover42-main-margin.png')
|
||||||
|
|
||||||
code = 0
|
code = 0
|
||||||
|
|
||||||
os.chdir('./docs')
|
os.chdir('./docs')
|
||||||
|
|||||||
8
clover/CHANGELOG.rst
Normal file
8
clover/CHANGELOG.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
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 2.8.3)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
project(clover)
|
project(clover)
|
||||||
|
|
||||||
## Compile as C++11, supported in ROS Kinetic and newer
|
## Compile as C++11, supported in ROS Kinetic and newer
|
||||||
@@ -241,12 +241,12 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||||
# )
|
# )
|
||||||
|
|
||||||
## Mark executables and/or libraries for installation
|
# Mark executables and/or libraries for installation
|
||||||
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
|
install(TARGETS simple_offboard clover_rc camera_markers vpe_publisher clover_led shell clover
|
||||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||||
# )
|
)
|
||||||
|
|
||||||
## Mark cpp header files for installation
|
## Mark cpp header files for installation
|
||||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||||
@@ -266,13 +266,21 @@ catkin_install_python(PROGRAMS src/selfcheck.py
|
|||||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
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
|
# Only install udev rules when building a Debian package
|
||||||
# FIXME: Other operating systems may have other prefixes
|
# FIXME: Other operating systems may have other prefixes
|
||||||
string(FIND ${CMAKE_INSTALL_PREFIX} "/opt/ros" _PREFIX_INDEX)
|
string(FIND ${CMAKE_INSTALL_PREFIX} "/opt/ros" _PREFIX_INDEX)
|
||||||
if (${_PREFIX_INDEX} EQUAL 0)
|
if (${_PREFIX_INDEX} EQUAL 0)
|
||||||
message(STATUS "Building as a Debian package - adding udev rules as installable files")
|
message(STATUS "Building as a Debian package - adding udev rules as installable files")
|
||||||
install(FILES
|
install(FILES
|
||||||
config/99-px4fmu.rules
|
udev/99-px4fmu.rules
|
||||||
DESTINATION /lib/udev/rules.d
|
DESTINATION /lib/udev/rules.d
|
||||||
)
|
)
|
||||||
else()
|
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:
|
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
|
```bash
|
||||||
cd ~/catkin_ws/src/clover/clover/config
|
cd ~/catkin_ws/src/clover/clover/udev
|
||||||
sudo cp 99-px4fmu.rules /lib/udev/rules.d
|
sudo cp 99-px4fmu.rules /lib/udev/rules.d
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -44,16 +44,12 @@ Alternatively you may change the `fcu_url` property in `mavros.launch` file to p
|
|||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
To start connection to SITL, use:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
roslaunch clover sitl.launch
|
|
||||||
```
|
|
||||||
|
|
||||||
To start connection to the flight controller, use:
|
To start connection to the flight controller, use:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
roslaunch clover clover.launch
|
roslaunch clover clover.launch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For the simulation information see the [corresponding article](https://clover.coex.tech/en/simulation.html).
|
||||||
|
|
||||||
> Note that the package is configured to connect to `/dev/px4fmu` by default (see [previous section](#manual-installation)). Install udev rules or specify path to your FCU device in `mavros.launch`.
|
> Note that the package is configured to connect to `/dev/px4fmu` by default (see [previous section](#manual-installation)). Install udev rules or specify path to your FCU device in `mavros.launch`.
|
||||||
|
|||||||
@@ -15,17 +15,17 @@ set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
|
|||||||
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
||||||
land = rospy.ServiceProxy('land', Trigger)
|
land = rospy.ServiceProxy('land', Trigger)
|
||||||
|
|
||||||
# Take off and hover 1 m above the ground
|
print('Take off and hover 1 m above the ground')
|
||||||
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
||||||
|
|
||||||
# Wait for 3 seconds
|
# Wait for 5 seconds
|
||||||
rospy.sleep(3)
|
rospy.sleep(5)
|
||||||
|
|
||||||
# Fly forward 1 m
|
print('Fly forward 1 m')
|
||||||
navigate(x=1, y=0, z=0, frame_id='body')
|
navigate(x=1, y=0, z=0, frame_id='body')
|
||||||
|
|
||||||
# Wait for 3 seconds
|
# Wait for 5 seconds
|
||||||
rospy.sleep(3)
|
rospy.sleep(5)
|
||||||
|
|
||||||
# Perform landing
|
print('Perform landing')
|
||||||
land()
|
land()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Information: https://clover.coex.tech/en/aruco.html
|
# Information: https://clover.coex.tech/aruco
|
||||||
|
|
||||||
import rospy
|
import rospy
|
||||||
from clover import srv
|
from clover import srv
|
||||||
@@ -15,23 +15,23 @@ set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)
|
|||||||
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)
|
||||||
land = rospy.ServiceProxy('land', Trigger)
|
land = rospy.ServiceProxy('land', Trigger)
|
||||||
|
|
||||||
# Take off and hover 1 m above the ground
|
print('Take off and hover 1 m above the ground')
|
||||||
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
||||||
|
|
||||||
# Wait for 3 seconds
|
# Wait for 5 seconds
|
||||||
rospy.sleep(3)
|
rospy.sleep(5)
|
||||||
|
|
||||||
# Fly 1 meter above ArUco marker 0
|
print('Fly 1 meter above ArUco marker 0')
|
||||||
navigate(x=0, y=0, z=1, frame_id='aruco_0')
|
navigate(x=0, y=0, z=1, frame_id='aruco_0')
|
||||||
|
|
||||||
# Wait for 3 seconds
|
# Wait for 5 seconds
|
||||||
rospy.sleep(3)
|
rospy.sleep(5)
|
||||||
|
|
||||||
# Fly to x=1 y=1 z=1 relative to ArUco markers map
|
print('Fly to x=1 y=1 z=1 relative to ArUco markers map')
|
||||||
navigate(x=1, y=1, z=1, frame_id='aruco_map')
|
navigate(x=1, y=1, z=1, frame_id='aruco_map')
|
||||||
|
|
||||||
# Wait for 3 seconds
|
# Wait for 5 seconds
|
||||||
rospy.sleep(3)
|
rospy.sleep(5)
|
||||||
|
|
||||||
# Perform landing
|
print('Perform landing')
|
||||||
land()
|
land()
|
||||||
11
clover/examples/get_telemetry.py
Normal file
11
clover/examples/get_telemetry.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# 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())
|
||||||
47
clover/examples/gps.py
Normal file
47
clover/examples/gps.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# 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,4 +1,4 @@
|
|||||||
# Information: https://clover.coex.tech/en/leds.html
|
# Information: https://clover.coex.tech/led
|
||||||
|
|
||||||
import rospy
|
import rospy
|
||||||
from clover.srv import SetLEDEffect
|
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
|
return res
|
||||||
rospy.sleep(0.2)
|
rospy.sleep(0.2)
|
||||||
|
|
||||||
# Take off 1 meter
|
print('Take off 1 meter')
|
||||||
navigate_wait(z=1, frame_id='body', auto_arm=True)
|
navigate_wait(z=1, frame_id='body', auto_arm=True)
|
||||||
|
|
||||||
# Fly forward 1 m
|
print('Fly forward 1 m')
|
||||||
navigate_wait(x=1, frame_id='body')
|
navigate_wait(x=1, frame_id='body')
|
||||||
|
|
||||||
# Land
|
print('Land')
|
||||||
land()
|
land()
|
||||||
15
clover/examples/subscriber.py
Normal file
15
clover/examples/subscriber.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# 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_map" default="false"/>
|
||||||
<arg name="aruco_vpe" default="false"/>
|
<arg name="aruco_vpe" default="false"/>
|
||||||
<arg name="placement" default="floor"/> <!-- markers placement: floor, ceiling, unknown -->
|
<arg name="placement" default="floor"/> <!-- markers placement: floor, ceiling, unknown -->
|
||||||
<arg name="length" default="0.33"/> <!-- not-in-map markers length, m -->
|
<arg name="length" default="0.22"/> <!-- not-in-map markers length, m -->
|
||||||
<arg name="map" default="map.txt"/> <!-- markers map file name -->
|
<arg name="map" default="map.txt"/> <!-- markers map file name -->
|
||||||
|
|
||||||
<!-- For additional help go to https://clover.coex.tech/aruco -->
|
<!-- For additional help go to https://clover.coex.tech/aruco -->
|
||||||
|
|
||||||
<!-- aruco_detect: detect aruco markers, estimate poses -->
|
<!-- aruco_detect: detect aruco markers, estimate poses -->
|
||||||
<node name="aruco_detect" pkg="nodelet" if="$(arg aruco_detect)" type="nodelet" args="load aruco_pose/aruco_detect 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 main_camera_nodelet_manager" output="screen" clear_params="true" respawn="true">
|
||||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||||
<remap from="map_markers" to="aruco_map/markers" if="$(arg aruco_map)"/>
|
<remap from="map_markers" to="aruco_map/markers"/>
|
||||||
<param name="estimate_poses" value="true"/>
|
<param name="estimate_poses" value="true"/>
|
||||||
<param name="send_tf" value="true"/>
|
<param name="send_tf" value="true"/>
|
||||||
<param name="known_tilt" value="map" if="$(eval placement == 'floor')"/>
|
<param name="known_tilt" value="map" if="$(eval placement == 'floor')"/>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
</node>
|
</node>
|
||||||
|
|
||||||
<!-- aruco_map: estimate aruco map pose -->
|
<!-- aruco_map: estimate aruco map pose -->
|
||||||
<node name="aruco_map" pkg="nodelet" type="nodelet" if="$(arg aruco_map)" args="load aruco_pose/aruco_map 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 main_camera_nodelet_manager" output="screen" clear_params="true" respawn="true">
|
||||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||||
<remap from="markers" to="aruco_detect/markers"/>
|
<remap from="markers" to="aruco_detect/markers"/>
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
<arg name="rangefinder_vl53l1x" default="true"/>
|
<arg name="rangefinder_vl53l1x" default="true"/>
|
||||||
<arg name="led" default="true"/>
|
<arg name="led" default="true"/>
|
||||||
<arg name="blocks" default="false"/>
|
<arg name="blocks" default="false"/>
|
||||||
<arg name="rc" default="true"/>
|
<arg name="rc" default="false"/>
|
||||||
<arg name="shell" default="true"/>
|
|
||||||
|
|
||||||
<arg name="simulator" default="false"/> <!-- flag that we are operating on a simulated drone -->
|
<arg name="simulator" default="false"/> <!-- flag that we are operating on a simulated drone -->
|
||||||
|
|
||||||
@@ -37,18 +36,13 @@
|
|||||||
<include file="$(find clover)/launch/aruco.launch" if="$(arg aruco)"/>
|
<include file="$(find clover)/launch/aruco.launch" if="$(arg aruco)"/>
|
||||||
|
|
||||||
<!-- optical flow -->
|
<!-- optical flow -->
|
||||||
<node pkg="nodelet" type="nodelet" name="optical_flow" args="load clover/optical_flow 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 main_camera_nodelet_manager" if="$(arg optical_flow)" clear_params="true" output="screen" respawn="true">
|
||||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||||
<param name="calc_flow_gyro" value="true"/>
|
<param name="calc_flow_gyro" value="true"/>
|
||||||
<param name="roi_rad" value="0.8"/>
|
<param name="roi_rad" value="0.8"/>
|
||||||
</node>
|
</node>
|
||||||
|
|
||||||
<!-- main nodelet manager -->
|
|
||||||
<node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" clear_params="true" 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"/>
|
<node pkg="tf2_ros" type="static_transform_publisher" name="map_flipped_frame" args="0 0 0 3.1415926 3.1415926 0 map map_flipped"/>
|
||||||
|
|
||||||
<!-- simplified offboard control -->
|
<!-- simplified offboard control -->
|
||||||
@@ -91,9 +85,6 @@
|
|||||||
<param name="use_fake_gcs" value="false"/>
|
<param name="use_fake_gcs" value="false"/>
|
||||||
</node>
|
</node>
|
||||||
|
|
||||||
<!-- Shell access through ROS service -->
|
|
||||||
<node name="shell" pkg="clover" type="shell" output="screen" if="$(arg shell)"/>
|
|
||||||
|
|
||||||
<!-- Update static directory -->
|
<!-- Update static directory -->
|
||||||
<node pkg="roswww_static" name="roswww_static" type="main.py" clear_params="true">
|
<node pkg="roswww_static" name="roswww_static" type="main.py" clear_params="true">
|
||||||
<param name="default_package" value="clover"/>
|
<param name="default_package" value="clover"/>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
posctl: { r: 50, g: 100, b: 220 }
|
posctl: { r: 50, g: 100, b: 220 }
|
||||||
offboard: { r: 220, g: 20, b: 250 }
|
offboard: { r: 220, g: 20, b: 250 }
|
||||||
low_battery: { threshold: 3.6, effect: blink_fast, r: 255, g: 0, b: 0 }
|
low_battery: { threshold: 3.6, effect: blink_fast, r: 255, g: 0, b: 0 }
|
||||||
error: { effect: flash, r: 255, g: 0, b: 0 }
|
error: { effect: flash, r: 255, g: 0, b: 0, ignore: [ "[lpe] vision position timeout" ]}
|
||||||
</rosparam>
|
</rosparam>
|
||||||
</node>
|
</node>
|
||||||
</launch>
|
</launch>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up -->
|
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up -->
|
||||||
<arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
|
<arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
|
||||||
|
<arg name="device" default="/dev/video0"/> <!-- v4l2 device -->
|
||||||
<arg name="simulator" default="false"/>
|
<arg name="simulator" default="false"/>
|
||||||
|
|
||||||
<node if="$(eval direction_z == 'down' and direction_y == 'backward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
<node if="$(eval direction_z == 'down' and direction_y == 'backward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
||||||
@@ -17,9 +18,14 @@
|
|||||||
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
|
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
|
||||||
<!-- <node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/> -->
|
<!-- <node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/> -->
|
||||||
|
|
||||||
|
<!-- camera nodelet manager -->
|
||||||
|
<node pkg="nodelet" type="nodelet" name="main_camera_nodelet_manager" args="manager" output="screen" clear_params="true" respawn="true">
|
||||||
|
<param name="num_worker_threads" value="2"/>
|
||||||
|
</node>
|
||||||
|
|
||||||
<!-- camera node -->
|
<!-- camera node -->
|
||||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet nodelet_manager" clear_params="true" unless="$(arg simulator)" respawn="true">
|
<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="/dev/video0"/> <!-- v4l2 device -->
|
<param name="device_path" value="$(arg device)"/>
|
||||||
<param name="frame_id" value="main_camera_optical"/>
|
<param name="frame_id" value="main_camera_optical"/>
|
||||||
<param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/>
|
<param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/>
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,16 @@
|
|||||||
<arg name="viz" default="true"/>
|
<arg name="viz" default="true"/>
|
||||||
<arg name="respawn" default="true"/>
|
<arg name="respawn" default="true"/>
|
||||||
<arg name="distance_sensor_remap" default="rangefinder/range"/>
|
<arg name="distance_sensor_remap" default="rangefinder/range"/>
|
||||||
|
<arg name="usb_device" default="/dev/px4fmu"/>
|
||||||
|
<arg name="prefix" default="" unless="$(eval fcu_conn == 'usb')"/>
|
||||||
|
<arg name="prefix" default="rosrun clover waitfile $(arg usb_device)" if="$(eval fcu_conn == 'usb')"/>
|
||||||
|
|
||||||
<node pkg="mavros" type="mavros_node" name="mavros" 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" launch-prefix="$(arg prefix)" required="false" clear_params="true" respawn="$(arg respawn)" unless="$(eval fcu_conn == 'none')" respawn_delay="1" output="screen">
|
||||||
<!-- UART connection -->
|
<!-- UART connection -->
|
||||||
<param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/>
|
<param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/>
|
||||||
|
|
||||||
<!-- USB connection -->
|
<!-- USB connection -->
|
||||||
<param name="fcu_url" value="/dev/px4fmu" if="$(eval fcu_conn == 'usb')"/>
|
<param name="fcu_url" value="$(arg usb_device)" if="$(eval fcu_conn == 'usb')"/>
|
||||||
|
|
||||||
<!-- sitl before PX4 1.9.0 -->
|
<!-- sitl before PX4 1.9.0 -->
|
||||||
<param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/>
|
<param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/>
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
<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"?>
|
<?xml version="1.0"?>
|
||||||
<package format="3">
|
<package format="3">
|
||||||
<name>clover</name>
|
<name>clover</name>
|
||||||
<version>0.0.1</version>
|
<version>0.21.1</version>
|
||||||
<description>The Clover package</description>
|
<description>The Clover package</description>
|
||||||
|
|
||||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <ros/ros.h>
|
#include <ros/ros.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include <clover/SetLEDEffect.h>
|
#include <clover/SetLEDEffect.h>
|
||||||
@@ -29,6 +30,7 @@ ros::Timer timer;
|
|||||||
ros::Time start_time;
|
ros::Time start_time;
|
||||||
double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period;
|
double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period;
|
||||||
double low_battery_threshold;
|
double low_battery_threshold;
|
||||||
|
std::vector<std::string> error_ignore;
|
||||||
bool blink_state;
|
bool blink_state;
|
||||||
led_msgs::SetLEDs set_leds;
|
led_msgs::SetLEDs set_leds;
|
||||||
led_msgs::LEDStateArray state, start_state;
|
led_msgs::LEDStateArray state, start_state;
|
||||||
@@ -274,6 +276,10 @@ void handleMavrosState(const mavros_msgs::State& msg)
|
|||||||
void handleLog(const rosgraph_msgs::Log& log)
|
void handleLog(const rosgraph_msgs::Log& log)
|
||||||
{
|
{
|
||||||
if (log.level >= rosgraph_msgs::Log::ERROR) {
|
if (log.level >= rosgraph_msgs::Log::ERROR) {
|
||||||
|
// check if ignored
|
||||||
|
for (auto const& str : error_ignore) {
|
||||||
|
if (log.msg.find(str) != std::string::npos) return;
|
||||||
|
}
|
||||||
notify("error");
|
notify("error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,6 +308,7 @@ int main(int argc, char **argv)
|
|||||||
nh_priv.param("rainbow_period", rainbow_period, 5.0);
|
nh_priv.param("rainbow_period", rainbow_period, 5.0);
|
||||||
|
|
||||||
nh_priv.param("notify/low_battery/threshold", low_battery_threshold, 3.7);
|
nh_priv.param("notify/low_battery/threshold", low_battery_threshold, 3.7);
|
||||||
|
nh_priv.param("notify/error/ignore", error_ignore, {});
|
||||||
|
|
||||||
ros::service::waitForService("set_leds"); // cannot work without set_leds service
|
ros::service::waitForService("set_leds"); // cannot work without set_leds service
|
||||||
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true);
|
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true);
|
||||||
|
|||||||
@@ -75,9 +75,6 @@ private:
|
|||||||
velo_pub_ = nh_priv.advertise<geometry_msgs::TwistStamped>("angular_velocity", 1);
|
velo_pub_ = nh_priv.advertise<geometry_msgs::TwistStamped>("angular_velocity", 1);
|
||||||
shift_pub_ = nh_priv.advertise<geometry_msgs::Vector3Stamped>("shift", 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_.time_delta_distance_us = 0;
|
||||||
flow_.distance = -1; // no distance sensor available
|
flow_.distance = -1; // no distance sensor available
|
||||||
flow_.temperature = 0;
|
flow_.temperature = 0;
|
||||||
@@ -153,7 +150,7 @@ private:
|
|||||||
cv::Point2d shift = cv::phaseCorrelate(prev_, curr_, hann_, &response);
|
cv::Point2d shift = cv::phaseCorrelate(prev_, curr_, hann_, &response);
|
||||||
|
|
||||||
// Publish raw shift in pixels
|
// Publish raw shift in pixels
|
||||||
static geometry_msgs::Vector3Stamped shift_vec;
|
geometry_msgs::Vector3Stamped shift_vec;
|
||||||
shift_vec.header.stamp = msg->header.stamp;
|
shift_vec.header.stamp = msg->header.stamp;
|
||||||
shift_vec.header.frame_id = msg->header.frame_id;
|
shift_vec.header.frame_id = msg->header.frame_id;
|
||||||
shift_vec.vector.x = shift.x;
|
shift_vec.vector.x = shift.x;
|
||||||
@@ -179,8 +176,8 @@ private:
|
|||||||
double flow_x = atan2(points_undist[0].x, focal_length_x);
|
double flow_x = atan2(points_undist[0].x, focal_length_x);
|
||||||
double flow_y = atan2(points_undist[0].y, focal_length_y);
|
double flow_y = atan2(points_undist[0].y, focal_length_y);
|
||||||
|
|
||||||
// // Convert to FCU frame
|
// Convert to FCU frame
|
||||||
static geometry_msgs::Vector3Stamped flow_camera, flow_fcu;
|
geometry_msgs::Vector3Stamped flow_camera, flow_fcu;
|
||||||
flow_camera.header.frame_id = msg->header.frame_id;
|
flow_camera.header.frame_id = msg->header.frame_id;
|
||||||
flow_camera.header.stamp = msg->header.stamp;
|
flow_camera.header.stamp = msg->header.stamp;
|
||||||
flow_camera.vector.x = flow_y; // +y means counter-clockwise rotation around Y axis
|
flow_camera.vector.x = flow_y; // +y means counter-clockwise rotation around Y axis
|
||||||
@@ -196,18 +193,21 @@ private:
|
|||||||
ros::Duration integration_time = msg->header.stamp - prev_stamp_;
|
ros::Duration integration_time = msg->header.stamp - prev_stamp_;
|
||||||
uint32_t integration_time_us = integration_time.toSec() * 1.0e6;
|
uint32_t integration_time_us = integration_time.toSec() * 1.0e6;
|
||||||
|
|
||||||
|
// Calculate flow gyro
|
||||||
|
flow_.integrated_xgyro = NAN;
|
||||||
|
flow_.integrated_ygyro = NAN;
|
||||||
|
flow_.integrated_zgyro = NAN;
|
||||||
|
|
||||||
if (calc_flow_gyro_) {
|
if (calc_flow_gyro_) {
|
||||||
try {
|
try {
|
||||||
auto flow_gyro_camera = calcFlowGyro(msg->header.frame_id, prev_stamp_, msg->header.stamp);
|
auto flow_gyro_camera = calcFlowGyro(msg->header.frame_id, prev_stamp_, msg->header.stamp);
|
||||||
static geometry_msgs::Vector3Stamped flow_gyro_fcu;
|
geometry_msgs::Vector3Stamped flow_gyro_fcu;
|
||||||
tf_buffer_->transform(flow_gyro_camera, flow_gyro_fcu, fcu_frame_id_);
|
tf_buffer_->transform(flow_gyro_camera, flow_gyro_fcu, fcu_frame_id_);
|
||||||
flow_.integrated_xgyro = flow_gyro_fcu.vector.x;
|
flow_.integrated_xgyro = flow_gyro_fcu.vector.x;
|
||||||
flow_.integrated_ygyro = flow_gyro_fcu.vector.y;
|
flow_.integrated_ygyro = flow_gyro_fcu.vector.y;
|
||||||
flow_.integrated_zgyro = flow_gyro_fcu.vector.z;
|
flow_.integrated_zgyro = flow_gyro_fcu.vector.z;
|
||||||
} catch (const tf2::TransformException& e) {
|
} catch (const tf2::TransformException& e) {
|
||||||
// Invalidate previous frame
|
// Transform not available, keep NANs in flow gyro
|
||||||
prev_.release();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +219,10 @@ private:
|
|||||||
flow_.quality = (uint8_t)(response * 255);
|
flow_.quality = (uint8_t)(response * 255);
|
||||||
flow_pub_.publish(flow_);
|
flow_pub_.publish(flow_);
|
||||||
|
|
||||||
|
prev_ = curr_.clone();
|
||||||
|
prev_stamp_ = msg->header.stamp;
|
||||||
|
|
||||||
|
publish_debug:
|
||||||
// Publish debug image
|
// Publish debug image
|
||||||
if (img_pub_.getNumSubscribers() > 0) {
|
if (img_pub_.getNumSubscribers() > 0) {
|
||||||
// publish debug image
|
// publish debug image
|
||||||
@@ -232,15 +236,12 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Publish estimated angular velocity
|
// Publish estimated angular velocity
|
||||||
static geometry_msgs::TwistStamped velo;
|
geometry_msgs::TwistStamped velo;
|
||||||
velo.header.stamp = msg->header.stamp;
|
velo.header.stamp = msg->header.stamp;
|
||||||
velo.header.frame_id = fcu_frame_id_;
|
velo.header.frame_id = fcu_frame_id_;
|
||||||
velo.twist.angular.x = flow_.integrated_x / integration_time.toSec();
|
velo.twist.angular.x = flow_fcu.vector.x / integration_time.toSec();
|
||||||
velo.twist.angular.y = flow_.integrated_y / integration_time.toSec();
|
velo.twist.angular.y = flow_fcu.vector.y / integration_time.toSec();
|
||||||
velo_pub_.publish(velo);
|
velo_pub_.publish(velo);
|
||||||
|
|
||||||
prev_ = curr_.clone();
|
|
||||||
prev_stamp_ = msg->header.stamp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ from mavros import mavlink
|
|||||||
|
|
||||||
rospy.init_node('selfcheck')
|
rospy.init_node('selfcheck')
|
||||||
|
|
||||||
|
os.environ['ROSCONSOLE_FORMAT']='[${severity}]: ${message}'
|
||||||
|
|
||||||
|
|
||||||
tf_buffer = tf2_ros.Buffer()
|
tf_buffer = tf2_ros.Buffer()
|
||||||
tf_listener = tf2_ros.TransformListener(tf_buffer)
|
tf_listener = tf2_ros.TransformListener(tf_buffer)
|
||||||
@@ -618,7 +620,7 @@ def check_boot_duration():
|
|||||||
|
|
||||||
@check('CPU usage')
|
@check('CPU usage')
|
||||||
def check_cpu_usage():
|
def check_cpu_usage():
|
||||||
WHITELIST = 'nodelet',
|
WHITELIST = 'nodelet', 'gzclient', 'gzserver'
|
||||||
CMD = "top -n 1 -b -i | tail -n +8 | awk '{ printf(\"%-8s\\t%-8s\\t%-8s\\n\", $1, $9, $12); }'"
|
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()
|
output = subprocess.check_output(CMD, shell=True).decode()
|
||||||
processes = output.split('\n')
|
processes = output.split('\n')
|
||||||
@@ -753,7 +755,7 @@ def check_rpi_health():
|
|||||||
# with some of the FLAGs OR'ed together
|
# with some of the FLAGs OR'ed together
|
||||||
output = subprocess.check_output(['vcgencmd', 'get_throttled']).decode()
|
output = subprocess.check_output(['vcgencmd', 'get_throttled']).decode()
|
||||||
except OSError:
|
except OSError:
|
||||||
failure('could not call vcgencmd binary; not a Raspberry Pi?')
|
info('could not call vcgencmd binary; not a Raspberry Pi?')
|
||||||
return
|
return
|
||||||
|
|
||||||
throttle_mask = int(output.split('=')[1], base=16)
|
throttle_mask = int(output.split('=')[1], base=16)
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ inline bool waitTransform(const string& target, const string& source,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIMEOUT(msg, timeout) (ros::Time::now() - msg.header.stamp > timeout)
|
#define TIMEOUT(msg, timeout) (msg.header.stamp.isZero() || (ros::Time::now() - msg.header.stamp > timeout))
|
||||||
|
|
||||||
bool getTelemetry(GetTelemetry::Request& req, GetTelemetry::Response& res)
|
bool getTelemetry(GetTelemetry::Request& req, GetTelemetry::Response& res)
|
||||||
{
|
{
|
||||||
@@ -441,6 +441,10 @@ void publish(const ros::Time stamp)
|
|||||||
|
|
||||||
// publish setpoint frame
|
// publish setpoint frame
|
||||||
if (!setpoint.child_frame_id.empty()) {
|
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.x = position_msg.pose.position.x;
|
||||||
setpoint.transform.translation.y = position_msg.pose.position.y;
|
setpoint.transform.translation.y = position_msg.pose.position.y;
|
||||||
setpoint.transform.translation.z = position_msg.pose.position.z;
|
setpoint.transform.translation.z = position_msg.pose.position.z;
|
||||||
@@ -712,7 +716,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sp_type == VELOCITY) {
|
if (sp_type == VELOCITY) {
|
||||||
static Vector3Stamped vel;
|
Vector3Stamped vel;
|
||||||
vel.header.frame_id = frame_id;
|
vel.header.frame_id = frame_id;
|
||||||
vel.header.stamp = stamp;
|
vel.header.stamp = stamp;
|
||||||
vel.vector.x = vx;
|
vel.vector.x = vx;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void publishZero(const ros::TimerEvent& e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ROS_INFO_THROTTLE(10, "publish zero");
|
ROS_INFO_THROTTLE(10, "publish zero");
|
||||||
static geometry_msgs::PoseStamped zero;
|
geometry_msgs::PoseStamped zero;
|
||||||
zero.header.frame_id = local_frame_id;
|
zero.header.frame_id = local_frame_id;
|
||||||
zero.header.stamp = e.current_real;
|
zero.header.stamp = e.current_real;
|
||||||
zero.pose.orientation.w = 1;
|
zero.pose.orientation.w = 1;
|
||||||
|
|||||||
9
clover/src/waitfile
Executable file
9
clover/src/waitfile
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/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,19 +33,3 @@ def test_web_video_server(node):
|
|||||||
# Python 3
|
# Python 3
|
||||||
import urllib.request as urllib
|
import urllib.request as urllib
|
||||||
urllib.urlopen("http://localhost:8080").read()
|
urllib.urlopen("http://localhost:8080").read()
|
||||||
|
|
||||||
def test_shell(node):
|
|
||||||
execute = rospy.ServiceProxy('exec', srv.Execute)
|
|
||||||
execute.wait_for_service(5)
|
|
||||||
|
|
||||||
res = execute(cmd='echo foo')
|
|
||||||
assert res.code == 0
|
|
||||||
assert res.output == 'foo\n'
|
|
||||||
|
|
||||||
res = execute(cmd='foo')
|
|
||||||
assert res.code == 32512
|
|
||||||
assert res.output == ''
|
|
||||||
|
|
||||||
res = execute(cmd='ls foo')
|
|
||||||
assert res.code == 512
|
|
||||||
assert res.output == ''
|
|
||||||
|
|||||||
@@ -12,4 +12,6 @@ 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"
|
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0013", ATTRS{product}=="PX4 FMU v4.x PRO", SYMLINK+="px4fmu"
|
||||||
# Omnibus
|
# Omnibus
|
||||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="26ac", ATTRS{idProduct}=="0001", ATTRS{product}=="PX4 OmnibusF4SD", SYMLINK+="px4fmu"
|
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
clover/www/clover.log
Symbolic link
1
clover/www/clover.log
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/var/log/clover.log
|
||||||
1
clover/www/clover_version
Symbolic link
1
clover/www/clover_version
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/etc/clover_version
|
||||||
@@ -1,25 +1,36 @@
|
|||||||
|
<title>Clover Drone Kit Tools</title>
|
||||||
|
|
||||||
<h1>Clover Drone Kit Tools</h1>
|
<h1>Clover Drone Kit Tools</h1>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="docs">View documentation</a> (snapshot of <a href="https://clover.coex.tech">clover.coex.tech</a>)</li>
|
<li><a href="docs">View documentation</a> (snapshot of <a href="https://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="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><a href="" id="butterfly">Open web terminal</a> (<code>Butterfly</code>)</li>
|
||||||
<li><a href="viz.html">View 3D visualization</a> (<code>ros3djs</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="aruco_map.html">3D visualization for markers map</a> (<code>ros3djs</code>)</li>
|
|
||||||
<li><a href="../clover_blocks/">Blocks programming</a> (<code>Blockly</code>)</li>
|
<li><a href="../clover_blocks/">Blocks programming</a> (<code>Blockly</code>)</li>
|
||||||
|
<li><a href="clover.log">Clover console</a> (<code>/var/log/clover.log</code>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="version"></div>
|
<div class="version"></div>
|
||||||
|
|
||||||
<script src="js/roslib.js"></script>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
document.querySelector("#wvs").href = location.protocol + '//' + location.hostname + ':8080';
|
document.querySelector("#wvs").href = location.protocol + '//' + location.hostname + ':8080';
|
||||||
document.querySelector("#butterfly").href = location.protocol + '//' + location.hostname + ':57575';
|
document.querySelector("#butterfly").href = location.protocol + '//' + location.hostname + ':57575';
|
||||||
|
|
||||||
|
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
|
// Determine image version
|
||||||
var ros = new ROSLIB.Ros({ url: 'ws://' + location.hostname + ':9090' });
|
fetch('clover_version').then(function(response) {
|
||||||
var exec = new ROSLIB.Service({ ros: ros, name : '/exec', serviceType : 'clover/Execute' });
|
if (response.status !== 200) return;
|
||||||
exec.callService(new ROSLIB.ServiceRequest({ cmd: 'cat /etc/clover_version' }), function(result) {
|
response.text().then(function(text) {
|
||||||
document.querySelector('.version').innerHTML = 'Version: ' + result.output;
|
document.querySelector('.version').innerHTML = 'Version: ' + text;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
236
clover/www/js/json-to-pretty-yaml.js
Normal file
236
clover/www/js/json-to-pretty-yaml.js
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
// 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]);
|
||||||
72
clover/www/js/topics.js
Normal file
72
clover/www/js/topics.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
const url = 'ws://' + location.hostname + ':9090';
|
||||||
|
const ros = new ROSLIB.Ros({ url: url });
|
||||||
|
|
||||||
|
ros.on('connection', function () {
|
||||||
|
document.body.classList.add('connected');
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
ros.on('close', function () {
|
||||||
|
document.body.classList.remove('connected');
|
||||||
|
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) {
|
||||||
|
title.innerHTML = 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 = `${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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
27
clover/www/topics.html
Normal file
27
clover/www/topics.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<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; }
|
||||||
|
</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>
|
||||||
8
clover_blocks/CHANGELOG.rst
Normal file
8
clover_blocks/CHANGELOG.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Changelog for package clover_blocks
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
0.21.1 (2020-11-17)
|
||||||
|
-------------------
|
||||||
|
* First release of clover_blocks package to ROS
|
||||||
|
* Contributors: Oleg Kalachev
|
||||||
@@ -73,6 +73,13 @@ catkin_install_python(PROGRAMS src/clover_blocks
|
|||||||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
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 ##
|
## Testing ##
|
||||||
#############
|
#############
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Internal package documentation is given below.
|
|||||||
|
|
||||||
## Frontend
|
## Frontend
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## `clover_blocks` node
|
## `clover_blocks` node
|
||||||
|
|
||||||
@@ -30,7 +30,8 @@ The frontend files are located in [`www`](./www/) subdirectory. The frontend app
|
|||||||
Parameters read by frontend:
|
Parameters read by frontend:
|
||||||
|
|
||||||
* `~navigate_tolerance` (*float*) – distance tolerance in meters, used for navigate-like blocks (default: 0.2).
|
* `~navigate_tolerance` (*float*) – distance tolerance in meters, used for navigate-like blocks (default: 0.2).
|
||||||
* `~yaw_tolerance` (*float*) – yaw angle tolerance in degrees, used in set_yaw block (default: 20).
|
* `~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).
|
||||||
* `~sleep_time` (*float*) – duration of sleep in loop cycles, used for navigate-like blocks (default: 0.2).
|
* `~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).
|
* `~confirm_run` (*bool*) – enable confirmation to run the program (default: true).
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<package format="2">
|
<package format="2">
|
||||||
<name>clover_blocks</name>
|
<name>clover_blocks</name>
|
||||||
<version>0.0.0</version>
|
<version>0.21.1</version>
|
||||||
<description>Blockly programming support for Clover</description>
|
<description>Blockly programming support for Clover</description>
|
||||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||||
<license>MIT</license>
|
<license>MIT</license>
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import rospy
|
import rospy
|
||||||
import os
|
import os, sys
|
||||||
|
import traceback
|
||||||
import threading
|
import threading
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
@@ -116,7 +117,12 @@ def run(req):
|
|||||||
rospy.loginfo('Program forced to stop')
|
rospy.loginfo('Program forced to stop')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
rospy.logerr(str(e))
|
rospy.logerr(str(e))
|
||||||
error_pub.publish(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)
|
||||||
|
|
||||||
rospy.loginfo('Program terminated')
|
rospy.loginfo('Program terminated')
|
||||||
running_lock.release()
|
running_lock.release()
|
||||||
@@ -140,6 +146,7 @@ def stop(req):
|
|||||||
return {'success': True}
|
return {'success': True}
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: find dir in installed package
|
||||||
programs_path = rospy.get_param('~programs_dir', os.path.dirname(os.path.abspath(__file__)) + '/../programs')
|
programs_path = rospy.get_param('~programs_dir', os.path.dirname(os.path.abspath(__file__)) + '/../programs')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,14 @@ function considerFrameId(e) {
|
|||||||
this.getInput('Y').fieldRow[0].setValue('y');
|
this.getInput('Y').fieldRow[0].setValue('y');
|
||||||
this.getInput('Z').fieldRow[0].setValue('z');
|
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
|
if (this.getInput('ID')) { // block has marker id field
|
||||||
this.getInput('ID').setVisible(frameId == 'ARUCO'); // toggle id field
|
this.getInput('ID').setVisible(frameId == 'ARUCO'); // toggle id field
|
||||||
@@ -65,6 +73,9 @@ function updateSetpointBlock(e) {
|
|||||||
|
|
||||||
Blockly.Blocks['navigate'] = {
|
Blockly.Blocks['navigate'] = {
|
||||||
init: function () {
|
init: function () {
|
||||||
|
let navFrameId = frameIds.slice();
|
||||||
|
navFrameId.push(['global', 'GLOBAL_LOCAL'])
|
||||||
|
navFrameId.push(['global, WGS 84 alt.', 'GLOBAL'])
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("navigate to point");
|
.appendField("navigate to point");
|
||||||
this.appendValueInput("X")
|
this.appendValueInput("X")
|
||||||
@@ -73,12 +84,20 @@ Blockly.Blocks['navigate'] = {
|
|||||||
this.appendValueInput("Y")
|
this.appendValueInput("Y")
|
||||||
.setCheck("Number")
|
.setCheck("Number")
|
||||||
.appendField("left");
|
.appendField("left");
|
||||||
|
this.appendValueInput("LAT")
|
||||||
|
.setCheck("Number")
|
||||||
|
.appendField("latitude")
|
||||||
|
.setVisible(false);
|
||||||
|
this.appendValueInput("LON")
|
||||||
|
.setCheck("Number")
|
||||||
|
.appendField("longitude")
|
||||||
|
.setVisible(false)
|
||||||
this.appendValueInput("Z")
|
this.appendValueInput("Z")
|
||||||
.setCheck("Number")
|
.setCheck("Number")
|
||||||
.appendField("up");
|
.appendField("up");
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("relative to")
|
.appendField("relative to")
|
||||||
.appendField(new Blockly.FieldDropdown(frameIds), "FRAME_ID");
|
.appendField(new Blockly.FieldDropdown(navFrameId), "FRAME_ID");
|
||||||
this.appendValueInput("ID")
|
this.appendValueInput("ID")
|
||||||
.setCheck("Number")
|
.setCheck("Number")
|
||||||
.appendField("with ID")
|
.appendField("with ID")
|
||||||
@@ -268,7 +287,7 @@ Blockly.Blocks['mode'] = {
|
|||||||
.appendField("current flight mode");
|
.appendField("current flight mode");
|
||||||
this.setOutput(true, "String");
|
this.setOutput(true, "String");
|
||||||
this.setColour(COLOR_STATE);
|
this.setColour(COLOR_STATE);
|
||||||
this.setTooltip("");
|
this.setTooltip("Returns current flight mode (POSCTL, OFFBOARD, etc).");
|
||||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -375,7 +394,7 @@ Blockly.Blocks['take_off'] = {
|
|||||||
this.setPreviousStatement(true, null);
|
this.setPreviousStatement(true, null);
|
||||||
this.setNextStatement(true, null);
|
this.setNextStatement(true, null);
|
||||||
this.setColour(COLOR_FLIGHT);
|
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);
|
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -391,7 +410,7 @@ Blockly.Blocks['land'] = {
|
|||||||
this.setPreviousStatement(true, null);
|
this.setPreviousStatement(true, null);
|
||||||
this.setNextStatement(true, null);
|
this.setNextStatement(true, null);
|
||||||
this.setColour(COLOR_FLIGHT);
|
this.setColour(COLOR_FLIGHT);
|
||||||
this.setTooltip("");
|
this.setTooltip("Land the drone.");
|
||||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -400,10 +419,10 @@ Blockly.Blocks['global_position'] = {
|
|||||||
init: function () {
|
init: function () {
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("current")
|
.appendField("current")
|
||||||
.appendField(new Blockly.FieldDropdown([["latitude", "LATITUDE"], ["longitude", "LONGITUDE"], ["altitude", "ALTITUDE"]]), "NAME");
|
.appendField(new Blockly.FieldDropdown([["latitude", "LAT"], ["longitude", "LON"], ["altitude", "ALT"]]), "FIELD");
|
||||||
this.setOutput(true, "Number");
|
this.setOutput(true, "Number");
|
||||||
this.setColour(230);
|
this.setColour(COLOR_STATE);
|
||||||
this.setTooltip("");
|
this.setTooltip("Returns current global position (latitude, longitude, altitude above the WGS 84 ellipsoid).");
|
||||||
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
this.setHelpUrl(DOCS_URL + '#' + this.type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,6 +52,8 @@
|
|||||||
<value name="X"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
<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="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="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="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>
|
<value name="ID"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||||
</block>
|
</block>
|
||||||
@@ -85,6 +87,7 @@
|
|||||||
<value name="ID"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
<value name="ID"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||||
</block>
|
</block>
|
||||||
<block type="get_attitude"></block>
|
<block type="get_attitude"></block>
|
||||||
|
<block type="global_position"></block>
|
||||||
<block type="distance">
|
<block type="distance">
|
||||||
<value name="X"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
<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="Y"><shadow type="math_number"><field name="NUM">0</field></shadow></value>
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ var workspace = Blockly.inject('blockly', {
|
|||||||
function readParams() {
|
function readParams() {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
ros.readParam('navigate_tolerance', true, 0.2),
|
ros.readParam('navigate_tolerance', true, 0.2),
|
||||||
ros.readParam('yaw_tolerance', true, 20),
|
ros.readParam('navigate_global_tolerance', true, 1),
|
||||||
|
ros.readParam('yaw_tolerance', true, 1),
|
||||||
ros.readParam('sleep_time', true, 0.2),
|
ros.readParam('sleep_time', true, 0.2),
|
||||||
ros.readParam('confirm_run', true, true),
|
ros.readParam('confirm_run', true, true),
|
||||||
]);
|
]);
|
||||||
@@ -210,7 +211,7 @@ function loadPrograms() {
|
|||||||
updateChanged();
|
updateChanged();
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
document.querySelector('.backend-fail').style.display = 'inline';
|
document.querySelector('.backend-fail').style.display = 'inline';
|
||||||
alert(`Error loading programs list.\n\nHave you enabled clover_blocks in clover.launch?`);
|
alert(`Error loading programs list.\n\nHave you enabled 'blocks' in clover.launch?`);
|
||||||
runButton.disabled = true;
|
runButton.disabled = true;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,18 @@ const NAVIGATE_WAIT = () => `\ndef navigate_wait(x=0, y=0, z=0, speed=0.5, frame
|
|||||||
return
|
return
|
||||||
rospy.sleep(${params.sleep_time})\n`;
|
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():
|
const LAND_WAIT = () => `\ndef land_wait():
|
||||||
land()
|
land()
|
||||||
while get_telemetry().armed:
|
while get_telemetry().armed:
|
||||||
@@ -68,6 +80,9 @@ function generateROSDefinitions() {
|
|||||||
if (rosDefinitions.offboard) {
|
if (rosDefinitions.offboard) {
|
||||||
code += `get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)\n`;
|
code += `get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)\n`;
|
||||||
code += `navigate = rospy.ServiceProxy('navigate', srv.Navigate)\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) {
|
if (rosDefinitions.setVelocity) {
|
||||||
code += `set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)\n`;
|
code += `set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)\n`;
|
||||||
}
|
}
|
||||||
@@ -94,6 +109,10 @@ function generateROSDefinitions() {
|
|||||||
Blockly.Python.definitions_['import_math'] = 'import math';
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
||||||
code += NAVIGATE_WAIT();
|
code += NAVIGATE_WAIT();
|
||||||
}
|
}
|
||||||
|
if (rosDefinitions.navigateGlobalWait) {
|
||||||
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
||||||
|
code += NAVIGATE_GLOBAL_WAIT();
|
||||||
|
}
|
||||||
if (rosDefinitions.landWait) {
|
if (rosDefinitions.landWait) {
|
||||||
code += LAND_WAIT();
|
code += LAND_WAIT();
|
||||||
}
|
}
|
||||||
@@ -161,14 +180,37 @@ Blockly.Python.navigate = function(block) {
|
|||||||
let x = Blockly.Python.valueToCode(block, 'X', Blockly.Python.ORDER_NONE);
|
let x = Blockly.Python.valueToCode(block, 'X', Blockly.Python.ORDER_NONE);
|
||||||
let y = Blockly.Python.valueToCode(block, 'Y', 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 z = Blockly.Python.valueToCode(block, 'Z', Blockly.Python.ORDER_NONE);
|
||||||
let frameId = buildFrameId(block);
|
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 speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
|
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();
|
simpleOffboard();
|
||||||
|
|
||||||
if (block.getFieldValue('WAIT') == 'TRUE') {
|
// global coordinates
|
||||||
|
if (frameId.startsWith('GLOBAL')) {
|
||||||
|
rosDefinitions.navigateGlobal = 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`;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
frameId = buildFrameId(block);
|
||||||
|
let params = [`x=${x}`, `y=${y}`, `z=${z}`, `frame_id=${frameId}`, `speed=${speed}`];
|
||||||
|
|
||||||
|
if (wait) {
|
||||||
rosDefinitions.navigateWait = true;
|
rosDefinitions.navigateWait = true;
|
||||||
simpleOffboard();
|
simpleOffboard();
|
||||||
|
|
||||||
@@ -180,6 +222,7 @@ Blockly.Python.navigate = function(block) {
|
|||||||
}
|
}
|
||||||
return `navigate(${params.join(', ')})\n`;
|
return `navigate(${params.join(', ')})\n`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Blockly.Python.set_velocity = function(block) {
|
Blockly.Python.set_velocity = function(block) {
|
||||||
@@ -315,6 +358,12 @@ Blockly.Python.get_attitude = function(block) {
|
|||||||
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
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) {
|
Blockly.Python.distance = function(block) {
|
||||||
rosDefinitions.distance = true;
|
rosDefinitions.distance = true;
|
||||||
simpleOffboard();
|
simpleOffboard();
|
||||||
|
|||||||
9
clover_description/CHANGELOG.rst
Normal file
9
clover_description/CHANGELOG.rst
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
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;
|
* `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`);
|
* `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`);
|
* `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 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)).
|
* `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)).
|
||||||
|
|
||||||
For example, in order to spawn a drone without a GPS module, you may use the following command:
|
For example, in order to spawn a drone without a GPS module, you may use the following command:
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<launch>
|
<launch>
|
||||||
<arg name="model" default="$(find clover_description)/urdf/drones/clover4.xacro"/>
|
<arg name="model" default="$(find clover_description)/urdf/clover/clover4.xacro"/>
|
||||||
|
|
||||||
<param name="robot_description" command="$(find xacro)/xacro.py $(arg model)"/>
|
<param name="robot_description" command="xacro $(arg model)"/>
|
||||||
|
|
||||||
<node name="rviz" pkg="rviz" type="rviz" required="true"/>
|
<node name="rviz" pkg="rviz" type="rviz" required="true"/>
|
||||||
</launch>
|
</launch>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<package format="2">
|
<package format="2">
|
||||||
<name>clover_description</name>
|
<name>clover_description</name>
|
||||||
<version>0.0.1</version>
|
<version>0.21.1</version>
|
||||||
<description>The clover_description package provides URDF models of the Clover series of quadcopters.</description>
|
<description>The clover_description package provides URDF models of the Clover series of quadcopters.</description>
|
||||||
|
|
||||||
<maintainer email="sfalexrog@gmail.com">Alexey Rogachevskiy</maintainer>
|
<maintainer email="sfalexrog@gmail.com">Alexey Rogachevskiy</maintainer>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<robot name="clover_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
<robot name="clover" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||||
|
|
||||||
<xacro:arg name="main_camera" default="true"/>
|
<xacro:arg name="main_camera" default="true"/>
|
||||||
<xacro:arg name="rangefinder" default="true"/>
|
<xacro:arg name="rangefinder" default="true"/>
|
||||||
@@ -8,10 +8,10 @@
|
|||||||
<xacro:arg name="maintain_camera_rate" default="false"/>
|
<xacro:arg name="maintain_camera_rate" default="false"/>
|
||||||
<xacro:arg name="use_clover_physics" default="false"/>
|
<xacro:arg name="use_clover_physics" default="false"/>
|
||||||
|
|
||||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_base.xacro" />
|
<xacro:include filename="clover4_base.xacro" />
|
||||||
<xacro:include filename="$(find clover_description)/urdf/sensors/rpi_cam.urdf.xacro"/>
|
<xacro:include filename="../sensors/rpi_cam.urdf.xacro"/>
|
||||||
<xacro:include filename="$(find clover_description)/urdf/sensors/distance_sensor.urdf.xacro"/>
|
<xacro:include filename="../sensors/distance_sensor.urdf.xacro"/>
|
||||||
<xacro:include filename="$(find clover_description)/urdf/leds/led_strip.xacro"/>
|
<xacro:include filename="../leds/led_strip.xacro"/>
|
||||||
|
|
||||||
<!-- Create camera plugin -->
|
<!-- Create camera plugin -->
|
||||||
<xacro:if value="$(arg main_camera)">
|
<xacro:if value="$(arg main_camera)">
|
||||||
@@ -36,11 +36,17 @@
|
|||||||
</xacro:if>
|
</xacro:if>
|
||||||
|
|
||||||
<xacro:if value="$(arg gps)">
|
<xacro:if value="$(arg gps)">
|
||||||
<!-- Instantiate gps plugin. -->
|
<gazebo>
|
||||||
<xacro:gps_plugin_macro
|
<include>
|
||||||
namespace="${namespace}"
|
<uri>model://gps</uri>
|
||||||
gps_noise="true"
|
<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>
|
||||||
</xacro:if>
|
</xacro:if>
|
||||||
|
|
||||||
</robot>
|
</robot>
|
||||||
|
|||||||
@@ -1,40 +1,15 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<robot name="clover" xmlns:xacro="http://ros.org/wiki/xacro">
|
<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' />
|
<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='enable_logging' default='false' />
|
||||||
<xacro:arg name='log_file' default='iris' />
|
<xacro:arg name='log_file' default='clover' />
|
||||||
|
|
||||||
<!-- macros for gazebo plugins, sensors -->
|
<!-- macros for gazebo plugins, sensors -->
|
||||||
<xacro:include filename="$(find clover_description)/urdf/component_snippets.urdf.xacro" />
|
<xacro:include filename="../component_snippets.urdf.xacro" />
|
||||||
|
|
||||||
<!-- Instantiate iris "mechanics" -->
|
<!-- Instantiate iris "mechanics" -->
|
||||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_physics.xacro" />
|
<xacro:include filename="clover4_physics.xacro" />
|
||||||
|
|
||||||
<xacro:if value="$(arg enable_wind)">
|
<xacro:if value="$(arg enable_wind)">
|
||||||
<xacro:wind_plugin_macro
|
<xacro:wind_plugin_macro
|
||||||
@@ -49,126 +24,8 @@
|
|||||||
/>
|
/>
|
||||||
</xacro:if>
|
</xacro:if>
|
||||||
|
|
||||||
<!-- Instantiate magnetometer plugin. -->
|
<!-- Gazebo plugins -->
|
||||||
<xacro:magnetometer_plugin_macro
|
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_gazebo.xacro" />
|
||||||
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)">
|
<xacro:if value="$(arg enable_logging)">
|
||||||
<!-- Instantiate a logger -->
|
<!-- Instantiate a logger -->
|
||||||
|
|||||||
183
clover_description/urdf/clover/clover4_gazebo.xacro
Normal file
183
clover_description/urdf/clover/clover4_gazebo.xacro
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<?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="iris" xmlns:xacro="http://ros.org/wiki/xacro">
|
<robot name="clover" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||||
<!-- Properties -->
|
<!-- Properties -->
|
||||||
<xacro:property name="namespace" value="" />
|
<xacro:property name="namespace" value="" />
|
||||||
<xacro:property name="rotor_velocity_slowdown_sim" value="10" />
|
<xacro:property name="rotor_velocity_slowdown_sim" value="10" />
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
</xacro:unless>
|
</xacro:unless>
|
||||||
|
|
||||||
<!-- Included URDF Files -->
|
<!-- Included URDF Files -->
|
||||||
<xacro:include filename="$(find clover_description)/urdf/clover/clover4_macros.xacro" />
|
<xacro:include filename="clover4_macros.xacro" />
|
||||||
|
|
||||||
<!-- Instantiate multirotor_base_macro once -->
|
<!-- Instantiate multirotor_base_macro once -->
|
||||||
<xacro:clover4_base_macro
|
<xacro:clover4_base_macro
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<robot name="rpi_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
<robot name="rpi_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||||
<xacro:include filename="$(find clover_description)/urdf/camera_sensor.urdf.xacro"/>
|
<xacro:include filename="../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">
|
<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">
|
<joint name="${name}_joint" type="fixed">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<robot name="pinhole_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
<robot name="pinhole_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||||
<xacro:include filename="$(find clover_description)/urdf/camera_sensor.urdf.xacro"/>
|
<xacro:include filename="../camera_sensor.urdf.xacro"/>
|
||||||
<xacro:camera_sensor name="main_camera" width="640" height="480" rate="30" horizontal_fov="${120.0*pi/180.0}"/>
|
<xacro:camera_sensor name="main_camera" width="640" height="480" rate="30" horizontal_fov="${120.0*pi/180.0}"/>
|
||||||
</robot>
|
</robot>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<robot name="rpi_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
<robot name="rpi_camera" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||||
<xacro:include filename="$(find clover_description)/urdf/camera_sensor.urdf.xacro"/>
|
<xacro:include filename="../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">
|
<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">
|
<joint name="${name}_joint" type="fixed">
|
||||||
|
|||||||
8
clover_simulation/CHANGELOG.rst
Normal file
8
clover_simulation/CHANGELOG.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
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})
|
add_dependencies(throttling_camera ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||||
|
|
||||||
install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||||
install(DIRECTORY meshes DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
install(DIRECTORY models DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||||
install(DIRECTORY resources DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
install(DIRECTORY resources DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
|
||||||
|
|
||||||
catkin_install_python(PROGRAMS scripts/aruco_gen
|
catkin_install_python(PROGRAMS scripts/aruco_gen
|
||||||
|
|||||||
@@ -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:
|
The plugin accepts the following parameters during instantiation:
|
||||||
|
|
||||||
* `robotNamespace` (*string*, default: "") - a ROS namespace for the plugin;
|
* `robotNamespace` (*string*, default: "") - a ROS namespace for the plugin;
|
||||||
* `ledCount` (*integer*, required) - total numer of LEDs in a strip.
|
* `ledCount` (*integer*, required) - total number of LEDs in a strip.
|
||||||
|
|
||||||
The plugin will provide the following service:
|
The plugin will provide the following service:
|
||||||
|
|
||||||
|
|||||||
36
clover_simulation/airframes/4500_clover
Normal file
36
clover_simulation/airframes/4500_clover
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/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,41 +1,57 @@
|
|||||||
<launch>
|
<launch>
|
||||||
|
<arg name="type" default="gazebo"/> <!-- gazebo, jmavsim, none (only clover packages) -->
|
||||||
<arg name="mav_id" default="0"/>
|
<arg name="mav_id" default="0"/>
|
||||||
<arg name="est" default="ekf2"/> <!-- PX4 estimator: lpe, ekf2 -->
|
<arg name="est" default="ekf2"/> <!-- PX4 estimator: lpe, ekf2 -->
|
||||||
<arg name="vehicle" default="clover"/> <!-- PX4 vehicle configuration: clover, clover_vpe -->
|
<arg name="vehicle" default="clover"/> <!-- PX4 vehicle configuration: clover, clover_vpe -->
|
||||||
<arg name="main_camera" default="true"/> <!-- Simulated vision position estimation camera (optical flow, ArUco) -->
|
<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="rangefinder" default="true"/> <!-- Simulated downward-facing rangefinder, vl53l1x-like -->
|
||||||
<arg name="led" default="true"/> <!-- Simulated LED strip, ws281x-like -->
|
<arg name="led" default="true"/> <!-- Simulated LED strip, ws281x-like -->
|
||||||
<arg name="gps" default="false"/> <!--Simulated GPS module -->
|
<arg name="gps" default="false"/> <!--Simulated GPS module -->
|
||||||
<arg name="use_clover_physics" default="false"/> <!-- Use inertial parameters from CAD models -->
|
<arg name="use_clover_physics" default="false"/> <!-- Use inertial parameters from CAD models -->
|
||||||
|
<arg name="gui" default="true"/> <!-- Run Gazebo with GUI -->
|
||||||
|
|
||||||
<!-- Gazebo instance -->
|
<!-- Gazebo instance -->
|
||||||
<include file="$(find gazebo_ros)/launch/empty_world.launch">
|
<include file="$(find gazebo_ros)/launch/empty_world.launch" if="$(eval type == 'gazebo')">
|
||||||
<!-- Workaround for crashes in VMware -->
|
<!-- Workaround for crashes in VMware -->
|
||||||
<env name="SVGA_VGPU10" value="0"/>
|
<env name="SVGA_VGPU10" value="0"/>
|
||||||
<arg name="gui" value="true"/>
|
<arg name="gui" value="$(arg gui)"/>
|
||||||
<arg name="world_name" value="$(find clover_simulation)/resources/worlds/clover.world"/>
|
<arg name="world_name" value="$(find clover_simulation)/resources/worlds/clover_aruco.world"/>
|
||||||
<arg name="verbose" value="true"/>
|
<arg name="verbose" value="true"/>
|
||||||
</include>
|
</include>
|
||||||
|
|
||||||
<!-- PX4 instance -->
|
<!-- PX4 instance -->
|
||||||
<node name="sitl_$(arg mav_id)" pkg="px4" type="px4" output="screen" args="$(find px4)/ROMFS/px4fmu_common -s etc/init.d-posix/rcS -i $(arg mav_id)">
|
<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')">
|
||||||
<env name="PX4_SIM_MODEL" value="$(arg vehicle)"/>
|
<env name="PX4_SIM_MODEL" value="$(arg vehicle)"/>
|
||||||
<env name="PX4_ESTIMATOR" value="$(arg est)"/>
|
<env name="PX4_ESTIMATOR" value="$(arg est)"/>
|
||||||
</node>
|
</node>
|
||||||
|
|
||||||
<!-- Clover model -->
|
<!-- Clover model -->
|
||||||
<include file="$(find clover_description)/launch/spawn_drone.launch">
|
<include file="$(find clover_description)/launch/spawn_drone.launch" if="$(eval type == 'gazebo')">
|
||||||
<arg name="main_camera" value="$(arg main_camera)"/>
|
<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="rangefinder" value="$(arg rangefinder)"/>
|
||||||
<arg name="led" value="$(arg led)"/>
|
<arg name="led" value="$(arg led)"/>
|
||||||
<arg name="gps" value="$(arg gps)"/>
|
<arg name="gps" value="$(arg gps)"/>
|
||||||
<arg name="use_clover_physics" value="$(arg use_clover_physics)"/>
|
<arg name="use_clover_physics" value="$(arg use_clover_physics)"/>
|
||||||
</include>
|
</include>
|
||||||
|
|
||||||
|
<node name="jmavsim" pkg="px4" type="jmavsim_run.sh" output="screen" if="$(eval type == 'jmavsim')">
|
||||||
|
<env name="HEADLESS" value="1" if="$(eval not gui)"/>
|
||||||
|
</node>
|
||||||
|
|
||||||
|
<param name="use_sim_time" value="false" if="$(eval type == 'jmavsim')"/>
|
||||||
|
|
||||||
<!-- Clover services -->
|
<!-- Clover services -->
|
||||||
<include file="$(find clover)/launch/clover.launch">
|
<include file="$(find clover)/launch/clover.launch">
|
||||||
<arg name="simulator" value="true"/>
|
<arg name="simulator" value="true"/>
|
||||||
<arg name="fcu_conn" value="sitl"/>
|
<arg name="fcu_conn" value="sitl"/>
|
||||||
<arg name="fcu_ip" value="127.0.0.1"/>
|
<arg name="fcu_ip" value="127.0.0.1"/>
|
||||||
|
<arg name="gcs_bridge" value=""/>
|
||||||
|
<arg name="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>
|
</include>
|
||||||
</launch>
|
</launch>
|
||||||
|
|||||||
24
clover_simulation/models/aruco_100/marker_100.sdf
Normal file
24
clover_simulation/models/aruco_100/marker_100.sdf
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?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>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
material aruco/marker_100
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
texture_unit
|
||||||
|
{
|
||||||
|
texture aruco_marker_100.png
|
||||||
|
filtering none
|
||||||
|
scale 1.0 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 94 B |
13
clover_simulation/models/aruco_100/model.config
Normal file
13
clover_simulation/models/aruco_100/model.config
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?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>
|
||||||
24
clover_simulation/models/aruco_101/marker_101.sdf
Normal file
24
clover_simulation/models/aruco_101/marker_101.sdf
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?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>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
material aruco/marker_101
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
texture_unit
|
||||||
|
{
|
||||||
|
texture aruco_marker_101.png
|
||||||
|
filtering none
|
||||||
|
scale 1.0 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 94 B |
13
clover_simulation/models/aruco_101/model.config
Normal file
13
clover_simulation/models/aruco_101/model.config
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?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>
|
||||||
24
clover_simulation/models/aruco_102/marker_102.sdf
Normal file
24
clover_simulation/models/aruco_102/marker_102.sdf
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?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>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
material aruco/marker_102
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
texture_unit
|
||||||
|
{
|
||||||
|
texture aruco_marker_102.png
|
||||||
|
filtering none
|
||||||
|
scale 1.0 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 94 B |
13
clover_simulation/models/aruco_102/model.config
Normal file
13
clover_simulation/models/aruco_102/model.config
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?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>
|
||||||
1693
clover_simulation/models/aruco_cmit_txt/aruco_model.sdf
Normal file
1693
clover_simulation/models/aruco_cmit_txt/aruco_model.sdf
Normal file
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