Compare commits

..

37 Commits

Author SHA1 Message Date
Oleg Kalachev
72b343575f sitemap config 2022-04-19 11:35:51 +04:00
Oleg Kalachev
0849413fe2 Fix hostname 2022-04-19 00:44:47 +04:00
Oleg Kalachev
2cab14c52f Update sitemap2 2022-04-19 00:44:15 +04:00
Oleg Kalachev
c20957cbf1 Update sitemap2 2022-04-16 01:13:57 +04:00
Oleg Kalachev
e9f892466f Some settings for sitemap2 2022-04-16 01:13:31 +04:00
Oleg Kalachev
91061cc9f1 Fix link 2022-04-15 03:30:19 +04:00
Oleg Kalachev
9db0c44177 Shorten titles of some sections in summary 2022-04-15 03:26:16 +04:00
Oleg Kalachev
5b3c3f0722 Remove links to next articles 2022-04-15 03:25:38 +04:00
Oleg Kalachev
84b1318f3d Styles for centered and bordered images 2022-04-15 03:08:40 +04:00
Oleg Kalachev
955011e812 Cleanup, add sitemap plugin 2022-04-14 23:41:09 +04:00
Oleg Kalachev
2561e8e6cb Localize navbar 2022-04-12 23:49:07 +04:00
Oleg Kalachev
d1209fd064 Add some links to navbar 2022-04-12 07:48:42 +04:00
Oleg Kalachev
e68fac8aad Styles for circle blocks 2022-04-12 06:35:43 +04:00
Oleg Kalachev
4f64fdf2e4 Some styling for Clover versions table 2022-04-12 06:35:10 +04:00
Oleg Kalachev
b77d4ed045 Some styling for logo 2022-04-12 06:32:30 +04:00
Oleg Kalachev
e2b8cb4be2 Add some logo 2022-04-12 05:55:00 +04:00
Oleg Kalachev
8db8075f15 Remove duplicating item from summary 2022-04-12 05:51:08 +04:00
Oleg Kalachev
578728b3a9 Exclude outdates documents from build 2022-04-12 05:37:20 +04:00
Oleg Kalachev
7154f5afc2 Allow using some deprecated and non-standard html tags 2022-04-12 05:36:55 +04:00
Oleg Kalachev
48fd45ea9a Fix HTML tag 2022-04-12 05:32:15 +04:00
Oleg Kalachev
12ca9c0eb9 Remove clear script as it doesn't work 2022-04-12 04:55:55 +04:00
Oleg Kalachev
784ce35080 Use @source in srcset 2022-04-12 04:55:25 +04:00
Oleg Kalachev
6c42c522ce Lowercase all images as VuePress doesn't handle uppercase extensions 2022-04-12 04:55:12 +04:00
Oleg Kalachev
b36d69b54f Add built docs site to .gitignore 2022-04-12 04:54:03 +04:00
Oleg Kalachev
0056bb1810 Fix some markdown mistakes 2022-04-12 04:53:52 +04:00
Oleg Kalachev
37ec19a19f Remove non-existent image 2022-04-12 04:50:41 +04:00
Oleg Kalachev
ea5151db51 Add markdown-it-attrs plugin for custom headers anchors
Syntax: # Header {#header-id}
2022-04-12 02:00:30 +04:00
Oleg Kalachev
bc032e5afb Include subarticles in flatten articles list 2022-04-12 01:55:33 +04:00
Oleg Kalachev
ed619935ce Config update 2022-04-12 01:01:53 +04:00
Oleg Kalachev
3b3b5b6a89 Implement plugin to convert gitbook rich-quotes to custom containers 2022-04-12 01:01:34 +04:00
Oleg Kalachev
4190353569 Insert intro article to each group 2022-04-12 00:40:05 +04:00
Oleg Kalachev
7c2e020a89 Linkify: true 2022-04-11 23:30:01 +04:00
Oleg Kalachev
6321ef8aa0 Toggle sidebar 2022-04-11 23:29:37 +04:00
Oleg Kalachev
172890ed13 Config for GitHub links 2022-04-11 23:29:14 +04:00
Oleg Kalachev
ae1e39dd82 Perform some cleanup 2022-04-11 23:28:36 +04:00
Oleg Kalachev
241b766bad Start working on transferring to VuePress 2022-04-09 07:32:58 +04:00
Oleg Kalachev
84bbe2e565 docs: fix some html problems 2022-04-08 20:27:20 +04:00
226 changed files with 615 additions and 2595 deletions

1
.gitattributes vendored
View File

