Compare commits

..

99 Commits

Author SHA1 Message Date
Alexey Rogachevskiy
cda7858fb9 clover: Update ros3djs, THREE.js 2020-03-19 21:44:16 +03:00
Alexey Rogachevskiy
a01d199890 selfcheck: Be more Python3-compatible 2020-03-19 21:21:21 +03:00
Alexey Rogachevskiy
63a792b29d aruco_pose: Use python2 shebang
This shebang will be ignored with newer dynamic_reconfigure packages, and its presence should allow builds to succeed when older dynamic_reconfigure is used.
2020-03-18 21:46:09 +03:00
Alexey Rogachevskiy
360eb02909 Revert "aruco_pose: Use bash trampoline for dynamic_reconfigure"
This reverts commit 6b9d90d3d7.

Newer dynamic_reconfigure uses PYTHON_EXECUTABLE CMake substitution, eliminating the need for a shebang (or a trampoline).
2020-03-18 21:44:39 +03:00
Alexey Rogachevskiy
688b4e3acb aruco_pose: Convert largemap test to ros_pytest 2020-03-18 21:05:49 +03:00
Alexey Rogachevskiy
8042669ade clever: Remove shebang from basic.py test
Tests executed by ros_pytest are not meant to have shebangs anyway.
2020-03-18 20:47:09 +03:00
Alexey Rogachevskiy
6b9d90d3d7 aruco_pose: Use bash trampoline for dynamic_reconfigure 2020-03-18 19:17:17 +03:00
Alexey Rogachevskiy
4f110d4eaa builder: Install rpi_ws281x for Python 2 and 3 2020-03-18 17:10:50 +03:00
Alexey Rogachevskiy
f7eda0be97 Merge remote-tracking branch 'origin/master' into buster-python3 2020-03-18 16:03:02 +03:00
Alexey Rogachevskiy
1da2f76758 builder: Use pip3 for butterfly installation 2020-03-18 16:00:04 +03:00
Alexey Rogachevskiy
60a77a35a5 builder: Make pip refer to pip2 by default
This may break rosdep down the line, but it seems to call `pip3` explicitly
2020-03-18 15:58:12 +03:00
Oleg Kalachev
461f4f5904 Add new camera calibration article 2020-03-18 00:40:57 +03:00
Oleg Kalachev
4f8020ff35 docs: rename old camera calibration article 2020-03-18 00:40:57 +03:00
Oleg Kalachev
267aaf45d3 selfcheck.py: correctly detect unset aruco_detect/length 2020-03-17 23:11:46 +03:00
Oleg Kalachev
0b74430a11 selfcheck.py: don’t fall down on unset known_tilt 2020-03-17 23:07:16 +03:00
Oleg Kalachev
1746381da1 Add ROS service for executing shell commands (#210)
* Add ROS service for executing shell commands

* Show image version on index web page

* Add test for exec service

* Add shell node to clover.launch

* Remake exec handling, consider exit code and exec failures
2020-03-17 20:11:59 +03:00
Oleg Kalachev
6879723771 image: add some examples (#222)
* image: add some examples

* Rename 'fligth' node to 'leds'

* image: copy examples to /home/pi/examples

* examples: add information links

Co-authored-by: Alamoris <gonzalez1139@gmail.com>
2020-03-12 20:20:27 +03:00
Oleg Kalachev
b474f99665 genmap.py: print column names in output 2020-03-11 13:21:24 +03:00
Oleg Kalachev
60b0059ef1 genmap.py: make <first> argument not required 2020-03-11 13:21:05 +03:00
Oleg Kalachev
8dfb9a8f6c simple_offboard: add position setpoint frame 2020-03-10 19:23:40 +03:00
Oleg Kalachev
2c36fdb560 docs: add info on -h key of genmap.py 2020-03-10 17:20:00 +03:00
Oleg Kalachev
8d37c424eb genmap.py: add example usage 2020-03-10 17:06:17 +03:00
Oleg Kalachev
2f70ce4372 docs: fix 2020-03-10 13:55:27 +03:00
Oleg Kalachev
e9527b5efd led: don’t crash on incorrect mode value 2020-03-06 04:25:48 +03:00
Oleg Kalachev
351b33cc5f genmap.py: make top-left by default (#220)
* genmap.py: make top-left by default

* docs: make top left by default in genmap

* genmap.py: fix usage string
2020-03-06 02:04:19 +03:00
Alexey Rogachevskiy
a427d86f41 docs: Update contribution guidelines translation 2020-02-25 14:25:31 +03:00
Alexey Rogachevskiy
ef0f926a79 docs: Add failsafe config link to power.md (en) 2020-02-25 13:05:19 +03:00
Alexey Rogachevskiy
0b587b7dae docs: Translate failsafe article (en) 2020-02-25 13:03:22 +03:00
Alexey Rogachevskiy
770a76a450 init_rpi: Place wpa_supplicant.conf to /boot 2020-02-20 22:11:24 +03:00
Alexey Rogachevskiy
0ffde38b8b builder: Install ptvsd for python2 explicitly 2020-02-20 21:43:48 +03:00
Alexey Rogachevskiy
99632bf554 Merge remote-tracking branch 'origin/master' into buster-python3 2020-02-20 15:44:08 +03:00
Oleg Kalachev
16b2538dfa docs: commented out links to lessons that have not been translated 2020-02-20 00:48:45 +03:00
Oleg Kalachev
d01e6990b1 docs: add failsafe article 2020-02-20 00:21:44 +03:00
Oleg Kalachev
6fbdfb7817 clover.launch: enable optical flow by default 2020-02-19 18:28:14 +03:00
Oleg Kalachev
e05431cc75 docs: fix sonar example 2020-02-19 18:27:52 +03:00
Alexey Rogachevskiy
4c940f0b8b init_rpi: Unblock wi-fi on first boot 2020-02-19 17:00:49 +03:00
Alexey Rogachevskiy
2672b6784f builder: Set country for wpa_supplicant 2020-02-19 15:17:53 +03:00
Alexey Rogachevskiy
d44a80b357 builder: Don't try to deactivate nonexistent venv 2020-02-19 13:24:42 +03:00
Alexey Rogachevskiy
22ba3a1406 builder: Use raspbian 2020-02-13 release as base 2020-02-19 12:43:32 +03:00
Alexey Rogachevskiy
7cc91b2e32 Install ptvsd by default (#217)
* builder: Install ptvsd by default

* builder: Add ptvsd version check
2020-02-17 21:54:20 +03:00
Alexey Rogachevskiy
77189b5f5f builder: Install butterfly system-wide 2020-02-17 14:52:24 +03:00
Alexey Rogachevskiy
b37a32d4dc builder: Add pip for python2 back 2020-02-17 14:44:41 +03:00
Alexey Rogachevskiy
d6f8f4017f clover: Update roslib.js and ros3d.js 2020-02-14 19:22:02 +03:00
Oleg Kalachev
fca584cefe optical_flow: parameter for setting ROI in radians (#213)
* optical_flow: parameter for setting ROI in radians

* Compatibility with old OpenCV
2020-02-13 20:00:11 +03:00
Arthur Golubtsov
099e115def Fix typo 2020-02-13 10:10:24 +03:00
Oleg Kalachev
d2b9ec7166 Remove unused fpv_camera.launch 2020-02-13 07:39:45 +03:00
Alexey Rogachevskiy
b359414377 builder: Drop python2 tests 2020-02-12 23:29:04 +03:00
Alexey Rogachevskiy
6d4dd6956f tests: Use python3 for most of it, python2 for cv2 2020-02-12 22:18:03 +03:00
Oleg Kalachev
bda966bc90 Simplify camera orientation setting (#204)
* main_camera.launch: simplify camera orientation setting

* Fix camera transforms

* Move camera transform description closer to transform tempalte

* orientation => direction

* Fix
2020-02-12 20:48:29 +03:00
Oleg Kalachev
d182542153 aruco.launch: set default corner refinement method to 2 (contour) 2020-02-12 20:40:54 +03:00
Alexey Rogachevskiy
cb26f0933e builder: Fix python3.yaml identation 2020-02-11 19:44:51 +03:00
Alexey Rogachevskiy
d944f57ebb builder: Put python3.yaml into image 2020-02-11 19:20:54 +03:00
Alexey Rogachevskiy
ad430284de builder: Fix typo (meodic -> melodic) 2020-02-11 18:59:23 +03:00
Alexey Rogachevskiy
b5cf47fdb5 tests: Create ServiceProxy during validation 2020-02-11 18:53:17 +03:00
Alexey Rogachevskiy
99f24abf8d builder: Build against python3 2020-02-11 18:46:23 +03:00
Alamoris
bc74af3006 docs: Update cad models article 2020-02-11 13:18:41 +03:00
timkondratiev
d88cbaee85 docs: update Raspberry and rangefinder connection image (#211)
* Change rangefinder connection

Proper pin connection

* Delete outdated image

* Add updated image

* _
2020-02-09 04:18:49 +03:00
Oleg Kalachev
49d1fb5215 Add some excludes to check of assets sizes 2020-02-07 16:23:51 +03:00
Oleg Kalachev
e750395e01 docs: add illustration on focusing camera 2020-02-06 19:48:34 +03:00
Alamoris
5439e5c1df docs: Fix language typos 2020-02-06 17:35:57 +03:00
Alamoris
aac7dcae2f docs: Add camera holder stl model 2020-02-06 16:58:51 +03:00
Alexey Rogachevskiy
df78f17efb selfcheck: Print board model (/proc/device-tree/model) (#209) 2020-02-05 21:10:36 +03:00
Alexey Rogachevskiy
0fa7e0e496 selfcheck: Fix typo in constant name 2020-02-05 15:07:29 +03:00
Oleg Kalachev
dee58f2e47 Merge branch 'master' of github.com:CopterExpress/clever 2020-02-04 23:00:51 +03:00
Oleg Kalachev
197e02f4ba docs: fix links to camera setup article 2020-02-04 23:00:43 +03:00
Alexey Rogachevskiy
f7934554e4 builder: Move wpa_supplicant configuration to init_rpi (#207) 2020-02-04 13:18:28 +03:00
Oleg Kalachev
9a7ffef858 docs: make the main programming example more complete 2020-02-02 06:33:55 +03:00
Oleg Kalachev
d0619b4543 docs: fix link 2020-02-02 04:44:44 +03:00
Oleg Kalachev
0f0deb85da docs: fix blocking takeoff snippet 2020-01-31 19:51:09 +03:00
Oleg Kalachev
89ccf9c2b9 Rename package to clover (#179) 2020-01-31 03:24:21 +03:00
Alexey Rogachevskiy
32ff2d4e15 docs: Fix typo in aruco_marker.md 2020-01-30 17:50:03 +03:00
Oleg Kalachev
366fcc14f6 docs: navigate_wait fixes 2020-01-29 23:37:44 +03:00
Oleg Kalachev
2cd334c474 aruco_pose: dynamic reconfiguration of aruco detector (#180)
* aruco_detect: dynamic reconfiguration

* aruco_pose: Depend on dynamic_reconfigure

* aruco_pose: Use c++11 features instead of Boost

* aruco_pose: Rearrange parameters, reset to OpenCV defaults

* Update constrains for some parameters

* aruco_pose: don’t hard-cord defaults for dynamic reconfigure

* aruco_pose: add missing parameters

* aruco_pose: fix tests

* aruco_pose: typo

* aruco_pose: fix

* aruco_pose: fix test

* aruco_pose: hardcode some new dynamic reconfigure parameters

Co-authored-by: Alexey Rogachevskiy <sfalexrog@gmail.com>
Co-authored-by: Arthur Golubtsov <goldartt@gmail.com>
2020-01-29 05:17:39 +03:00
Alamoris
647652f85f docs: add 4g modem example 2020-01-27 13:20:08 +03:00
Oleg Kalachev
4022eb773d clever.launch: enable vl53l1x rangefinder by default 2020-01-26 02:48:48 +03:00
Oleg Kalachev
79a6a802f4 selfcheck.py: don’t consider lack of global position a failure 2020-01-24 07:22:39 +03:00
Oleg Kalachev
77f2bc739e selfcheck.py: clarify text 2020-01-23 23:13:23 +03:00
Alexey Rogachevskiy
05464ce767 selfcheck: Be more descriptive about throttling flags 2020-01-21 20:49:01 +03:00
Alexey Rogachevskiy
d5eae45e49 docs: Fix typo in Clever 3 assembly (en) 2020-01-21 14:07:23 +03:00
Sergey
cfe35e1c83 Update assemble_3.md (#201) 2020-01-21 13:59:39 +03:00
Alexey Rogachevskiy
10648825c0 selfcheck: Fix constant naming 2020-01-16 20:52:45 +03:00
Alexey Rogachevskiy
f8fb8a0a1a docs: add info on focusing camera (en) 2020-01-16 20:01:53 +03:00
Oleg Kalachev
a958742d9f docs: typo 2020-01-15 21:51:51 +03:00
Oleg Kalachev
8d7a12f2b4 docs: typos 2020-01-15 21:50:24 +03:00
Oleg Kalachev
856e0a5ed0 docs: small fix 2020-01-14 21:03:25 +03:00
Oleg Kalachev
da6cb48b62 docs: fix 2020-01-14 20:41:28 +03:00
Oleg Kalachev
459a93986e docs: add info on focusing camera (ru) 2020-01-14 19:35:40 +03:00
Oleg Kalachev
f6b3c8ab86 gitbook: fix redirects 2020-01-14 19:35:40 +03:00
Alamoris
20a29c3dd6 English-language article on connecting a copter using a 4g network (#200)
* docs: Add en version about 4g

* docs/4g: proofreading (en)

Co-authored-by: Alexey Rogachevskiy <sfalexrog@gmail.com>
2020-01-12 16:32:15 +03:00
Oleg Kalachev
49b436b505 docs: small fixes 2020-01-12 16:04:42 +03:00
Alamoris
6739a685d8 docs: update snippet flip code 2020-01-10 19:34:47 +03:00
Alamoris
d8d7839e0e docs: update article about CAD models 2020-01-10 17:34:37 +03:00
Alamoris
331a2a40bc Actualize clover4 assembling (#191)
* docs: actuilize ru clover 4 article

* docs: renamed image names in article

* docs: Update image folder name, update clever4 assembling instruction

* docs: Add part about voltae indicator

* docs: Delete reinforcing_pads.dxf
2020-01-10 15:31:07 +03:00
Alamoris
40856b9401 Merge pull request #199 from Alamoris/4g_connection
4g control instruction
2020-01-08 16:41:20 +03:00
Alamoris
9ca597dfd7 docs: Fix some spelling and logical typos 2020-01-08 15:43:46 +03:00
Alamoris
1f2484a9ef docs: Some small fixes 2019-12-31 15:55:41 +03:00
Alamoris
81cb04c912 docs: Fix markdown typos 2019-12-30 18:29:39 +03:00
Alamoris
085850cfdd docs: Add 4g setup instruction 2019-12-30 18:16:48 +03:00
Oleg Kalachev
5bef4a1e21 docs: bring robocross 2019 article back 2019-12-26 18:23:55 +03:00
259 changed files with 24961 additions and 5670 deletions

View File

@@ -57,7 +57,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 +65,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

View File

@@ -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
View 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"))

View File

@@ -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

View File

@@ -27,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>

View File

@@ -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)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (C) 2018 Copter Express Technologies
#
@@ -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

View File

@@ -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">

View File

@@ -1,26 +1,19 @@
#!/usr/bin/env python
import sys
import unittest
import json
import rospy
import rostest
import pytest
from sensor_msgs.msg import Image
from visualization_msgs.msg import MarkerArray as VisMarkerArray
@pytest.fixture
def node():
return rospy.init_node('test_aruco_largemap', anonymous=True)
class TestArucoPose(unittest.TestCase):
def setUp(self):
rospy.init_node('test_aruco_largemap', anonymous=True)
def test_large_map_image(node):
img = rospy.wait_for_message('aruco_map/image', Image, timeout=5)
assert img.width == 2000
assert img.height == 2000
assert img.encoding in ('mono8', 'rgb8')
def test_map_image(self):
img = rospy.wait_for_message('aruco_map/image', Image, timeout=5)
self.assertEqual(img.width, 2000)
self.assertEqual(img.height, 2000)
self.assertIn(img.encoding, ('mono8', 'rgb8'))
def test_map_visualization(self):
vis = rospy.wait_for_message('aruco_map/visualization', VisMarkerArray, timeout=5)
rostest.rosrun('aruco_pose', 'test_aruco_largemap', TestArucoPose, sys.argv)
def test_large_map_visualization(node):
vis = rospy.wait_for_message('aruco_map/visualization', VisMarkerArray, timeout=5)
assert len(vis.markers) == 11

View File

@@ -9,5 +9,6 @@
<param name="map" value="$(find aruco_pose)/test/largemap.txt"/>
</node>
<test test-name="test_aruco_pose_largemap" pkg="aruco_pose" type="largemap.py"/>
<param name="test_module" value="$(find aruco_pose)/test/largemap.py"/>
<test test-name="test_node_pass" pkg="ros_pytest" type="ros_pytest_runner"/>
</launch>

View File

View 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
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env python3
from distutils.core import setup
setup(name='clever',
version='1.0',
description='Clever transitional package for backwards compatibility',
author='Oleg Kalachev',
packages=['clever'],
)

View File

@@ -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

View File

@@ -0,0 +1,31 @@
# Information: https://clever.coex.tech/en/programming.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)
# Takeoff 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()

View File

@@ -0,0 +1,25 @@
# Information: https://clever.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

View File

@@ -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"

View 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]

View File

@@ -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:
# ---------

View File

@@ -0,0 +1,9 @@
python3-wxgtk:
debian:
buster: [python3-wxgtk4.0]
python3-serial:
debian:
buster: [python3-serial]
python3-requests:
debian:
buster: [python3-requests]

View File

@@ -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,24 @@ ${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/python3.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'

View File

@@ -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"

View File

@@ -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"

View File

@@ -65,10 +65,11 @@ 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/30-clover.list
echo "yaml file:///etc/ros/rosdep/python3.yaml" > /etc/ros/rosdep/sources.list.d/40-python3.list
my_travis_retry rosdep update
echo_stamp "Populate rosdep for ROS user"
@@ -87,31 +88,35 @@ resolve_rosdep() {
}
export ROS_IP='127.0.0.1' # needed for running tests
export ROS_PYTHON_VERSION=3
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 pip3 install wheel
my_travis_retry pip3 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 "Enable ROS services"
systemctl enable roscore
systemctl enable clover
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 \
@@ -130,7 +135,7 @@ echo_stamp "Install GeographicLib datasets (needed for mavros)" \
# FIXME: Buster comes with tornado==5.1.1 but we need tornado==4.2.1 for rosbridge_suite
# (note that Python 3 will still have a more recent version)
pip install tornado==4.2.1
pip3 install tornado==4.2.1
echo_stamp "Running tests"
cd /home/pi/catkin_ws

View File

@@ -67,8 +67,8 @@ 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
echo "deb http://deb.coex.tech/clever buster main" > /etc/apt/sources.list.d/clever.list
echo "deb http://deb.coex.tech/melodic-py3 buster main" > /etc/apt/sources.list.d/rpi-ros-melodic.list
echo "deb http://deb.coex.tech/clover buster main" > /etc/apt/sources.list.d/clover.list
echo_stamp "Update apt cache"
@@ -95,20 +95,21 @@ libjpeg8 \
tcpdump \
ltrace \
libpoco-dev \
python-rosdep \
python-rosinstall-generator \
python-wstool \
python-rosinstall \
python3-rosdep \
python3-rosinstall-generator \
python3-wstool \
python3-rosinstall \
build-essential \
libffi-dev \
monkey \
pigpio python-pigpio python3-pigpio \
i2c-tools \
espeak espeak-data python-espeak \
espeak espeak-data python3-espeak \
ntpdate \
python-dev \
python3-dev \
python-systemd \
python3-venv \
python3-systemd \
mjpg-streamer \
python3-opencv \
&& echo_stamp "Everything was installed!" "SUCCESS" \
@@ -132,13 +133,14 @@ pip3 --version
echo_stamp "Install and enable Butterfly (web terminal)"
echo_stamp "Workaround for tornado >= 6.0 breaking butterfly"
my_travis_retry pip3 install tornado==5.1.1
my_travis_retry pip3 install tornado==4.2.1
my_travis_retry pip3 install butterfly
my_travis_retry pip3 install butterfly[systemd]
systemctl enable butterfly.socket
echo_stamp "Install ws281x library"
my_travis_retry pip install --prefer-binary rpi_ws281x
my_travis_retry pip2 install --prefer-binary rpi_ws281x
my_travis_retry pip3 install --prefer-binary rpi_ws281x
echo_stamp "Setup Monkey"
mv /etc/monkey/sites/default /etc/monkey/sites/default.orig
@@ -153,6 +155,10 @@ 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 pip2 install ptvsd
my_travis_retry pip3 install ptvsd
echo_stamp "Add .vimrc"
cat << EOF > /home/pi/.vimrc
set mouse-=a

View File

@@ -18,13 +18,16 @@ echo "Run image tests"
export ROS_DISTRO='melodic'
export ROS_IP='127.0.0.1'
export ROS_PYTHON_VERSION=3
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
# Disable Python 2 tests for image - we're dropping support, right?
# ./tests_py2.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

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# validate all required modules installed
@@ -14,9 +14,11 @@ 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
get_telemetry = rospy.ServiceProxy('get_telemetry', GetTelemetry)
import tf2_ros
import tf2_geometry_msgs
@@ -27,4 +29,4 @@ import rpi_ws281x
import pigpio
from espeak import espeak
print cv2.getBuildInformation()
print(cv2.getBuildInformation())

View File

@@ -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
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env python3
# test backwards compatibility
from clever.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
SetAttitude, SetRates, SetLEDEffect

7
builder/test/tests_py2.py Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env python
# Make sure our Python 2 software is installed
import cv2
print(cv2.getBuildInformation())

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env python3
# Make sure our Python 3 software is installed
import cv2
print(cv2.getBuildInformation())

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,5 +0,0 @@
<library path="lib/libclever">
<class name="clever/optical_flow" type="OpticalFlow" base_class_type="nodelet::Nodelet">
<description/>
</class>
</library>

View File

@@ -1,5 +0,0 @@
flask==1.1.1
docopt==0.6.2
geopy==1.11.0
smbus2==0.2.1
VL53L1X==0.0.2

File diff suppressed because one or more lines are too long

View File

@@ -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)
@@ -81,6 +81,7 @@ add_service_files(
SetAttitude.srv
SetRates.srv
SetLEDEffect.srv
Execute.srv
)
## Generate actions in the 'action' folder
@@ -127,7 +128,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 +146,7 @@ include_directories(
)
# Declare a C++ library
add_library(clever
add_library(${PROJECT_NAME}
src/optical_flow.cpp
)
@@ -167,6 +168,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 +183,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,7 +202,7 @@ 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}
)
@@ -252,7 +259,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()

View File

@@ -10,6 +10,7 @@
<remap from="image_raw" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/>
<remap from="map_markers" to="aruco_map/markers" if="$(arg aruco_map)"/>
<param name="cornerRefinementMethod" value="2"/>
<param name="estimate_poses" value="true"/>
<param name="send_tf" value="true"/>
<param name="known_tilt" value="map"/>
@@ -31,7 +32,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"/>

View File

@@ -5,17 +5,18 @@
<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="gcs_bridge" value="$(arg gcs_bridge)"/>
@@ -28,13 +29,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 +47,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 +70,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>

View File

@@ -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"/>

View File

@@ -0,0 +1,37 @@
<launch>
<!-- article about camera setup: https://clever.coex.tech/camera_frame -->
<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_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="clover" type="camera_markers" ns="main_camera" name="main_camera_markers">
<param name="scale" value="3.0"/>
</node>
</launch>

View File

@@ -29,7 +29,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"/>

View File

@@ -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"/>

View File

@@ -0,0 +1,5 @@
<library path="lib/libclover">
<class name="clover/optical_flow" type="OpticalFlow" base_class_type="nodelet::Nodelet">
<description/>
</class>
</library>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0"?>
<package format="2">
<name>clever</name>
<package format="3">
<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>
@@ -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>
@@ -36,8 +37,10 @@
<depend>rosbridge_server</depend>
<depend>web_video_server</depend>
<depend>tf2_web_republisher</depend>
<depend>python-lxml</depend>
<exec_depend>python-pymavlink</exec_depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python-lxml</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3-lxml</depend>
<exec_depend condition="$ROS_PYTHON_VERSION == 2">python-pymavlink</exec_depend>
<exec_depend condition="$ROS_PYTHON_VERSION == 3">python-pymavlink</exec_depend>
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->

5
clover/requirements.txt Normal file
View File

@@ -0,0 +1,5 @@
flask==1.1.1
docopt==0.6.2
geopy==1.20.0
smbus2==0.3.0
VL53L1X==0.0.4

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -1,5 +1,5 @@
/*
* CLEVER mobile remote control backend
* Clover mobile remote control backend
* Send ManualControl messages through UDP
* 'latched_state' topic
*

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# coding=utf-8
# Copyright (C) 2018 Copter Express Technologies
@@ -138,7 +138,7 @@ def mavlink_exec(cmd, timeout=3.0):
timeout=3,
baudrate=0,
count=len(cmd),
data=map(ord, cmd.ljust(70, '\0')))
data=[ord(c) for c in cmd.ljust(70, '\0')])
msg.pack(link)
ros_msg = mavlink.convert_to_rosmsg(msg)
mavlink_pub.publish(ros_msg)
@@ -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://clever.coex.tech/firmware')
est = get_param('SYS_MC_EST_GROUP')
if est == 1:
@@ -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')
@@ -606,7 +609,7 @@ def check_rangefinder():
@check('Boot duration')
def check_boot_duration():
output = subprocess.check_output('systemd-analyze')
output = subprocess.check_output('systemd-analyze').decode()
r = re.compile(r'([\d\.]+)s\s*$', flags=re.MULTILINE)
duration = float(r.search(output).groups()[0])
if duration > 15:
@@ -617,7 +620,7 @@ def check_boot_duration():
def check_cpu_usage():
WHITELIST = 'nodelet',
CMD = "top -n 1 -b -i | tail -n +8 | awk '{ printf(\"%-8s\\t%-8s\\t%-8s\\n\", $1, $9, $12); }'"
output = subprocess.check_output(CMD, shell=True)
output = subprocess.check_output(CMD, shell=True).decode()
processes = output.split('\n')
for process in processes:
if not process:
@@ -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(),
stderr=subprocess.STDOUT)
output = subprocess.check_output('systemctl show -p ActiveState --value clover.service'.split(),
stderr=subprocess.STDOUT).decode()
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')
@@ -730,32 +733,47 @@ 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
# <parameter>=<value>
# In case of `get_throttled`, <value> is a hexadecimal number
# with some of the FLAGs OR'ed together
output = subprocess.check_output(['vcgencmd', 'get_throttled'])
output = subprocess.check_output(['vcgencmd', 'get_throttled']).decode()
except OSError:
failure('could not call vcgencmd binary; not a Raspberry Pi?')
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
View 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();
}

View File

@@ -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) {
@@ -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
View File

@@ -0,0 +1,7 @@
int32 CODE_FAIL = -1
int32 CODE_TIMEOUT = -2
string cmd
---
string output
int32 code

View File

@@ -1,11 +1,11 @@
#!/usr/bin/env python
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 +27,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 == ''

View File

@@ -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>

View File

@@ -1,4 +1,4 @@
<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>
@@ -8,7 +8,17 @@
<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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

915
clover/www/js/three.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -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() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 790 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 KiB

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