Compare commits
131 Commits
v0.19-rc.2
...
v0.20-rc.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d48c79c52 | ||
|
|
ad46a0918c | ||
|
|
9487522992 | ||
|
|
80b35d3b90 | ||
|
|
12e292c9d7 | ||
|
|
9b28e9cad2 | ||
|
|
d57ab82f38 | ||
|
|
c8da639eab | ||
|
|
c7e7edec70 | ||
|
|
72869fcf2b | ||
|
|
387d2c2341 | ||
|
|
a665caeea3 | ||
|
|
3079d2a3e1 | ||
|
|
7d5bdf4f22 | ||
|
|
2a3efa2908 | ||
|
|
ddee29a0e8 | ||
|
|
8596be07c6 | ||
|
|
a480ebe80a | ||
|
|
77ca50b901 | ||
|
|
ead9b904fa | ||
|
|
90956ecd44 | ||
|
|
f070c60e14 | ||
|
|
68edf07f6e | ||
|
|
7f161b1ad7 | ||
|
|
a41a432ef3 | ||
|
|
2b896b06d9 | ||
|
|
5070cafbfb | ||
|
|
9c0af7285c | ||
|
|
c67d937842 | ||
|
|
b79d87242f | ||
|
|
4d0ddcb319 | ||
|
|
3ff4ee6c4c | ||
|
|
90049182cf | ||
|
|
33f4601fdc | ||
|
|
2a62891d60 | ||
|
|
b043737e91 | ||
|
|
c61a0485ff | ||
|
|
f1539177eb | ||
|
|
6cbbb5580e | ||
|
|
c2d22ae12a | ||
|
|
7160d804cd | ||
|
|
3ac51baf7c | ||
|
|
48cc82001d | ||
|
|
43eae885c6 | ||
|
|
2bb29ff389 | ||
|
|
3811cbff3e | ||
|
|
2d49f58fb8 | ||
|
|
bbcf75b806 | ||
|
|
461f4f5904 | ||
|
|
4f8020ff35 | ||
|
|
267aaf45d3 | ||
|
|
0b74430a11 | ||
|
|
1746381da1 | ||
|
|
6879723771 | ||
|
|
b474f99665 | ||
|
|
60b0059ef1 | ||
|
|
8dfb9a8f6c | ||
|
|
2c36fdb560 | ||
|
|
8d37c424eb | ||
|
|
2f70ce4372 | ||
|
|
e9527b5efd | ||
|
|
351b33cc5f | ||
|
|
a427d86f41 | ||
|
|
ef0f926a79 | ||
|
|
0b587b7dae | ||
|
|
770a76a450 | ||
|
|
3e79c25147 | ||
|
|
16b2538dfa | ||
|
|
d01e6990b1 | ||
|
|
6fbdfb7817 | ||
|
|
e05431cc75 | ||
|
|
4c940f0b8b | ||
|
|
2672b6784f | ||
|
|
22ba3a1406 | ||
|
|
7cc91b2e32 | ||
|
|
d6f8f4017f | ||
|
|
2f69ad3f43 | ||
|
|
b08ad5a618 | ||
|
|
fca584cefe | ||
|
|
099e115def | ||
|
|
d2b9ec7166 | ||
|
|
bda966bc90 | ||
|
|
d182542153 | ||
|
|
bc74af3006 | ||
|
|
d88cbaee85 | ||
|
|
49d1fb5215 | ||
|
|
e750395e01 | ||
|
|
5439e5c1df | ||
|
|
aac7dcae2f | ||
|
|
df78f17efb | ||
|
|
0fa7e0e496 | ||
|
|
dee58f2e47 | ||
|
|
197e02f4ba | ||
|
|
f7934554e4 | ||
|
|
9a7ffef858 | ||
|
|
d0619b4543 | ||
|
|
0f0deb85da | ||
|
|
89ccf9c2b9 | ||
|
|
32ff2d4e15 | ||
|
|
366fcc14f6 | ||
|
|
2cd334c474 | ||
|
|
647652f85f | ||
|
|
4022eb773d | ||
|
|
79a6a802f4 | ||
|
|
77f2bc739e | ||
|
|
05464ce767 | ||
|
|
d5eae45e49 | ||
|
|
cfe35e1c83 | ||
|
|
10648825c0 | ||
|
|
f8fb8a0a1a | ||
|
|
a958742d9f | ||
|
|
8d7a12f2b4 | ||
|
|
856e0a5ed0 | ||
|
|
da6cb48b62 | ||
|
|
459a93986e | ||
|
|
f6b3c8ab86 | ||
|
|
20a29c3dd6 | ||
|
|
49b436b505 | ||
|
|
6739a685d8 | ||
|
|
d8d7839e0e | ||
|
|
331a2a40bc | ||
|
|
40856b9401 | ||
|
|
9ca597dfd7 | ||
|
|
1f2484a9ef | ||
|
|
81cb04c912 | ||
|
|
085850cfdd | ||
|
|
5bef4a1e21 | ||
|
|
1447e73fed | ||
|
|
75278552b3 | ||
|
|
320f7a43ce | ||
|
|
26e9ab0c7f |
@@ -105,7 +105,8 @@
|
||||
"TCP",
|
||||
"UDP",
|
||||
"QR",
|
||||
"Li-ion"
|
||||
"Li-ion",
|
||||
"Nvidia"
|
||||
],
|
||||
"code_blocks": false
|
||||
},
|
||||
|
||||
33
.travis.yml
@@ -1,4 +1,5 @@
|
||||
sudo: required
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: generic
|
||||
services:
|
||||
- docker
|
||||
@@ -43,7 +44,7 @@ jobs:
|
||||
- cd images && zip ${IMAGE_NAME}.zip ${IMAGE_NAME}
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: ${GITHUB_OAUTH_TOKEN}
|
||||
token: ${GITHUB_OAUTH_TOKEN}
|
||||
file: ${IMAGE_NAME}.zip
|
||||
skip_cleanup: true
|
||||
on:
|
||||
@@ -57,7 +58,7 @@ jobs:
|
||||
before_script:
|
||||
- docker pull ${NATIVE_DOCKER}
|
||||
script:
|
||||
- docker run --rm -v $(pwd):/root/catkin_ws/src/clever ${NATIVE_DOCKER} /root/catkin_ws/src/clever/builder/standalone-install.sh
|
||||
- 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:
|
||||
@@ -65,7 +66,7 @@ jobs:
|
||||
before_script:
|
||||
- docker pull ${NATIVE_DOCKER}
|
||||
script:
|
||||
- docker run --rm -v $(pwd):/root/catkin_ws/src/clever ${NATIVE_DOCKER} /root/catkin_ws/src/clever/builder/standalone-install.sh
|
||||
- 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
|
||||
@@ -82,18 +83,18 @@ jobs:
|
||||
- ./check_unused_assets.py
|
||||
- gitbook install
|
||||
- gitbook build
|
||||
deploy:
|
||||
provider: pages
|
||||
local-dir: _book
|
||||
skip-cleanup: true
|
||||
github-token: ${GITHUB_OAUTH_TOKEN}
|
||||
keep-history: true
|
||||
target-branch: master
|
||||
repo: CopterExpress/clever.coex.tech
|
||||
fqdn: clever.coex.tech
|
||||
verbose: true
|
||||
on:
|
||||
branch: master
|
||||
# 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: Annotate
|
||||
name: Auto-generate changelog
|
||||
language: python
|
||||
|
||||
105
README.md
@@ -1,103 +1,40 @@
|
||||
# CLEVER
|
||||
# COEX Clover Drone Kit
|
||||
|
||||
<img src="docs/assets/clever4-front-white.png" align="right" width="400px" alt="CLEVER drone">
|
||||
<img src="docs/assets/clever4-front-white.png" align="right" width="400px" alt="Clover Drone">
|
||||
|
||||
CLEVER (Russian: *"Клевер"*, meaning *"Clover"*) is an educational programmable drone kit consisting of an unassembled quadcopter, open source software and documentation. The kit includes Pixhawk/Pixracer autopilot running PX4 firmware, Raspberry Pi 3 as companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices.
|
||||
Clover is an educational programmable drone kit consisting of an unassembled quadcopter, open source software and documentation. The kit includes Pixracer-compatible autopilot running PX4 firmware, Raspberry Pi 4 as companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices.
|
||||
|
||||
Copter Express has implemented a large number of different autonomous drone projects using exactly the same platform: [automated pizza delivery](https://www.youtube.com/watch?v=hmkAoZOtF58) in Samara and Kazan, coffee delivery in Skolkovo Innovation Center, [autonomous quadcopter with charging station](https://www.youtube.com/watch?v=RjX6nUqw1mI) for site monitoring and security, winning drones on [Robocross-2016](https://www.youtube.com/watch?v=dGbDaz_VmYU) and [Robocross-2017](https://youtu.be/AQnd2CRczbQ) competitions and many others.
|
||||
The main documentation is available [on Gitbook](https://clover.coex.tech/).
|
||||
|
||||
**The main documentation is available [on Gitbook](https://clever.coex.tech/).**
|
||||
Official website: <a href="https://coex.tech/clover">coex.tech/clover</a>.
|
||||
|
||||
Use it to learn how to assemble, configure, pilot and program autonomous CLEVER drone.
|
||||
## Video compilation
|
||||
|
||||
[](https://youtu.be/u3omgsYC4Fk)
|
||||
|
||||
Clover drone is used on a wide range of educational events, including [Copter Hack](https://www.youtube.com/watch?v=xgXheg3TTs4), WorldSkills Drone Operation competition, [Autonomous Vehicles Track of NTI Olympics 2016–2020](https://www.youtube.com/watch?v=E1_ehvJRKxg), Quadro Hack 2019 (National University of Science and Technology MISiS), Russian Robot Olympiad (autonomous flights), and others.
|
||||
|
||||
## Raspberry Pi image
|
||||
|
||||
**Preconfigured image for Raspberry Pi 3 with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clever/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/clever)
|
||||
[](https://travis-ci.org/CopterExpress/clover)
|
||||
|
||||
Image includes:
|
||||
Image features:
|
||||
|
||||
* Raspbian Buster
|
||||
* ROS Melodic
|
||||
* [ROS Melodic](http://wiki.ros.org/melodic)
|
||||
* Configured networking
|
||||
* OpenCV
|
||||
* mavros
|
||||
* Periphery drivers (`pigpiod`, `rpi_ws281x`, etc)
|
||||
* CLEVER software bundle for autonomous drone control
|
||||
* [`mavros`](http://wiki.ros.org/mavros)
|
||||
* Periphery drivers for ROS ([GPIO](https://clover.coex.tech/en/gpio.html), [LED strip](https://clover.coex.tech/en/leds.html), etc)
|
||||
* `aruco_pose` package for marker-assisted navigation
|
||||
* `clover` package for autonomous drone control
|
||||
|
||||
API description (in Russian) for autonomous flights is available [on GitBook](https://clever.coex.tech/simple_offboard.html).
|
||||
API description for autonomous flights is available [on GitBook](https://clover.coex.tech/en/simple_offboard.html).
|
||||
|
||||
## Manual installation
|
||||
|
||||
Install ROS Melodic according to the [documentation](http://wiki.ros.org/melodic/Installation), then [create a Catkin workspace](http://wiki.ros.org/catkin/Tutorials/create_a_workspace).
|
||||
|
||||
Clone this repo to directory `~/catkin_ws/src/clever`:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/src
|
||||
git clone https://github.com/CopterExpress/clever.git clever
|
||||
```
|
||||
|
||||
All the required ROS packages (including `mavros` and `opencv`) can be installed using `rosdep`:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/
|
||||
rosdep install -y --from-paths src --ignore-src
|
||||
```
|
||||
|
||||
Build ROS packages (on memory constrained platforms you might be going to need to use `-j1` key):
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws
|
||||
catkin_make -j1
|
||||
```
|
||||
|
||||
To complete `mavros` install you'll need to install `geographiclib` datasets:
|
||||
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh | sudo bash
|
||||
```
|
||||
|
||||
You may optionally install udev rules to provide `/dev/px4fmu` symlink to your PX4-based flight controller connected over USB. Copy `99-px4fmu.rules` to your `/lib/udev/rules.d` folder:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/src/clever/clever/config
|
||||
sudo cp 99-px4fmu.rules /lib/udev/rules.d
|
||||
```
|
||||
|
||||
Alternatively you may change the `fcu_url` property in `mavros.launch` file to point to your flight controller device.
|
||||
|
||||
## Running
|
||||
|
||||
Enable systemd service `roscore` (if not running):
|
||||
|
||||
```bash
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clever/builder/assets/roscore.service
|
||||
sudo systemctl start roscore
|
||||
```
|
||||
|
||||
To start connection to SITL, use:
|
||||
|
||||
```bash
|
||||
roslaunch clever sitl.launch
|
||||
```
|
||||
|
||||
To start connection to the flight controller, use:
|
||||
|
||||
```bash
|
||||
roslaunch clever clever.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`.
|
||||
|
||||
Also, you can enable and start the systemd service:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clever/deploy/clever.service
|
||||
sudo systemctl start clever
|
||||
```
|
||||
For manual package installation and running see [`clover` package documentation](clover/README.md).
|
||||
|
||||
## License
|
||||
|
||||
While the Clever 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.
|
||||
|
||||
@@ -21,6 +21,7 @@ find_package(catkin REQUIRED COMPONENTS
|
||||
tf2_geometry_msgs
|
||||
sensor_msgs
|
||||
message_generation
|
||||
dynamic_reconfigure
|
||||
)
|
||||
|
||||
find_package(OpenCV 3 REQUIRED COMPONENTS core imgproc calib3d)
|
||||
@@ -111,10 +112,9 @@ generate_messages(
|
||||
## and list every .cfg file to be processed
|
||||
|
||||
## Generate dynamic reconfigure parameters in the 'cfg' folder
|
||||
# generate_dynamic_reconfigure_options(
|
||||
# cfg/DynReconf1.cfg
|
||||
# cfg/DynReconf2.cfg
|
||||
# )
|
||||
generate_dynamic_reconfigure_options(
|
||||
cfg/DetectorParams.cfg
|
||||
)
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
@@ -151,7 +151,7 @@ add_library(aruco_pose
|
||||
src/draw.cpp
|
||||
)
|
||||
|
||||
add_dependencies(${PROJECT_NAME} aruco_pose_generate_messages_cpp)
|
||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_generate_messages_cpp ${PROJECT_NAME}_gencfg)
|
||||
|
||||
## Declare a C++ executable
|
||||
## With catkin_make all packages are built within a single CMake context
|
||||
|
||||
107
aruco_pose/cfg/DetectorParams.cfg
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python
|
||||
PACKAGE = "aruco_pose"
|
||||
|
||||
from dynamic_reconfigure.parameter_generator_catkin import *
|
||||
import cv2.aruco
|
||||
|
||||
p = cv2.aruco.DetectorParameters_create()
|
||||
|
||||
gen = ParameterGenerator()
|
||||
|
||||
gen.add("adaptiveThreshConstant", double_t, 0,
|
||||
"Constant for adaptive thresholding before finding contours",
|
||||
p.adaptiveThreshConstant, 0, 100)
|
||||
|
||||
gen.add("adaptiveThreshWinSizeMin", int_t, 0,
|
||||
"Minimum window size for adaptive thresholding before finding contours",
|
||||
p.adaptiveThreshWinSizeMin, 1, 100)
|
||||
|
||||
gen.add("adaptiveThreshWinSizeMax", int_t, 0,
|
||||
"Maximum window size for adaptive thresholding before finding contours",
|
||||
p.adaptiveThreshWinSizeMax, 1, 100)
|
||||
|
||||
gen.add("adaptiveThreshWinSizeStep", int_t, 0,
|
||||
"Increments from adaptiveThreshWinSizeMin to adaptiveThreshWinSizeMax during the thresholding",
|
||||
p.adaptiveThreshWinSizeStep, 1, 100)
|
||||
|
||||
gen.add("cornerRefinementMaxIterations", int_t, 0,
|
||||
"Maximum number of iterations for stop criteria of the corner refinement process",
|
||||
p.cornerRefinementMaxIterations, 1, 1000)
|
||||
|
||||
corner_refine_enum = gen.enum([ gen.const("CORNER_REFINE_NONE", int_t, 0, "No refinement"),
|
||||
gen.const("CORNER_REFINE_SUBPIX", int_t, 1, "Do subpixel refinement"),
|
||||
gen.const("CORNER_REFINE_CONTOUR", int_t, 2, "Use contour-Points"),
|
||||
gen.const("CORNER_REFINE_APRILTAG", int_t, 3, "Use the AprilTag2 approach")],
|
||||
"An enum to set corner refinement method")
|
||||
|
||||
gen.add("cornerRefinementMethod", int_t, 0, "Corner refinement method", 0, 0, 3, edit_method=corner_refine_enum)
|
||||
|
||||
gen.add("cornerRefinementMinAccuracy", double_t, 0,
|
||||
"Minimum error for the stop criteria of the corner refinement process",
|
||||
p.cornerRefinementMinAccuracy, 0, 1)
|
||||
|
||||
gen.add("cornerRefinementWinSize", int_t, 0,
|
||||
"Window size for the corner refinement process (in pixels)",
|
||||
p.cornerRefinementWinSize, 1, 100)
|
||||
|
||||
gen.add("detectInvertedMarker", bool_t, 0,
|
||||
"check if there is a white marker. In order to generate a 'white' marker just invert a normal marker by using a tilde",
|
||||
False)
|
||||
|
||||
gen.add("errorCorrectionRate", double_t, 0,
|
||||
"Error correction rate respect to the maximum error correction capability for each dictionary",
|
||||
p.errorCorrectionRate, 0, 1)
|
||||
|
||||
gen.add("minCornerDistanceRate", double_t, 0,
|
||||
"Minimum distance between corners for detected markers relative to its perimeter",
|
||||
p.minCornerDistanceRate, 0, 0.25)
|
||||
|
||||
gen.add("markerBorderBits", int_t, 0,
|
||||
"Number of bits of the marker border, i.e. marker border width",
|
||||
p.markerBorderBits, 1, 10)
|
||||
|
||||
gen.add("maxErroneousBitsInBorderRate", double_t, 0,
|
||||
"Maximum number of accepted erroneous bits in the border (i.e. number of allowed white bits in the border)",
|
||||
p.maxErroneousBitsInBorderRate, 0, 1)
|
||||
|
||||
gen.add("minDistanceToBorder", int_t, 0,
|
||||
"Minimum distance of any corner to the image border for detected markers (in pixels)",
|
||||
p.minDistanceToBorder, 0, 1000)
|
||||
|
||||
gen.add("minMarkerDistanceRate", double_t, 0,
|
||||
"minimum mean distance beetween two marker corners to be considered similar, so that the smaller one is removed. The rate is relative to the smaller perimeter of the two markers",
|
||||
p.minMarkerDistanceRate, 0, 1)
|
||||
|
||||
gen.add("minMarkerPerimeterRate", double_t, 0,
|
||||
"Determine minimum perimeter for marker contour to be detected. This is defined as a rate respect to the maximum dimension of the input image",
|
||||
p.minMarkerPerimeterRate, 0, 4)
|
||||
|
||||
gen.add("maxMarkerPerimeterRate", double_t, 0,
|
||||
"Determine maximum perimeter for marker contour to be detected. This is defined as a rate respect to the maximum dimension of the input image",
|
||||
p.maxMarkerPerimeterRate, 0, 4)
|
||||
|
||||
gen.add("minOtsuStdDev", double_t, 0,
|
||||
"Minimun standard deviation in pixels values during the decodification step to apply Otsu thresholding (otherwise, all the bits are set to 0 or 1 depending on mean higher than 128 or not)",
|
||||
p.minOtsuStdDev, 0, 100)
|
||||
|
||||
gen.add("perspectiveRemoveIgnoredMarginPerCell", double_t, 0,
|
||||
"Width of the margin of pixels on each cell not considered for the determination of the cell bit. Represents the rate respect to the total size of the cell, i.e. perpectiveRemovePixelPerCell",
|
||||
p.perspectiveRemoveIgnoredMarginPerCell, 0, 1)
|
||||
|
||||
gen.add("perspectiveRemovePixelPerCell", int_t, 0,
|
||||
"Number of bits (per dimension) for each cell of the marker when removing the perspective",
|
||||
p.perspectiveRemovePixelPerCell, 1, 100)
|
||||
|
||||
gen.add("polygonalApproxAccuracyRate", double_t, 0,
|
||||
"Minimum accuracy during the polygonal approximation process to determine which contours are squares",
|
||||
p.polygonalApproxAccuracyRate, 0, 1)
|
||||
|
||||
gen.add("aprilTagQuadDecimate", double_t, 0,
|
||||
"Detection of quads can be done on a lower-resolution image, improving speed at a cost of pose accuracy and a slight decrease in detection rate. Decoding the binary payload is still done at full resolution",
|
||||
0, 0, 1000)
|
||||
|
||||
gen.add("aprilTagQuadSigma", double_t, 0,
|
||||
"What Gaussian blur should be applied to the segmented image (used for quad detection?) Parameter is the standard deviation in pixels. Very noisy images benefit from non-zero values",
|
||||
0, 0, 1000)
|
||||
|
||||
exit(gen.generate(PACKAGE, "aruco_pose", "Detector"))
|
||||
@@ -1,3 +1,4 @@
|
||||
# id length x y z rot_z rot_y rot_x
|
||||
1 0.33 0 0 0 0 0 0
|
||||
2 0.33 1 0 0 0 0 0
|
||||
3 0.33 0 1 0 0 0 0
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
<depend>tf2</depend>
|
||||
<depend>tf2_ros</depend>
|
||||
<depend>tf2_geometry_msgs</depend>
|
||||
<!-- FIXME: OpenCV3 is not in Melodic -->
|
||||
<!-- <depend>opencv3</depend> -->
|
||||
<depend>cv_bridge</depend>
|
||||
<depend>image_transport</depend>
|
||||
<depend>message_generation</depend>
|
||||
@@ -29,6 +27,7 @@
|
||||
<depend>visualization_msgs</depend>
|
||||
<depend>sensor_msgs</depend>
|
||||
<depend>rostest</depend>
|
||||
<depend>dynamic_reconfigure</depend>
|
||||
|
||||
<test_depend>image_publisher</test_depend>
|
||||
<test_depend>ros_pytest</test_depend>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
|
||||
#include <image_transport/image_transport.h>
|
||||
#include <cv_bridge/cv_bridge.h>
|
||||
#include <dynamic_reconfigure/server.h>
|
||||
#include <geometry_msgs/Vector3.h>
|
||||
#include <geometry_msgs/Pose.h>
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
@@ -46,8 +47,11 @@
|
||||
|
||||
#include <aruco_pose/Marker.h>
|
||||
#include <aruco_pose/MarkerArray.h>
|
||||
#include <aruco_pose/DetectorConfig.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
using std::vector;
|
||||
using cv::Mat;
|
||||
@@ -58,6 +62,7 @@ private:
|
||||
tf2_ros::TransformBroadcaster br_;
|
||||
tf2_ros::Buffer tf_buffer_;
|
||||
tf2_ros::TransformListener tf_listener_{tf_buffer_};
|
||||
std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>> dyn_srv_;
|
||||
cv::Ptr<cv::aruco::Dictionary> dictionary_;
|
||||
cv::Ptr<cv::aruco::DetectorParameters> parameters_;
|
||||
image_transport::Publisher debug_pub_;
|
||||
@@ -110,6 +115,12 @@ public:
|
||||
vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1);
|
||||
img_sub_ = it.subscribeCamera("image_raw", 1, &ArucoDetect::imageCallback, this);
|
||||
|
||||
dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>>(nh_priv_);
|
||||
dynamic_reconfigure::Server<aruco_pose::DetectorConfig>::CallbackType cb;
|
||||
|
||||
cb = std::bind(&ArucoDetect::paramCallback, this, std::placeholders::_1, std::placeholders::_2);
|
||||
dyn_srv_->setCallback(cb);
|
||||
|
||||
NODELET_INFO("ready");
|
||||
}
|
||||
|
||||
@@ -341,6 +352,37 @@ private:
|
||||
map_markers_ids_.insert(marker.id);
|
||||
}
|
||||
}
|
||||
|
||||
void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level)
|
||||
{
|
||||
parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant;
|
||||
parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin;
|
||||
parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax;
|
||||
parameters_->adaptiveThreshWinSizeStep = config.adaptiveThreshWinSizeStep;
|
||||
parameters_->cornerRefinementMaxIterations = config.cornerRefinementMaxIterations;
|
||||
parameters_->cornerRefinementMethod = config.cornerRefinementMethod;
|
||||
parameters_->cornerRefinementMinAccuracy = config.cornerRefinementMinAccuracy;
|
||||
parameters_->cornerRefinementWinSize = config.cornerRefinementWinSize;
|
||||
#if ((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR >= 4) && (CV_VERSION_REVISION >= 7)) || (CV_VERSION_MAJOR > 3)
|
||||
parameters_->detectInvertedMarker = config.detectInvertedMarker;
|
||||
#endif
|
||||
parameters_->errorCorrectionRate = config.errorCorrectionRate;
|
||||
parameters_->minCornerDistanceRate = config.minCornerDistanceRate;
|
||||
parameters_->markerBorderBits = config.markerBorderBits;
|
||||
parameters_->maxErroneousBitsInBorderRate = config.maxErroneousBitsInBorderRate;
|
||||
parameters_->minDistanceToBorder = config.minDistanceToBorder;
|
||||
parameters_->minMarkerDistanceRate = config.minMarkerDistanceRate;
|
||||
parameters_->minMarkerPerimeterRate = config.minMarkerPerimeterRate;
|
||||
parameters_->maxMarkerPerimeterRate = config.maxMarkerPerimeterRate;
|
||||
parameters_->minOtsuStdDev = config.minOtsuStdDev;
|
||||
parameters_->perspectiveRemoveIgnoredMarginPerCell = config.perspectiveRemoveIgnoredMarginPerCell;
|
||||
parameters_->perspectiveRemovePixelPerCell = config.perspectiveRemovePixelPerCell;
|
||||
parameters_->polygonalApproxAccuracyRate = config.polygonalApproxAccuracyRate;
|
||||
#if ((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR >= 4) && (CV_VERSION_REVISION >= 2)) || (CV_VERSION_MAJOR > 3)
|
||||
parameters_->aprilTagQuadDecimate = config.aprilTagQuadDecimate;
|
||||
parameters_->aprilTagQuadSigma = config.aprilTagQuadSigma;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
PLUGINLIB_EXPORT_CLASS(ArucoDetect, nodelet::Nodelet)
|
||||
|
||||
@@ -394,7 +394,7 @@ publish_debug:
|
||||
int num_markers = board_->dictionary->bytesList.rows;
|
||||
if (num_markers <= id) {
|
||||
NODELET_ERROR("Marker id %d is not in dictionary; current dictionary contains %d markers. "
|
||||
"Please see https://github.com/CopterExpress/clever/blob/master/aruco_pose/README.md#parameters for details",
|
||||
"Please see https://github.com/CopterExpress/clover/blob/master/aruco_pose/README.md#parameters for details",
|
||||
id, num_markers);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,17 +13,21 @@
|
||||
Generate map file for aruco_map nodelet.
|
||||
|
||||
Usage:
|
||||
genmap.py <length> <x> <y> <dist_x> <dist_y> <first> [--top-left]
|
||||
genmap.py <length> <x> <y> <dist_x> <dist_y> [<first>] [--top-left | --bottom-left]
|
||||
genmap.py (-h | --help)
|
||||
|
||||
Options:
|
||||
<length> Marker side length
|
||||
<x> Marker count along X axis
|
||||
<y> Marker count along Y axis
|
||||
<dist_x> Distance between markers along X axis
|
||||
<dist_y> Distance between markers along Y axis
|
||||
<first> First marker ID
|
||||
--top-left First marker is on top-left (not bottom-left)
|
||||
<length> Marker side length
|
||||
<x> Marker count along X axis
|
||||
<y> Marker count along Y axis
|
||||
<dist_x> Distance between markers along X axis
|
||||
<dist_y> Distance between markers along Y axis
|
||||
<first> First marker ID [default: 0]
|
||||
--top-left First marker is on top-left (default)
|
||||
--bottom-left First marker is on bottom-left
|
||||
|
||||
Example:
|
||||
rosrun aruco_pose genmap.py 0.33 2 4 1 1 0 > $(catkin_find aruco_pose map)/test_map.txt
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
@@ -34,20 +38,21 @@ from docopt import docopt
|
||||
arguments = docopt(__doc__)
|
||||
|
||||
length = float(arguments['<length>'])
|
||||
first = int(arguments['<first>'])
|
||||
first = int(arguments['<first>'] if arguments['<first>'] is not None else 0)
|
||||
markers_x = int(arguments['<x>'])
|
||||
markers_y = int(arguments['<y>'])
|
||||
dist_x = float(arguments['<dist_x>'])
|
||||
dist_y = float(arguments['<dist_y>'])
|
||||
top_left = arguments['--top-left']
|
||||
bottom_left = arguments['--bottom-left']
|
||||
|
||||
max_y = (markers_y - 1) * dist_y
|
||||
|
||||
print('# id\tlength\tx\ty\tz\trot_z\trot_y\trot_x')
|
||||
for y in range(markers_y):
|
||||
for x in range(markers_x):
|
||||
pos_x = x * dist_x
|
||||
pos_y = y * dist_y
|
||||
if top_left:
|
||||
if not bottom_left:
|
||||
pos_y = max_y - pos_y
|
||||
print('{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t'.format(first, length, pos_x, pos_y, 0, 0, 0, 0))
|
||||
first += 1
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<param name="length_override/3" value="0.1"/>
|
||||
<param name="estimate_poses" value="true"/>
|
||||
<param name="send_tf" value="true"/>
|
||||
<param name="cornerRefinementMethod" value="1"/>
|
||||
</node>
|
||||
|
||||
<node name="aruco_map" pkg="nodelet" type="nodelet" args="load aruco_pose/aruco_map nodelet_manager" clear_params="true" required="true">
|
||||
|
||||
12
book.json
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "Clever",
|
||||
"title": "Clover",
|
||||
"description": "Конструктор квадрокоптера «Клевер»",
|
||||
"author": "Copter Express",
|
||||
"language": "en",
|
||||
@@ -28,7 +28,7 @@
|
||||
"blank": true
|
||||
},
|
||||
"sitemap": {
|
||||
"hostname": "https://clever.coex.tech"
|
||||
"hostname": "https://clover.coex.tech"
|
||||
},
|
||||
"toolbar": {
|
||||
"buttons":
|
||||
@@ -37,19 +37,19 @@
|
||||
"label": "Edit page on github",
|
||||
"icon": "fa fa-pencil-square-o",
|
||||
"position" : "left",
|
||||
"url": "https://github.com/CopterExpress/clever/edit/master/docs/{{filepath_lang}}"
|
||||
"url": "https://github.com/CopterExpress/clover/edit/master/docs/{{filepath_lang}}"
|
||||
},
|
||||
{
|
||||
"label": "GitHub",
|
||||
"icon": "fa fa-github",
|
||||
"position" : "left",
|
||||
"url": "https://github.com/CopterExpress/clever"
|
||||
"url": "https://github.com/CopterExpress/clover"
|
||||
}
|
||||
]
|
||||
},
|
||||
"addcssjs": {
|
||||
"css": ["../clever.css"],
|
||||
"js": ["../clever.js"]
|
||||
"css": ["../clover.css"],
|
||||
"js": ["../clover.js"]
|
||||
},
|
||||
"language-picker": {
|
||||
"languages": [["ru", "Russian"], ["en", "English"]]
|
||||
|
||||
0
builder/assets/clever/clever/__init__.py
Normal file
3
builder/assets/clever/clever/srv.py
Normal file
@@ -0,0 +1,3 @@
|
||||
print("Warning: clever package is renamed to clover")
|
||||
|
||||
from clover.srv import *
|
||||
10
builder/assets/clever/setup.py
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(name='clever',
|
||||
version='1.0',
|
||||
description='Clever transitional package for backwards compatibility',
|
||||
author='Oleg Kalachev',
|
||||
packages=['clever'],
|
||||
)
|
||||
@@ -1,12 +1,12 @@
|
||||
[Unit]
|
||||
Description=Clever ROS package
|
||||
Description=Clover ROS package
|
||||
Requires=roscore.service
|
||||
|
||||
[Service]
|
||||
User=pi
|
||||
ExecStart=/bin/bash -c ". /home/pi/catkin_ws/devel/setup.sh; \
|
||||
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clever clever.launch --wait --screen --skip-log-check \
|
||||
2> >(tee /tmp/clever.err)"
|
||||
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clover clover.launch --wait --screen --skip-log-check \
|
||||
2> >(tee /tmp/clover.err)"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
31
builder/assets/examples/flight.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Information: https://clover.coex.tech/programming
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
from std_srvs.srv import Trigger
|
||||
|
||||
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)
|
||||
|
||||
# Take off and hover 1 m above the ground
|
||||
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
||||
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
# Fly forward 1 m
|
||||
navigate(x=1, y=0, z=0, frame_id='body')
|
||||
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
# Perform landing
|
||||
land()
|
||||
37
builder/assets/examples/flight_marker.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Information: https://clover.coex.tech/en/aruco.html
|
||||
|
||||
import rospy
|
||||
from clover import srv
|
||||
from std_srvs.srv import Trigger
|
||||
|
||||
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)
|
||||
|
||||
# Take off and hover 1 m above the ground
|
||||
navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
|
||||
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
# Fly 1 meter above ArUco marker 0
|
||||
navigate(x=0, y=0, z=1, frame_id='aruco_0')
|
||||
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
# Fly to x=1 y=1 z=1 relative to ArUco markers map
|
||||
navigate(x=1, y=1, z=1, frame_id='aruco_map')
|
||||
|
||||
# Wait for 3 seconds
|
||||
rospy.sleep(3)
|
||||
|
||||
# Perform landing
|
||||
land()
|
||||
25
builder/assets/examples/leds.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Information: https://clover.coex.tech/en/leds.html
|
||||
|
||||
import rospy
|
||||
from clover.srv import SetLEDEffect
|
||||
|
||||
rospy.init_node('leds')
|
||||
|
||||
set_effect = rospy.ServiceProxy('led/set_effect', SetLEDEffect) # define proxy to ROS-service
|
||||
|
||||
set_effect(r=255, g=0, b=0) # fill strip with red color
|
||||
rospy.sleep(2)
|
||||
|
||||
set_effect(r=0, g=100, b=0) # fill strip with green color
|
||||
rospy.sleep(2)
|
||||
|
||||
set_effect(effect='fade', r=0, g=0, b=255) # fade to blue color
|
||||
rospy.sleep(2)
|
||||
|
||||
set_effect(effect='flash', r=255, g=0, b=0) # flash twice with red color
|
||||
rospy.sleep(5)
|
||||
|
||||
set_effect(effect='blink', r=255, g=255, b=255) # blink with white color
|
||||
rospy.sleep(5)
|
||||
|
||||
set_effect(effect='rainbow') # show rainbow
|
||||
41
builder/assets/examples/navigate_wait.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# Information: https://clover.coex.tech/en/snippets.html#block-nav
|
||||
|
||||
import math
|
||||
import rospy
|
||||
from clover import srv
|
||||
from std_srvs.srv import Trigger
|
||||
|
||||
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)
|
||||
|
||||
def navigate_wait(x=0, y=0, z=0, yaw=float('nan'), yaw_rate=0, speed=0.5, \
|
||||
frame_id='body', tolerance=0.2, auto_arm=False):
|
||||
|
||||
res = navigate(x=x, y=y, z=z, yaw=yaw, yaw_rate=yaw_rate, speed=speed, \
|
||||
frame_id=frame_id, auto_arm=auto_arm)
|
||||
|
||||
if not res.success:
|
||||
return res
|
||||
|
||||
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:
|
||||
return res
|
||||
rospy.sleep(0.2)
|
||||
|
||||
# Take off 1 meter
|
||||
navigate_wait(z=1, frame_id='body', auto_arm=True)
|
||||
|
||||
# Fly forward 1 m
|
||||
navigate_wait(x=1, frame_id='body')
|
||||
|
||||
# Land
|
||||
land()
|
||||
@@ -35,9 +35,26 @@ echo_stamp() {
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
NEW_SSID='CLEVER-'$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e "s/[^0-9]//g" | cut -c 1-4)
|
||||
NEW_SSID='clover-'$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e "s/[^0-9]//g" | cut -c 1-4)
|
||||
echo_stamp "Setting SSID to ${NEW_SSID}"
|
||||
sudo sed -i.OLD "s/CLEVER/${NEW_SSID}/" /etc/wpa_supplicant/wpa_supplicant.conf
|
||||
# TODO: Use wpa_cli insted direct file edit
|
||||
# FIXME: We rely on raspberrypi-net-mods to copy our file to /etc/wpa_supplicant.
|
||||
# This is not very reliable, but seems to fix our rfkill problem.
|
||||
cat << EOF >> /boot/wpa_supplicant.conf
|
||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
|
||||
update_config=1
|
||||
country=GB
|
||||
network={
|
||||
ssid="${NEW_SSID}"
|
||||
psk="cloverwifi"
|
||||
mode=2
|
||||
proto=WPA RSN
|
||||
key_mgmt=WPA-PSK
|
||||
pairwise=CCMP
|
||||
group=CCMP
|
||||
auth_alg=OPEN
|
||||
}
|
||||
EOF
|
||||
|
||||
NEW_HOSTNAME=$(echo ${NEW_SSID} | tr '[:upper:]' '[:lower:]')
|
||||
echo_stamp "Setting hostname to $NEW_HOSTNAME"
|
||||
@@ -45,6 +62,10 @@ hostnamectl set-hostname $NEW_HOSTNAME
|
||||
sed -i 's/127\.0\.1\.1.*/127.0.1.1\t'${NEW_HOSTNAME}' '${NEW_HOSTNAME}'.local/g' /etc/hosts
|
||||
# .local (mdns) hostname added to make it accesable when wlan and ethernet interfaces are down
|
||||
|
||||
echo_stamp "Enable ROS services"
|
||||
systemctl enable roscore
|
||||
systemctl enable clover
|
||||
|
||||
echo_stamp "Harware setup"
|
||||
/root/hardware_setup.sh
|
||||
|
||||
|
||||
735
builder/assets/melodic-rosdep-clover.yaml
Normal file
@@ -0,0 +1,735 @@
|
||||
catkin:
|
||||
debian:
|
||||
buster: [ros-melodic-catkin]
|
||||
genmsg:
|
||||
debian:
|
||||
buster: [ros-melodic-genmsg]
|
||||
gencpp:
|
||||
debian:
|
||||
buster: [ros-melodic-gencpp]
|
||||
geneus:
|
||||
debian:
|
||||
buster: [ros-melodic-geneus]
|
||||
genlisp:
|
||||
debian:
|
||||
buster: [ros-melodic-genlisp]
|
||||
gennodejs:
|
||||
debian:
|
||||
buster: [ros-melodic-gennodejs]
|
||||
genpy:
|
||||
debian:
|
||||
buster: [ros-melodic-genpy]
|
||||
bond_core:
|
||||
debian:
|
||||
buster: [ros-melodic-bond-core]
|
||||
cmake_modules:
|
||||
debian:
|
||||
buster: [ros-melodic-cmake-modules]
|
||||
class_loader:
|
||||
debian:
|
||||
buster: [ros-melodic-class-loader]
|
||||
common_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-common-msgs]
|
||||
common_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-common-tutorials]
|
||||
cpp_common:
|
||||
debian:
|
||||
buster: [ros-melodic-cpp-common]
|
||||
desktop:
|
||||
debian:
|
||||
buster: [ros-melodic-desktop]
|
||||
diagnostics:
|
||||
debian:
|
||||
buster: [ros-melodic-diagnostics]
|
||||
executive_smach:
|
||||
debian:
|
||||
buster: [ros-melodic-executive-smach]
|
||||
geometry:
|
||||
debian:
|
||||
buster: [ros-melodic-geometry]
|
||||
geometry_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-geometry-tutorials]
|
||||
gl_dependency:
|
||||
debian:
|
||||
buster: [ros-melodic-gl-dependency]
|
||||
image_common:
|
||||
debian:
|
||||
buster: [ros-melodic-image-common]
|
||||
image_pipeline:
|
||||
debian:
|
||||
buster: [ros-melodic-image-pipeline]
|
||||
image_transport_plugins:
|
||||
debian:
|
||||
buster: [ros-melodic-image-transport-plugins]
|
||||
laser_pipeline:
|
||||
debian:
|
||||
buster: [ros-melodic-laser-pipeline]
|
||||
mavlink:
|
||||
debian:
|
||||
buster: [ros-melodic-mavlink]
|
||||
media_export:
|
||||
debian:
|
||||
buster: [ros-melodic-media-export]
|
||||
message_generation:
|
||||
debian:
|
||||
buster: [ros-melodic-message-generation]
|
||||
message_runtime:
|
||||
debian:
|
||||
buster: [ros-melodic-message-runtime]
|
||||
mk:
|
||||
debian:
|
||||
buster: [ros-melodic-mk]
|
||||
nodelet_core:
|
||||
debian:
|
||||
buster: [ros-melodic-nodelet-core]
|
||||
orocos_kdl:
|
||||
debian:
|
||||
buster: [ros-melodic-orocos-kdl]
|
||||
perception:
|
||||
debian:
|
||||
buster: [ros-melodic-perception]
|
||||
perception_pcl:
|
||||
debian:
|
||||
buster: [ros-melodic-perception-pcl]
|
||||
python_orocos_kdl:
|
||||
debian:
|
||||
buster: [ros-melodic-python-orocos-kdl]
|
||||
qt_dotgraph:
|
||||
debian:
|
||||
buster: [ros-melodic-qt-dotgraph]
|
||||
qt_gui:
|
||||
debian:
|
||||
buster: [ros-melodic-qt-gui]
|
||||
qt_gui_py_common:
|
||||
debian:
|
||||
buster: [ros-melodic-qt-gui-py-common]
|
||||
qwt_dependency:
|
||||
debian:
|
||||
buster: [ros-melodic-qwt-dependency]
|
||||
robot:
|
||||
debian:
|
||||
buster: [ros-melodic-robot]
|
||||
ros:
|
||||
debian:
|
||||
buster: [ros-melodic-ros]
|
||||
ros_base:
|
||||
debian:
|
||||
buster: [ros-melodic-ros-base]
|
||||
ros_comm:
|
||||
debian:
|
||||
buster: [ros-melodic-ros-comm]
|
||||
ros_core:
|
||||
debian:
|
||||
buster: [ros-melodic-ros-core]
|
||||
ros_environment:
|
||||
debian:
|
||||
buster: [ros-melodic-ros-environment]
|
||||
ros_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-ros-tutorials]
|
||||
rosapi:
|
||||
debian:
|
||||
buster: [ros-melodic-rosapi]
|
||||
rosbag_migration_rule:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbag-migration-rule]
|
||||
rosbash:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbash]
|
||||
rosboost_cfg:
|
||||
debian:
|
||||
buster: [ros-melodic-rosboost-cfg]
|
||||
rosbridge_server:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbridge-server]
|
||||
rosbridge_suite:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbridge-suite]
|
||||
rosbuild:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbuild]
|
||||
rosclean:
|
||||
debian:
|
||||
buster: [ros-melodic-rosclean]
|
||||
roscpp_core:
|
||||
debian:
|
||||
buster: [ros-melodic-roscpp-core]
|
||||
roscpp_traits:
|
||||
debian:
|
||||
buster: [ros-melodic-roscpp-traits]
|
||||
roscreate:
|
||||
debian:
|
||||
buster: [ros-melodic-roscreate]
|
||||
rosgraph:
|
||||
debian:
|
||||
buster: [ros-melodic-rosgraph]
|
||||
roslang:
|
||||
debian:
|
||||
buster: [ros-melodic-roslang]
|
||||
roslint:
|
||||
debian:
|
||||
buster: [ros-melodic-roslint]
|
||||
roslisp:
|
||||
debian:
|
||||
buster: [ros-melodic-roslisp]
|
||||
rosmake:
|
||||
debian:
|
||||
buster: [ros-melodic-rosmake]
|
||||
rosmaster:
|
||||
debian:
|
||||
buster: [ros-melodic-rosmaster]
|
||||
rospack:
|
||||
debian:
|
||||
buster: [ros-melodic-rospack]
|
||||
roslib:
|
||||
debian:
|
||||
buster: [ros-melodic-roslib]
|
||||
rosparam:
|
||||
debian:
|
||||
buster: [ros-melodic-rosparam]
|
||||
rospy:
|
||||
debian:
|
||||
buster: [ros-melodic-rospy]
|
||||
rosserial:
|
||||
debian:
|
||||
buster: [ros-melodic-rosserial]
|
||||
rosserial_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-rosserial-msgs]
|
||||
rosserial_python:
|
||||
debian:
|
||||
buster: [ros-melodic-rosserial-python]
|
||||
rosservice:
|
||||
debian:
|
||||
buster: [ros-melodic-rosservice]
|
||||
rostime:
|
||||
debian:
|
||||
buster: [ros-melodic-rostime]
|
||||
roscpp_serialization:
|
||||
debian:
|
||||
buster: [ros-melodic-roscpp-serialization]
|
||||
python_qt_binding:
|
||||
debian:
|
||||
buster: [ros-melodic-python-qt-binding]
|
||||
roslaunch:
|
||||
debian:
|
||||
buster: [ros-melodic-roslaunch]
|
||||
rosunit:
|
||||
debian:
|
||||
buster: [ros-melodic-rosunit]
|
||||
angles:
|
||||
debian:
|
||||
buster: [ros-melodic-angles]
|
||||
libmavconn:
|
||||
debian:
|
||||
buster: [ros-melodic-libmavconn]
|
||||
rosconsole:
|
||||
debian:
|
||||
buster: [ros-melodic-rosconsole]
|
||||
pluginlib:
|
||||
debian:
|
||||
buster: [ros-melodic-pluginlib]
|
||||
qt_gui_cpp:
|
||||
debian:
|
||||
buster: [ros-melodic-qt-gui-cpp]
|
||||
resource_retriever:
|
||||
debian:
|
||||
buster: [ros-melodic-resource-retriever]
|
||||
rosconsole_bridge:
|
||||
debian:
|
||||
buster: [ros-melodic-rosconsole-bridge]
|
||||
roslz4:
|
||||
debian:
|
||||
buster: [ros-melodic-roslz4]
|
||||
rosserial_client:
|
||||
debian:
|
||||
buster: [ros-melodic-rosserial-client]
|
||||
rostest:
|
||||
debian:
|
||||
buster: [ros-melodic-rostest]
|
||||
rqt_action:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-action]
|
||||
rqt_bag:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-bag]
|
||||
rqt_bag_plugins:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-bag-plugins]
|
||||
rqt_common_plugins:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-common-plugins]
|
||||
rqt_console:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-console]
|
||||
rqt_dep:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-dep]
|
||||
rqt_graph:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-graph]
|
||||
rqt_gui:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-gui]
|
||||
rqt_logger_level:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-logger-level]
|
||||
rqt_moveit:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-moveit]
|
||||
rqt_msg:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-msg]
|
||||
rqt_nav_view:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-nav-view]
|
||||
rqt_plot:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-plot]
|
||||
rqt_pose_view:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-pose-view]
|
||||
rqt_publisher:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-publisher]
|
||||
rqt_py_console:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-py-console]
|
||||
rqt_reconfigure:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-reconfigure]
|
||||
rqt_robot_dashboard:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-robot-dashboard]
|
||||
rqt_robot_monitor:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-robot-monitor]
|
||||
rqt_robot_plugins:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-robot-plugins]
|
||||
rqt_robot_steering:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-robot-steering]
|
||||
rqt_runtime_monitor:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-runtime-monitor]
|
||||
rqt_service_caller:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-service-caller]
|
||||
rqt_shell:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-shell]
|
||||
rqt_srv:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-srv]
|
||||
rqt_tf_tree:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-tf-tree]
|
||||
rqt_top:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-top]
|
||||
rqt_topic:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-topic]
|
||||
rqt_web:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-web]
|
||||
smach:
|
||||
debian:
|
||||
buster: [ros-melodic-smach]
|
||||
smclib:
|
||||
debian:
|
||||
buster: [ros-melodic-smclib]
|
||||
std_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-std-msgs]
|
||||
actionlib_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-actionlib-msgs]
|
||||
bond:
|
||||
debian:
|
||||
buster: [ros-melodic-bond]
|
||||
diagnostic_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-diagnostic-msgs]
|
||||
geometry_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-geometry-msgs]
|
||||
eigen_conversions:
|
||||
debian:
|
||||
buster: [ros-melodic-eigen-conversions]
|
||||
kdl_conversions:
|
||||
debian:
|
||||
buster: [ros-melodic-kdl-conversions]
|
||||
nav_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-nav-msgs]
|
||||
rosbridge_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbridge-msgs]
|
||||
rosgraph_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-rosgraph-msgs]
|
||||
rosmsg:
|
||||
debian:
|
||||
buster: [ros-melodic-rosmsg]
|
||||
rqt_py_common:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-py-common]
|
||||
shape_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-shape-msgs]
|
||||
smach_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-smach-msgs]
|
||||
std_srvs:
|
||||
debian:
|
||||
buster: [ros-melodic-std-srvs]
|
||||
tf2_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-msgs]
|
||||
tf2:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2]
|
||||
tf2_eigen:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-eigen]
|
||||
trajectory_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-trajectory-msgs]
|
||||
control_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-control-msgs]
|
||||
urdf_parser_plugin:
|
||||
debian:
|
||||
buster: [ros-melodic-urdf-parser-plugin]
|
||||
urdfdom_py:
|
||||
debian:
|
||||
buster: [ros-melodic-urdfdom-py]
|
||||
uuid_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-uuid-msgs]
|
||||
geographic_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-geographic-msgs]
|
||||
vision_opencv:
|
||||
debian:
|
||||
buster: [ros-melodic-vision-opencv]
|
||||
visualization_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-visualization-msgs]
|
||||
visualization_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-visualization-tutorials]
|
||||
viz:
|
||||
debian:
|
||||
buster: [ros-melodic-viz]
|
||||
webkit_dependency:
|
||||
debian:
|
||||
buster: [ros-melodic-webkit-dependency]
|
||||
xmlrpcpp:
|
||||
debian:
|
||||
buster: [ros-melodic-xmlrpcpp]
|
||||
roscpp:
|
||||
debian:
|
||||
buster: [ros-melodic-roscpp]
|
||||
bondcpp:
|
||||
debian:
|
||||
buster: [ros-melodic-bondcpp]
|
||||
bondpy:
|
||||
debian:
|
||||
buster: [ros-melodic-bondpy]
|
||||
nodelet:
|
||||
debian:
|
||||
buster: [ros-melodic-nodelet]
|
||||
nodelet_tutorial_math:
|
||||
debian:
|
||||
buster: [ros-melodic-nodelet-tutorial-math]
|
||||
pluginlib_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-pluginlib-tutorials]
|
||||
roscpp_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-roscpp-tutorials]
|
||||
rosout:
|
||||
debian:
|
||||
buster: [ros-melodic-rosout]
|
||||
async_web_server_cpp:
|
||||
debian:
|
||||
buster: [ros-melodic-async-web-server-cpp]
|
||||
camera_calibration:
|
||||
debian:
|
||||
buster: [ros-melodic-camera-calibration]
|
||||
diagnostic_aggregator:
|
||||
debian:
|
||||
buster: [ros-melodic-diagnostic-aggregator]
|
||||
diagnostic_updater:
|
||||
debian:
|
||||
buster: [ros-melodic-diagnostic-updater]
|
||||
diagnostic_common_diagnostics:
|
||||
debian:
|
||||
buster: [ros-melodic-diagnostic-common-diagnostics]
|
||||
dynamic_reconfigure:
|
||||
debian:
|
||||
buster: [ros-melodic-dynamic-reconfigure]
|
||||
filters:
|
||||
debian:
|
||||
buster: [ros-melodic-filters]
|
||||
joint_state_publisher:
|
||||
debian:
|
||||
buster: [ros-melodic-joint-state-publisher]
|
||||
message_filters:
|
||||
debian:
|
||||
buster: [ros-melodic-message-filters]
|
||||
ros_pytest:
|
||||
debian:
|
||||
buster: [ros-melodic-ros-pytest]
|
||||
rosauth:
|
||||
debian:
|
||||
buster: [ros-melodic-rosauth]
|
||||
rosbag_storage:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbag-storage]
|
||||
rosnode:
|
||||
debian:
|
||||
buster: [ros-melodic-rosnode]
|
||||
rospy_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-rospy-tutorials]
|
||||
rosshow:
|
||||
debian:
|
||||
buster: [ros-melodic-rosshow]
|
||||
rostopic:
|
||||
debian:
|
||||
buster: [ros-melodic-rostopic]
|
||||
rqt_gui_cpp:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-gui-cpp]
|
||||
rqt_gui_py:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-gui-py]
|
||||
self_test:
|
||||
debian:
|
||||
buster: [ros-melodic-self-test]
|
||||
smach_ros:
|
||||
debian:
|
||||
buster: [ros-melodic-smach-ros]
|
||||
tf2_py:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-py]
|
||||
topic_tools:
|
||||
debian:
|
||||
buster: [ros-melodic-topic-tools]
|
||||
rosbag:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbag]
|
||||
actionlib:
|
||||
debian:
|
||||
buster: [ros-melodic-actionlib]
|
||||
actionlib_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-actionlib-tutorials]
|
||||
diagnostic_analysis:
|
||||
debian:
|
||||
buster: [ros-melodic-diagnostic-analysis]
|
||||
nodelet_topic_tools:
|
||||
debian:
|
||||
buster: [ros-melodic-nodelet-topic-tools]
|
||||
roswtf:
|
||||
debian:
|
||||
buster: [ros-melodic-roswtf]
|
||||
rqt_launch:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-launch]
|
||||
sensor_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-sensor-msgs]
|
||||
camera_calibration_parsers:
|
||||
debian:
|
||||
buster: [ros-melodic-camera-calibration-parsers]
|
||||
cv_bridge:
|
||||
debian:
|
||||
buster: [ros-melodic-cv-bridge]
|
||||
image_geometry:
|
||||
debian:
|
||||
buster: [ros-melodic-image-geometry]
|
||||
image_transport:
|
||||
debian:
|
||||
buster: [ros-melodic-image-transport]
|
||||
camera_info_manager:
|
||||
debian:
|
||||
buster: [ros-melodic-camera-info-manager]
|
||||
compressed_depth_image_transport:
|
||||
debian:
|
||||
buster: [ros-melodic-compressed-depth-image-transport]
|
||||
compressed_image_transport:
|
||||
debian:
|
||||
buster: [ros-melodic-compressed-image-transport]
|
||||
cv_camera:
|
||||
debian:
|
||||
buster: [ros-melodic-cv-camera]
|
||||
image_proc:
|
||||
debian:
|
||||
buster: [ros-melodic-image-proc]
|
||||
image_publisher:
|
||||
debian:
|
||||
buster: [ros-melodic-image-publisher]
|
||||
map_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-map-msgs]
|
||||
mavros_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-mavros-msgs]
|
||||
pcl_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-pcl-msgs]
|
||||
pcl_conversions:
|
||||
debian:
|
||||
buster: [ros-melodic-pcl-conversions]
|
||||
polled_camera:
|
||||
debian:
|
||||
buster: [ros-melodic-polled-camera]
|
||||
rqt_image_view:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-image-view]
|
||||
stereo_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-stereo-msgs]
|
||||
image_view:
|
||||
debian:
|
||||
buster: [ros-melodic-image-view]
|
||||
rosbridge_library:
|
||||
debian:
|
||||
buster: [ros-melodic-rosbridge-library]
|
||||
stereo_image_proc:
|
||||
debian:
|
||||
buster: [ros-melodic-stereo-image-proc]
|
||||
tf2_ros:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-ros]
|
||||
depth_image_proc:
|
||||
debian:
|
||||
buster: [ros-melodic-depth-image-proc]
|
||||
mavros:
|
||||
debian:
|
||||
buster: [ros-melodic-mavros]
|
||||
tf:
|
||||
debian:
|
||||
buster: [ros-melodic-tf]
|
||||
interactive_markers:
|
||||
debian:
|
||||
buster: [ros-melodic-interactive-markers]
|
||||
interactive_marker_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-interactive-marker-tutorials]
|
||||
laser_geometry:
|
||||
debian:
|
||||
buster: [ros-melodic-laser-geometry]
|
||||
laser_assembler:
|
||||
debian:
|
||||
buster: [ros-melodic-laser-assembler]
|
||||
laser_filters:
|
||||
debian:
|
||||
buster: [ros-melodic-laser-filters]
|
||||
pcl_ros:
|
||||
debian:
|
||||
buster: [ros-melodic-pcl-ros]
|
||||
tf2_geometry_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-geometry-msgs]
|
||||
image_rotate:
|
||||
debian:
|
||||
buster: [ros-melodic-image-rotate]
|
||||
tf2_kdl:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-kdl]
|
||||
tf2_web_republisher:
|
||||
debian:
|
||||
buster: [ros-melodic-tf2-web-republisher]
|
||||
tf_conversions:
|
||||
debian:
|
||||
buster: [ros-melodic-tf-conversions]
|
||||
theora_image_transport:
|
||||
debian:
|
||||
buster: [ros-melodic-theora-image-transport]
|
||||
turtlesim:
|
||||
debian:
|
||||
buster: [ros-melodic-turtlesim]
|
||||
turtle_actionlib:
|
||||
debian:
|
||||
buster: [ros-melodic-turtle-actionlib]
|
||||
turtle_tf:
|
||||
debian:
|
||||
buster: [ros-melodic-turtle-tf]
|
||||
turtle_tf2:
|
||||
debian:
|
||||
buster: [ros-melodic-turtle-tf2]
|
||||
urdf:
|
||||
debian:
|
||||
buster: [ros-melodic-urdf]
|
||||
kdl_parser:
|
||||
debian:
|
||||
buster: [ros-melodic-kdl-parser]
|
||||
kdl_parser_py:
|
||||
debian:
|
||||
buster: [ros-melodic-kdl-parser-py]
|
||||
mavros_extras:
|
||||
debian:
|
||||
buster: [ros-melodic-mavros-extras]
|
||||
robot_state_publisher:
|
||||
debian:
|
||||
buster: [ros-melodic-robot-state-publisher]
|
||||
rviz:
|
||||
debian:
|
||||
buster: [ros-melodic-rviz]
|
||||
librviz_tutorial:
|
||||
debian:
|
||||
buster: [ros-melodic-librviz-tutorial]
|
||||
rqt_rviz:
|
||||
debian:
|
||||
buster: [ros-melodic-rqt-rviz]
|
||||
rviz_plugin_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-rviz-plugin-tutorials]
|
||||
rviz_python_tutorial:
|
||||
debian:
|
||||
buster: [ros-melodic-rviz-python-tutorial]
|
||||
urdf_tutorial:
|
||||
debian:
|
||||
buster: [ros-melodic-urdf-tutorial]
|
||||
usb_cam:
|
||||
debian:
|
||||
buster: [ros-melodic-usb-cam]
|
||||
visualization_marker_tutorials:
|
||||
debian:
|
||||
buster: [ros-melodic-visualization-marker-tutorials]
|
||||
vl53l1x:
|
||||
debian:
|
||||
buster: [ros-melodic-vl53l1x]
|
||||
web_video_server:
|
||||
debian:
|
||||
buster: [ros-melodic-web-video-server]
|
||||
xacro:
|
||||
debian:
|
||||
buster: [ros-melodic-xacro]
|
||||
led_msgs:
|
||||
debian:
|
||||
buster: [ros-melodic-led-msgs]
|
||||
ws281x:
|
||||
debian:
|
||||
buster: [ros-melodic-ws281x]
|
||||
ddynamic_reconfigure:
|
||||
debian:
|
||||
buster: [ros-melodic-ddynamic-reconfigure]
|
||||
librealsense2:
|
||||
debian:
|
||||
buster: [ros-melodic-librealsense2]
|
||||
realsense2_camera:
|
||||
debian:
|
||||
buster: [ros-melodic-realsense2-camera]
|
||||
realsense2_description:
|
||||
debian:
|
||||
buster: [ros-melodic-realsense2-description]
|
||||
@@ -20,7 +20,7 @@
|
||||
# Example:
|
||||
# DocumentRoot /home/krypton/htdocs
|
||||
|
||||
DocumentRoot /home/pi/catkin_ws/src/clever/clever/www
|
||||
DocumentRoot /home/pi/catkin_ws/src/clover/clover/www
|
||||
|
||||
# Redirect:
|
||||
# ---------
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
set -e # Exit immidiately on non-zero result
|
||||
|
||||
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-09-30/2019-09-26-raspbian-buster-lite.zip"
|
||||
SOURCE_IMAGE="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2020-02-14/2020-02-13-raspbian-buster-lite.zip"
|
||||
|
||||
export DEBIAN_FRONTEND=${DEBIAN_FRONTEND:='noninteractive'}
|
||||
export LANG=${LANG:='C.UTF-8'}
|
||||
@@ -89,7 +89,7 @@ shopt -s dotglob
|
||||
for dir in ${REPO_DIR}/*; do
|
||||
# Don't try to copy image into itself
|
||||
if [[ $dir != *"images" && $dir != *"imgcache" ]]; then
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy $dir '/home/pi/catkin_ws/src/clever/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy $dir '/home/pi/catkin_ws/src/clover/'
|
||||
fi;
|
||||
done
|
||||
|
||||
@@ -104,21 +104,23 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/butterf
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/monkey.service' '/lib/systemd/system/'
|
||||
# software install
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-software.sh'
|
||||
# examples
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/examples' '/home/pi/'
|
||||
# network setup
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-network.sh'
|
||||
|
||||
# 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)
|
||||
# Clever
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/clever.service' '/lib/systemd/system/'
|
||||
# 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/melodic-rosdep-clever.yaml' '/etc/ros/rosdep/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/melodic-rosdep-clover.yaml' '/etc/ros/rosdep/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/ros_python_paths' '/etc/sudoers.d/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/pigpiod.service' '/lib/systemd/system/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/launch.nanorc' '/usr/share/nano/'
|
||||
# ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/kinetic-ros-clever.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}'/clever/config/99-px4fmu.rules' '/lib/udev/rules.d/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${REPO_DIR}'/clover/config/99-px4fmu.rules' '/lib/udev/rules.d/'
|
||||
# Add rename script
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-ros.sh' ${REPO_URL} ${IMAGE_VERSION} false false ${NUMBER_THREADS}
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} exec ${SCRIPTS_DIR}'/image-validate.sh'
|
||||
|
||||
@@ -34,12 +34,12 @@ echo_stamp() {
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
echo_stamp "Write CLEVER information"
|
||||
echo_stamp "Write Clover information"
|
||||
|
||||
# Clever image version
|
||||
echo "$1" >> /etc/clever_version
|
||||
# Clover image version
|
||||
echo "$1" >> /etc/clover_version
|
||||
# Origin image file name
|
||||
echo "${2%.*}" >> /etc/clever_origin
|
||||
echo "${2%.*}" >> /etc/clover_origin
|
||||
|
||||
echo_stamp "Write magic script to /etc/rc.local"
|
||||
MAGIC_SCRIPT="sudo /root/init_rpi.sh; sudo sed -i '/sudo \\\/root\\\/init_rpi.sh/d' /etc/rc.local && sudo reboot"
|
||||
|
||||
@@ -34,34 +34,24 @@ echo_stamp() {
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
echo_stamp "#1 Write to /etc/wpa_supplicant/wpa_supplicant.conf"
|
||||
|
||||
# TODO: Use wpa_cli insted direct file edit
|
||||
cat << EOF >> /etc/wpa_supplicant/wpa_supplicant.conf
|
||||
network={
|
||||
ssid="CLEVER"
|
||||
psk="cleverwifi"
|
||||
mode=2
|
||||
proto=WPA RSN
|
||||
key_mgmt=WPA-PSK
|
||||
pairwise=CCMP
|
||||
group=CCMP
|
||||
auth_alg=OPEN
|
||||
}
|
||||
EOF
|
||||
|
||||
echo_stamp "#2 Write STATIC to /etc/dhcpcd.conf"
|
||||
echo_stamp "#1 Write STATIC to /etc/dhcpcd.conf"
|
||||
|
||||
cat << EOF >> /etc/dhcpcd.conf
|
||||
interface wlan0
|
||||
static ip_address=192.168.11.1/24
|
||||
EOF
|
||||
|
||||
echo_stamp "#2 Set wpa_supplicant country"
|
||||
|
||||
cat << EOF >> /etc/wpa_supplicant/wpa_supplicant.conf
|
||||
country=GB
|
||||
EOF
|
||||
|
||||
echo_stamp "#3 Write dhcp-config to /etc/dnsmasq.conf"
|
||||
|
||||
cat << EOF >> /etc/dnsmasq.conf
|
||||
interface=wlan0
|
||||
address=/clever/coex/192.168.11.1
|
||||
address=/clover/coex/192.168.11.1
|
||||
dhcp-range=192.168.11.100,192.168.11.200,12h
|
||||
no-hosts
|
||||
filterwin2k
|
||||
@@ -70,8 +60,4 @@ domain-needed
|
||||
quiet-dhcp6
|
||||
EOF
|
||||
|
||||
#echo_stamp "#4 Write magic script for rename SSID to /etc/rc.local"
|
||||
#RENAME_SSID="sudo sed -i.OLD \"s/CLEVER/CLEVER-\$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e 's/[^0-9]//g' | cut -c 1-4)/g\" /etc/wpa_supplicant/wpa_supplicant.conf && sudo sed -i '/sudo sed/d' /etc/rc.local && sudo reboot"
|
||||
#sed -i "19a$RENAME_SSID" /etc/rc.local
|
||||
|
||||
echo_stamp "#5 End of network installation"
|
||||
echo_stamp "#4 End of network installation"
|
||||
|
||||
@@ -65,10 +65,10 @@ my_travis_retry() {
|
||||
return $result
|
||||
}
|
||||
|
||||
# TODO: 'kinetic-rosdep-clever.yaml' should add only if we use our repo?
|
||||
# TODO: 'kinetic-rosdep-clover.yaml' should add only if we use our repo?
|
||||
echo_stamp "Init rosdep"
|
||||
my_travis_retry rosdep init
|
||||
echo "yaml file:///etc/ros/rosdep/melodic-rosdep-clever.yaml" >> /etc/ros/rosdep/sources.list.d/20-default.list
|
||||
echo "yaml file:///etc/ros/rosdep/melodic-rosdep-clover.yaml" >> /etc/ros/rosdep/sources.list.d/20-default.list
|
||||
my_travis_retry rosdep update
|
||||
|
||||
echo_stamp "Populate rosdep for ROS user"
|
||||
@@ -88,30 +88,29 @@ resolve_rosdep() {
|
||||
|
||||
export ROS_IP='127.0.0.1' # needed for running tests
|
||||
|
||||
echo_stamp "Reconfiguring Clever repository for simplier unshallowing"
|
||||
cd /home/pi/catkin_ws/src/clever
|
||||
echo_stamp "Reconfiguring Clover repository for simplier unshallowing"
|
||||
cd /home/pi/catkin_ws/src/clover
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
|
||||
echo_stamp "Installing CLEVER" \
|
||||
&& cd /home/pi/catkin_ws/src/clever \
|
||||
&& git status \
|
||||
&& cd /home/pi/catkin_ws \
|
||||
&& resolve_rosdep $(pwd) \
|
||||
&& my_travis_retry pip install wheel \
|
||||
&& my_travis_retry pip install -r /home/pi/catkin_ws/src/clever/clever/requirements.txt \
|
||||
&& source /opt/ros/melodic/setup.bash \
|
||||
&& catkin_make -j2 -DCMAKE_BUILD_TYPE=Release \
|
||||
&& systemctl enable roscore \
|
||||
&& systemctl enable clever \
|
||||
&& echo_stamp "All CLEVER was installed!" "SUCCESS" \
|
||||
|| (echo_stamp "CLEVER installation was failed!" "ERROR"; exit 1)
|
||||
echo_stamp "Build and install Clover"
|
||||
cd /home/pi/catkin_ws
|
||||
resolve_rosdep $(pwd)
|
||||
my_travis_retry pip install wheel
|
||||
my_travis_retry pip install -r /home/pi/catkin_ws/src/clover/clover/requirements.txt
|
||||
source /opt/ros/melodic/setup.bash
|
||||
catkin_make -j2 -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
echo_stamp "Build CLEVER documentation"
|
||||
cd /home/pi/catkin_ws/src/clever
|
||||
echo_stamp "Install clever package (for backwards compatibility)"
|
||||
cd /home/pi/catkin_ws/src/clover/builder/assets/clever
|
||||
./setup.py install
|
||||
rm -rf build # remove build artifacts
|
||||
|
||||
echo_stamp "Build Clover documentation"
|
||||
cd /home/pi/catkin_ws/src/clover
|
||||
NPM_CONFIG_UNSAFE_PERM=true npm install gitbook-cli -g
|
||||
NPM_CONFIG_UNSAFE_PERM=true gitbook install
|
||||
gitbook build
|
||||
touch node_modules/CATKIN_IGNORE docs/CATKIN_IGNORE _book/CATKIN_IGNORE clever/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
|
||||
|
||||
echo_stamp "Installing additional ROS packages"
|
||||
apt-get install -y --no-install-recommends \
|
||||
|
||||
@@ -68,9 +68,7 @@ apt-get update \
|
||||
echo "deb http://packages.ros.org/ros/ubuntu buster main" > /etc/apt/sources.list.d/ros-latest.list
|
||||
echo "deb http://deb.coex.tech/opencv3 buster main" > /etc/apt/sources.list.d/opencv3.list
|
||||
echo "deb http://deb.coex.tech/rpi-ros-melodic buster main" > /etc/apt/sources.list.d/rpi-ros-melodic.list
|
||||
# FIXME: We still don't have these packages built for Buster
|
||||
# FIXME: Check these packages after their installation
|
||||
echo "deb http://deb.coex.tech/clever stretch main" > /etc/apt/sources.list.d/clever.list
|
||||
echo "deb http://deb.coex.tech/clover buster main" > /etc/apt/sources.list.d/clover.list
|
||||
|
||||
echo_stamp "Update apt cache"
|
||||
|
||||
@@ -97,6 +95,7 @@ libjpeg8 \
|
||||
tcpdump \
|
||||
ltrace \
|
||||
libpoco-dev \
|
||||
libzbar0 \
|
||||
python-rosdep \
|
||||
python-rosinstall-generator \
|
||||
python-wstool \
|
||||
@@ -155,6 +154,14 @@ cp -R node-v10.15.0-linux-armv6l/* /usr/local/
|
||||
rm -rf node-v10.15.0-linux-armv6l/
|
||||
rm node-v10.15.0-linux-armv6l.tar.gz
|
||||
|
||||
echo_stamp "Installing ptvsd"
|
||||
my_travis_retry pip install ptvsd
|
||||
my_travis_retry pip3 install ptvsd
|
||||
|
||||
echo_stamp "Installing pyzbar"
|
||||
my_travis_retry pip install pyzbar
|
||||
my_travis_retry pip3 install pyzbar
|
||||
|
||||
echo_stamp "Add .vimrc"
|
||||
cat << EOF > /home/pi/.vimrc
|
||||
set mouse-=a
|
||||
|
||||
@@ -21,10 +21,11 @@ export ROS_IP='127.0.0.1'
|
||||
source /opt/ros/melodic/setup.bash
|
||||
source /home/pi/catkin_ws/devel/setup.bash
|
||||
|
||||
cd /home/pi/catkin_ws/src/clever/builder/test/
|
||||
cd /home/pi/catkin_ws/src/clover/builder/test/
|
||||
./tests.sh
|
||||
./tests.py
|
||||
./tests_py3.py
|
||||
[[ $(./tests_clever.py) == "Warning: clever package is renamed to clover" ]] # test backwards compatibility
|
||||
|
||||
echo "Move /etc/ld.so.preload back to its original position"
|
||||
mv /etc/ld.so.preload.disabled-for-build /etc/ld.so.preload
|
||||
|
||||
@@ -14,7 +14,7 @@ from mavros_msgs.msg import State, StatusText, ExtendedState
|
||||
from mavros_msgs.srv import CommandBool, CommandLong, SetMode
|
||||
|
||||
from std_srvs.srv import Trigger
|
||||
from clever.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
||||
from clover.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
||||
SetAttitude, SetRates, SetLEDEffect
|
||||
|
||||
import tf2_ros
|
||||
@@ -26,5 +26,6 @@ from pymavlink import mavutil
|
||||
import rpi_ws281x
|
||||
import pigpio
|
||||
from espeak import espeak
|
||||
from pyzbar import pyzbar
|
||||
|
||||
print cv2.getBuildInformation()
|
||||
|
||||
@@ -12,6 +12,10 @@ python3 --version
|
||||
ipython --version
|
||||
ipython3 --version
|
||||
|
||||
# ptvsd does not have a stand-alone binary
|
||||
python -m ptvsd --version
|
||||
python3 -m ptvsd --version
|
||||
|
||||
node -v
|
||||
npm -v
|
||||
|
||||
@@ -34,7 +38,7 @@ mjpg_streamer --version
|
||||
# ros stuff
|
||||
|
||||
roscore -h
|
||||
rosversion clever
|
||||
rosversion clover
|
||||
rosversion aruco_pose
|
||||
rosversion vl53l1x
|
||||
rosversion mavros
|
||||
@@ -48,3 +52,6 @@ rosversion usb_cam
|
||||
rosversion cv_camera
|
||||
rosversion web_video_server
|
||||
rosversion rosshow
|
||||
|
||||
# validate examples are present
|
||||
[[ $(ls /home/pi/examples/*) ]]
|
||||
|
||||
6
builder/test/tests_clever.py
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# test backwards compatibility
|
||||
|
||||
from clever.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
||||
SetAttitude, SetRates, SetLEDEffect
|
||||
@@ -3,5 +3,6 @@
|
||||
# Make sure our Python 3 software is installed
|
||||
|
||||
import cv2
|
||||
from pyzbar import pyzbar
|
||||
|
||||
print(cv2.getBuildInformation())
|
||||
|
||||
@@ -17,7 +17,8 @@ EXCLUDE = 'rviz.png', 'ssid.png', 'sitl_docker_demo.png', 'qgc-params.png', 'but
|
||||
'cl3_mountBEC.JPG', 'cl3_mountRpiCamera.JPG', 'clever4-front-black-large.png', \
|
||||
'qgc-battery.png', 'qgc-radio.png', 'qgc-cal-acc.png', 'qgc-esc.png', 'qgc-cal-compass.png', \
|
||||
'qgc.png', 'qgc-parameters.png', 'clever4-front-white-large.png', 'qgc-modes.png', \
|
||||
'qgc-requires-setup.png', 'clever4-front-white.png', 'clever4-kit-white.png', '26_1.png', 'battery_holder.stl'
|
||||
'qgc-requires-setup.png', 'clever4-front-white.png', 'clever4-kit-white.png', '26_1.png', 'battery_holder.stl', \
|
||||
'camera_case.stl', 'camera_mount.stl'
|
||||
|
||||
code = 0
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
image_width: 320
|
||||
image_height: 240
|
||||
distortion_model: plumb_bob
|
||||
camera_name: raspicam
|
||||
camera_matrix:
|
||||
rows: 3
|
||||
cols: 3
|
||||
data:
|
||||
- 166.23942373073172
|
||||
- 0.
|
||||
- 162.19011246829268
|
||||
- 0.
|
||||
- 166.5880923974026
|
||||
- 109.82227735714285
|
||||
- 0.
|
||||
- 0.
|
||||
- 1.
|
||||
distortion_coefficients:
|
||||
rows: 1
|
||||
cols: 8
|
||||
data: [ 2.15356885e-01, -1.17472846e-01, -3.06197672e-04,
|
||||
-1.09444025e-04, -4.53657258e-03, 5.73090623e-01,
|
||||
-1.27574577e-01, -2.86125589e-02, 0.00000000e+00,
|
||||
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
|
||||
0.00000000e+00, 0.00000000e+00]
|
||||
rectification_matrix:
|
||||
rows: 3
|
||||
cols: 3
|
||||
data: [1, 0, 0, 0, 1, 0, 0, 0, 1]
|
||||
projection_matrix:
|
||||
rows: 3
|
||||
cols: 4
|
||||
data:
|
||||
- 166.23942373073172
|
||||
- 0.
|
||||
- 162.19011246829268
|
||||
- 0.
|
||||
- 0.
|
||||
- 166.5880923974026
|
||||
- 109.82227735714285
|
||||
- 0.
|
||||
- 0.
|
||||
- 0.
|
||||
- 1.
|
||||
- 0.
|
||||
@@ -1,6 +0,0 @@
|
||||
<launch>
|
||||
<arg name="device" default="/dev/video1"/>
|
||||
<arg name="port" default="9999"/>
|
||||
|
||||
<node name="fpv_camera" pkg="clever" type="fpv_camera" args="$(arg device) $(arg port)" output="screen"/>
|
||||
</launch>
|
||||
@@ -1,39 +0,0 @@
|
||||
<launch>
|
||||
<!-- Camera position and orientation are represented by base_link -> main_camera_optical transform -->
|
||||
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
|
||||
|
||||
<!-- article about camera setup: https://clever.coex.tech/camera_frame -->
|
||||
|
||||
<!-- camera is oriented downward, camera cable goes backward [option 1] -->
|
||||
<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 is oriented downward, camera cable goes forward [option 2] -->
|
||||
<!--<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 is oriented upward, camera cable goes backward [option 3] -->
|
||||
<!--<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 1.5707963 0 0 base_link main_camera_optical"/>-->
|
||||
|
||||
<!-- camera is oriented upward, camera cable goes forward [option 4] -->
|
||||
<!--<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 -1.5707963 0 0 base_link main_camera_optical"/>-->
|
||||
|
||||
<!-- camera node -->
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet nodelet_manager" clear_params="true">
|
||||
<param name="device_path" value="/dev/video0"/> <!-- v4l2 device -->
|
||||
<param name="frame_id" value="main_camera_optical"/>
|
||||
<param name="camera_info_url" value="file://$(find clever)/camera_info/fisheye_cam_320.yaml"/>
|
||||
|
||||
<param name="rate" value="100"/> <!-- poll rate -->
|
||||
<param name="cv_cap_prop_fps" value="40"/> <!-- camera FPS -->
|
||||
<param name="capture_delay" value="0.02"/> <!-- approximate delay on frame retrieving -->
|
||||
<param name="rescale_camera_info" value="true"/> <!-- automatically rescale camera calibration info -->
|
||||
|
||||
<!-- camera resolution, NOTE: camera_info file should match it -->
|
||||
<param name="image_width" value="320"/>
|
||||
<param name="image_height" value="240"/>
|
||||
</node>
|
||||
|
||||
<!-- camera visualization markers -->
|
||||
<node pkg="clever" type="camera_markers" ns="main_camera" name="main_camera_markers">
|
||||
<param name="scale" value="3.0"/>
|
||||
</node>
|
||||
</launch>
|
||||
@@ -1,5 +0,0 @@
|
||||
<library path="lib/libclever">
|
||||
<class name="clever/optical_flow" type="OpticalFlow" base_class_type="nodelet::Nodelet">
|
||||
<description/>
|
||||
</class>
|
||||
</library>
|
||||
54809
clever/www/js/ros3d.js
vendored
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(clever)
|
||||
project(clover)
|
||||
|
||||
## Compile as C++11, supported in ROS Kinetic and newer
|
||||
add_compile_options(-std=c++11)
|
||||
@@ -30,6 +30,12 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
|
||||
find_package(GeographicLib REQUIRED)
|
||||
|
||||
find_package(OpenCV 3 REQUIRED
|
||||
COMPONENTS
|
||||
calib3d
|
||||
imgproc
|
||||
)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
# find_package(Boost REQUIRED COMPONENTS system)
|
||||
|
||||
@@ -81,6 +87,7 @@ add_service_files(
|
||||
SetAttitude.srv
|
||||
SetRates.srv
|
||||
SetLEDEffect.srv
|
||||
Execute.srv
|
||||
)
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
@@ -127,7 +134,7 @@ generate_messages(
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
# INCLUDE_DIRS include
|
||||
LIBRARIES clever
|
||||
LIBRARIES ${PROJECT_NAME}
|
||||
# CATKIN_DEPENDS other_catkin_pkg
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
@@ -145,7 +152,7 @@ include_directories(
|
||||
)
|
||||
|
||||
# Declare a C++ library
|
||||
add_library(clever
|
||||
add_library(${PROJECT_NAME}
|
||||
src/optical_flow.cpp
|
||||
)
|
||||
|
||||
@@ -167,6 +174,8 @@ add_executable(vpe_publisher src/vpe_publisher.cpp)
|
||||
|
||||
add_executable(led src/led.cpp)
|
||||
|
||||
add_executable(shell src/shell.cpp)
|
||||
|
||||
target_link_libraries(simple_offboard
|
||||
${catkin_LIBRARIES}
|
||||
${GeographicLib_LIBRARIES}
|
||||
@@ -180,9 +189,13 @@ target_link_libraries(vpe_publisher ${catkin_LIBRARIES})
|
||||
|
||||
target_link_libraries(led ${catkin_LIBRARIES})
|
||||
|
||||
add_dependencies(simple_offboard clever_generate_messages_cpp)
|
||||
target_link_libraries(shell ${catkin_LIBRARIES})
|
||||
|
||||
add_dependencies(led clever_generate_messages_cpp)
|
||||
add_dependencies(simple_offboard ${PROJECT_NAME}_generate_messages_cpp)
|
||||
|
||||
add_dependencies(led ${PROJECT_NAME}_generate_messages_cpp)
|
||||
|
||||
add_dependencies(shell ${PROJECT_NAME}_generate_messages_cpp)
|
||||
|
||||
## Rename C++ executable without prefix
|
||||
## The above recommended prefix causes long target names, the following renames the
|
||||
@@ -195,8 +208,9 @@ add_dependencies(led clever_generate_messages_cpp)
|
||||
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
target_link_libraries(clever
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${catkin_LIBRARIES}
|
||||
${OpenCV_LIBRARIES}
|
||||
)
|
||||
|
||||
#############
|
||||
@@ -252,7 +266,7 @@ endif()
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_clever.cpp)
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_${PROJECT_NAME}.cpp)
|
||||
# if(TARGET ${PROJECT_NAME}-test)
|
||||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
|
||||
# endif()
|
||||
73
clover/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# `clover` ROS package
|
||||
|
||||
A bundle for autonomous navigation and drone control.
|
||||
|
||||
## Manual installation
|
||||
|
||||
Install ROS Melodic according to the [documentation](http://wiki.ros.org/melodic/Installation), then [create a Catkin workspace](http://wiki.ros.org/catkin/Tutorials/create_a_workspace).
|
||||
|
||||
Clone this repo to directory `~/catkin_ws/src/clover`:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/src
|
||||
git clone https://github.com/CopterExpress/clover.git clover
|
||||
```
|
||||
|
||||
All the required ROS packages (including `mavros` and `opencv`) can be installed using `rosdep`:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/
|
||||
rosdep install -y --from-paths src --ignore-src
|
||||
```
|
||||
|
||||
Build ROS packages (on memory constrained platforms you might be going to need to use `-j1` key):
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws
|
||||
catkin_make -j1
|
||||
```
|
||||
|
||||
To complete `mavros` install you'll need to install `geographiclib` datasets:
|
||||
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh | sudo bash
|
||||
```
|
||||
|
||||
You may optionally install udev rules to provide `/dev/px4fmu` symlink to your PX4-based flight controller connected over USB. Copy `99-px4fmu.rules` to your `/lib/udev/rules.d` folder:
|
||||
|
||||
```bash
|
||||
cd ~/catkin_ws/src/clover/clover/config
|
||||
sudo cp 99-px4fmu.rules /lib/udev/rules.d
|
||||
```
|
||||
|
||||
Alternatively you may change the `fcu_url` property in `mavros.launch` file to point to your flight controller device.
|
||||
|
||||
## Running
|
||||
|
||||
Enable systemd service `roscore` (if not running):
|
||||
|
||||
```bash
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clover/builder/assets/roscore.service
|
||||
sudo systemctl start roscore
|
||||
```
|
||||
|
||||
To start connection to SITL, use:
|
||||
|
||||
```bash
|
||||
roslaunch clover sitl.launch
|
||||
```
|
||||
|
||||
To start connection to the flight controller, use:
|
||||
|
||||
```bash
|
||||
roslaunch clover clover.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`.
|
||||
|
||||
Also, you can enable and start the systemd service:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clover/deploy/clover.service
|
||||
sudo systemctl start clover
|
||||
```
|
||||
@@ -1,17 +1,17 @@
|
||||
image_width: 640
|
||||
image_height: 480
|
||||
distortion_model: plumb_bob
|
||||
camera_name: raspicam
|
||||
camera_name: main_camera_optical
|
||||
camera_matrix:
|
||||
rows: 3
|
||||
cols: 3
|
||||
data:
|
||||
- 332.47884746146343
|
||||
- 0.
|
||||
- 324.38022493658536
|
||||
- 320.0
|
||||
- 0.
|
||||
- 333.1761847948052
|
||||
- 219.6445547142857
|
||||
- 240.0
|
||||
- 0.
|
||||
- 0.
|
||||
- 1.
|
||||
@@ -3,7 +3,7 @@
|
||||
<arg name="aruco_map" default="false"/>
|
||||
<arg name="aruco_vpe" default="false"/>
|
||||
|
||||
<!-- For additional help go to https://clever.coex.tech/aruco -->
|
||||
<!-- For additional help go to https://clover.coex.tech/aruco -->
|
||||
|
||||
<!-- aruco_detect: detect aruco markers, estimate poses -->
|
||||
<node name="aruco_detect" pkg="nodelet" if="$(arg aruco_detect)" type="nodelet" args="load aruco_pose/aruco_detect nodelet_manager" output="screen" clear_params="true">
|
||||
@@ -14,6 +14,9 @@
|
||||
<param name="send_tf" value="true"/>
|
||||
<param name="known_tilt" value="map"/>
|
||||
<param name="length" value="0.33"/>
|
||||
<!-- aruco detector parameters -->
|
||||
<param name="cornerRefinementMethod" value="2"/> <!-- contour refinement -->
|
||||
<param name="minMarkerPerimeterRate" value="0.075"/> <!-- 0.075 for 320x240, 0.0375 for 640x480 -->
|
||||
</node>
|
||||
|
||||
<!-- aruco_map: estimate aruco map pose -->
|
||||
@@ -31,7 +34,7 @@
|
||||
</node>
|
||||
|
||||
<!-- vpe publisher from aruco markers -->
|
||||
<node name="vpe_publisher" pkg="clever" type="vpe_publisher" if="$(arg aruco_vpe)" output="screen" clear_params="true">
|
||||
<node name="vpe_publisher" pkg="clover" type="vpe_publisher" if="$(arg aruco_vpe)" output="screen" clear_params="true">
|
||||
<remap from="~pose_cov" to="aruco_map/pose"/>
|
||||
<remap from="~vpe" to="mavros/vision_pose/pose"/>
|
||||
<param name="frame_id" value="aruco_map_detected"/>
|
||||
@@ -1,23 +1,26 @@
|
||||
<launch>
|
||||
<arg name="fcu_conn" default="usb"/>
|
||||
<arg name="fcu_ip" default="127.0.0.1"/>
|
||||
<arg name="fcu_sys_id" default="1"/>
|
||||
<arg name="gcs_bridge" default="tcp"/>
|
||||
<arg name="web_video_server" default="true"/>
|
||||
<arg name="rosbridge" default="true"/>
|
||||
<arg name="main_camera" default="true"/>
|
||||
<arg name="optical_flow" default="false"/>
|
||||
<arg name="optical_flow" default="true"/>
|
||||
<arg name="aruco" default="false"/>
|
||||
<arg name="rangefinder_vl53l1x" default="false"/>
|
||||
<arg name="rangefinder_vl53l1x" default="true"/>
|
||||
<arg name="led" default="true"/>
|
||||
<arg name="rc" default="true"/>
|
||||
<arg name="shell" default="true"/>
|
||||
|
||||
<!-- log formatting -->
|
||||
<env name="ROSCONSOLE_FORMAT" value="[${severity}] [${time}]: ${logger}: ${message}"/>
|
||||
|
||||
<!-- mavros -->
|
||||
<include file="$(find clever)/launch/mavros.launch">
|
||||
<include file="$(find clover)/launch/mavros.launch">
|
||||
<arg name="fcu_conn" value="$(arg fcu_conn)"/>
|
||||
<arg name="fcu_ip" value="$(arg fcu_ip)"/>
|
||||
<arg name="fcu_sys_id" value="$(arg fcu_sys_id)"/>
|
||||
<arg name="gcs_bridge" value="$(arg gcs_bridge)"/>
|
||||
</include>
|
||||
|
||||
@@ -28,13 +31,14 @@
|
||||
</node>
|
||||
|
||||
<!-- aruco markers -->
|
||||
<include file="$(find clever)/launch/aruco.launch" if="$(arg aruco)"/>
|
||||
<include file="$(find clover)/launch/aruco.launch" if="$(arg aruco)"/>
|
||||
|
||||
<!-- optical flow -->
|
||||
<node pkg="nodelet" type="nodelet" name="optical_flow" args="load clever/optical_flow nodelet_manager" if="$(arg optical_flow)" clear_params="true" output="screen">
|
||||
<node pkg="nodelet" type="nodelet" name="optical_flow" args="load clover/optical_flow nodelet_manager" if="$(arg optical_flow)" clear_params="true" output="screen">
|
||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<param name="calc_flow_gyro" value="true"/>
|
||||
<param name="roi_rad" value="0.8"/>
|
||||
</node>
|
||||
|
||||
<!-- main nodelet manager -->
|
||||
@@ -45,14 +49,14 @@
|
||||
<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 -->
|
||||
<node name="simple_offboard" pkg="clever" type="simple_offboard" output="screen" clear_params="true">
|
||||
<node name="simple_offboard" pkg="clover" type="simple_offboard" output="screen" clear_params="true">
|
||||
<param name="reference_frames/body" value="map"/>
|
||||
<param name="reference_frames/base_link" value="map"/>
|
||||
<param name="reference_frames/navigate_target" value="map"/>
|
||||
</node>
|
||||
|
||||
<!-- main camera -->
|
||||
<include file="$(find clever)/launch/main_camera.launch" if="$(arg main_camera)"/>
|
||||
<include file="$(find clover)/launch/main_camera.launch" if="$(arg main_camera)"/>
|
||||
|
||||
<!-- rosbridge -->
|
||||
<include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" if="$(eval rosbridge or rc)"/>
|
||||
@@ -68,11 +72,14 @@
|
||||
</node>
|
||||
|
||||
<!-- led strip -->
|
||||
<include file="$(find clever)/launch/led.launch" if="$(arg led)"/>
|
||||
<include file="$(find clover)/launch/led.launch" if="$(arg led)"/>
|
||||
|
||||
<!-- rc backend -->
|
||||
<node name="rc" pkg="clever" type="rc" output="screen" if="$(arg rc)" clear_params="true">
|
||||
<node name="rc" pkg="clover" type="rc" output="screen" if="$(arg rc)" clear_params="true">
|
||||
<!-- Send fake GCS heartbeats. Set to "true" for upstream PX4 -->
|
||||
<param name="use_fake_gcs" value="false"/>
|
||||
</node>
|
||||
|
||||
<!-- Shell access through ROS service -->
|
||||
<node name="shell" pkg="clover" type="shell" output="screen" if="$(arg shell)"/>
|
||||
</launch>
|
||||
@@ -3,7 +3,7 @@
|
||||
<arg name="led_effect" default="true"/>
|
||||
<arg name="led_notify" default="true"/>
|
||||
|
||||
<!-- For additional help go to https://clever.coex.tech/led -->
|
||||
<!-- For additional help go to https://clover.coex.tech/led -->
|
||||
|
||||
<!-- ws281x led strip driver -->
|
||||
<node pkg="ws281x" name="led" type="ws281x_node" clear_params="true" output="screen" if="$(arg ws281x)">
|
||||
@@ -17,7 +17,7 @@
|
||||
</node>
|
||||
|
||||
<!-- high level led effects control, events notification with leds -->
|
||||
<node pkg="clever" name="led_effect" type="led" ns="led" clear_params="true" output="screen" if="$(arg led_effect)">
|
||||
<node pkg="clover" name="led_effect" type="led" ns="led" clear_params="true" output="screen" if="$(arg led_effect)">
|
||||
<param name="blink_rate" value="2"/>
|
||||
<param name="fade_period" value="0.5"/>
|
||||
<param name="rainbow_period" value="5"/>
|
||||
37
clover/launch/main_camera.launch
Normal file
@@ -0,0 +1,37 @@
|
||||
<launch>
|
||||
<!-- article about camera setup: https://clover.coex.tech/camera_setup -->
|
||||
|
||||
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up -->
|
||||
<arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
|
||||
|
||||
<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 == 'forward')" 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 == 'up' and direction_y == 'backward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 1.5707963 0 0 base_link main_camera_optical"/>
|
||||
<node if="$(eval direction_z == 'up' and direction_y == 'forward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 0.07 -1.5707963 0 0 base_link main_camera_optical"/>
|
||||
|
||||
<!-- Template for custom camera orientation -->
|
||||
<!-- Camera position and orientation are represented by base_link -> main_camera_optical transform -->
|
||||
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
|
||||
<!-- <node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/> -->
|
||||
|
||||
<!-- camera node -->
|
||||
<node pkg="nodelet" type="nodelet" name="main_camera" args="load cv_camera/CvCameraNodelet nodelet_manager" clear_params="true">
|
||||
<param name="device_path" value="/dev/video0"/> <!-- v4l2 device -->
|
||||
<param name="frame_id" value="main_camera_optical"/>
|
||||
<param name="camera_info_url" value="file://$(find clover)/camera_info/fisheye_cam.yaml"/>
|
||||
|
||||
<param name="rate" value="100"/> <!-- poll rate -->
|
||||
<param name="cv_cap_prop_fps" value="40"/> <!-- camera FPS -->
|
||||
<param name="capture_delay" value="0.02"/> <!-- approximate delay on frame retrieving -->
|
||||
<param name="rescale_camera_info" value="true"/> <!-- automatically rescale camera calibration info -->
|
||||
|
||||
<!-- camera resolution -->
|
||||
<param name="image_width" value="320"/>
|
||||
<param name="image_height" value="240"/>
|
||||
</node>
|
||||
|
||||
<!-- camera visualization markers -->
|
||||
<node pkg="clover" type="camera_markers" ns="main_camera" name="main_camera_markers">
|
||||
<param name="scale" value="3.0"/>
|
||||
</node>
|
||||
</launch>
|
||||
@@ -1,6 +1,7 @@
|
||||
<launch>
|
||||
<arg name="fcu_conn" default="usb"/> <!-- options: usb, uart, tcp, udp, sitl -->
|
||||
<arg name="fcu_ip" default="127.0.0.1"/>
|
||||
<arg name="fcu_sys_id" default="1"/>
|
||||
<arg name="gcs_bridge" default="tcp"/>
|
||||
<arg name="viz" default="true"/>
|
||||
<arg name="respawn" default="true"/>
|
||||
@@ -19,6 +20,9 @@
|
||||
<!-- sitl since PX4 1.9.0 -->
|
||||
<param name="fcu_url" value="udp://@$(arg fcu_ip):14580" if="$(eval fcu_conn == 'sitl')"/>
|
||||
|
||||
<!-- set target_system_id -->
|
||||
<param name="target_system_id" value="$(arg fcu_sys_id)" />
|
||||
|
||||
<!-- gcs bridge -->
|
||||
<param name="gcs_url" value="tcp-l://0.0.0.0:5760" if="$(eval gcs_bridge == 'tcp')"/>
|
||||
<param name="gcs_url" value="udp://0.0.0.0:14550@14550" if="$(eval gcs_bridge == 'udp')"/>
|
||||
@@ -29,7 +33,7 @@
|
||||
<param name="conn/timeout" value="8"/>
|
||||
|
||||
<!-- basic params -->
|
||||
<rosparam command="load" file="$(find clever)/launch/mavros_config.yaml"/>
|
||||
<rosparam command="load" file="$(find clover)/launch/mavros_config.yaml"/>
|
||||
|
||||
<!-- remap rangefinder -->
|
||||
<remap from="mavros/distance_sensor/rangefinder_sub" to="rangefinder/range"/>
|
||||
@@ -1,9 +1,9 @@
|
||||
<launch>
|
||||
<!-- Clever configuration for testing in sitl -->
|
||||
<!-- clover configuration for testing in sitl -->
|
||||
<arg name="ip" default="127.0.0.1"/>
|
||||
<arg name="rosbridge" default="false"/>
|
||||
|
||||
<include file="$(find clever)/launch/clever.launch">
|
||||
<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"/>
|
||||
5
clover/nodelet_plugins.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<library path="lib/libclover">
|
||||
<class name="clover/optical_flow" type="OpticalFlow" base_class_type="nodelet::Nodelet">
|
||||
<description/>
|
||||
</class>
|
||||
</library>
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>clever</name>
|
||||
<name>clover</name>
|
||||
<version>0.0.1</version>
|
||||
<description>The CLEVER package</description>
|
||||
<description>The Clover package</description>
|
||||
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
<license>MIT</license>
|
||||
|
||||
<url type="website">https://clever.coex.tech/</url>
|
||||
<url type="website">https://clover.coex.tech/</url>
|
||||
<author email="okalachev@gmail.com">Oleg Kalachev</author>
|
||||
<author email="urpylka@gmail.com">Artem Smirnov</author>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
<!-- Package format specifier version 2.0 allows specifying dependencies for both
|
||||
build- and runtime in a single <depend> element -->
|
||||
<depend>message_generation</depend>
|
||||
<depend>roscpp</depend>
|
||||
<depend>rospy</depend>
|
||||
<depend>std_srvs</depend>
|
||||
@@ -33,8 +34,6 @@
|
||||
<depend>mavros_extras</depend>
|
||||
<depend>cv_camera</depend>
|
||||
<depend>cv_bridge</depend>
|
||||
<!-- FIXME: OpenCV3 is not in Melodic -->
|
||||
<!-- <depend>opencv3</depend> -->
|
||||
<depend>rosbridge_server</depend>
|
||||
<depend>web_video_server</depend>
|
||||
<depend>tf2_web_republisher</depend>
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Usage
|
||||
# fpv_camera <video_device> <http port>
|
||||
# camera_stream <video_device> <http port>
|
||||
|
||||
echo "Starting FPV camera $1 on :$2"
|
||||
echo "Starting camera stream $1 on :$2"
|
||||
mjpg_streamer -i "/usr/lib/input_uvc.so -d $1 -r 320x240 -f 30" -o "/usr/lib/output_http.so -w /usr/share/mjpg_streamer/www -p $2"
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <string>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <clever/SetLEDEffect.h>
|
||||
#include <clover/SetLEDEffect.h>
|
||||
#include <led_msgs/SetLEDs.h>
|
||||
#include <led_msgs/LEDState.h>
|
||||
#include <led_msgs/LEDStateArray.h>
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <mavros_msgs/State.h>
|
||||
#include <rosgraph_msgs/Log.h>
|
||||
|
||||
clever::SetLEDEffect::Request current_effect;
|
||||
clover::SetLEDEffect::Request current_effect;
|
||||
int led_count;
|
||||
ros::Timer timer;
|
||||
ros::Time start_time;
|
||||
@@ -144,7 +144,7 @@ void proceed(const ros::TimerEvent& event)
|
||||
}
|
||||
}
|
||||
|
||||
bool setEffect(clever::SetLEDEffect::Request& req, clever::SetLEDEffect::Response& res)
|
||||
bool setEffect(clover::SetLEDEffect::Request& req, clover::SetLEDEffect::Response& res)
|
||||
{
|
||||
res.success = true;
|
||||
|
||||
@@ -237,7 +237,7 @@ void notify(const std::string& event)
|
||||
ros::param::has("~notify/" + event + "/g") ||
|
||||
ros::param::has("~notify/" + event + "/b")) {
|
||||
ROS_INFO_THROTTLE(5, "led: notify %s", event.c_str());
|
||||
clever::SetLEDEffect effect;
|
||||
clover::SetLEDEffect effect;
|
||||
effect.request.effect = ros::param::param("~notify/" + event + "/effect", std::string(""));
|
||||
effect.request.r = ros::param::param("~notify/" + event + "/r", 0);
|
||||
effect.request.g = ros::param::param("~notify/" + event + "/g", 0);
|
||||
@@ -263,7 +263,10 @@ void handleMavrosState(const mavros_msgs::State& msg)
|
||||
// remove the part before "."
|
||||
mode = mode.substr(mode.find(".") + 1);
|
||||
}
|
||||
notify(mode);
|
||||
std::string err;
|
||||
if (ros::names::validate(mode, err)) {
|
||||
notify(mode);
|
||||
}
|
||||
}
|
||||
mavros_state = msg;
|
||||
}
|
||||
@@ -46,7 +46,9 @@ private:
|
||||
image_transport::CameraSubscriber img_sub_;
|
||||
image_transport::Publisher img_pub_;
|
||||
mavros_msgs::OpticalFlowRad flow_;
|
||||
int roi_, roi_2_;
|
||||
int roi_px_;
|
||||
double roi_rad_;
|
||||
cv::Rect roi_;
|
||||
Mat hann_;
|
||||
Mat prev_, curr_;
|
||||
Mat camera_matrix_, dist_coeffs_;
|
||||
@@ -63,8 +65,8 @@ private:
|
||||
|
||||
nh.param<std::string>("mavros/local_position/tf/frame_id", local_frame_id_, "map");
|
||||
nh.param<std::string>("mavros/local_position/tf/child_frame_id", fcu_frame_id_, "base_link");
|
||||
nh_priv.param("roi", roi_, 128);
|
||||
roi_2_ = roi_ / 2;
|
||||
nh_priv.param("roi", roi_px_, 128);
|
||||
nh_priv.param("roi_rad", roi_rad_, 0.0);
|
||||
nh_priv.param("calc_flow_gyro", calc_flow_gyro_, false);
|
||||
|
||||
img_sub_ = it.subscribeCamera("image_raw", 1, &OpticalFlow::flow, this);
|
||||
@@ -112,9 +114,31 @@ private:
|
||||
|
||||
auto img = cv_bridge::toCvShare(msg, "mono8")->image;
|
||||
|
||||
// Apply ROI
|
||||
if (roi_ != 0) {
|
||||
img = img(cv::Rect((msg->width / 2 - roi_2_), (msg->height / 2 - roi_2_), roi_, roi_));
|
||||
if (roi_.width == 0) { // ROI is not calculated
|
||||
// Calculate ROI
|
||||
if (roi_rad_ != 0) {
|
||||
std::vector<cv::Point3f> object_points = {
|
||||
cv::Point3f(-sin(roi_rad_ / 2), -sin(roi_rad_ / 2), cos(roi_rad_ / 2)),
|
||||
cv::Point3f(sin(roi_rad_ / 2), sin(roi_rad_ / 2), cos(roi_rad_ / 2)),
|
||||
};
|
||||
|
||||
std::vector<double> vec { 0, 0, 0 };
|
||||
std::vector<cv::Point2f> img_points;
|
||||
cv::projectPoints(object_points, vec, vec, camera_matrix_, dist_coeffs_, img_points);
|
||||
|
||||
roi_ = cv::Rect(cv::Point2i(round(img_points[0].x), round(img_points[0].y)),
|
||||
cv::Point2i(round(img_points[1].x), round(img_points[1].y)));
|
||||
|
||||
ROS_INFO("ROI: %d %d - %d %d ", roi_.tl().x, roi_.tl().y, roi_.br().x, roi_.br().y);
|
||||
|
||||
} else if (roi_px_ != 0) {
|
||||
roi_ = cv::Rect((msg->width / 2 - roi_px_ / 2), (msg->height / 2 - roi_px_ / 2), roi_px_, roi_px_);
|
||||
}
|
||||
}
|
||||
|
||||
if (roi_.width != 0) { // ROI is set
|
||||
// Apply ROI
|
||||
img = img(roi_);
|
||||
}
|
||||
|
||||
img.convertTo(curr_, CV_32F);
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* CLEVER mobile remote control backend
|
||||
* Clover mobile remote control backend
|
||||
* Send ManualControl messages through UDP
|
||||
* 'latched_state' topic
|
||||
*
|
||||
@@ -200,17 +200,17 @@ def check_fcu():
|
||||
info('no version data available from SITL')
|
||||
|
||||
r = re.compile(r'^FW (git tag|version): (v?\d\.\d\.\d.*)$')
|
||||
is_clever_firmware = False
|
||||
is_clover_firmware = False
|
||||
for ver_line in version_str.split('\n'):
|
||||
match = r.search(ver_line)
|
||||
if match is not None:
|
||||
field, version = match.groups()
|
||||
info('firmware %s: %s' % (field, version))
|
||||
if 'clever' in version:
|
||||
is_clever_firmware = True
|
||||
if 'clover' in version or 'clever' in version:
|
||||
is_clover_firmware = True
|
||||
|
||||
if not is_clever_firmware:
|
||||
failure('not running Clever PX4 firmware, https://clever.coex.tech/firmware')
|
||||
if not is_clover_firmware:
|
||||
failure('not running Clover PX4 firmware, https://clover.coex.tech/firmware')
|
||||
|
||||
est = get_param('SYS_MC_EST_GROUP')
|
||||
if est == 1:
|
||||
@@ -250,11 +250,11 @@ def check_fcu():
|
||||
try:
|
||||
battery = rospy.wait_for_message('mavros/battery', BatteryState, timeout=3)
|
||||
if not battery.cell_voltage:
|
||||
failure('cell voltage is not available, https://clever.coex.tech/power')
|
||||
failure('cell voltage is not available, https://clover.coex.tech/power')
|
||||
else:
|
||||
cell = battery.cell_voltage[0]
|
||||
if cell > 4.3 or cell < 3.0:
|
||||
failure('incorrect cell voltage: %.2f V, https://clever.coex.tech/power', cell)
|
||||
failure('incorrect cell voltage: %.2f V, https://clover.coex.tech/power', cell)
|
||||
elif cell < 3.7:
|
||||
failure('critically low cell voltage: %.2f V, recharge battery', cell)
|
||||
except rospy.ROSException:
|
||||
@@ -311,7 +311,7 @@ def check_camera(name):
|
||||
if not optical or not cable:
|
||||
info('%s: custom camera orientation detected', name)
|
||||
else:
|
||||
info('camera is oriented %s, camera cable goes %s', optical, cable)
|
||||
info('camera is oriented %s, cable from camera goes %s', optical, cable)
|
||||
|
||||
except tf2_ros.TransformException:
|
||||
failure('cannot transform from base_link to camera frame')
|
||||
@@ -339,8 +339,11 @@ def is_process_running(binary, exact=False, full=False):
|
||||
@check('ArUco markers')
|
||||
def check_aruco():
|
||||
if is_process_running('aruco_detect', full=True):
|
||||
info('aruco_detect/length = %g m', rospy.get_param('aruco_detect/length'))
|
||||
known_tilt = rospy.get_param('aruco_detect/known_tilt')
|
||||
try:
|
||||
info('aruco_detect/length = %g m', rospy.get_param('aruco_detect/length'))
|
||||
except KeyError:
|
||||
failure('aruco_detect/length parameter is not set')
|
||||
known_tilt = rospy.get_param('aruco_detect/known_tilt', '')
|
||||
if known_tilt == 'map':
|
||||
known_tilt += ' (ALL markers are on the floor)'
|
||||
elif known_tilt == 'map_flipped':
|
||||
@@ -356,7 +359,7 @@ def check_aruco():
|
||||
return
|
||||
|
||||
if is_process_running('aruco_map', full=True):
|
||||
known_tilt = rospy.get_param('aruco_map/known_tilt')
|
||||
known_tilt = rospy.get_param('aruco_map/known_tilt', '')
|
||||
if known_tilt == 'map':
|
||||
known_tilt += ' (marker\'s map is on the floor)'
|
||||
elif known_tilt == 'map_flipped':
|
||||
@@ -516,7 +519,7 @@ def check_global_position():
|
||||
try:
|
||||
rospy.wait_for_message('mavros/global_position/global', NavSatFix, timeout=1)
|
||||
except rospy.ROSException:
|
||||
failure('no global position')
|
||||
info('no global position')
|
||||
|
||||
|
||||
@check('Optical flow')
|
||||
@@ -629,16 +632,16 @@ def check_cpu_usage():
|
||||
cpu.strip(), cmd.strip(), pid.strip())
|
||||
|
||||
|
||||
@check('clever.service')
|
||||
def check_clever_service():
|
||||
@check('clover.service')
|
||||
def check_clover_service():
|
||||
try:
|
||||
output = subprocess.check_output('systemctl show -p ActiveState --value clever.service'.split(),
|
||||
output = subprocess.check_output('systemctl show -p ActiveState --value clover.service'.split(),
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
failure('systemctl returned %s: %s', e.returncode, e.output)
|
||||
return
|
||||
if 'inactive' in output:
|
||||
failure('service is not running, try sudo systemctl restart clever')
|
||||
failure('service is not running, try sudo systemctl restart clover')
|
||||
return
|
||||
elif 'failed' in output:
|
||||
failure('service failed to run, check your launch-files')
|
||||
@@ -646,7 +649,7 @@ def check_clever_service():
|
||||
r = re.compile(r'^(.*)\[(FATAL|ERROR)\] \[\d+.\d+\]: (.*?)(\x1b(.*))?$')
|
||||
error_count = OrderedDict()
|
||||
try:
|
||||
for line in open('/tmp/clever.err', 'r'):
|
||||
for line in open('/tmp/clover.err', 'r'):
|
||||
node_error = r.search(line)
|
||||
if node_error:
|
||||
msg = node_error.groups()[1] + ': ' + node_error.groups()[2]
|
||||
@@ -670,9 +673,9 @@ def check_clever_service():
|
||||
@check('Image')
|
||||
def check_image():
|
||||
try:
|
||||
info('version: %s', open('/etc/clever_version').read().strip())
|
||||
info('version: %s', open('/etc/clover_version').read().strip())
|
||||
except IOError:
|
||||
info('no /etc/clever_version file, not the Clever image?')
|
||||
info('no /etc/clover_version file, not the Clover image?')
|
||||
|
||||
|
||||
@check('Preflight status')
|
||||
@@ -715,7 +718,7 @@ def check_network():
|
||||
if ros_hostname in parts:
|
||||
break
|
||||
else:
|
||||
failure('not found %s in /etc/hosts, ROS will malfunction if network interfaces are down, https://clever.coex.tech/hostname', ros_hostname)
|
||||
failure('not found %s in /etc/hosts, ROS will malfunction if network interfaces are down, https://clover.coex.tech/hostname', ros_hostname)
|
||||
|
||||
|
||||
@check('RPi health')
|
||||
@@ -730,7 +733,18 @@ def check_rpi_health():
|
||||
FLAG_UNDERVOLTAGE_OCCURRED = 0x10000
|
||||
FLAG_FREQ_CAP_OCCURRED = 0x20000
|
||||
FLAG_THROTTLING_OCCURRED = 0x40000
|
||||
FLAG_THERMAL_LIMIT_OUCCURRED = 0x80000
|
||||
FLAG_THERMAL_LIMIT_OCCURRED = 0x80000
|
||||
|
||||
FLAG_DESCRIPTIONS = (
|
||||
(FLAG_THROTTLING_NOW, 'system throttled to prevent damage'),
|
||||
(FLAG_THROTTLING_OCCURRED, 'your system is susceptible to throttling'),
|
||||
(FLAG_UNDERVOLTAGE_NOW, 'not enough power for onboard computer, flight inadvisable'),
|
||||
(FLAG_UNDERVOLTAGE_OCCURRED, 'power supply cannot provide enough power'),
|
||||
(FLAG_FREQ_CAP_NOW, 'CPU reached thermal limit and is throttled now'),
|
||||
(FLAG_FREQ_CAP_OCCURRED, 'CPU may overheat during drone operation, consider additional cooling'),
|
||||
(FLAG_THERMAL_LIMIT_NOW, 'CPU reached soft thermal limit, frequency reduced'),
|
||||
(FLAG_THERMAL_LIMIT_OCCURRED, 'CPU may reach soft thermal limit, consider additional cooling'),
|
||||
)
|
||||
|
||||
try:
|
||||
# vcgencmd outputs a single string in a form of
|
||||
@@ -743,19 +757,23 @@ def check_rpi_health():
|
||||
return
|
||||
|
||||
throttle_mask = int(output.split('=')[1], base=16)
|
||||
if throttle_mask & (FLAG_THROTTLING_NOW | FLAG_THROTTLING_OCCURRED):
|
||||
failure('system throttled to prevent damage')
|
||||
if throttle_mask & (FLAG_UNDERVOLTAGE_NOW | FLAG_UNDERVOLTAGE_OCCURRED):
|
||||
failure('not enough power for onboard computer, flight inadvisable')
|
||||
if throttle_mask & (FLAG_FREQ_CAP_NOW | FLAG_FREQ_CAP_OCCURRED):
|
||||
failure('CPU frequency reduced to avoid overheating')
|
||||
if throttle_mask & (FLAG_THERMAL_LIMIT_NOW | FLAG_THERMAL_LIMIT_OUCCURRED):
|
||||
failure('CPU over soft temperature limit, expect performance loss')
|
||||
for flag_description in FLAG_DESCRIPTIONS:
|
||||
if throttle_mask & flag_description[0]:
|
||||
failure(flag_description[1])
|
||||
|
||||
|
||||
@check('Board')
|
||||
def check_board():
|
||||
try:
|
||||
info('%s', open('/proc/device-tree/model').readline())
|
||||
except IOError:
|
||||
info('could not open /proc/device-tree/model, not a Raspberry Pi?')
|
||||
|
||||
|
||||
def selfcheck():
|
||||
check_image()
|
||||
check_clever_service()
|
||||
check_board()
|
||||
check_clover_service()
|
||||
check_network()
|
||||
check_fcu()
|
||||
check_imu()
|
||||
50
clover/src/shell.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <ros/ros.h>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <std_msgs/String.h>
|
||||
|
||||
#include <clover/Execute.h>
|
||||
|
||||
ros::Duration timeout;
|
||||
|
||||
// TODO: handle timeout
|
||||
bool handle(clover::Execute::Request& req, clover::Execute::Response& res)
|
||||
{
|
||||
ROS_INFO("Execute: %s", req.cmd.c_str());
|
||||
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
|
||||
FILE *fp = popen(req.cmd.c_str(), "r");
|
||||
|
||||
if (fp == NULL) {
|
||||
res.code = clover::Execute::Request::CODE_FAIL;
|
||||
res.output = "popen() failed";
|
||||
return true;
|
||||
}
|
||||
|
||||
while (fgets(buffer.data(), buffer.size(), fp) != nullptr) {
|
||||
res.output += buffer.data();
|
||||
}
|
||||
|
||||
res.code = pclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "shell");
|
||||
ros::NodeHandle nh, nh_priv("~");
|
||||
|
||||
timeout = ros::Duration(nh_priv.param("timeout", 3.0));
|
||||
|
||||
auto gt_serv = nh.advertiseService("exec", &handle);
|
||||
|
||||
ROS_INFO("shell: ready");
|
||||
ros::spin();
|
||||
}
|
||||
@@ -37,18 +37,18 @@
|
||||
#include <mavros_msgs/State.h>
|
||||
#include <mavros_msgs/StatusText.h>
|
||||
|
||||
#include <clever/GetTelemetry.h>
|
||||
#include <clever/Navigate.h>
|
||||
#include <clever/NavigateGlobal.h>
|
||||
#include <clever/SetPosition.h>
|
||||
#include <clever/SetVelocity.h>
|
||||
#include <clever/SetAttitude.h>
|
||||
#include <clever/SetRates.h>
|
||||
#include <clover/GetTelemetry.h>
|
||||
#include <clover/Navigate.h>
|
||||
#include <clover/NavigateGlobal.h>
|
||||
#include <clover/SetPosition.h>
|
||||
#include <clover/SetVelocity.h>
|
||||
#include <clover/SetAttitude.h>
|
||||
#include <clover/SetRates.h>
|
||||
|
||||
using std::string;
|
||||
using namespace geometry_msgs;
|
||||
using namespace sensor_msgs;
|
||||
using namespace clever;
|
||||
using namespace clover;
|
||||
using mavros_msgs::PositionTarget;
|
||||
using mavros_msgs::AttitudeTarget;
|
||||
using mavros_msgs::Thrust;
|
||||
@@ -90,7 +90,7 @@ PositionTarget position_raw_msg;
|
||||
AttitudeTarget att_raw_msg;
|
||||
Thrust thrust_msg;
|
||||
TwistStamped rates_msg;
|
||||
TransformStamped target;
|
||||
TransformStamped target, setpoint;
|
||||
geometry_msgs::TransformStamped body;
|
||||
|
||||
// State
|
||||
@@ -433,6 +433,17 @@ void publish(const ros::Time stamp)
|
||||
position_raw_msg.position = position_msg.pose.position;
|
||||
position_raw_pub.publish(position_raw_msg);
|
||||
}
|
||||
|
||||
// publish setpoint frame
|
||||
if (!setpoint.child_frame_id.empty()) {
|
||||
setpoint.transform.translation.x = position_msg.pose.position.x;
|
||||
setpoint.transform.translation.y = position_msg.pose.position.y;
|
||||
setpoint.transform.translation.z = position_msg.pose.position.z;
|
||||
setpoint.transform.rotation = position_msg.pose.orientation;
|
||||
setpoint.header.frame_id = position_msg.header.frame_id;
|
||||
setpoint.header.stamp = position_msg.header.stamp;
|
||||
transform_broadcaster->sendTransform(setpoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (setpoint_type == VELOCITY) {
|
||||
@@ -479,7 +490,7 @@ inline void checkState()
|
||||
throw std::runtime_error("State timeout, check mavros settings");
|
||||
|
||||
if (!state.connected)
|
||||
throw std::runtime_error("No connection to FCU, https://clever.coex.tech/connection");
|
||||
throw std::runtime_error("No connection to FCU, https://clover.coex.tech/connection");
|
||||
}
|
||||
|
||||
#define ENSURE_FINITE(var) { if (!std::isfinite(var)) throw std::runtime_error(#var " argument cannot be NaN or Inf"); }
|
||||
@@ -764,6 +775,7 @@ int main(int argc, char **argv)
|
||||
nh.param<string>("mavros/local_position/tf/frame_id", local_frame, "map");
|
||||
nh.param<string>("mavros/local_position/tf/child_frame_id", fcu_frame, "base_link");
|
||||
nh_priv.param("target_frame", target.child_frame_id, string("navigate_target"));
|
||||
nh_priv.param("setpoint", setpoint.child_frame_id, string("setpoint"));
|
||||
nh_priv.param("auto_release", auto_release, true);
|
||||
nh_priv.param("land_only_in_offboard", land_only_in_offboard, true);
|
||||
nh_priv.param("nav_from_sp", nav_from_sp, true);
|
||||
7
clover/srv/Execute.srv
Normal file
@@ -0,0 +1,7 @@
|
||||
int32 CODE_FAIL = -1
|
||||
int32 CODE_TIMEOUT = -2
|
||||
|
||||
string cmd
|
||||
---
|
||||
string output
|
||||
int32 code
|
||||
@@ -2,10 +2,11 @@
|
||||
import rospy
|
||||
import pytest
|
||||
from mavros_msgs.msg import State
|
||||
from clover import srv
|
||||
|
||||
@pytest.fixture()
|
||||
def node():
|
||||
return rospy.init_node('clever_test', anonymous=True)
|
||||
return rospy.init_node('clover_test', anonymous=True)
|
||||
|
||||
def test_state(node):
|
||||
state = rospy.wait_for_message('mavros/state', State, timeout=10)
|
||||
@@ -27,3 +28,19 @@ def test_simple_offboard_services_available():
|
||||
def test_web_video_server(node):
|
||||
import urllib2
|
||||
urllib2.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 == ''
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<node pkg="mavros" type="mavros_node" name="mavros" required="true" output="screen">
|
||||
<param name="fcu_url" value="udp://@127.0.1:14557"/>
|
||||
<rosparam command="load" file="$(find clever)/launch/mavros_config.yaml"/>
|
||||
<rosparam command="load" file="$(find clover)/launch/mavros_config.yaml"/>
|
||||
</node>
|
||||
|
||||
<node name="visualization" pkg="mavros_extras" type="visualization" required="true">
|
||||
@@ -23,19 +23,21 @@
|
||||
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="map_flipped_frame" args="0 0 0 3.1415926 3.1415926 0 map map_flipped" required="true"/>
|
||||
|
||||
<node name="simple_offboard" pkg="clever" type="simple_offboard" required="true" output="screen">
|
||||
<node name="simple_offboard" pkg="clover" type="simple_offboard" required="true" output="screen">
|
||||
<param name="reference_frames/body" value="map"/>
|
||||
<param name="reference_frames/base_link" value="map"/>
|
||||
</node>
|
||||
|
||||
<node name="tf2_web_republisher" pkg="tf2_web_republisher" type="tf2_web_republisher" required="true"/>
|
||||
|
||||
<node name="rc" pkg="clever" type="rc" required="true" output="screen"/>
|
||||
<node name="rc" pkg="clover" type="rc" required="true" output="screen"/>
|
||||
|
||||
<node pkg="clever" name="led_effect" type="led" ns="led" clear_params="true" output="screen" required="true">
|
||||
<node name="shell" pkg="clover" type="shell" required="true" output="screen"/>
|
||||
|
||||
<node pkg="clover" name="led_effect" type="led" ns="led" clear_params="true" output="screen" required="true">
|
||||
<rosparam param="notify">startup: { r: 255, g: 255, b: 255 }</rosparam>
|
||||
</node>
|
||||
|
||||
<param name="test_module" value="$(find clever)/test/basic.py"/>
|
||||
<param name="test_module" value="$(find clover)/test/basic.py"/>
|
||||
<test test-name="basic_test" pkg="ros_pytest" type="ros_pytest_runner"/>
|
||||
</launch>
|
||||
@@ -1,14 +1,24 @@
|
||||
<h1>CLEVER Drone Kit Tools</h1>
|
||||
<h1>Clover Drone Kit Tools</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="docs">View documentation</a> (snapshot of <a href="https://clever.coex.tech">clever.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="" 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="viz.html">View 3D visualization</a> (<code>ros3djs</code>)</li>
|
||||
<li><a href="aruco_map.html">3D visualization for markers map</a> (<code>ros3djs</code>)</li>
|
||||
</ul>
|
||||
|
||||
<div class="version"></div>
|
||||
|
||||
<script src="js/roslib.js"></script>
|
||||
<script type="text/javascript">
|
||||
document.querySelector("#wvs").href = location.origin + ':8080';
|
||||
document.querySelector("#butterfly").href = location.origin + ':57575';
|
||||
|
||||
// Determine image version
|
||||
var ros = new ROSLIB.Ros({ url: 'ws://' + location.hostname + ':9090' });
|
||||
var exec = new ROSLIB.Service({ ros: ros, name : '/exec', serviceType : 'clover/Execute' });
|
||||
exec.callService(new ROSLIB.ServiceRequest({ cmd: 'cat /etc/clover_version' }), function(result) {
|
||||
document.querySelector('.version').innerHTML = 'Version: ' + result.output;
|
||||
});
|
||||
</script>
|
||||
3887
clover/www/js/ros3d.js
vendored
Normal file
1071
clever/www/js/roslib.js → clover/www/js/roslib.js
vendored
@@ -7,7 +7,7 @@ var titleEl = document.querySelector('title');
|
||||
ros.on('error', function(error) {
|
||||
titleEl.innerText = 'Disconnected';
|
||||
err = error;
|
||||
alert('Connection error: please enable \'rosbridge\' in clever.launch!');
|
||||
alert('Connection error: please enable \'rosbridge\' in clover.launch!');
|
||||
});
|
||||
|
||||
ros.on('connection', function() {
|
||||
|
Before Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 192 KiB |
|
Before Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 254 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 452 KiB |
|
Before Width: | Height: | Size: 491 KiB |
|
Before Width: | Height: | Size: 433 KiB |
|
Before Width: | Height: | Size: 496 KiB |
|
Before Width: | Height: | Size: 790 KiB |
|
Before Width: | Height: | Size: 365 KiB |
|
Before Width: | Height: | Size: 502 KiB |