@@ -3,7 +3,6 @@ roslib.js linguist-vendored
eventemitter2.js linguist-vendored eventemitter2.js linguist-vendored
ros3d.js linguist-vendored ros3d.js linguist-vendored
three.min.js linguist-vendored three.min.js linguist-vendored
json-to-pretty-yaml.js linguist-vendored
aruco_pose/vendor/* linguist-vendored aruco_pose/vendor/* linguist-vendored
blockly/* linguist-vendored blockly/* linguist-vendored
highlight/* linguist-vendored highlight/* linguist-vendored

View File

@@ -16,36 +16,8 @@ jobs:
# docker run --rm -v $(pwd):/root/catkin_ws/src/clover ros:melodic-ros-base /root/catkin_ws/src/clover/builder/standalone-install.sh # docker run --rm -v $(pwd):/root/catkin_ws/src/clover ros:melodic-ros-base /root/catkin_ws/src/clover/builder/standalone-install.sh
noetic: noetic:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ros:noetic-ros-base
defaults:
run:
working-directory: catkin_ws
shell: bash
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: - name: Native Noetic build
path: catkin_ws/src/clover run: |
- name: Install requirements docker run --rm -v $(pwd):/root/catkin_ws/src/clover ros:noetic-ros-base /root/catkin_ws/src/clover/builder/standalone-install.sh
run: apt-get update && apt-get -y install python3-pip fakeroot python3-bloom debhelper dpkg-dev
- name: Install dependencies
run: rosdep update && rosdep install --from-paths src --ignore-src -y
- name: Install GeographicLib datasets
run: wget -qO- https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh | bash
- name: catkin_make
run: source /opt/ros/$ROS_DISTRO/setup.bash && catkin_make
- name: Run tests
run: source devel/setup.bash && catkin_make run_tests && catkin_test_results
- name: Build Debian packages
run: |
source devel/setup.bash
for file in `find . -name "package.xml"`; do
cd $(dirname ${file})
bloom-generate rosdebian --os-name ubuntu --os-version $(lsb_release -cs) --ros-distro $ROS_DISTRO
fakeroot debian/rules binary
cd -
done
- uses: actions/upload-artifact@v3
with:
name: debian-packages
path: catkin_ws/src/clover/*.deb
retention-days: 1

View File

@@ -4,25 +4,16 @@ on:
push: push:
branches: [ '*' ] branches: [ '*' ]
pull_request: pull_request:
branches: [ '*' ] branches: [ master ]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
defaults:
run:
shell: bash
jobs: jobs:
docs: docs:
runs-on: ubuntu-22.04 runs-on: ubuntu-18.04
steps: steps:
- name: Cancel previous runs
uses: styfle/cancel-workflow-action@0.9.1
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v1 uses: actions/setup-node@v1
@@ -64,23 +55,14 @@ jobs:
- name: Download older PDFs - name: Download older PDFs
if: ${{ !steps.generate-pdf.outputs.GITBOOK_PDF_OK }} if: ${{ !steps.generate-pdf.outputs.GITBOOK_PDF_OK }}
run: | run: |
rm -f _book/clover*.pdf rm _book/clover*.pdf
wget --no-verbose https://clover.coex.tech/clover_ru.pdf -P _book/ wget --no-verbose https://clover.coex.tech/clover_ru.pdf -P _book/
wget --no-verbose https://clover.coex.tech/clover_en.pdf -P _book/ wget --no-verbose https://clover.coex.tech/clover_en.pdf -P _book/
- name: Upload artifact - name: Deploy
# if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: JamesIves/github-pages-deploy-action@4.1.3
uses: actions/upload-pages-artifact@v1 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
with: with:
path: _book branch: gh-pages
folder: _book
deploy-docs: clean: true
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} single-commit: true # to avoid multiple copies of large pdf files
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: docs
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1

3
.gitignore vendored
View File

@@ -7,3 +7,6 @@ package-lock.json
clover_blocks/programs/*.* clover_blocks/programs/*.*
!clover_blocks/programs/examples/* !clover_blocks/programs/examples/*
/.vscode/ /.vscode/
docs/.vuepress/.cache/
docs/.vuepress/.temp/
docs/.vuepress/dist

View File

@@ -83,10 +83,11 @@ add_message_files(
) )
## Generate services in the 'srv' folder ## Generate services in the 'srv' folder
add_service_files( # add_service_files(
FILES # FILES
SetMarkers.srv # Service1.srv
) # Service2.srv
# )
## Generate actions in the 'action' folder ## Generate actions in the 'action' folder
# add_action_files( # add_action_files(
@@ -119,7 +120,6 @@ generate_messages(
## Generate dynamic reconfigure parameters in the 'cfg' folder ## Generate dynamic reconfigure parameters in the 'cfg' folder
generate_dynamic_reconfigure_options( generate_dynamic_reconfigure_options(
cfg/Detector.cfg cfg/Detector.cfg
cfg/Map.cfg
) )
################################### ###################################
@@ -251,5 +251,4 @@ if (CATKIN_ENABLE_TESTING)
add_rostest(test/test_node_failure.test) add_rostest(test/test_node_failure.test)
add_rostest(test/largemap.test) add_rostest(test/largemap.test)
add_rostest(test/crash_opencv.test) add_rostest(test/crash_opencv.test)
add_rostest(test/duplicate.test)
endif() endif()

View File

@@ -51,7 +51,6 @@ It's recommended to run it within the same nodelet manager with the camera nodel
* `image_raw` (*sensor_msgs/Image*) camera image * `image_raw` (*sensor_msgs/Image*) camera image
* `camera_info` (*sensor_msgs/CameraInfo*) camera calibration info * `camera_info` (*sensor_msgs/CameraInfo*) camera calibration info
* `map_markers` (*aruco_pose/MarkerArray*) list of markers to disable TF transform publishing
#### Published #### Published
@@ -75,7 +74,6 @@ It's recommended to run it within the same nodelet manager with the camera nodel
* `~image_width` debug image width (default: 2000) * `~image_width` debug image width (default: 2000)
* `~image_height` debug image height (default: 2000) * `~image_height` debug image height (default: 2000)
* `~image_margin`  debug image margin (default: 200) * `~image_margin`  debug image margin (default: 200)
* `~image_axis` whether debug image should contain axis (default: true)
* `~dictionary` (*int*)  ArUco dictionary (default: 2) - should be the same as `dictionary` parameter of `aruco_detect` nodelet * `~dictionary` (*int*)  ArUco dictionary (default: 2) - should be the same as `dictionary` parameter of `aruco_detect` nodelet
Map file has one marker per line with the following line format: Map file has one marker per line with the following line format:
@@ -99,7 +97,6 @@ See examples in [`map`](map/) directory.
#### Published #### Published
* `~pose` (*geometry_msgs/PoseWithCovarianceStamped*) estimated map pose * `~pose` (*geometry_msgs/PoseWithCovarianceStamped*) estimated map pose
* `~map` (*aruco_pose/MarkerArray*) list of markers in the loaded map
* `~image` (*sensor_msgs/Image*) planarized map image * `~image` (*sensor_msgs/Image*) planarized map image
* `~visualization` (*visualization_msgs/MarkerArray*) markers map visualization for rviz * `~visualization` (*visualization_msgs/MarkerArray*) markers map visualization for rviz
* `~debug` (*sensor_msgs/Image*) debug image with detected markers and map axis * `~debug` (*sensor_msgs/Image*) debug image with detected markers and map axis

View File

@@ -10,8 +10,6 @@ gen = ParameterGenerator()
gen.add("enabled", bool_t, 0, "if detection enabled", True) gen.add("enabled", bool_t, 0, "if detection enabled", True)
gen.add("length", double_t, 0, "markers' side length", min=0, max=10)
gen.add("adaptiveThreshConstant", double_t, 0, gen.add("adaptiveThreshConstant", double_t, 0,
"Constant for adaptive thresholding before finding contours", "Constant for adaptive thresholding before finding contours",
p.adaptiveThreshConstant, 0, 100) p.adaptiveThreshConstant, 0, 100)

View File

@@ -1,14 +0,0 @@
#!/usr/bin/env python
PACKAGE = "aruco_pose"
from dynamic_reconfigure.parameter_generator_catkin import *
gen = ParameterGenerator()
gen.add("enabled", bool_t, 0, "if map detection enabled", True)
gen.add("map", str_t, 0, "full path for the map file")
gen.add("image_axis", bool_t, 0, "debug image axis", default=True)
exit(gen.generate(PACKAGE, "aruco_pose", "Map"))

View File

@@ -1,4 +1,3 @@
# id length x y z rot_z rot_y rot_x
0 0.33 0.0 9.0 0 0 0 0 0 0.33 0.0 9.0 0 0 0 0
1 0.33 1.0 9.0 0 0 0 0 1 0.33 1.0 9.0 0 0 0 0
2 0.33 2.0 9.0 0 0 0 0 2 0.33 2.0 9.0 0 0 0 0

View File

@@ -1,4 +1,3 @@
# id length x y z rot_z rot_y rot_x
107 0.33 0 0 0 0 0 0 107 0.33 0 0 0 0 0 0
106 0.33 0.77 0 0 0 0 0 106 0.33 0.77 0 0 0 0 0
105 0.33 0 0.77 0 0 0 0 105 0.33 0 0.77 0 0 0 0

View File

@@ -1,4 +1,3 @@
# id length x y z rot_z rot_y rot_x
14 0.365 0.000 0.0 0 0 0 0 14 0.365 0.000 0.0 0 0 0 0
15 0.365 1.335 0.0 0 0 0 0 15 0.365 1.335 0.0 0 0 0 0
30 0.365 2.865 0.0 0 0 0 0 30 0.365 2.865 0.0 0 0 0 0

View File

@@ -48,7 +48,6 @@
#include <aruco_pose/Marker.h> #include <aruco_pose/Marker.h>
#include <aruco_pose/MarkerArray.h> #include <aruco_pose/MarkerArray.h>
#include <aruco_pose/DetectorConfig.h> #include <aruco_pose/DetectorConfig.h>
#include <aruco_pose/SetMarkers.h>
#include "utils.h" #include "utils.h"
#include <memory> #include <memory>
@@ -70,10 +69,8 @@ private:
image_transport::CameraSubscriber img_sub_; image_transport::CameraSubscriber img_sub_;
ros::Publisher markers_pub_, vis_markers_pub_; ros::Publisher markers_pub_, vis_markers_pub_;
ros::Subscriber map_markers_sub_; ros::Subscriber map_markers_sub_;
ros::ServiceServer set_markers_srv_;
bool estimate_poses_, send_tf_, auto_flip_; bool estimate_poses_, send_tf_, auto_flip_;
double length_; double length_;
ros::Duration transform_timeout_;
std::unordered_map<int, double> length_override_; std::unordered_map<int, double> length_override_;
std::string frame_id_prefix_, known_tilt_; std::string frame_id_prefix_, known_tilt_;
Mat camera_matrix_, dist_coeffs_; Mat camera_matrix_, dist_coeffs_;
@@ -100,7 +97,6 @@ public:
ros::shutdown(); ros::shutdown();
} }
readLengthOverride(nh_priv_); readLengthOverride(nh_priv_);
transform_timeout_ = ros::Duration(nh_priv_.param("transform_timeout", 0.02));
known_tilt_ = nh_priv_.param<std::string>("known_tilt", ""); known_tilt_ = nh_priv_.param<std::string>("known_tilt", "");
auto_flip_ = nh_priv_.param("auto_flip", false); auto_flip_ = nh_priv_.param("auto_flip", false);
@@ -118,8 +114,6 @@ public:
dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>>(nh_priv_); dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<aruco_pose::DetectorConfig>>(nh_priv_);
dyn_srv_->setCallback(std::bind(&ArucoDetect::paramCallback, this, std::placeholders::_1, std::placeholders::_2)); dyn_srv_->setCallback(std::bind(&ArucoDetect::paramCallback, this, std::placeholders::_1, std::placeholders::_2));
set_markers_srv_ = nh_priv_.advertiseService("set_length_override", &ArucoDetect::setMarkers, this);
debug_pub_ = it_priv.advertise("debug", 1); debug_pub_ = it_priv.advertise("debug", 1);
markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1); markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1);
vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1); vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1);
@@ -178,7 +172,7 @@ private:
if (!known_tilt_.empty()) { if (!known_tilt_.empty()) {
try { try {
snap_to = tf_buffer_->lookupTransform(msg->header.frame_id, known_tilt_, snap_to = tf_buffer_->lookupTransform(msg->header.frame_id, known_tilt_,
msg->header.stamp, transform_timeout_); msg->header.stamp, ros::Duration(0.02));
} catch (const tf2::TransformException& e) { } catch (const tf2::TransformException& e) {
NODELET_WARN_THROTTLE(5, "can't snap: %s", e.what()); NODELET_WARN_THROTTLE(5, "can't snap: %s", e.what());
} }
@@ -187,8 +181,6 @@ private:
array_.markers.reserve(ids.size()); array_.markers.reserve(ids.size());
aruco_pose::Marker marker; aruco_pose::Marker marker;
vector<geometry_msgs::TransformStamped> transforms;
transforms.reserve(ids.size());
geometry_msgs::TransformStamped transform; geometry_msgs::TransformStamped transform;
transform.header.stamp = msg->header.stamp; transform.header.stamp = msg->header.stamp;
transform.header.frame_id = msg->header.frame_id; transform.header.frame_id = msg->header.frame_id;
@@ -206,33 +198,20 @@ private:
snapOrientation(marker.pose.orientation, snap_to.transform.rotation, auto_flip_); snapOrientation(marker.pose.orientation, snap_to.transform.rotation, auto_flip_);
} }
// TODO: check IDs are unique
if (send_tf_) { if (send_tf_) {
transform.child_frame_id = getChildFrameId(ids[i]); transform.child_frame_id = getChildFrameId(ids[i]);
// check if such static transform is in the map // check if such static transform is in the map
if (map_markers_ids_.find(ids[i]) == map_markers_ids_.end()) { if (map_markers_ids_.find(ids[i]) == map_markers_ids_.end()) {
// check if a markers with that id is already added transform.transform.rotation = marker.pose.orientation;
bool send = true; fillTranslation(transform.transform.translation, tvecs[i]);
for (auto &t : transforms) { br_->sendTransform(transform);
if (t.child_frame_id == transform.child_frame_id) {
send = false;
break;
}
}
if (send) {
transform.transform.rotation = marker.pose.orientation;
fillTranslation(transform.transform.translation, tvecs[i]);
transforms.push_back(transform);
}
} }
} }
} }
array_.markers.push_back(marker); array_.markers.push_back(marker);
} }
if (send_tf_) {
br_->sendTransform(transforms);
}
} }
markers_pub_.publish(array_); markers_pub_.publish(array_);
@@ -367,29 +346,6 @@ private:
} }
} }
bool setMarkers(aruco_pose::SetMarkers::Request& req, aruco_pose::SetMarkers::Response& res)
{
for (auto const& marker : req.markers) {
if (marker.id > 999) {
res.message = "Invalid marker id: " + std::to_string(marker.id);
ROS_ERROR("%s", res.message.c_str());
return true;
}
if (!std::isfinite(marker.length) || marker.length <= 0) {
res.message = "Invalid marker " + std::to_string(marker.id) + " length: " + std::to_string(marker.length);
ROS_ERROR("%s", res.message.c_str());
return true;
}
}
for (auto const& marker : req.markers) {
length_override_[marker.id] = marker.length;
}
res.success = true;
return true;
}
void mapMarkersCallback(const aruco_pose::MarkerArray& msg) void mapMarkersCallback(const aruco_pose::MarkerArray& msg)
{ {
map_markers_ids_.clear(); map_markers_ids_.clear();
@@ -400,8 +356,7 @@ private:
void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level) void paramCallback(aruco_pose::DetectorConfig &config, uint32_t level)
{ {
enabled_ = config.enabled && config.length > 0; enabled_ = config.enabled;
length_ = config.length;
parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant; parameters_->adaptiveThreshConstant = config.adaptiveThreshConstant;
parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin; parameters_->adaptiveThreshWinSizeMin = config.adaptiveThreshWinSizeMin;
parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax; parameters_->adaptiveThreshWinSizeMax = config.adaptiveThreshWinSizeMax;

View File

@@ -19,13 +19,11 @@
#include <vector> #include <vector>
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <memory>
#include <ros/ros.h> #include <ros/ros.h>
#include <nodelet/nodelet.h> #include <nodelet/nodelet.h>
#include <pluginlib/class_list_macros.h> #include <pluginlib/class_list_macros.h>
#include <image_transport/image_transport.h> #include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h> #include <cv_bridge/cv_bridge.h>
#include <dynamic_reconfigure/server.h>
#include <tf/transform_datatypes.h> #include <tf/transform_datatypes.h>
#include <tf2_ros/buffer.h> #include <tf2_ros/buffer.h>
#include <tf2_ros/transform_listener.h> #include <tf2_ros/transform_listener.h>
@@ -43,7 +41,6 @@
#include <aruco_pose/MarkerArray.h> #include <aruco_pose/MarkerArray.h>
#include <aruco_pose/Marker.h> #include <aruco_pose/Marker.h>
#include <aruco_pose/MapConfig.h>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp> #include <opencv2/aruco.hpp>
@@ -77,9 +74,6 @@ private:
tf2_ros::StaticTransformBroadcaster static_br_; tf2_ros::StaticTransformBroadcaster static_br_;
tf2_ros::Buffer tf_buffer_; tf2_ros::Buffer tf_buffer_;
tf2_ros::TransformListener tf_listener_{tf_buffer_}; tf2_ros::TransformListener tf_listener_{tf_buffer_};
std::shared_ptr<dynamic_reconfigure::Server<aruco_pose::MapConfig>> dyn_srv_;
bool enabled_ = true;
std::string type_;
visualization_msgs::MarkerArray vis_array_; visualization_msgs::MarkerArray vis_array_;
std::string known_tilt_, map_, markers_frame_, markers_parent_frame_; std::string known_tilt_, map_, markers_frame_, markers_parent_frame_;
int image_width_, image_height_, image_margin_; int image_width_, image_height_, image_margin_;
@@ -95,14 +89,15 @@ public:
// TODO: why image_transport doesn't work here? // TODO: why image_transport doesn't work here?
img_pub_ = nh_priv_.advertise<sensor_msgs::Image>("image", 1, true); img_pub_ = nh_priv_.advertise<sensor_msgs::Image>("image", 1, true);
markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("map", 1, true); markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1, true);
board_ = cv::makePtr<cv::aruco::Board>(); board_ = cv::makePtr<cv::aruco::Board>();
board_->dictionary = cv::aruco::getPredefinedDictionary( board_->dictionary = cv::aruco::getPredefinedDictionary(
static_cast<cv::aruco::PREDEFINED_DICTIONARY_NAME>(nh_priv_.param("dictionary", 2))); static_cast<cv::aruco::PREDEFINED_DICTIONARY_NAME>(nh_priv_.param("dictionary", 2)));
camera_matrix_ = cv::Mat::zeros(3, 3, CV_64F); camera_matrix_ = cv::Mat::zeros(3, 3, CV_64F);
type_ = nh_priv_.param<std::string>("type", "map"); std::string type, map;
type = nh_priv_.param<std::string>("type", "map");
transform_.child_frame_id = nh_priv_.param<std::string>("frame_id", "aruco_map"); transform_.child_frame_id = nh_priv_.param<std::string>("frame_id", "aruco_map");
known_tilt_ = nh_priv_.param<std::string>("known_tilt", ""); known_tilt_ = nh_priv_.param<std::string>("known_tilt", "");
auto_flip_ = nh_priv_.param("auto_flip", false); auto_flip_ = nh_priv_.param("auto_flip", false);
@@ -115,13 +110,13 @@ public:
// createStripLine(); // createStripLine();
if (type_ == "map") { if (type == "map") {
map_ = nh_priv_.param<std::string>("map" , ""); param(nh_priv_, "map", map);
loadMap(map_); loadMap(map);
} else if (type_ == "gridboard") { } else if (type == "gridboard") {
createGridBoard(nh_priv_); createGridBoard(nh_priv_);
} else { } else {
NODELET_FATAL("unknown type: %s", type_.c_str()); NODELET_FATAL("unknown type: %s", type.c_str());
ros::shutdown(); ros::shutdown();
} }
@@ -129,7 +124,10 @@ public:
vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1, true); vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1, true);
debug_pub_ = it_priv.advertise("debug", 1); debug_pub_ = it_priv.advertise("debug", 1);
publishMap(); publishMarkersFrames();
publishMarkers();
publishMapImage();
vis_markers_pub_.publish(vis_array_);
image_sub_.subscribe(nh_, "image_raw", 1); image_sub_.subscribe(nh_, "image_raw", 1);
info_sub_.subscribe(nh_, "camera_info", 1); info_sub_.subscribe(nh_, "camera_info", 1);
@@ -138,12 +136,6 @@ public:
sync_.reset(new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(10), image_sub_, info_sub_, markers_sub_)); sync_.reset(new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(10), image_sub_, info_sub_, markers_sub_));
sync_->registerCallback(boost::bind(&ArucoMap::callback, this, _1, _2, _3)); sync_->registerCallback(boost::bind(&ArucoMap::callback, this, _1, _2, _3));
dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<aruco_pose::MapConfig>>(nh_priv_);
dynamic_reconfigure::Server<aruco_pose::MapConfig>::CallbackType cb;
cb = std::bind(&ArucoMap::paramCallback, this, std::placeholders::_1, std::placeholders::_2);
dyn_srv_->setCallback(cb);
NODELET_INFO("ready"); NODELET_INFO("ready");
} }
@@ -151,9 +143,6 @@ public:
const sensor_msgs::CameraInfoConstPtr& cinfo, const sensor_msgs::CameraInfoConstPtr& cinfo,
const aruco_pose::MarkerArrayConstPtr& markers) const aruco_pose::MarkerArrayConstPtr& markers)
{ {
if (!enabled_) return;
if (markers->markers.empty()) return; // map not loaded
int valid = 0; int valid = 0;
int count = markers->markers.size(); int count = markers->markers.size();
std::vector<int> ids; std::vector<int> ids;
@@ -279,17 +268,9 @@ publish_debug:
std::ifstream f(filename); std::ifstream f(filename);
std::string line; std::string line;
clearMarkers();
if (map_ == "") {
NODELET_INFO("No map loaded");
return;
}
if (!f.good()) { if (!f.good()) {
NODELET_ERROR("%s - %s", strerror(errno), filename.c_str()); NODELET_FATAL("%s - %s", strerror(errno), filename.c_str());
map_ = ""; ros::shutdown();
return;
} }
while (std::getline(f, line)) { while (std::getline(f, line)) {
@@ -315,10 +296,9 @@ publish_debug:
s.putback(first); s.putback(first);
} else { } else {
// Probably garbage data; inform user and throw an exception, possibly killing nodelet // Probably garbage data; inform user and throw an exception, possibly killing nodelet
NODELET_ERROR("Malformed input: %s", line.c_str()); NODELET_FATAL("Malformed input: %s", line.c_str());
map_ = ""; ros::shutdown();
clearMarkers(); throw std::runtime_error("Malformed input");
return;
} }
if (!(s >> id >> length >> x >> y)) { if (!(s >> id >> length >> x >> y)) {
@@ -349,14 +329,6 @@ publish_debug:
NODELET_INFO("loading %s complete (%d markers)", filename.c_str(), static_cast<int>(board_->ids.size())); NODELET_INFO("loading %s complete (%d markers)", filename.c_str(), static_cast<int>(board_->ids.size()));
} }
void publishMap()
{
publishMarkersFrames();
publishMarkers();
publishMapImage();
vis_markers_pub_.publish(vis_array_);
}
void createGridBoard(ros::NodeHandle& nh) void createGridBoard(ros::NodeHandle& nh)
{ {
NODELET_INFO("generate gridboard"); NODELET_INFO("generate gridboard");
@@ -398,15 +370,6 @@ publish_debug:
} }
} }
void clearMarkers()
{
board_->ids.clear();
board_->objPoints.clear();
markers_.markers.clear();
vis_array_.markers.clear();
markers_transforms_.clear();
}
// void createStripLine() // void createStripLine()
// { // {
// visualization_msgs::Marker marker; // visualization_msgs::Marker marker;
@@ -546,22 +509,6 @@ publish_debug:
msg.image = image; msg.image = image;
img_pub_.publish(msg.toImageMsg()); img_pub_.publish(msg.toImageMsg());
} }
void paramCallback(aruco_pose::MapConfig &config, uint32_t level)
{
// https://github.com/CopterExpress/clover/commit/2cd334c474e3ed04ef65ca1ba7f08ab535a3dc6d#diff-942723f9452c398ae93f1a91427f9a7b614be5e5871f8a3e590f324d804f0d58R356
enabled_ = config.enabled;
if (type_ == "map" && config.map != map_) {
map_ = config.map;
loadMap(map_);
publishMap();
}
if (config.image_axis != image_axis_) {
image_axis_ = config.image_axis;
publishMapImage();
}
}
}; };
PLUGINLIB_EXPORT_CLASS(ArucoMap, nodelet::Nodelet) PLUGINLIB_EXPORT_CLASS(ArucoMap, nodelet::Nodelet)

View File

@@ -1,7 +0,0 @@
# * Add or change markers in the map
# * Change markers' properties, e. g. lengths
Marker[] markers # if length or pose is nan - remove from map
---
bool success
string message

View File

@@ -143,7 +143,7 @@ def test_map_image(node):
assert img.encoding in ('mono8', 'rgb8') assert img.encoding in ('mono8', 'rgb8')
def test_map_markers(node): def test_map_markers(node):
markers = rospy.wait_for_message('aruco_map/map', MarkerArray, timeout=5) markers = rospy.wait_for_message('aruco_map/markers', MarkerArray, timeout=5)
assert markers.markers[0].id == 1 assert markers.markers[0].id == 1
assert markers.markers[1].id == 2 assert markers.markers[1].id == 2
assert markers.markers[2].id == 3 assert markers.markers[2].id == 3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -1,8 +0,0 @@
import pytest
import subprocess
def test_no_tf_repeated_data():
# `/rosout` acts weirdly inside rostest, so using a subprocess
cmd = """python -c 'import rospy, tf; rospy.init_node("foo"); listener = tf.TransformListener(); rospy.sleep(2)'"""
output = str(subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT))
assert 'TF_REPEATED_DATA' not in output, 'TF_REPEATED_DATA was logged on duplicate markers'

View File

@@ -1,21 +0,0 @@
<launch>
<node pkg="image_publisher" type="image_publisher" name="main_camera" args="$(find aruco_pose)/test/duplicate.png">
<param name="frame_id" value="main_camera_optical"/>
<param name="publish_rate" value="10"/>
<param name="camera_info_url" value="file://$(find aruco_pose)/test/camera_info.yaml" />
</node>
<node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" required="true"/>
<node pkg="nodelet" clear_params="true" type="nodelet" name="aruco_detect" args="load aruco_pose/aruco_detect nodelet_manager" required="true">
<remap from="image_raw" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/>
<param name="length" value="0.33"/>
<param name="estimate_poses" value="true"/>
<param name="send_tf" value="true"/>
<param name="cornerRefinementMethod" value="1"/>
</node>
<param name="test_module" value="$(find aruco_pose)/test/duplicate.py"/>
<test test-name="aruco_pose_test" pkg="ros_pytest" type="ros_pytest_runner"/>
</launch>

View File

@@ -2,7 +2,6 @@ import rospy
import pytest import pytest
from visualization_msgs.msg import MarkerArray as VisMarkerArray from visualization_msgs.msg import MarkerArray as VisMarkerArray
from aruco_pose.msg import MarkerArray
@pytest.fixture @pytest.fixture
@@ -10,5 +9,5 @@ def node():
return rospy.init_node('aruco_pose_test', anonymous=True) return rospy.init_node('aruco_pose_test', anonymous=True)
def test_node_failure(node): def test_node_failure(node):
assert rospy.wait_for_message('aruco_map/visualization', VisMarkerArray, timeout=5).markers == [] with pytest.raises(rospy.exceptions.ROSException):
assert rospy.wait_for_message('aruco_map/map', MarkerArray, timeout=5).markers == [] rospy.wait_for_message('aruco_map/visualization', VisMarkerArray, timeout=5)

View File

@@ -60,7 +60,7 @@ rosversion image_view
# validate some versions # validate some versions
[[ $(rosversion cv_camera) == "0.5.1" ]] # patched version with init fix [[ $(rosversion cv_camera) == "0.5.1" ]] # patched version with init fix
[[ $(rosversion ws281x) == "0.0.13" ]] [[ $(rosversion ws281x) == "0.0.12" ]]
# validate examples are present # validate examples are present
[[ $(ls /home/pi/examples/*) ]] [[ $(ls /home/pi/examples/*) ]]

View File

@@ -17,7 +17,6 @@ find_package(catkin REQUIRED COMPONENTS
message_generation message_generation
geometry_msgs geometry_msgs
sensor_msgs sensor_msgs
led_msgs
geographic_msgs geographic_msgs
tf tf
tf2 tf2
@@ -25,7 +24,6 @@ find_package(catkin REQUIRED COMPONENTS
tf2_ros tf2_ros
image_transport image_transport
cv_bridge cv_bridge
dynamic_reconfigure
) )
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
@@ -128,9 +126,10 @@ generate_messages(
## and list every .cfg file to be processed ## and list every .cfg file to be processed
## Generate dynamic reconfigure parameters in the 'cfg' folder ## Generate dynamic reconfigure parameters in the 'cfg' folder
generate_dynamic_reconfigure_options( # generate_dynamic_reconfigure_options(
cfg/Flow.cfg # cfg/DynReconf1.cfg
) # cfg/DynReconf2.cfg
# )
################################### ###################################
## catkin specific configuration ## ## catkin specific configuration ##
@@ -212,8 +211,6 @@ add_dependencies(clover_led ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(shell ${PROJECT_NAME}_generate_messages_cpp) add_dependencies(shell ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_gencfg)
## Rename C++ executable without prefix ## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the ## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use ## target back to the shorter version for ease of user use

View File

@@ -1,10 +0,0 @@
#!/usr/bin/env python
PACKAGE = "clover"
from dynamic_reconfigure.parameter_generator_catkin import *
gen = ParameterGenerator()
gen.add("enabled", bool_t, 0, "if optical flow enabled", True)
exit(gen.generate(PACKAGE, "clover", "Flow"))

View File

@@ -15,13 +15,12 @@
<node name="aruco_detect" pkg="nodelet" if="$(eval aruco_detect and not disable)" type="nodelet" args="load aruco_pose/aruco_detect main_camera_nodelet_manager" output="screen" clear_params="true" respawn="true"> <node name="aruco_detect" pkg="nodelet" if="$(eval aruco_detect and not disable)" type="nodelet" args="load aruco_pose/aruco_detect main_camera_nodelet_manager" output="screen" clear_params="true" respawn="true">
<remap from="image_raw" to="main_camera/image_raw"/> <remap from="image_raw" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/> <remap from="camera_info" to="main_camera/camera_info"/>
<remap from="map_markers" to="aruco_map/map"/> <remap from="map_markers" to="aruco_map/markers"/>
<param name="estimate_poses" value="true"/> <param name="estimate_poses" value="true"/>
<param name="send_tf" value="true"/> <param name="send_tf" value="true"/>
<param name="known_tilt" value="map" if="$(eval placement == 'floor')"/> <param name="known_tilt" value="map" if="$(eval placement == 'floor')"/>
<param name="known_tilt" value="map_flipped" if="$(eval placement == 'ceiling')"/> <param name="known_tilt" value="map_flipped" if="$(eval placement == 'ceiling')"/>
<param name="length" value="$(arg length)"/> <param name="length" value="$(arg length)"/>
<param name="transform_timeout" value="0.1"/>
<!-- aruco detector parameters --> <!-- aruco detector parameters -->
<param name="cornerRefinementMethod" value="2"/> <!-- contour refinement --> <param name="cornerRefinementMethod" value="2"/> <!-- contour refinement -->
<param name="minMarkerPerimeterRate" value="0.075"/> <!-- 0.075 for 320x240, 0.0375 for 640x480 --> <param name="minMarkerPerimeterRate" value="0.075"/> <!-- 0.075 for 320x240, 0.0375 for 640x480 -->

View File

@@ -12,7 +12,7 @@
<arg name="led" default="true"/> <arg name="led" default="true"/>
<arg name="blocks" default="false"/> <arg name="blocks" default="false"/>
<arg name="rc" default="false"/> <arg name="rc" default="false"/>
<arg name="force_init" default="true"/> <!-- force estimator to init by publishing zero pose --> <arg name="force_init" value="true"/> <!-- force estimator to init by publishing zero pose -->
<arg name="simulator" default="false"/> <!-- flag that we are operating on a simulated drone --> <arg name="simulator" default="false"/> <!-- flag that we are operating on a simulated drone -->

View File

@@ -4,8 +4,6 @@
<arg name="direction_z" default="down"/> <!-- direction the camera points: down, up --> <arg name="direction_z" default="down"/> <!-- direction the camera points: down, up -->
<arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward --> <arg name="direction_y" default="backward"/> <!-- direction the camera cable points: backward, forward -->
<arg name="device" default="/dev/video0"/> <!-- v4l2 device --> <arg name="device" default="/dev/video0"/> <!-- v4l2 device -->
<arg name="throttled_topic" default="true"/> <!-- enable throttled image topic -->
<arg name="throttled_topic_rate" default="5.0"/> <!-- throttled image topic rate -->
<arg name="simulator" default="false"/> <arg name="simulator" default="false"/>
<node if="$(eval direction_z == 'down' and direction_y == 'backward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/> <node if="$(eval direction_z == 'down' and direction_y == 'backward')" pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
@@ -45,8 +43,4 @@
<node pkg="clover" type="camera_markers" ns="main_camera" name="main_camera_markers"> <node pkg="clover" type="camera_markers" ns="main_camera" name="main_camera_markers">
<param name="scale" value="3.0"/> <param name="scale" value="3.0"/>
</node> </node>
<!-- image topic throttled -->
<node pkg="topic_tools" name="main_camera_throttle" type="throttle" ns="main_camera"
args="messages image_raw $(arg throttled_topic_rate) image_raw_throttled" if="$(arg throttled_topic)"/>
</launch> </launch>

View File

@@ -1,5 +1,5 @@
<launch> <launch>
<arg name="fcu_conn" default="usb"/> <!-- options: usb, uart, tcp, udp, sitl, hitl --> <arg name="fcu_conn" default="usb"/> <!-- options: usb, uart, tcp, udp, sitl -->
<arg name="fcu_ip" default="127.0.0.1"/> <arg name="fcu_ip" default="127.0.0.1"/>
<arg name="fcu_sys_id" default="1"/> <arg name="fcu_sys_id" default="1"/>
<arg name="gcs_bridge" default="tcp"/> <arg name="gcs_bridge" default="tcp"/>
@@ -23,9 +23,6 @@
<!-- sitl since PX4 1.9.0 --> <!-- sitl since PX4 1.9.0 -->
<param name="fcu_url" value="udp://@$(arg fcu_ip):14580" if="$(eval fcu_conn == 'sitl')"/> <param name="fcu_url" value="udp://@$(arg fcu_ip):14580" if="$(eval fcu_conn == 'sitl')"/>
<!-- hitl connection (to gazebo_mavlink_interface plugin) -->
<param name="fcu_url" value="udp://$(arg fcu_ip):14540@" if="$(eval fcu_conn == 'hitl')"/>
<!-- set target_system_id --> <!-- set target_system_id -->
<param name="target_system_id" value="$(arg fcu_sys_id)" /> <param name="target_system_id" value="$(arg fcu_sys_id)" />

View File

@@ -1,4 +0,0 @@
<launch>
<!-- shurtcut for running the simulation (`roslaunch clover simulator.launch`) -->
<include file="$(find clover_simulation)/launch/simulator.launch"/>
</launch>

View File

@@ -37,11 +37,8 @@
<depend>rosbridge_server</depend> <depend>rosbridge_server</depend>
<depend>web_video_server</depend> <depend>web_video_server</depend>
<depend>tf2_web_republisher</depend> <depend>tf2_web_republisher</depend>
<depend>libxml2</depend>
<depend>libxslt</depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python-lxml</depend> <depend condition="$ROS_PYTHON_VERSION == 2">python-lxml</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3-lxml</depend> <depend condition="$ROS_PYTHON_VERSION == 3">python3-lxml</depend>
<depend>dynamic_reconfigure</depend>
<exec_depend>python-pymavlink</exec_depend> <exec_depend>python-pymavlink</exec_depend>
<!-- Use test_depend for packages you need only for testing: --> <!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> --> <!-- <test_depend>gtest</test_depend> -->

View File

@@ -1,87 +0,0 @@
#!/usr/bin/env python3
import rospy
import math
import signal
import sys
import dynamic_reconfigure.client
from clover import srv
from std_srvs.srv import Trigger
from sensor_msgs.msg import Range
from aruco_pose.msg import MarkerArray
from util import handle_response
rospy.init_node('autotest_aruco', disable_signals=True) # disable signals to allow interrupting with ctrl+c
flow_client = dynamic_reconfigure.client.Client('optical_flow')
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
navigate = handle_response(rospy.ServiceProxy('navigate', srv.Navigate))
land = handle_response(rospy.ServiceProxy('land', Trigger))
def interrupt(sig, frame):
print('\nInterrupted, landing...')
land()
sys.exit(0)
signal.signal(signal.SIGINT, interrupt)
def print_current_map_position():
telem = get_telemetry()
dist = rospy.wait_for_message('rangefinder/range', Range).range
print('Map position:\tx={:.1f}\ty={:.1f}\tz={:.1f}\tyaw={:.1f}\tdist={:.2f}'.format(telem.x, telem.y, telem.z, telem.yaw, dist))
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)
markers = rospy.wait_for_message('aruco_map/map', MarkerArray, timeout=3)
left = min(marker.pose.position.x for marker in markers.markers)
bottom = min(marker.pose.position.y for marker in markers.markers)
width = max(marker.pose.position.x for marker in markers.markers)
height = max(marker.pose.position.y for marker in markers.markers)
center_x = left + width / 2
center_y = bottom + height / 2
print('Map rect: %g %g - %g %g' % (left, bottom, width, height))
input('Take off and hover 1 m [enter] ')
navigate_wait(x=0, y=0, z=1, frame_id='body', auto_arm=True)
print_current_map_position()
input('Go to corner %g %g 1.5 speed 1 [enter] ' % (width, height))
navigate_wait(x=width, y=height, z=1.5, speed=1, frame_id='aruco_map')
print_current_map_position()
input('Go to center %g %g 1.5 speed 5 [enter] ' % (center_x, center_y))
navigate_wait(x=center_x, y=center_y, z=1.5, speed=5, frame_id='aruco_map')
print_current_map_position()
input('Disable optical flow and keep hovering [enter] ')
flow_client.update_configuration({'enabled': False})
rospy.sleep(5)
input('Enable optical flow back [enter] ')
flow_client.update_configuration({'enabled': True})
input('Go to side 1 %g 2 heading top [enter] ' % (center_y))
navigate_wait(x=1, y=center_y, z=2, yaw=1.57, frame_id='aruco_map')
print_current_map_position()
marker_id = markers.markers[0].id
input('Go to marker %d z=1.5 [enter] ' % marker_id)
navigate_wait(x=0, y=0, z=1.5, yaw=0, frame_id='aruco_%d' % marker_id)
print_current_map_position()
input('Perform landing [enter] ')
land()

View File

@@ -1,100 +0,0 @@
#!/usr/bin/env python3
import rospy
import math
from math import nan
import signal
import sys
from clover import srv
from std_srvs.srv import Trigger
from sensor_msgs.msg import Range
from util import handle_response
rospy.init_node('autotest_flight', disable_signals=True) # disable signals to allow interrupting with ctrl+c
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
navigate = handle_response(rospy.ServiceProxy('navigate', srv.Navigate))
navigate_global = handle_response(rospy.ServiceProxy('navigate_global', srv.NavigateGlobal))
set_position = handle_response(rospy.ServiceProxy('set_position', srv.SetPosition))
set_velocity = handle_response(rospy.ServiceProxy('set_velocity', srv.SetVelocity))
set_attitude = handle_response(rospy.ServiceProxy('set_attitude', srv.SetAttitude))
set_rates = handle_response(rospy.ServiceProxy('set_rates', srv.SetRates))
land = handle_response(rospy.ServiceProxy('land', Trigger))
def interrupt(sig, frame):
print('\nInterrupted, landing...')
land()
sys.exit(0)
signal.signal(signal.SIGINT, interrupt)
def navigate_wait(x=0, y=0, z=0, yaw=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)
def print_distance():
dist = rospy.wait_for_message('rangefinder/range', Range).range
print('Distance: {:.2f}'.format(dist))
input('Take off and hover 1 m [enter] ')
navigate_wait(z=1, frame_id='body', auto_arm=True)
print_distance()
start = get_telemetry()
input('Fly forward 2 m [enter] ')
navigate_wait(x=2, frame_id='navigate_target')
print_distance()
input('Climb 0.5 m [enter] ')
navigate_wait(z=0.5, frame_id='navigate_target')
print_distance()
input('Rotate left 90° [enter] ')
navigate(yaw=math.pi / 2, frame_id='navigate_target')
rospy.sleep(3)
input('Use set_velocity to fly forward 2 m speed 1 [enter]')
set_velocity(vx=1, vy=0.0, vz=0, frame_id='body')
rospy.sleep(2)
set_position(frame_id='body')
input('Rotate right 90° [enter] ')
navigate(yaw=-math.pi / 2, frame_id='navigate_target')
rospy.sleep(3)
input('Use set_attitude to fly backwards [enter]')
set_attitude(pitch=-0.3, roll=0, yaw=0, thrust=0.5, frame_id='body')
rospy.sleep(0.3)
set_position(frame_id='body')
input('Use set_attitude to fly right [enter]')
set_attitude(pitch=0, roll=0.3, yaw=0, thrust=0.5, frame_id='body')
rospy.sleep(0.5)
set_position(frame_id='body')
input('Use set_rates to fly right [enter]')
set_rates(roll_rate=1.2, thrust=0.5)
rospy.sleep(0.4)
set_position(frame_id='body')
input('Rotate 360° to the right using yaw_rate [enter]')
set_position(x=nan, y=nan, z=nan, frame_id='body', yaw=nan, yaw_rate=-1)
rospy.sleep(2 * math.pi)
set_position(frame_id='body')
input('Return to start point [enter]')
navigate_wait(x=start.x, y=start.y, z=start.z, yaw=start.yaw, speed=1, frame_id='map')
input('Land [enter]')
land()

View File

@@ -1,72 +0,0 @@
#!/usr/bin/env python3
import rospy
import functools
from clover.srv import SetLEDEffect
from led_msgs.srv import SetLEDs
from led_msgs.msg import LEDStateArray, LEDState
from util import handle_response
rospy.init_node('autotest_led', disable_signals=True)
set_leds = handle_response(rospy.ServiceProxy('led/set_leds', SetLEDs))
set_effect = handle_response(rospy.ServiceProxy('led/set_effect', SetLEDEffect))
led_count = len(rospy.wait_for_message('led/state', LEDStateArray, timeout=10).leds)
print('LED count =', led_count)
print('== Testing effects ==')
input('Fill red [enter] ')
set_effect(r=255, g=0, b=0)
input('Fill green [enter] ')
set_effect(r=0, g=100, b=0)
input('Blink white [enter] ')
set_effect(effect='blink', r=255, g=255, b=255)
rospy.sleep(3)
input('Blink fast violet [enter] ')
set_effect(effect='blink_fast', r=220, g=20, b=250)
rospy.sleep(3)
input('Fade to blue [enter] ')
set_effect(effect='fade', r=0, g=0, b=255)
input('Wipe to yellow [enter] ')
set_effect(effect='wipe', r=255, g=255, b=40)
input('Flash red [enter] ')
set_effect(effect='flash', r=255, g=0, b=0)
rospy.sleep(1)
input('Rainbow [enter] ')
set_effect(effect='rainbow')
rospy.sleep(4)
input('Rainbow fill [enter] ')
set_effect(effect='rainbow_fill')
rospy.sleep(4)
input('Turn off [enter] ')
set_effect()
print('== Testing low-level control ==')
input('Fill orange [enter] ')
set_leds(leds=[LEDState(index=i, r=245, g=155, b=0) for i in range(led_count)])
input('Fill blue gradient [enter] ')
set_leds(leds=[LEDState(index=i, r=0, g=20, b=int(255 * i / led_count)) for i in range(led_count)])
input('Animate green dot [enter] ')
set_effect()
for i in range(led_count):
if i > 0:
set_leds(leds=[LEDState(index=i - 1, r=0, g=0, b=0)])
set_leds(leds=[LEDState(index=i, r=0, g=255, b=0)])
rospy.sleep(0.05)
input('Turn off [enter] ')
set_effect()

View File

@@ -1,11 +0,0 @@
import functools
# decorator to handle response and print error message
def handle_response(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
res = fn(*args, **kwargs)
if not res.success:
print('\033[91mError:\033[0m {}'.format(res.message))
return res
return wrapper

View File

@@ -31,6 +31,7 @@ ros::Time start_time;
double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period; double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period;
double low_battery_threshold; double low_battery_threshold;
std::vector<std::string> error_ignore; std::vector<std::string> error_ignore;
bool blink_state;
led_msgs::SetLEDs set_leds; led_msgs::SetLEDs set_leds;
led_msgs::LEDStateArray state, start_state; led_msgs::LEDStateArray state, start_state;
ros::ServiceClient set_leds_srv; ros::ServiceClient set_leds_srv;
@@ -86,8 +87,9 @@ void proceed(const ros::TimerEvent& event)
set_leds.request.leds.resize(led_count); set_leds.request.leds.resize(led_count);
if (current_effect.effect == "blink" || current_effect.effect == "blink_fast") { if (current_effect.effect == "blink" || current_effect.effect == "blink_fast") {
// enable on odd counter blink_state = !blink_state;
if (counter % 2 != 0) { // toggle all leds
if (blink_state) {
fill(current_effect.r, current_effect.g, current_effect.b); fill(current_effect.r, current_effect.g, current_effect.b);
} else { } else {
fill(0, 0, 0); fill(0, 0, 0);
@@ -220,7 +222,6 @@ bool setEffect(clover::SetLEDEffect::Request& req, clover::SetLEDEffect::Respons
counter = 0; counter = 0;
start_state = state; start_state = state;
start_time = ros::Time::now(); start_time = ros::Time::now();
proceed({ .current_real = start_time });
return true; return true;
} }

View File

@@ -22,13 +22,11 @@
#include <tf2/utils.h> #include <tf2/utils.h>
#include <tf2_ros/transform_listener.h> #include <tf2_ros/transform_listener.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h> #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#include <dynamic_reconfigure/server.h>
#include <mavros_msgs/OpticalFlowRad.h> #include <mavros_msgs/OpticalFlowRad.h>
#include <sensor_msgs/Imu.h> #include <sensor_msgs/Imu.h>
#include <geometry_msgs/Vector3Stamped.h> #include <geometry_msgs/Vector3Stamped.h>
#include <geometry_msgs/PointStamped.h> #include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/TwistStamped.h> #include <geometry_msgs/TwistStamped.h>
#include <clover/FlowConfig.h>
using cv::Mat; using cv::Mat;
@@ -40,7 +38,6 @@ public:
{} {}
private: private:
bool enabled_;
ros::Publisher flow_pub_, velo_pub_, shift_pub_; ros::Publisher flow_pub_, velo_pub_, shift_pub_;
ros::Time prev_stamp_; ros::Time prev_stamp_;
std::string fcu_frame_id_, local_frame_id_; std::string fcu_frame_id_, local_frame_id_;
@@ -57,7 +54,6 @@ private:
std::unique_ptr<tf2_ros::TransformListener> tf_listener_; std::unique_ptr<tf2_ros::TransformListener> tf_listener_;
bool calc_flow_gyro_; bool calc_flow_gyro_;
float flow_gyro_default_; float flow_gyro_default_;
std::shared_ptr<dynamic_reconfigure::Server<clover::FlowConfig>> dyn_srv_;
void onInit() void onInit()
{ {
@@ -87,12 +83,6 @@ private:
img_sub_ = it.subscribeCamera("image_raw", 1, &OpticalFlow::flow, this); img_sub_ = it.subscribeCamera("image_raw", 1, &OpticalFlow::flow, this);
dyn_srv_ = std::make_shared<dynamic_reconfigure::Server<clover::FlowConfig>>(nh_priv);
dynamic_reconfigure::Server<clover::FlowConfig>::CallbackType cb;
cb = std::bind(&OpticalFlow::paramCallback, this, std::placeholders::_1, std::placeholders::_2);
dyn_srv_->setCallback(cb);
NODELET_INFO("Optical Flow initialized"); NODELET_INFO("Optical Flow initialized");
} }
@@ -119,8 +109,6 @@ private:
void flow(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr& cinfo) void flow(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr& cinfo)
{ {
if (!enabled_) return;
parseCameraInfo(cinfo); parseCameraInfo(cinfo);
auto img = cv_bridge::toCvShare(msg, "mono8")->image; auto img = cv_bridge::toCvShare(msg, "mono8")->image;
@@ -154,7 +142,7 @@ private:
img.convertTo(curr_, CV_32F); img.convertTo(curr_, CV_32F);
if (prev_.empty() || (msg->header.stamp - prev_stamp_).toSec() > 0.1) { // outdated previous frame if (prev_.empty()) {
prev_ = curr_.clone(); prev_ = curr_.clone();
prev_stamp_ = msg->header.stamp; prev_stamp_ = msg->header.stamp;
cv::createHanningWindow(hann_, curr_.size(), CV_32F); cv::createHanningWindow(hann_, curr_.size(), CV_32F);
@@ -276,14 +264,6 @@ publish_debug:
return flow; return flow;
} }
void paramCallback(clover::FlowConfig &config, uint32_t level)
{
enabled_ = config.enabled;
if (!enabled_) {
prev_ = Mat(); // clear previous frame
}
}
}; };
PLUGINLIB_EXPORT_CLASS(OpticalFlow, nodelet::Nodelet) PLUGINLIB_EXPORT_CLASS(OpticalFlow, nodelet::Nodelet)

View File

@@ -91,7 +91,7 @@ private:
void fakeGCSThread() void fakeGCSThread()
{ {
// Awful workaround for fixing PX4 not sending STATUSTEXTs // Awful workaround for fixing PX4 not sending STATUSTEXTs
// if there is no GCS heartbeats. // if there is no GCS hearbeats.
// TODO: use timer // TODO: use timer
// TODO: remove, when PX4 get this fixed. // TODO: remove, when PX4 get this fixed.
ros::Publisher mavlink_pub = nh.advertise<mavros_msgs::Mavlink>("mavlink/to", 1); ros::Publisher mavlink_pub = nh.advertise<mavros_msgs::Mavlink>("mavlink/to", 1);

View File

@@ -336,7 +336,7 @@ def is_process_running(binary, exact=False, full=False):
if exact: if exact:
args.append('-x') # match exactly with the command name args.append('-x') # match exactly with the command name
if full: if full:
args.append('-f') # use full command line (including arguments) to match args.append('-f') # use full process name to match
args.append(binary) args.append(binary)
subprocess.check_output(args) subprocess.check_output(args)
return True return True
@@ -534,8 +534,6 @@ def check_global_position():
rospy.wait_for_message('mavros/global_position/global', NavSatFix, timeout=1) rospy.wait_for_message('mavros/global_position/global', NavSatFix, timeout=1)
except rospy.ROSException: except rospy.ROSException:
info('no global position') info('no global position')
if get_param('SYS_MC_EST_GROUP') == 2 and (get_param('EKF2_AID_MASK') & (1 << 0)):
failure('enabled GPS fusion may suppress vision position aiding')
@check('Optical flow') @check('Optical flow')
@@ -625,10 +623,6 @@ def check_rangefinder():
@check('Boot duration') @check('Boot duration')
def check_boot_duration(): def check_boot_duration():
if not os.path.exists('/etc/clover_version'):
info('skip check')
return # Don't check not on Clover's image
output = subprocess.check_output('systemd-analyze').decode() output = subprocess.check_output('systemd-analyze').decode()
r = re.compile(r'([\d\.]+)s\s*$', flags=re.MULTILINE) r = re.compile(r'([\d\.]+)s\s*$', flags=re.MULTILINE)
duration = float(r.search(output).groups()[0]) duration = float(r.search(output).groups()[0])
@@ -654,9 +648,6 @@ def check_cpu_usage():
@check('clover.service') @check('clover.service')
def check_clover_service(): def check_clover_service():
if not os.path.exists('/etc/clover_version'):
return # Don't check not on Clover's image
try: try:
output = subprocess.check_output('systemctl show -p ActiveState --value clover.service'.split(), output = subprocess.check_output('systemctl show -p ActiveState --value clover.service'.split(),
stderr=subprocess.STDOUT).decode() stderr=subprocess.STDOUT).decode()
@@ -712,10 +703,6 @@ def check_image():
@check('Preflight status') @check('Preflight status')
def check_preflight_status(): def check_preflight_status():
if is_process_running('px4', exact=True):
info('can\'t check in SITL')
return
# Make sure the console is available to us # Make sure the console is available to us
mavlink_exec('\n') mavlink_exec('\n')
cmdr_output = mavlink_exec('commander check') cmdr_output = mavlink_exec('commander check')
@@ -737,10 +724,6 @@ def check_preflight_status():
@check('Network') @check('Network')
def check_network(): def check_network():
if not os.path.exists('/etc/clover_version'):
# TODO:
return # Don't check not on Clover's image
ros_hostname = os.environ.get('ROS_HOSTNAME', '').strip() ros_hostname = os.environ.get('ROS_HOSTNAME', '').strip()
if not ros_hostname: if not ros_hostname:

View File

@@ -37,7 +37,6 @@
#include <mavros_msgs/State.h> #include <mavros_msgs/State.h>
#include <mavros_msgs/StatusText.h> #include <mavros_msgs/StatusText.h>
#include <mavros_msgs/ManualControl.h> #include <mavros_msgs/ManualControl.h>
#include <mavros_msgs/Altitude.h>
#include <clover/GetTelemetry.h> #include <clover/GetTelemetry.h>
#include <clover/Navigate.h> #include <clover/Navigate.h>
@@ -55,7 +54,6 @@ using namespace clover;
using mavros_msgs::PositionTarget; using mavros_msgs::PositionTarget;
using mavros_msgs::AttitudeTarget; using mavros_msgs::AttitudeTarget;
using mavros_msgs::Thrust; using mavros_msgs::Thrust;
using mavros_msgs::Altitude;
// tf2 // tf2
tf2_ros::Buffer tf_buffer; tf2_ros::Buffer tf_buffer;
@@ -98,12 +96,10 @@ Thrust thrust_msg;
TwistStamped rates_msg; TwistStamped rates_msg;
TransformStamped target, setpoint; TransformStamped target, setpoint;
geometry_msgs::TransformStamped body; geometry_msgs::TransformStamped body;
geometry_msgs::TransformStamped terrain;
// State // State
PoseStamped nav_start; PoseStamped nav_start;
PoseStamped setpoint_position, setpoint_position_transformed; PoseStamped setpoint_position, setpoint_position_transformed;
Vector3Stamped setpoint_z, setpoint_z_transformed; // for z-only commands
Vector3Stamped setpoint_velocity, setpoint_velocity_transformed; Vector3Stamped setpoint_velocity, setpoint_velocity_transformed;
QuaternionStamped setpoint_attitude, setpoint_attitude_transformed; QuaternionStamped setpoint_attitude, setpoint_attitude_transformed;
float setpoint_yaw_rate; float setpoint_yaw_rate;
@@ -126,8 +122,6 @@ enum setpoint_type_t setpoint_type = NONE;
enum { YAW, YAW_RATE, TOWARDS } setpoint_yaw_type; enum { YAW, YAW_RATE, TOWARDS } setpoint_yaw_type;
bool setpoint_z_valid = false;
// Last received telemetry messages // Last received telemetry messages
mavros_msgs::State state; mavros_msgs::State state;
mavros_msgs::StatusText statustext; mavros_msgs::StatusText statustext;
@@ -156,9 +150,6 @@ void handleState(const mavros_msgs::State& s)
inline void publishBodyFrame() inline void publishBodyFrame()
{ {
if (body.child_frame_id.empty()) return; if (body.child_frame_id.empty()) return;
if (!body.header.stamp.isZero() && body.header.stamp == local_position.header.stamp) {
return; // avoid TF_REPEATED_DATA warnings
}
tf::Quaternion q; tf::Quaternion q;
q.setRPY(0, 0, tf::getYaw(local_position.pose.orientation)); q.setRPY(0, 0, tf::getYaw(local_position.pose.orientation));
@@ -179,15 +170,6 @@ void handleLocalPosition(const PoseStamped& pose)
// TODO: terrain?, home? // TODO: terrain?, home?
} }
void handleAltitude(const Altitude& alt)
{
// publish terrain frame
if (!std::isfinite(alt.bottom_clearance)) return;
terrain.header.stamp = alt.header.stamp;
terrain.transform.translation.z = -alt.bottom_clearance;
transform_broadcaster->sendTransform(terrain);
}
// wait for transform without interrupting publishing setpoints // wait for transform without interrupting publishing setpoints
inline bool waitTransform(const string& target, const string& source, inline bool waitTransform(const string& target, const string& source,
const ros::Time& stamp, const ros::Duration& timeout) // editorconfig-checker-disable-line const ros::Time& stamp, const ros::Duration& timeout) // editorconfig-checker-disable-line
@@ -436,18 +418,6 @@ void publish(const ros::Time stamp)
} }
} }
if (setpoint_z_valid && setpoint_type == NAVIGATE || setpoint_type == NAVIGATE_GLOBAL || setpoint_type == POSITION) {
setpoint_z.header.stamp = stamp;
try {
tf_buffer.transform(setpoint_z, setpoint_z_transformed, local_frame, ros::Duration(0.05));
setpoint_position_transformed.pose.position.z = setpoint_z_transformed.vector.z;
} catch (const tf2::TransformException& e) {
ROS_WARN_THROTTLE(10, "can't transform z coordinate from %s to %s, ignoring z coordinate",
setpoint_z.header.frame_id.c_str(), local_frame.c_str());
}
}
if (setpoint_type == POSITION) { if (setpoint_type == POSITION) {
position_msg = setpoint_position_transformed; position_msg = setpoint_position_transformed;
} }
@@ -583,7 +553,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
// look up for reference frame // look up for reference frame
auto search = reference_frames.find(frame_id); auto search = reference_frames.find(frame_id);
const string& reference_frame = search == reference_frames.end() ? frame_id : search->second; // when not found it's the same frame const string& reference_frame = search == reference_frames.end() ? frame_id : search->second;
// Serve "partial" commands // Serve "partial" commands
@@ -610,33 +580,22 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
} }
} }
if (!auto_arm && std::isfinite(z) && if (!auto_arm && std::isfinite(yaw_rate) &&
isnan(x) && isnan(y) && isnan(vx) && isnan(vy) && isnan(vz) && isnan(x) && isnan(y) && isnan(z) && isnan(vx) && isnan(vy) && isnan(vz) &&
isnan(pitch) && isnan(roll) && isnan(thrust) && isnan(pitch) && isnan(roll) && isnan(yaw) && isnan(thrust) &&
isnan(lat) && isnan(lon)) { isnan(lat) && isnan(lon)) {
// set only the z // change only the yaw rate
if (setpoint_type == POSITION || setpoint_type == NAVIGATE || setpoint_type == NAVIGATE_GLOBAL) { if (setpoint_type == POSITION || setpoint_type == NAVIGATE || setpoint_type == NAVIGATE_GLOBAL || setpoint_type == VELOCITY) {
if (!waitTransform(setpoint_position.header.frame_id, frame_id, stamp, transform_timeout)) message = "Changing yaw rate only";
throw std::runtime_error("Can't transform from " + frame_id + " to " + setpoint_position.header.frame_id);
message = "Changing z only"; setpoint_yaw_type = YAW_RATE;
setpoint_yaw_rate = yaw_rate;
setpoint_z.header.frame_id = frame_id;
setpoint_z.header.stamp = stamp;
setpoint_z.vector.z = z;
setpoint_z_valid = true;
goto publish_setpoint; goto publish_setpoint;
} else { } else {
throw std::runtime_error("Setting z is possible only when position setpoint active"); throw std::runtime_error("Setting yaw rate is possible only when position or velocity setpoints active");
} }
} }
// commands without z
if (isnan(z) && setpoint_z_valid && (sp_type == NAVIGATE || sp_type == NAVIGATE_GLOBAL || sp_type == POSITION)) {
z = 0;
}
// Serve normal commands // Serve normal commands
if (sp_type == NAVIGATE || sp_type == POSITION) { if (sp_type == NAVIGATE || sp_type == POSITION) {
@@ -732,7 +691,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
// } // }
if (sp_type == POSITION || sp_type == NAVIGATE || sp_type == NAVIGATE_GLOBAL || sp_type == VELOCITY || sp_type == ATTITUDE) { if (sp_type == POSITION || sp_type == NAVIGATE || sp_type == NAVIGATE_GLOBAL || sp_type == VELOCITY || sp_type == ATTITUDE) {
// destination point and/or attitude // destination point and/or yaw
PoseStamped ps; PoseStamped ps;
ps.header.frame_id = frame_id; ps.header.frame_id = frame_id;
ps.header.stamp = stamp; ps.header.stamp = stamp;
@@ -741,12 +700,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
ps.pose.position.z = z; ps.pose.position.z = z;
ps.pose.orientation.w = 1.0; // Ensure quaternion is always valid ps.pose.orientation.w = 1.0; // Ensure quaternion is always valid
if (sp_type == ATTITUDE) { if (std::isnan(yaw)) {
ps.pose.position.x = 0;
ps.pose.position.y = 0;
ps.pose.position.z = 0;
ps.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(roll, pitch, yaw);
} else if (std::isnan(yaw)) {
setpoint_yaw_type = YAW_RATE; setpoint_yaw_type = YAW_RATE;
setpoint_yaw_rate = yaw_rate; setpoint_yaw_rate = yaw_rate;
} else if (std::isinf(yaw) && yaw > 0) { } else if (std::isinf(yaw) && yaw > 0) {
@@ -898,13 +852,6 @@ bool land(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
return false; return false;
} }
bool release(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
{
setpoint_timer.stop();
res.success = true;
return true;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
ros::init(argc, argv, "simple_offboard"); ros::init(argc, argv, "simple_offboard");
@@ -926,7 +873,6 @@ int main(int argc, char **argv)
nh_priv.param("check_kill_switch", check_kill_switch, true); nh_priv.param("check_kill_switch", check_kill_switch, true);
nh_priv.param("default_speed", default_speed, 0.5f); nh_priv.param("default_speed", default_speed, 0.5f);
nh_priv.param<string>("body_frame", body.child_frame_id, "body"); nh_priv.param<string>("body_frame", body.child_frame_id, "body");
nh_priv.param<string>("terrain_frame", terrain.child_frame_id, "terrain");
nh_priv.getParam("reference_frames", reference_frames); nh_priv.getParam("reference_frames", reference_frames);
// Default reference frames // Default reference frames
@@ -962,13 +908,6 @@ int main(int argc, char **argv)
auto manual_control_sub = nh.subscribe(mavros + "/manual_control/control", 1, &handleMessage<mavros_msgs::ManualControl, manual_control>); auto manual_control_sub = nh.subscribe(mavros + "/manual_control/control", 1, &handleMessage<mavros_msgs::ManualControl, manual_control>);
auto local_position_sub = nh.subscribe(mavros + "/local_position/pose", 1, &handleLocalPosition); auto local_position_sub = nh.subscribe(mavros + "/local_position/pose", 1, &handleLocalPosition);
ros::Subscriber altitude_sub;
if (!body.child_frame_id.empty() && !terrain.child_frame_id.empty()) {
terrain.header.frame_id = body.child_frame_id;
terrain.transform.rotation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, 0);
altitude_sub = nh.subscribe(mavros + "/altitude", 1, &handleAltitude);
}
// Setpoint publishers // Setpoint publishers
position_pub = nh.advertise<PoseStamped>(mavros + "/setpoint_position/local", 1); position_pub = nh.advertise<PoseStamped>(mavros + "/setpoint_position/local", 1);
position_raw_pub = nh.advertise<PositionTarget>(mavros + "/setpoint_raw/local", 1); position_raw_pub = nh.advertise<PositionTarget>(mavros + "/setpoint_raw/local", 1);
@@ -986,7 +925,6 @@ int main(int argc, char **argv)
auto sa_serv = nh.advertiseService("set_attitude", &setAttitude); auto sa_serv = nh.advertiseService("set_attitude", &setAttitude);
auto sr_serv = nh.advertiseService("set_rates", &setRates); auto sr_serv = nh.advertiseService("set_rates", &setRates);
auto ld_serv = nh.advertiseService("land", &land); auto ld_serv = nh.advertiseService("land", &land);
auto rl_serv = nh_priv.advertiseService("release", &release);
// Setpoint timer // Setpoint timer
setpoint_timer = nh.createTimer(ros::Duration(1 / nh_priv.param("setpoint_rate", 30.0)), &publishSetpoint, false, false); setpoint_timer = nh.createTimer(ros::Duration(1 / nh_priv.param("setpoint_rate", 30.0)), &publishSetpoint, false, false);

View File

@@ -33,14 +33,14 @@ ros::Subscriber local_position_sub;
ros::Timer zero_timer; ros::Timer zero_timer;
PoseStamped vpe, pose; PoseStamped vpe, pose;
ros::Time got_local_pos(0); ros::Time got_local_pos(0);
ros::Duration publish_zero_timeout, publish_zero_duration, offset_timeout; ros::Duration publish_zero_timout, publish_zero_duration, offset_timeout;
TransformStamped offset; TransformStamped offset;
void publishZero(const ros::TimerEvent& e) void publishZero(const ros::TimerEvent& e)
{ {
if (!vpe.header.stamp.isZero() && e.current_real - vpe.header.stamp < publish_zero_timeout) return; // have vpe if (e.current_real - vpe.header.stamp < publish_zero_timout) return; // have vpe
if (!pose.header.stamp.isZero() && e.current_real - pose.header.stamp < publish_zero_timeout) { // have local position if (e.current_real - pose.header.stamp < publish_zero_timout) { // have local position
if (got_local_pos.isZero()) { if (got_local_pos.isZero()) {
ROS_INFO("got local position"); ROS_INFO("got local position");
got_local_pos = e.current_real; got_local_pos = e.current_real;
@@ -124,8 +124,8 @@ int main(int argc, char **argv) {
nh_priv.param<string>("frame_id", frame_id, ""); nh_priv.param<string>("frame_id", frame_id, "");
nh_priv.param<string>("offset_frame_id", offset_frame_id, ""); nh_priv.param<string>("offset_frame_id", offset_frame_id, "");
nh.param<string>("mavros/local_position/frame_id", local_frame_id, "map"); nh_priv.param<string>("mavros/local_position/frame_id", local_frame_id, "map");
nh.param<string>("mavros/local_position/tf/child_frame_id", child_frame_id, "base_link"); nh_priv.param<string>("mavros/local_position/tf/child_frame_id", child_frame_id, "base_link");
offset_timeout = ros::Duration(nh_priv.param("offset_timeout", 3.0)); offset_timeout = ros::Duration(nh_priv.param("offset_timeout", 3.0));
if (!frame_id.empty()) { if (!frame_id.empty()) {
@@ -144,7 +144,7 @@ int main(int argc, char **argv) {
if (nh_priv.param("force_init", false) || nh_priv.param("publish_zero", false)) { // publish_zero is old name if (nh_priv.param("force_init", false) || nh_priv.param("publish_zero", false)) { // publish_zero is old name
// publish zero to initialize the local position // publish zero to initialize the local position
zero_timer = nh.createTimer(ros::Duration(0.1), &publishZero); zero_timer = nh.createTimer(ros::Duration(0.1), &publishZero);
publish_zero_timeout = ros::Duration(nh_priv.param("force_init_timeout", 5.0)); publish_zero_timout = ros::Duration(nh_priv.param("force_init_timeout", 5.0));
publish_zero_duration = ros::Duration(nh_priv.param("force_init_duration", 5.0)); publish_zero_duration = ros::Duration(nh_priv.param("force_init_duration", 5.0));
local_position_sub = nh.subscribe("mavros/local_position/pose", 1, &localPositionCallback); local_position_sub = nh.subscribe("mavros/local_position/pose", 1, &localPositionCallback);
} }

View File

@@ -24,7 +24,6 @@ def test_simple_offboard_services_available():
rospy.wait_for_service('set_attitude', timeout=5) rospy.wait_for_service('set_attitude', timeout=5)
rospy.wait_for_service('set_rates', timeout=5) rospy.wait_for_service('set_rates', timeout=5)
rospy.wait_for_service('land', timeout=5) rospy.wait_for_service('land', timeout=5)
rospy.wait_for_service('simple_offboard/release', timeout=5)
def test_web_video_server(node): def test_web_video_server(node):
try: try:

View File

@@ -37,9 +37,6 @@
<node name="clover_blocks" pkg="clover_blocks" type="clover_blocks" output="screen" required="true"/> <node name="clover_blocks" pkg="clover_blocks" type="clover_blocks" output="screen" required="true"/>
<node pkg="topic_tools" name="main_camera_throttle" type="throttle" ns="main_camera"
args="messages image_raw 5.0 image_raw_throttled" required="true"/>
<param name="test_module" value="$(find clover)/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"/> <test test-name="basic_test" pkg="ros_pytest" type="ros_pytest_runner"/>
</launch> </launch>

View File

@@ -40,7 +40,6 @@ function viewTopicsList() {
let rosdistro; let rosdistro;
function viewTopic(topic) { function viewTopic(topic) {
let counter = 0;
let index = '<a href=topics.html>Topics</a>'; let index = '<a href=topics.html>Topics</a>';
title.innerHTML = `${index}: ${topic}`; title.innerHTML = `${index}: ${topic}`;
topicMessage.style.display = 'block'; topicMessage.style.display = 'block';
@@ -52,11 +51,10 @@ function viewTopic(topic) {
}); });
new ROSLIB.Topic({ ros: ros, name: topic }).subscribe(function(msg) { new ROSLIB.Topic({ ros: ros, name: topic }).subscribe(function(msg) {
counter++;
document.title = topic; document.title = topic;
if (mouseDown) return; if (mouseDown) return;
if (msg.header && msg.header.stamp) { if (msg.header.stamp) {
if (params.date || params.offset) { if (params.date || params.offset) {
let date = new Date(msg.header.stamp.secs * 1e3 + msg.header.stamp.nsecs * 1e-6); let date = new Date(msg.header.stamp.secs * 1e3 + msg.header.stamp.nsecs * 1e-6);
if (params.date) msg.header.date = date.toISOString(); if (params.date) msg.header.date = date.toISOString();
@@ -64,8 +62,7 @@ function viewTopic(topic) {
} }
} }
let txt = `<div class=counter>${counter} received</div>${yamlStringify(msg)}`; // JSON.stringify(msg, null, 4); topicMessage.innerHTML = yamlStringify(msg); // JSON.stringify(msg, null, 4);
topicMessage.innerHTML = txt;
}); });
} }

View File

@@ -15,7 +15,6 @@
white-space: pre; white-space: pre;
font-family: monospace; font-family: monospace;
} }
.counter { color: #b9b9b9; margin-bottom: 1em; }
#topic-type { font-family: monospace; font-size: 0.5em; vertical-align: super; font-weight: normal; } #topic-type { font-family: monospace; font-size: 0.5em; vertical-align: super; font-weight: normal; }
.topic { font-family: monospace; } .topic { font-family: monospace; }
body.closed { background-color: rgb(207, 207, 207); } body.closed { background-color: rgb(207, 207, 207); }

View File

@@ -19,7 +19,7 @@ The frontend files are located in [`www`](./www/) subdirectory. The frontend app
### Services ### Services
* `~run` ([*clover_blocks/Run*](srv/Run.srv)) run Blockly-generated program (in Python). * `~run` ([*clover_blocks/Run*](srv/Run.srv)) run Blockly-generated program (in Python).
* `~stop` ([*std_srvs/Trigger*](http://docs.ros.org/noetic/api/std_srvs/html/srv/Trigger.html)) terminate the running program. * `~stop` ([*std_srvs/Trigger*](http://docs.ros.org/melodic/api/std_srvs/html/srv/Trigger.html)) terminate the running program.
* `~store` ([*clover_blocks/load*](srv/Store.srv)) store a user program (to `<package_path>/programs` by default). * `~store` ([*clover_blocks/load*](srv/Store.srv)) store a user program (to `<package_path>/programs` by default).
* `~load` ([*clover_blocks/load*](srv/Load.srv)) load all the stored programs. * `~load` ([*clover_blocks/load*](srv/Load.srv)) load all the stored programs.
@@ -45,11 +45,11 @@ http://<hostname>/clover_blocks/?navigate_tolerance=0.5&sleep_time=0.1
#### Published #### Published
* `~running` ([*std_msgs/Bool*](http://docs.ros.org/noetic/api/std_msgs/html/msg/Bool.html)) indicates if the program is currently running. * `~running` ([*std_msgs/Bool*](http://docs.ros.org/melodic/api/std_msgs/html/msg/Bool.html)) indicates if the program is currently running.
* `~block` ([*std_msgs/String*](http://docs.ros.org/noetic/api/std_msgs/html/msg/String.html)) current executing block (maximum topic rate is limited). * `~block` ([*std_msgs/String*](http://docs.ros.org/melodic/api/std_msgs/html/msg/String.html)) current executing block (maximum topic rate is limited).
* `~error` ([*std_msgs/String*](http://docs.ros.org/noetic/api/std_msgs/html/msg/String.html))  user program errors and exceptions. * `~error` ([*std_msgs/String*](http://docs.ros.org/melodic/api/std_msgs/html/msg/String.html))  user program errors and exceptions.
* `~prompt` ([*clover_blocks/Prompt*](msg/Prompt.msg)) user input request (includes random request ID string). * `~prompt` ([*clover_blocks/Prompt*](msg/Prompt.msg)) user input request (includes random request ID string).
This topic is published from the frontend side: This topic is published from the frontend side:
* `~prompt/<request_id>` ([*std_msgs/String*](http://docs.ros.org/noetic/api/std_msgs/html/msg/String.html))  user input response. * `~prompt/<request_id>` ([*std_msgs/String*](http://docs.ros.org/melodic/api/std_msgs/html/msg/String.html))  user input response.

View File

@@ -10,7 +10,7 @@ The simulation may be configured by a set of arguments:
* `mav_id` (*integer*, default: *0*) - MAVLink identifier of the vehicle. **Note**: Multi-vehicle simulation is possible, but requires extensive changes to launch files; * `mav_id` (*integer*, default: *0*) - MAVLink identifier of the vehicle. **Note**: Multi-vehicle simulation is possible, but requires extensive changes to launch files;
* `est` (*string*, default: *lpe*, possible values: *lpe*, *ekf2*) - PX4 estimator selection. Note that this may be overriden in the startup scripts for your craft; * `est` (*string*, default: *lpe*, possible values: *lpe*, *ekf2*) - PX4 estimator selection. Note that this may be overriden in the startup scripts for your craft;
* `vehicle` (*string*, default: *clover*) - PX4 vehicle name. Depending on this parameter, different PX4 presets will be loaded. * `vehicle` (*string*, default: *clover*) - PX4 vehicle name. Depending on this parameter, different PX4 presets will be loaded. **Note**: The default value, *clover*, requires you to use [Clover-specific PX4 branch](https://github.com/CopterExpress/Firmware/tree/v1.10.1-clever);
* `main_camera` (*boolean*, default: *true*) - controls whether the drone will have a vision position estimation camera; * `main_camera` (*boolean*, default: *true*) - controls whether the drone will have a vision position estimation camera;
* `rangefinder` (*boolean*, default: *true*) - controls whether the drone will have a laser rangefinder; * `rangefinder` (*boolean*, default: *true*) - controls whether the drone will have a laser rangefinder;
* `led` (*boolean*, default: *true*) - controls whether the drone will have a programmable LED strip; * `led` (*boolean*, default: *true*) - controls whether the drone will have a programmable LED strip;

View File

@@ -7,31 +7,30 @@
. ${R}etc/init.d-posix/airframes/10016_iris # base on iris . ${R}etc/init.d-posix/airframes/10016_iris # base on iris
param set-default ATT_W_EXT_HDG 0.5 param set ATT_W_EXT_HDG 0.5
param set-default ATT_EXT_HDG_M 1 # 0 = none, 1 = vision, 2 = mocap param set ATT_EXT_HDG_M 1
param set-default COM_DISARM_LAND 1.0 param set COM_DISARM_LAND 1.0
param set-default COM_RCL_EXCEPT 4 # enable offboard flights without rc
param set-default LPE_FLW_SCALE 1.0 param set LPE_FLW_SCALE 1.0
param set-default LPE_FLW_R 0.2 param set LPE_FLW_R 0.2
param set-default LPE_FLW_RR 0.0 param set LPE_FLW_RR 0.0
param set-default LPE_FLW_QMIN 10 param set LPE_FLW_QMIN 10
param set-default LPE_VIS_DELAY 0.0 param set LPE_VIS_DELAY 0.0
param set-default LPE_VIS_Z 0.1 param set LPE_VIS_Z 0.1
param set-default LPE_FUSION 86 # flow + vis + land detector + gyro comp param set LPE_FUSION 86
param set-default SENS_FLOW_ROT 0 param set SENS_FLOW_ROT 0
param set-default SENS_FLOW_MINHGT 0.0 param set SENS_FLOW_MINHGT 0.0
param set-default SENS_FLOW_MAXHGT 4.0 param set SENS_FLOW_MAXHGT 4.0
param set-default SENS_FLOW_MAXR 10.0 param set SENS_FLOW_MAXR 10.0
param set-default EKF2_AID_MASK 26 # flow + vis pos + vis yaw param set EKF2_AID_MASK 27 # gps + flow + vis pos + vis yaw
param set-default EKF2_OF_DELAY 0 param set EKF2_OF_DELAY 0
param set-default EKF2_OF_QMIN 10 param set EKF2_OF_QMIN 10
param set-default EKF2_OF_N_MIN 0.05 param set EKF2_OF_N_MIN 0.05
param set-default EKF2_OF_N_MAX 0.2 param set EKF2_OF_N_MAX 0.2
param set-default EKF2_HGT_MODE 2 # 0 = baro, 1 = gps, 2 = range, 3 = vision param set EKF2_HGT_MODE 2
param set-default EKF2_EVA_NOISE 0.1 param set EKF2_EVA_NOISE 0.1
param set-default EKF2_EVP_NOISE 0.1 param set EKF2_EVP_NOISE 0.1
param set-default EKF2_EV_DELAY 0 param set EKF2_EV_DELAY 0

View File

@@ -21,7 +21,7 @@
</include> </include>
<!-- PX4 instance --> <!-- PX4 instance -->
<node name="sitl_$(arg mav_id)" pkg="px4" type="px4" output="screen" required="true" args="$(find px4)/ROMFS/px4fmu_common -s etc/init.d-posix/rcS -i $(arg mav_id)" unless="$(eval type == 'none')"> <node name="sitl_$(arg mav_id)" pkg="px4" type="px4" output="screen" args="$(find px4)/ROMFS/px4fmu_common -s etc/init.d-posix/rcS -i $(arg mav_id)" unless="$(eval type == 'none')">
<env name="PX4_SIM_MODEL" value="$(arg vehicle)"/> <env name="PX4_SIM_MODEL" value="$(arg vehicle)"/>
<env name="PX4_ESTIMATOR" value="$(arg est)"/> <env name="PX4_ESTIMATOR" value="$(arg est)"/>
</node> </node>
@@ -36,7 +36,7 @@
<arg name="use_clover_physics" value="$(arg use_clover_physics)"/> <arg name="use_clover_physics" value="$(arg use_clover_physics)"/>
</include> </include>
<node name="jmavsim" pkg="px4" required="true" type="jmavsim_run.sh" output="screen" if="$(eval type == 'jmavsim')"> <node name="jmavsim" pkg="px4" type="jmavsim_run.sh" output="screen" if="$(eval type == 'jmavsim')">
<env name="HEADLESS" value="1" if="$(eval not gui)"/> <env name="HEADLESS" value="1" if="$(eval not gui)"/>
</node> </node>

83
docs/.vuepress/config.js Normal file
View File

@@ -0,0 +1,83 @@
const sidebar = require('./sidebar');
const hostname = 'https://clover.coex.tech/';
const allowedTags = ['font', 'center', 'nobr']; // allow using some deprecated and non-standard html tags
module.exports = {
lang: 'en-US',
title: 'Clover',
description: 'Clover Drone Kit',
// theme and its config
theme: '@vuepress/theme-default',
themeConfig: {
logo: 'clover-logo.png',
sidebar: {
'/ru/': sidebar.readSummary("./ru/SUMMARY.md"),
'/en/': sidebar.readSummary("./en/SUMMARY.md"),
},
sidebarDepth: 0,
locales: {
'/en/': {
selectLanguageName: 'English',
navbar: [
{ text: 'Official Site', link: 'https://coex.tech' },
{ text: 'Support Chat', link: 'https://t.me/COEXHelpdesk' },
]
},
'/ru/': {
selectLanguageName: 'Русский',
tip: 'СОВЕТ',
warning: 'ВНИМАНИЕ',
danger: 'ОПАСНО',
toggleDarkMode: 'Переключить темную тему',
navbar: [
{ text: 'Сайт', link: 'https://coex.tech' },
{ text: 'Чат поддержки', link: 'https://t.me/COEXHelpdesk' },
]
},
},
toggleSidebar: true,
repo: 'CopterExpress/clover',
docsBranch: 'master',
docsDir: 'docs',
lastUpdated: false,
contributors: false
},
pagePatterns: ['**/*.md', '!.vuepress', '!node_modules', '!ru/metodmaterials.md'],
locales: {
'/en/': {
lang: 'en',
title: 'Clover',
description: 'Clover Drone Kit'
},
'/ru/': {
lang: 'ru',
title: 'Клевер',
description: 'Конструктор квадрокоптера «Клевер»'
}
},
markdown: {
code: {
lineNumbers: false
},
linkify: true,
},
extendsMarkdown(md) {
md.use(require('markdown-it-attrs')); // to use custom headers anchors
},
bundlerConfig: {
vuePluginOptions: {
template: {
compilerOptions: {
isCustomElement: tag => allowedTags.includes(tag)
}
}
}
},
plugins: [
'@vuepress/plugin-search',
'vuepress-plugin-copy-code2',
['sitemap2', { hostname, excludeUrls: ['/', '/LANGS.html'] }],
require('./rich-quotes')
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

View File

@@ -0,0 +1,37 @@
// Plugin to convert GitBook rich quotes to custom containers
const types = {
info: 'tip',
note: 'tip',
tag: 'tip',
comment: 'tip',
hint: 'tip',
success: 'tip',
warning: 'warning',
caution: 'warning',
danger: 'danger',
quote: 'tip'
}
function replace(src) {
return src.replace(/^> \*\*(.*?)\*\* (.*\n(>.*\n)*)/gm, function (match, type, text) {
text = text.replace(/^>/gm, '');
return `::: ${types[type.toLowerCase()]}\n${text}\n:::`;
});
}
module.exports = {
name: 'vuepress-plugin-rich-quotes',
extendsMarkdown: (md) => {
var _render = md.render;
// TODO: a rough hack to replace rich quotes
// TODO: use proper plugin api
md.render = function(src, env) {
src = replace(src);
return _render.call(md, src, env);
}
},
};

50
docs/.vuepress/sidebar.js Normal file
View File

@@ -0,0 +1,50 @@
const fs = require('fs')
const regex = /(\s*?)\*\s\[(.*?)\]\((.*?)\)/;
exports.readSummary = function (path) {
let sidebar = [];
let lines = fs.readFileSync(path).toString().split('\n');
let item = {};
for (let line of lines) {
if (line.startsWith('#')) continue;
if (!line.trim()) continue;
let match = regex.exec(line);
if (!match) {
console.log('cannot parse', line);
continue;
}
level = match[1].length / 2;
text = match[2];
path = match[3].trim();
if (level == 0) {
if (item.path) {
// push new item
if (item.children) {
sidebar.push(item);
} else {
sidebar.push(item.path)
}
item = {};
}
item.text = text;
item.path = path;
item.collapsible = true;
} else if (level == 1 || level == 2) {
if (!item.children) {
item.children = [];
if (item.path) item.children.push(item.path);
}
item.children.push(path);
} else {
console.log('skip', text);
}
}
return sidebar;
}

View File

@@ -0,0 +1,49 @@
.big-clover {
max-width: 80% !important;
display: block;
margin-left: auto;
margin-right: auto;
}
/* change image for dark theme */
html .big-clover.dark { display: none; }
html.dark .big-clover { display: none; }
html.dark .big-clover.dark { display: block; }
img.logo {
transform: scale(2.5) translateX(-5%);
}
/* Centered images */
img.center {
display: block;
margin-left: auto;
margin-right: auto;
}
/* Images with border */
img.border {
border: 1px #e9e9e9 solid;
border-radius: 5px;
}
html.dark img.border {
border: none;
background: #fffffa;
}
table.versions td {
text-align: center;
background: white;
}
table.versions .subversion {
font-size: 80%;
}
.circle {
width: 0.8em;
height: 0.8em;
border-radius: 50%;
display: inline-block;
margin-right: 0.5em;
}

4
docs/README.md Normal file
View File

@@ -0,0 +1,4 @@
# Languages
* [English](en/)
* [Русский](ru/)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW 2019 (64-Bit) -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="255.858mm" height="78.1171mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 5794.02 1769"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
<defs>
<style type="text/css">
<![CDATA[
.fil1 {fill:#1F1B20}
.fil0 {fill:#1F1B20;fill-rule:nonzero}
]]>
</style>
</defs>
<g id="Слой_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<polygon class="fil0" points="3293.37,1768.99 2509.06,1768.97 2507.86,1661.12 3292.17,1660.65 "/>
<polygon class="fil0" points="3133.99,231.57 2664.24,231.57 2556.99,123.72 3237.05,123.23 "/>
<path class="fil0" d="M3647.51 123.72l1925.38 0 0 381.38 -107.85 -8.69 0 -264.84 -1809.74 0 -7.79 -107.85zm1925.38 676.77l0 968.51 -1653.42 0 -1.5 -108.34 1547.07 0.49 0 -850.17 107.85 -10.48z"/>
<path class="fil0" d="M2142.36 123.72l-1925.38 0 0 381.38 107.85 -8.69 0 -264.84 1809.74 0 7.79 -107.85zm-1925.38 676.77l0 968.51 1654.08 0 1.5 -108.34 -1547.73 0.49 0 -850.17 -107.85 -10.48z"/>
<path class="fil1" d="M2887.45 1229.18c-100.66,0 -189.34,-87.18 -244.46,-111.14 -55.12,-23.96 -215.7,-63.51 -215.7,-63.51 0,0 -88.67,-131.81 -110.24,-196.52 -21.57,-64.71 -38.35,-225.29 -38.35,-225.29 0,0 -28.76,-59.92 -38.35,-86.28 -9.59,-26.36 -19.17,-79.09 -19.17,-79.09l67.11 -59.92 -71.9 -21.57c0,0 -9.59,-131.82 -9.59,-184.54 0,-52.73 28.76,-201.32 28.76,-201.32 0,0 143.8,76.69 242.06,148.59 98.26,71.9 201.32,220.49 201.32,220.49 0,0 97.96,-32.96 220.19,-32.96 122.23,0 212.4,32.96 212.4,32.96 0,0 103.06,-148.59 201.32,-220.49 98.26,-71.9 242.06,-148.59 242.06,-148.59 29.86,154.29 35.16,239.28 25.77,366.69 -7.33,99.38 -20.22,164.6 -68.91,266.02 0,0 -16.78,146.2 -38.35,225.29 -21.57,79.09 -110.24,196.52 -110.24,196.52 0,0 -165.37,25.17 -221.69,53.92 -56.32,28.76 -153.38,120.73 -254.04,120.73zm-260.11 -471.35c0,0 -32.95,31.4 -32.95,71.54 0,40.15 29.36,76.45 29.36,76.45 0,0 30.97,-38.24 30.97,-73.59 0,-35.35 -27.38,-74.4 -27.38,-74.4zm-164.17 -37.15c0,0 84.84,-18.88 192.09,33.85 107.25,52.73 163.22,135.12 163.22,135.12 0,0 -122.28,71.58 -245.11,36.23 -122.83,-35.35 -110.2,-205.2 -110.2,-205.2zm687.07 37.15c0,0 32.95,31.4 32.95,71.54 0,40.15 -29.36,76.45 -29.36,76.45 0,0 -30.97,-38.24 -30.97,-73.59 0,-35.35 27.38,-74.4 27.38,-74.4zm164.17 -37.15c0,0 -84.84,-18.88 -192.09,33.85 -107.25,52.73 -163.22,135.12 -163.22,135.12 0,0 122.28,71.58 245.11,36.23 122.83,-35.35 110.2,-205.2 110.2,-205.2z"/>
<path class="fil1" d="M2895.05 1398.42c0,0 -216.07,-1.19 -337.7,-47.93 -121.63,-46.74 -147.39,-68.91 -147.39,-68.91l-149.64 380.47 134.66 0 1.2 105.45 -411.02 0 0 -105.45 154.43 0 105.6 -464.95c0,0 -226.48,-22.77 -424.21,-81.49 -197.72,-58.72 -354.7,-127.02 -492.51,-133.01 -137.81,-5.99 -114.44,-2.99 -198.32,-7.79 -83.88,-4.79 -142.6,-47.92 -142.6,-82.68 0,-34.75 1.2,-59.32 1.2,-97.66 0,-38.35 32.36,-46.74 32.36,-46.74l-1.2 -29.96 -22.77 0c0,-8.09 12.58,-46.74 -53.93,-46.74 -66.51,0 -175.67,58.19 -233.67,77.89 -58,19.71 -552.43,-15.58 -644.7,-41.94 -92.27,-26.36 -64.71,-77.89 -45.54,-94.67 19.17,-16.78 539.25,-63.51 645.9,-56.32 106.65,7.19 329.54,44.34 329.54,44.34l0 -26.36 25.76 0 0 -25.76 12.58 0c0,0 2.39,-94.67 2.39,-134.21 0,-39.54 37.23,-60.33 65.31,-59.9 28.08,0.43 63.2,25.75 63.2,61.1 0,35.35 2.7,128.82 2.7,128.82l7.49 -0.15 0 25.02 32.95 0 0 27.56c0,0 253.15,-39.85 361,-45.84 107.85,-5.99 594.37,37.15 617.14,58.72 22.77,21.57 35.95,77.89 -39.55,100.66 -75.5,22.77 -581.19,57.52 -639.91,46.74 -58.72,-10.79 -173.73,-77.7 -243.26,-76.69 -69.53,1.01 -56.62,35.95 -56.62,45.54l-22.78 -0.9 -0.16 18.87c0,0 83.07,-1.13 121.42,16.84 38.35,17.97 115.72,50.26 168.44,62.24 52.72,11.98 568.01,-14.38 636.31,-28.76 68.3,-14.38 115.48,-40.16 115.48,-40.16 0,0 16.34,115.66 47.5,189.95 31.16,74.3 86.28,147.39 109.05,164.17 22.77,16.78 156.98,45.54 196.52,59.92 39.55,14.38 110.24,58.72 149.79,86.28 39.55,27.56 112.97,44.34 172.89,44.34 59.92,0 126.57,-16.78 166.12,-44.34 39.55,-27.56 110.24,-71.9 149.79,-86.28 39.55,-14.38 173.76,-43.14 196.52,-59.92 22.77,-16.78 77.89,-89.88 109.05,-164.17 31.16,-74.3 47.5,-189.95 47.5,-189.95 0,0 47.17,25.78 115.48,40.16 68.3,14.38 583.59,40.74 636.31,28.76 52.72,-11.98 130.1,-44.27 168.44,-62.24 38.35,-17.97 121.42,-16.84 121.42,-16.84l-0.16 -18.87 -22.78 0.9c0,-9.59 12.91,-44.53 -56.62,-45.54 -69.53,-1.01 -184.54,65.91 -243.26,76.69 -58.72,10.79 -564.41,-23.97 -639.91,-46.74 -75.5,-22.77 -62.31,-79.09 -39.55,-100.66 22.77,-21.57 509.29,-64.71 617.14,-58.72 107.85,5.99 361,45.84 361,45.84l0 -27.56 32.95 0 0 -25.02 7.49 0.15c0,0 2.7,-93.47 2.7,-128.82 0,-35.35 35.12,-60.67 63.2,-61.1 28.08,-0.43 65.31,20.36 65.31,59.9 0,39.54 2.39,134.21 2.39,134.21l12.58 0 0 25.76 25.76 0 0 26.36c0,0 222.89,-37.15 329.54,-44.34 106.65,-7.19 626.73,39.54 645.9,56.32 19.17,16.78 46.74,68.3 -45.54,94.67 -92.27,26.36 -586.7,61.65 -644.7,41.94 -58,-19.71 -167.17,-77.89 -233.67,-77.89 -66.51,0 -53.93,38.65 -53.93,46.74l-22.77 0 -1.2 29.96c0,0 32.36,8.4 32.36,46.74 0,38.35 1.2,62.91 1.2,97.66 0,34.75 -58.72,77.88 -142.6,82.68 -83.88,4.79 -60.52,1.79 -198.32,7.79 -137.81,5.99 -294.79,74.3 -492.51,133.01 -197.72,58.72 -424.21,81.49 -424.21,81.49l105.6 464.95 154.43 0 0 105.45 -411.02 0 1.2 -105.45 134.66 0 -149.64 -380.47c0,0 -25.76,22.17 -147.39,68.91 -121.63,46.74 -341.62,47.93 -341.62,47.93z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 850.39 283.46" style="enable-background:new 0 0 850.39 283.46;" xml:space="preserve">
<style type="text/css">
.st0{fill:#333333;}
.st1{fill:#FFFFFF;}
.st2{fill:#CCCCCC;}
.st3{fill:#1E1183;}
.st4{fill:#F71523;}
.st5{fill:url(#SVGID_1_);}
.st6{fill:url(#SVGID_2_);}
.st7{fill:url(#SVGID_3_);}
.st8{opacity:0.05;fill:#FFFFFF;}
.st9{opacity:0.05;fill:#CCCCCC;}
.st10{opacity:0.05;fill:url(#SVGID_4_);}
.st11{opacity:0.05;fill:url(#SVGID_5_);}
.st12{opacity:0.05;fill:url(#SVGID_6_);}
.st13{opacity:0.05;fill:url(#SVGID_7_);}
.st14{opacity:0.05;fill:url(#SVGID_8_);}
.st15{opacity:0.05;fill:url(#SVGID_9_);}
.st16{opacity:0.05;fill:url(#SVGID_10_);}
.st17{opacity:0.05;fill:url(#SVGID_11_);}
.st18{opacity:0.05;fill:url(#SVGID_12_);}
</style>
<g>
<polygon class="st3" points="559.36,2.05 433.46,2.05 433.46,36.37 479.25,36.37 479.25,128.02 513.57,128.02 513.57,36.37
559.36,36.37 "/>
<polygon class="st3" points="702.71,36.37 702.71,2.05 576.81,2.05 576.81,2.12 576.75,2.12 576.75,128.02 576.81,128.02
611.07,128.02 702.71,128.02 702.71,93.7 611.07,93.7 611.07,82.23 668.45,82.23 668.45,47.91 611.07,47.91 611.07,36.37 "/>
<polygon class="st3" points="559.45,179.72 559.38,155.4 535.19,155.45 489.34,201.3 467.68,201.3 467.68,155.45 433.37,155.45
433.37,281.35 467.68,281.35 467.68,235.62 489.46,235.62 535.19,281.35 559.38,281.41 559.45,257.09 520.77,218.4 "/>
<path class="st3" d="M67.26,36.87h63.01V2.05H67.26c-34.8,0-63.01,28.21-63.01,63.01s28.21,63.01,63.01,63.01h63.01V93.25H67.26
c-15.57,0-28.19-12.62-28.19-28.19C39.07,49.49,51.69,36.87,67.26,36.87z"/>
<path class="st3" d="M238.36,218.4v63.01h34.82V218.4c0-34.8-28.21-63.01-63.01-63.01s-63.01,28.21-63.01,63.01v63.01h34.82V218.4
c0-15.57,12.62-28.19,28.19-28.19C225.74,190.21,238.36,202.83,238.36,218.4z"/>
<path class="st3" d="M353.08,190.21h63.01V155.4h-63.01c-34.8,0-63.01,28.21-63.01,63.01s28.21,63.01,63.01,63.01h63.01v-34.82
h-63.01c-15.57,0-28.19-12.62-28.19-28.19C324.88,202.83,337.51,190.21,353.08,190.21z"/>
<polygon class="st3" points="95.79,155.4 95.79,200.82 39.41,200.82 39.41,155.4 4.25,155.4 4.25,281.41 39.41,281.41
39.41,235.98 95.79,235.98 95.79,281.41 130.27,281.41 130.27,155.4 "/>
<path class="st4" d="M737.06,200.43c-0.42-25.12-21.44-45.04-46.57-45.04h-45.07v34.32l45.49,0c6.19,0,11.52,4.76,11.81,10.95
c0.31,6.61-4.95,12.06-11.49,12.06h-11.5c-18.95,0-34.32,15.36-34.32,34.32v0v34.26h91.64v-34.26h-45.82
C716.81,247.03,737.49,226.1,737.06,200.43z"/>
<path class="st3" d="M272.4,55.19c-5.46-34.37-37.74-57.8-72.11-52.35c-34.37,5.46-57.8,37.74-52.35,72.11
c5.46,34.37,37.74,57.8,72.11,52.35C254.42,121.84,277.85,89.56,272.4,55.19z M210.17,93.26c-15.57,0-28.19-12.62-28.19-28.19
c0-15.57,12.62-28.19,28.19-28.19c15.57,0,28.19,12.62,28.19,28.19C238.36,80.64,225.74,93.26,210.17,93.26z"/>
<rect x="593.74" y="155.4" transform="matrix(-1 -1.224647e-16 1.224647e-16 -1 1221.7888 356.6999)" class="st4" width="34.32" height="45.91"/>
<path class="st3" d="M370.51,2.12V2.05h-60.96v0.07h-19.48v125.9h34.32V93.26h46.13c25.17,0,45.57-20.4,45.57-45.57
C416.08,22.52,395.68,2.12,370.51,2.12z M364.98,64.71h-40.6V31.12h40.6v0.02c9.27,0,16.78,7.51,16.78,16.78
C381.77,57.19,374.25,64.71,364.98,64.71z"/>
<path class="st3" d="M846.12,47.69c0-25.17-20.4-45.57-45.57-45.57V2.05h-60.96v0.01h-19.48v126.02h34.32V93.26h32.67l34.76,34.76
l24.19,0.06l0.07-24.32l-19.03-19.03C838.61,76.45,846.12,62.95,846.12,47.69z M795.02,64.71
C795.02,64.71,795.02,64.71,795.02,64.71h-40.6V31.12h40.6v0.03c0,0,0,0,0,0c9.27,0,16.78,7.51,16.78,16.78
C811.8,57.19,804.29,64.71,795.02,64.71z"/>
<path class="st4" d="M846.1,195.54c0.31-22.05-18.25-40.09-40.3-40.09h-51.34v34.32h51.59v0.01c2.71,0,5.17,1.93,5.66,4.78
c0.33,1.96-0.48,3.98-1.98,5.29c-1.19,1.04-2.46,1.39-3.68,1.39v0.01h-27.06v34.32h27.06v0.01c2.71,0,5.17,1.93,5.66,4.78
c0.33,1.96-0.48,3.98-1.98,5.29c-1.19,1.04-2.46,1.39-3.68,1.39v0.01h-51.59v34.32h51.34c22.05,0,40.61-18.04,40.3-40.09
c-0.12-8.55-2.96-16.44-7.68-22.86C843.14,211.99,845.98,204.1,846.1,195.54z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

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