mirror of
https://github.com/CopterExpress/clover.git
synced 2026-06-01 15:39:32 +00:00
Compare commits
7 Commits
clover-doc
...
strict-war
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d715206fbe | ||
|
|
9fc07c9479 | ||
|
|
075779d81f | ||
|
|
fcfa1c2a30 | ||
|
|
7f1d89110b | ||
|
|
2f261c6a20 | ||
|
|
673343f042 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -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
|
||||||
|
|||||||
23
.github/workflows/docs-docker.yaml
vendored
23
.github/workflows/docs-docker.yaml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: Build docs Docker image
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: [ '*' ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
docs-docker:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Build Docker image
|
|
||||||
run: docker build -t clover-docs:latest docs
|
|
||||||
|
|
||||||
- name: Test Docker image
|
|
||||||
run: docker run -t --rm -v `pwd`:/clover clover-docs:latest
|
|
||||||
|
|
||||||
- name: Show results
|
|
||||||
run: |
|
|
||||||
ls -lh _book
|
|
||||||
ls -lh *.pdf
|
|
||||||
44
.github/workflows/docs.yml
vendored
44
.github/workflows/docs.yml
vendored
@@ -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
|
||||||
@@ -67,20 +58,11 @@ jobs:
|
|||||||
rm -f _book/clover*.pdf
|
rm -f _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
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ project(aruco_pose)
|
|||||||
## Compile as C++11, supported in ROS Kinetic and newer
|
## Compile as C++11, supported in ROS Kinetic and newer
|
||||||
add_compile_options(-std=c++11)
|
add_compile_options(-std=c++11)
|
||||||
|
|
||||||
|
add_compile_options(-Wall -Wextra -Werror)
|
||||||
|
|
||||||
## Find catkin macros and libraries
|
## Find catkin macros and libraries
|
||||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||||
## is used, also find other catkin packages
|
## is used, also find other catkin packages
|
||||||
@@ -119,7 +121,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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
|
|||||||
@@ -75,7 +75,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:
|
||||||
|
|||||||
@@ -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"))
|
|
||||||
@@ -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_;
|
||||||
@@ -102,7 +96,8 @@ public:
|
|||||||
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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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/*) ]]
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ project(clover)
|
|||||||
## Compile as C++11, supported in ROS Kinetic and newer
|
## Compile as C++11, supported in ROS Kinetic and newer
|
||||||
add_compile_options(-std=c++11)
|
add_compile_options(-std=c++11)
|
||||||
|
|
||||||
|
add_compile_options(-Wall -Wextra -Werror)
|
||||||
|
|
||||||
## Find catkin macros and libraries
|
## Find catkin macros and libraries
|
||||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||||
## is used, also find other catkin packages
|
## is used, also find other catkin packages
|
||||||
@@ -17,7 +19,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
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
<launch>
|
|
||||||
<!-- shurtcut for running the simulation (`roslaunch clover simulator.launch`) -->
|
|
||||||
<include file="$(find clover_simulation)/launch/simulator.launch"/>
|
|
||||||
</launch>
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,6 @@ private:
|
|||||||
prev_ = curr_.clone();
|
prev_ = curr_.clone();
|
||||||
prev_stamp_ = msg->header.stamp;
|
prev_stamp_ = msg->header.stamp;
|
||||||
|
|
||||||
publish_debug:
|
|
||||||
// Publish debug image
|
// Publish debug image
|
||||||
if (img_pub_.getNumSubscribers() > 0) {
|
if (img_pub_.getNumSubscribers() > 0) {
|
||||||
// publish debug image
|
// publish debug image
|
||||||
@@ -277,7 +276,7 @@ publish_debug:
|
|||||||
return flow;
|
return flow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void paramCallback(clover::FlowConfig &config, uint32_t level)
|
void paramCallback(clover::FlowConfig &config, [[maybe_unused]] uint32_t level)
|
||||||
{
|
{
|
||||||
enabled_ = config.enabled;
|
enabled_ = config.enabled;
|
||||||
if (!enabled_) {
|
if (!enabled_) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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')
|
||||||
@@ -650,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()
|
||||||
@@ -708,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')
|
||||||
@@ -733,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:
|
||||||
|
|||||||
@@ -150,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));
|
||||||
@@ -506,10 +503,10 @@ inline void checkManualControl()
|
|||||||
|
|
||||||
if (check_kill_switch) {
|
if (check_kill_switch) {
|
||||||
// switch values: https://github.com/PX4/PX4-Autopilot/blob/c302514a0809b1765fafd13c014d705446ae1113/msg/manual_control_setpoint.msg#L3
|
// switch values: https://github.com/PX4/PX4-Autopilot/blob/c302514a0809b1765fafd13c014d705446ae1113/msg/manual_control_setpoint.msg#L3
|
||||||
const uint8_t SWITCH_POS_NONE = 0; // switch is not mapped
|
[[maybe_unused]] const uint8_t SWITCH_POS_NONE = 0; // switch is not mapped
|
||||||
const uint8_t SWITCH_POS_ON = 1; // switch activated
|
[[maybe_unused]] const uint8_t SWITCH_POS_ON = 1; // switch activated
|
||||||
const uint8_t SWITCH_POS_MIDDLE = 2; // middle position
|
[[maybe_unused]] const uint8_t SWITCH_POS_MIDDLE = 2; // middle position
|
||||||
const uint8_t SWITCH_POS_OFF = 3; // switch not activated
|
[[maybe_unused]] const uint8_t SWITCH_POS_OFF = 3; // switch not activated
|
||||||
|
|
||||||
const int KILL_SWITCH_BIT = 12; // https://github.com/PX4/Firmware/blob/c302514a0809b1765fafd13c014d705446ae1113/src/modules/mavlink/mavlink_messages.cpp#L3975
|
const int KILL_SWITCH_BIT = 12; // https://github.com/PX4/Firmware/blob/c302514a0809b1765fafd13c014d705446ae1113/src/modules/mavlink/mavlink_messages.cpp#L3975
|
||||||
uint8_t kill_switch = (manual_control.buttons & (0b11 << KILL_SWITCH_BIT)) >> KILL_SWITCH_BIT;
|
uint8_t kill_switch = (manual_control.buttons & (0b11 << KILL_SWITCH_BIT)) >> KILL_SWITCH_BIT;
|
||||||
@@ -811,7 +808,7 @@ bool setRates(SetRates::Request& req, SetRates::Response& res) {
|
|||||||
return serve(RATES, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, req.pitch_rate, req.roll_rate, req.yaw_rate, NAN, NAN, req.thrust, NAN, "", req.auto_arm, res.success, res.message);
|
return serve(RATES, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, req.pitch_rate, req.roll_rate, req.yaw_rate, NAN, NAN, req.thrust, NAN, "", req.auto_arm, res.success, res.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool land(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
bool land([[maybe_unused]] std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (busy)
|
if (busy)
|
||||||
|
|||||||
@@ -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 (!vpe.header.stamp.isZero() && 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 (!pose.header.stamp.isZero() && 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;
|
||||||
@@ -109,7 +109,7 @@ void callback(const T& msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reset(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
bool reset([[maybe_unused]] std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
||||||
{
|
{
|
||||||
reset_flag = true;
|
reset_flag = true;
|
||||||
res.success = true;
|
res.success = true;
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 26 # 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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
# Build: sudo docker build -t clover-docs:latest .
|
|
||||||
|
|
||||||
# Run: docker run -it --rm -v ~/clover:/clover clover-docs:latest
|
|
||||||
|
|
||||||
# Save image: sudo docker save clover-docs:latest | gzip > clover-docs.tar.gz
|
|
||||||
|
|
||||||
FROM ubuntu:22.04
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y curl git
|
|
||||||
|
|
||||||
RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
|
|
||||||
RUN . $HOME/.nvm/nvm.sh && nvm install 10.15 && nvm use 10.15 && npm --version
|
|
||||||
|
|
||||||
RUN echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get install -y calibre msttcorefonts ghostscript
|
|
||||||
|
|
||||||
RUN . $HOME/.nvm/nvm.sh && curl https://raw.githubusercontent.com/CopterExpress/clover/master/builder/assets/install_gitbook.sh | bash
|
|
||||||
|
|
||||||
# RUN . $HOME/.nvm/nvm.sh && npm install markdownlint-cli@0.28.1 -g && PUPPETEER_SKIP_DOWNLOAD=1 npm install svgexport -g
|
|
||||||
RUN . $HOME/.nvm/nvm.sh && npm install markdownlint-cli@0.28.1 -g && npm install svgexport -g --unsafe-perm
|
|
||||||
|
|
||||||
RUN . $HOME/.nvm/nvm.sh && node -v && gitbook -V && markdownlint -V
|
|
||||||
|
|
||||||
RUN curl https://raw.githubusercontent.com/CopterExpress/clover/master/book.json > book.json
|
|
||||||
|
|
||||||
RUN . $HOME/.nvm/nvm.sh && gitbook install
|
|
||||||
|
|
||||||
CMD . $HOME/.nvm/nvm.sh && export QTWEBENGINE_DISABLE_SANDBOX=1 && cp -r node_modules /clover && cd /clover && gitbook build \
|
|
||||||
&& gitbook pdf ./ _book/clover.pdf && \
|
|
||||||
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/default -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages -dCompressFonts=true -r150 -sOutputFile=_book/clover_ru_compressed.pdf _book/clover_ru.pdf && \
|
|
||||||
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/default -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages -dCompressFonts=true -r150 -sOutputFile=_book/clover_en_compressed.pdf _book/clover_en.pdf && \
|
|
||||||
rm _book/clover_ru.pdf && mv _book/clover_ru_compressed.pdf _book/clover_ru.pdf && \
|
|
||||||
rm _book/clover_en.pdf && mv _book/clover_en_compressed.pdf _book/clover_en.pdf
|
|
||||||
@@ -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 |
@@ -96,7 +96,6 @@
|
|||||||
* [Migration to v0.20](migrate20.md)
|
* [Migration to v0.20](migrate20.md)
|
||||||
* [Migration to v0.22](migrate22.md)
|
* [Migration to v0.22](migrate22.md)
|
||||||
* [Events](events.md)
|
* [Events](events.md)
|
||||||
* [CopterHack-2023](copterhack2023.md)
|
|
||||||
* [CopterHack-2022](copterhack2022.md)
|
* [CopterHack-2022](copterhack2022.md)
|
||||||
* [CopterHack-2021](copterhack2021.md)
|
* [CopterHack-2021](copterhack2021.md)
|
||||||
* [CopterHack-2019](copterhack2019.md)
|
* [CopterHack-2019](copterhack2019.md)
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ There are several tools allowing to calibrate the camera and store calculated pa
|
|||||||
|
|
||||||
Main tutorial: http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration.
|
Main tutorial: http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration.
|
||||||
|
|
||||||
In order to calibrate the camera with the `camera_calibration` ROS-package you need a computer with OS GNU/Linux and [ROS Noetic](http://wiki.ros.org/noetic/Installation/Ubuntu) installed.
|
In order to calibrate the camera with the `camera_calibration` ROS-package you need a computer with OS GNU/Linux and [ROS Melodic](ros-install.md) installed.
|
||||||
|
|
||||||
<img src="../assets/camera_calibration.png" alt="ROS Camera Calibrator" class="zoom center" width=600>
|
<img src="../assets/camera_calibration.png" alt="ROS Camera Calibrator" class="zoom center" width=600>
|
||||||
|
|
||||||
1. Using the Terminal, install `camera_calibration` package to your computer:
|
1. Using the Terminal, install `camera_calibration` package to your computer:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install ros-noetic-camera-calibration
|
sudo apt-get install ros-melodic-camera-calibration
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Download the chessboard – [chessboard.pdf](../assets/chessboard.pdf). Print the chessboard on paper or open it on the computer screen.
|
2. Download the chessboard – [chessboard.pdf](../assets/chessboard.pdf). Print the chessboard on paper or open it on the computer screen.
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
# CopterHack 2023
|
|
||||||
|
|
||||||
<img src="../assets/copterhack2023.svg" width=300 align=right>
|
|
||||||
|
|
||||||
CopterHack 2023 is an international open-source projects competition on aerial robotics. The main direction of the CopterHack is team competition with a free choice of the project topic. The competition’s official language is English.
|
|
||||||
|
|
||||||
To learn more about the articles of the CopterHack finalist teams follow the links [CopterHack 2021](copterhack2021.md), [CopterHack 2022](copterhack2022.md).
|
|
||||||
|
|
||||||
The proposed projects are supposed to be open-source and be compatible with the Clover quadcopter platform. Teams-participants are supposed to work on their projects throughout the competition, bringing them closer to the state of the finished product while being assisted by industry experts through lectures and regular feedback.
|
|
||||||
|
|
||||||
## CopterHack 2023 stages
|
|
||||||
|
|
||||||
The qualifying and project development stages will be held in an online format, however, the final round will be in a hybrid mode (offline + online). The competition involves monthly updates from the teams with regular feedback from the jury. All teams are required to prepare a final video and presentation on the project's results to participate in the final stage.
|
|
||||||
|
|
||||||
1. Qualifying stage. Applications are accepted on the deadline date until October 31, 2022.
|
|
||||||
2. Projects development stage. This stage includes monthly updates and mentorship of participants. Starting date - November 1, 2022. Deadline date - February 28, 2023.
|
|
||||||
3. All teams-participants are required to make the final video to proceed to the final round. Final videos are required to be uploaded until March 31, 2023.
|
|
||||||
4. The final round. Projects presentation takes place April 23, 2023.
|
|
||||||
|
|
||||||
## Conditions and criteria for evaluation the final result
|
|
||||||
|
|
||||||
General project requirements:
|
|
||||||
|
|
||||||
1. Open-source.
|
|
||||||
2. Compatibility with the Clover platform.
|
|
||||||
|
|
||||||
Judging criteria for the jury at the final:
|
|
||||||
|
|
||||||
1. Readiness and the article (max. 10 points): the degree of readiness of the project; an accessible and understandable description of the project in the article; a link to the code with comments, diagrams, drawings. It should be possible to reproduce the project and get the result according to the article.
|
|
||||||
2. Amount of work done (max. 6 points): the amount of work done by the team in the framework within of CopterHack, its complexity, and the technical level.
|
|
||||||
3. Usefulness for Clover (max. 6 points): the relevance to the Clover and PX4 platform application in practice, the potential level of demand from other Clover users.
|
|
||||||
4. Presentation at the final (max. 3 points): quality and entertainment points of the final presentation; completeness of the project coverage; demonstration; answers to the jury's questions.
|
|
||||||
|
|
||||||
## Prize fund
|
|
||||||
|
|
||||||
Basing on the results of the evaluation of projects at the final round, the jury will select the winners with the following prizes.
|
|
||||||
|
|
||||||
* 1st place: $3000 (USD).
|
|
||||||
* 2nd place: $2000 (USD).
|
|
||||||
* 3rd place: $1000 (USD).
|
|
||||||
* 4th place: $500 (USD).
|
|
||||||
* 5th place: $500 (USD).
|
|
||||||
|
|
||||||
The competition partners can reward the teams according to additional criteria identified during the evaluation of projects during the final round.
|
|
||||||
|
|
||||||
## How to apply?
|
|
||||||
|
|
||||||
> **Note** In order to be able to apply, you must have an account on [GitHub](https://github.com).
|
|
||||||
|
|
||||||
Prepare your application and send it as a Draft Pull Request to [Clover repository](https://github.com/CopterExpress/clover)
|
|
||||||
|
|
||||||
1. Fork the Clover repository:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/github-fork.png" alt="GitHub Fork">
|
|
||||||
|
|
||||||
2. On the web page of your fork, go to the `docs/en` section and create a new file in the [Markdown](http://en.wikipedia.org/wiki/Markdown) format:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/create_new_file.png" alt="GitHub Create New File">
|
|
||||||
|
|
||||||
3. Enter the title of your article. For example, `new-article.md`
|
|
||||||
|
|
||||||
<img src="../assets/github_application/new_article.png" alt="GitHub New Article">
|
|
||||||
|
|
||||||
4. Fill in your application by the recommended template:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Project name
|
|
||||||
|
|
||||||
[CopterHack-2023](copterhack2023.md), team **Team name**.
|
|
||||||
|
|
||||||
## Team information
|
|
||||||
|
|
||||||
The list of team members:
|
|
||||||
|
|
||||||
(Describe the team: full name, contacts (Telegram username), role in the team).
|
|
||||||
|
|
||||||
* Alexander Sokolov, @aleksandrsokolov111, engineer.
|
|
||||||
* Elena Smirnova, @elenasmirnova111, programmer.
|
|
||||||
|
|
||||||
## Project description
|
|
||||||
|
|
||||||
### Project idea
|
|
||||||
|
|
||||||
Briefly describe the idea and stage of the project.
|
|
||||||
|
|
||||||
### The potential outcomes
|
|
||||||
|
|
||||||
Describe how you see the project result.
|
|
||||||
|
|
||||||
### Using Clover platform
|
|
||||||
|
|
||||||
Describe how the Clover platform will be used in your project.
|
|
||||||
|
|
||||||
### Additional information at the request of participants
|
|
||||||
|
|
||||||
For example, information about the team's experience while working on projects, attach a link to articles, videos.
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Go to the bottom of the page and create a new branch with the title of your article:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/propose_new_file.png" alt="GitHub Propose New File">
|
|
||||||
|
|
||||||
> **Note** Don't commit changes directly to the `master` branch, create a new branch.
|
|
||||||
|
|
||||||
6. If necessary, place additional visual assets in the `docs/assets` folder and add them to your article.
|
|
||||||
|
|
||||||
7. Send a Draft Pull Request from your branch to Clover:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/github-pull-request-create.png" alt="GitHub Create Pull">
|
|
||||||
|
|
||||||
8. In the Pull Request comments, you will be given feedback on the application.
|
|
||||||
|
|
||||||
9. Please note, in the *Checks* block the *Documentation* field should contain a tick, id cross appeared, click *Details* link to see the list of issues in you article found by markdownlint. If you need to change added files, edit them in you branch – changes will appear in the Pull Request automatically. **Do not open a new Pull Request for the same application**.
|
|
||||||
|
|
||||||
10. During the contest, you will work on this document, bringing it closer to the finished state. By the end of the contest you are expected to publish your article which is supposed to be the result of your work in CopterHack.
|
|
||||||
|
|
||||||
Teams-participants are supposed to be added to the special Telegram group, where one can send the project's updates and get feedback from the Jury. For all participating teams, COEX will provide a 40% discount on the Clover drone kit.
|
|
||||||
|
|
||||||
> **Info** There are no restrictions on the age, education, and number of people in a team.
|
|
||||||
|
|
||||||
## CopterHack 2023 projects’ papers contest
|
|
||||||
|
|
||||||
Our participants have been engaged in advanced projects in the field of aerial robotics for already two years. This year we are planning to launch a new type of contest stimulating participants to present the research results running within the whole contest, at high -level international conferences as well as to publish them in Russian and international magazines in thematic areas.
|
|
||||||
|
|
||||||
Original articles are accepted in following nominations:
|
|
||||||
|
|
||||||
* $2000 (USD) for an article in a magazine of first quartile (Q1), indexed in Scopus, Web of Science.
|
|
||||||
* $1000 (USD) for an article in a magazine, indexed in Scopus, Web of Science.
|
|
||||||
* $500 (USD) for an article, published in Compendium (Conference Proceedings), indexed in Scopus, Web of Science.
|
|
||||||
|
|
||||||
> **Note** [Easy way to find quartiles for journals in Web of Science and Scopus](https://www.texpedi.com/2021/07/how-to-find-journal-quartile.html).
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
|
|
||||||
1. The article is required to reflect the results of the project, developed within CopterHack 2023.
|
|
||||||
2. The article is required to be accepted for publication by the moment of application for the Contest.
|
|
||||||
3. It is required to indicate in the acknowledgement area that work is accomplished within the Contest.
|
|
||||||
|
|
||||||
**Applications deadline**: December 10, 2023. The application for the contest should be submitted through the [Google Form](https://docs.google.com/forms/d/e/1FAIpQLSf52x0CTur-wUCG2URwY-p85gEUBUvgC0mPVNot0RHVjqcLZA/viewform).
|
|
||||||
|
|
||||||
**Results announcement**: December 24, 2023.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
For all questions: [CopterHack in Telegram](https://t.me/CopterHack).
|
|
||||||
|
|
||||||
> **Info** Please contact [Oleg Ponfilenok in Telegram](https://t.me/ponfilenok) if you are interested in becoming the contest's partner or jury member.
|
|
||||||
@@ -22,7 +22,7 @@ In case of using LPE ([COEX patched firmware](firmware.md)):
|
|||||||
|
|
||||||
|Parameter|Value|Comment|
|
|Parameter|Value|Comment|
|
||||||
|-|-|-|
|
|-|-|-|
|
||||||
|`LPE_FUSION`|86|Checkboxes: *flow* + *vis* + *land detector* + *gyro comp*. If flying over horizontal floor *pub agl as lpos down* checkbox is allowed.<br>Details: [Optical Flow](optical_flow.md), [ArUco markers](aruco_map.md), [GPS](gps.md).|
|
|`LPE_FUSION`|86|Checkboxes: *flow* + *vis* + *land Detector* + *gyro comp*. If flying over horizontal floor *pub agl as lpos down* checkbox is allowed.<br>Details: [Optical Flow](optical_flow.md), [ArUco markers](aruco_map.md), [GPS](gps.md).|
|
||||||
|`LPE_VIS_DELAY`|0.0||
|
|`LPE_VIS_DELAY`|0.0||
|
||||||
|`LPE_VIS_Z`|0.1||
|
|`LPE_VIS_Z`|0.1||
|
||||||
|`LPE_FLW_SCALE`|1.0||
|
|`LPE_FLW_SCALE`|1.0||
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ To use rviz and rqt, a PC running Ubuntu Linux (or a virtual machine such as [Pa
|
|||||||
|
|
||||||
> **Hint** You can use the [preconfigured virtual machine image](simulation_vm.md) with ROS and Clover toolkit.
|
> **Hint** You can use the [preconfigured virtual machine image](simulation_vm.md) with ROS and Clover toolkit.
|
||||||
|
|
||||||
Install package `ros-noetic-desktop-full` or `ros-noetic-desktop` using the [installation documentation](http://wiki.ros.org/noetic/Installation/Ubuntu).
|
Install package `ros-melodic-desktop-full` or `ros-melodic-desktop` using the [installation documentation](http://wiki.ros.org/melodic/Installation/Ubuntu).
|
||||||
|
|
||||||
Start rviz
|
Start rviz
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -132,12 +132,6 @@ You can test autonomous flight using example scripts in `~/catkin_ws/src/clover/
|
|||||||
|
|
||||||
## Additional steps
|
## Additional steps
|
||||||
|
|
||||||
To make it possible to run Gazebo simulation environment without Clover (`gazebo` command), add into your `.bashrc` sourcing Gazebo's initialization script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "source /usr/share/gazebo/setup.sh" >> ~/.bashrc
|
|
||||||
```
|
|
||||||
|
|
||||||
Optionally, install roscore systemd service to have roscore running in background:
|
Optionally, install roscore systemd service to have roscore running in background:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
In addition to [native installation instructions](simulation_native.md), we provide a [preconfigured developer virtual machine image](https://github.com/CopterExpress/clover_vm/releases/latest). The image contains:
|
In addition to [native installation instructions](simulation_native.md), we provide a [preconfigured developer virtual machine image](https://github.com/CopterExpress/clover_vm/releases/latest). The image contains:
|
||||||
|
|
||||||
* Ubuntu 20.04 with XFCE lightweight desktop environment;
|
* Ubuntu 18.04 with XFCE lightweight desktop environment;
|
||||||
* ROS packages required to develop for the Clover platform;
|
* ROS packages required to develop for the Clover platform;
|
||||||
* QGroundControl;
|
* QGroundControl;
|
||||||
* preconfigured Gazebo simulation environment;
|
* preconfigured Gazebo simulation environment;
|
||||||
@@ -16,6 +16,8 @@ The VM is an easy way to set up a simulation environment, but can be used as a d
|
|||||||
|
|
||||||
You can download the latest VM image [in the VM releases repository](https://github.com/CopterExpress/clover_vm/releases).
|
You can download the latest VM image [in the VM releases repository](https://github.com/CopterExpress/clover_vm/releases).
|
||||||
|
|
||||||
|
> **Note** The virtual machine should be used when native installation is not feasible or possible. You may experience reduced performance in programs that use 3D rendering, like rviz and Gazebo.
|
||||||
|
|
||||||
## Setting up the VM
|
## Setting up the VM
|
||||||
|
|
||||||
You need to use a VM manager that supports OVF format, like [VirtualBox](https://www.virtualbox.org/wiki/Downloads), [VMware Player](https://www.vmware.com/products/workstation-player.html) or [VMware Workstation](https://www.vmware.com/products/workstation-pro.html).
|
You need to use a VM manager that supports OVF format, like [VirtualBox](https://www.virtualbox.org/wiki/Downloads), [VMware Player](https://www.vmware.com/products/workstation-player.html) or [VMware Workstation](https://www.vmware.com/products/workstation-pro.html).
|
||||||
|
|||||||
@@ -390,26 +390,6 @@ rospy.sleep(5)
|
|||||||
flow_client.update_configuration({'enabled': True})
|
flow_client.update_configuration({'enabled': True})
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- markdownlint-disable MD044 -->
|
|
||||||
|
|
||||||
### # {#aruco-map-dynamic}
|
|
||||||
|
|
||||||
> **Info** For [RPi image](image.md) version > 0.23.
|
|
||||||
|
|
||||||
Change the used [ArUco markers map file](aruco_map.md) dynamically:
|
|
||||||
|
|
||||||
<!-- markdownlint-enable MD044 -->
|
|
||||||
|
|
||||||
```python
|
|
||||||
import rospy
|
|
||||||
import dynamic_reconfigure.client
|
|
||||||
|
|
||||||
rospy.init_node('flight')
|
|
||||||
map_client = dynamic_reconfigure.client.Client('aruco_map')
|
|
||||||
|
|
||||||
map_client.update_configuration({'map': '/home/pi/catkin_ws/src/clover/aruco_pose/map/office.txt'})
|
|
||||||
```
|
|
||||||
|
|
||||||
### # {#wait-global-position}
|
### # {#wait-global-position}
|
||||||
|
|
||||||
Wait for global position to appear (finishing [GPS receiver](gps.md) initialization):
|
Wait for global position to appear (finishing [GPS receiver](gps.md) initialization):
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Parameters `width`, `height`, etc. re also available. Read more about `web_video
|
|||||||
|
|
||||||
## Browse with rqt_image_view
|
## Browse with rqt_image_view
|
||||||
|
|
||||||
To browse images with the rqt tools the user needs a computer with Ubuntu 20.04 and [ROS Noetic](http://wiki.ros.org/noetic/Installation/Ubuntu).
|
To browse images with the rqt tools the user needs a computer with Ubuntu 18.04 and [ROS Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu).
|
||||||
|
|
||||||
[Connect to the Clover Wi-Fi network](wifi.md) an run `rqt_image_view` with its IP-address:
|
[Connect to the Clover Wi-Fi network](wifi.md) an run `rqt_image_view` with its IP-address:
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,6 @@
|
|||||||
* [Виртуальная MAVLink-камера](duocam_mavlink.md)
|
* [Виртуальная MAVLink-камера](duocam_mavlink.md)
|
||||||
* [Настройка DuoCam](duocam_setup.md)
|
* [Настройка DuoCam](duocam_setup.md)
|
||||||
* [Мероприятия](events.md)
|
* [Мероприятия](events.md)
|
||||||
* [CopterHack-2023](copterhack2023.md)
|
|
||||||
* [CopterHack-2022](copterhack2022.md)
|
* [CopterHack-2022](copterhack2022.md)
|
||||||
* [CopterHack-2021](copterhack2021.md)
|
* [CopterHack-2021](copterhack2021.md)
|
||||||
* [CopterHack-2019](copterhack2019.md)
|
* [CopterHack-2019](copterhack2019.md)
|
||||||
|
|||||||
@@ -10,14 +10,14 @@
|
|||||||
|
|
||||||
Основной туториал: http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration.
|
Основной туториал: http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration.
|
||||||
|
|
||||||
Для калибровки камеры с использованием ROS-пакета camera_calibration необходим компьютер с установленным ОС GNU/Linux и [ROS Noetic](http://wiki.ros.org/noetic/Installation/Ubuntu).
|
Для калибровки камеры с использованием ROS-пакета camera_calibration необходим компьютер с установленным ОС GNU/Linux и [ROS Melodic](ros-install.md).
|
||||||
|
|
||||||
<img src="../assets/camera_calibration.png" alt="ROS Camera Calibrator" class="zoom center" width=600>
|
<img src="../assets/camera_calibration.png" alt="ROS Camera Calibrator" class="zoom center" width=600>
|
||||||
|
|
||||||
1. Используя Терминал, установите на компьютер пакет `camera_calibration`:
|
1. Используя Терминал, установите на компьютер пакет `camera_calibration`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install ros-noetic-camera-calibration
|
sudo apt-get install ros-melodic-camera-calibration
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Скачайте калибровочную доску – [`chessboard.pdf`](../assets/chessboard.pdf). Распечатайте доску на принтере либо выведите ее на экран компьютера.
|
2. Скачайте калибровочную доску – [`chessboard.pdf`](../assets/chessboard.pdf). Распечатайте доску на принтере либо выведите ее на экран компьютера.
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
# CopterHack 2023
|
|
||||||
|
|
||||||
<img src="../assets/copterhack2023.svg" width=300 align=right>
|
|
||||||
|
|
||||||
CopterHack 2023 — это международный конкурс по разработке проектов по летающей робототехнике с открытым исходным кодом. Основным языком конкурса является английский.
|
|
||||||
|
|
||||||
Ознакомиться со статьями команд-финалистов предыдущих лет можно в статьях о [CopterHack 2021](copterhack2021.md), [CopterHack 2022](copterhack2022.md).
|
|
||||||
|
|
||||||
На конкурс принимаются проекты с открытым исходным кодом и совместимые с платформой квадрокоптера "Клевер". На протяжении конкурса команды работают на собственными идеями и разработками, приближая их к состоянию готового продукта. В этом участникам помогают эксперты отрасли через лекции и регулярную обратную связь.
|
|
||||||
|
|
||||||
## Этапы CopterHack 2023
|
|
||||||
|
|
||||||
Отборочный и проектный этапы конкурса проходят в онлайн-формате, формат проведения финала – гибридный (оффлайн + онлайн). Конкурс подразумевает ежемесячные апдейты от команд с получением регулярной обратной связи от жюри. Для участия в заключительном этапе необходимо подготовить финальное видео и презентацию о результатах проекта.
|
|
||||||
|
|
||||||
1. Отборочный этап. Подача заявок (до 31 октября 2022).
|
|
||||||
2. Проектный этап. Менторство проектов (1 ноября 2022 — 28 февраля 2023).
|
|
||||||
3. Подготовка финального видео (1 — 31 марта 2023).
|
|
||||||
4. Заключительный этап. Финальная защита проектов на английском языке (23 апреля 2023).
|
|
||||||
|
|
||||||
## Условия и критерии оценки
|
|
||||||
|
|
||||||
Условия, предъявляемые к проектам:
|
|
||||||
|
|
||||||
1. Открытый исходный код/модели/схемы/чертежи.
|
|
||||||
2. Совместимость с платформой "Клевер".
|
|
||||||
|
|
||||||
Критерии оценивания жюри в финале:
|
|
||||||
|
|
||||||
1. Готовность и статья (макс. 10 баллов): степень готовности проекта; доступное и понятное описание проекта в статье; прикреплены код с комментариями, схемы, чертежи. По статье должно быть возможно повторить проект, получить результат.
|
|
||||||
2. Объем проделанной работы (макс. 6 баллов): объем проделанной командой работы в рамках CopterHack, ее сложность и технический уровень.
|
|
||||||
3. Полезность для Клевера (макс. 6 баллов): актуальность применения на практике в платформе Клевер и PX4, потенциальный уровень спроса на разработку со стороны других пользователей Клевера.
|
|
||||||
4. Презентация на финале (макс. 3 балла): качество и зрелищность финальной презентации; полнота освещения проекта; демонстрация; ответы на вопросы жюри.
|
|
||||||
|
|
||||||
## Призовой фонд
|
|
||||||
|
|
||||||
Призы от компании COEX по результатам оценивания жюри на финале:
|
|
||||||
|
|
||||||
* I место: $3000.
|
|
||||||
* II место: $2000.
|
|
||||||
* III место: $1000.
|
|
||||||
* IV место: $500.
|
|
||||||
* V место: $500.
|
|
||||||
|
|
||||||
Партнеры конкурса могут поощрить команды по дополнительным критериям, выявленным в результате оценки проектов в ходе финала.
|
|
||||||
|
|
||||||
## Как подать заявку?
|
|
||||||
|
|
||||||
> **Note** Для подачи заявки необходимо иметь аккаунт на [GitHub](https://github.com).
|
|
||||||
|
|
||||||
Подготовьте вашу заявку и пришлите ее в виде Draft Pull Request в [репозиторий Клевера](https://github.com/CopterExpress/clover).
|
|
||||||
|
|
||||||
1. Сделайте форк репозитория Клевера:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/github-fork.png" alt="GitHub Fork">
|
|
||||||
|
|
||||||
2. На странице вашего форка зайдите в раздел `docs/ru` и создайте новый файл в формате [Markdown](https://ru.wikipedia.org/wiki/Markdown):
|
|
||||||
|
|
||||||
<img src="../assets/github_application/create_new_file.png" alt="GitHub Create New File">
|
|
||||||
|
|
||||||
3. Введите название вашей статьи. Например, `new-article.md`
|
|
||||||
|
|
||||||
<img src="../assets/github_application/new_article.png" alt="GitHub New Article">
|
|
||||||
|
|
||||||
4. Оформите вашу заявку в соответствии с рекомендуемым шаблоном:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Название проекта
|
|
||||||
|
|
||||||
[CopterHack-2023](copterhack2023.md), команда **Название команды**.
|
|
||||||
|
|
||||||
## Информация о команде
|
|
||||||
|
|
||||||
Состав команды:
|
|
||||||
|
|
||||||
(Опишите состав команды: имя и фамилия, контакты (имя пользователя в Telegram), роль в команде).
|
|
||||||
|
|
||||||
* Александр Соколов, @aleksandrsokolov111, инженер.
|
|
||||||
* Елена Смирнова, @elenasmirnova111, программист.
|
|
||||||
|
|
||||||
## Описание проекта
|
|
||||||
|
|
||||||
### Идея проекта
|
|
||||||
|
|
||||||
Опишите кратко идею и стадию проекта.
|
|
||||||
|
|
||||||
### Планируемые результаты
|
|
||||||
|
|
||||||
Опишите как вы видите результат проекта.
|
|
||||||
|
|
||||||
### Использование платформы "Клевер"
|
|
||||||
|
|
||||||
Опишите как в вашем проекте будет использоваться платформа "Клевер".
|
|
||||||
|
|
||||||
### Дополнительная информация по желанию участников
|
|
||||||
|
|
||||||
Например, информация об опыте работы команды над проектами, прикрепить ссылку на статьи, видео.
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Перейдите вниз страницы и создайте новую ветку с названием вашей статьи:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/propose_new_file.png" alt="GitHub Propose New File">
|
|
||||||
|
|
||||||
> **Note** Не добавляйте ваши изменения непосредственно в ветку `master`, создайте новую ветку.
|
|
||||||
|
|
||||||
6. При необходимости поместите дополнительные визуальные материалы в папку `docs/assets` и оформите на них ссылки в вашей статье.
|
|
||||||
|
|
||||||
7. Сделайте Draft Pull Request вашей ветки в master Клевера:
|
|
||||||
|
|
||||||
<img src="../assets/github_application/github-pull-request-create.png" alt="GitHub Create Pull">
|
|
||||||
|
|
||||||
8. В комментариях Pull Request вам будет дана обратная связь по заявке.
|
|
||||||
|
|
||||||
9. Обратите внимание на блок *Checks*, в графе Documentation должна стоять галочка. Если там стоит крестик, перейдите по ссылке *Details*, чтобы увидеть список проблем с оформлением статьи. При необходимости изменения добавляемых файлов, меняйте их в вашей ветке – изменения будут появляться в Pull Request автоматически. **Не создавайте новый Pull Request для одной и той же заявки**.
|
|
||||||
|
|
||||||
10. На протяжении конкурса вы будете работать над этим документом, приближая его к состоянию статьи. В документе будет видна история разработки и ежемесячные апдейты. К финалу конкурса вы сможете опубликовать вашу статью, это и будет результат вашей работы в CopterHack.
|
|
||||||
|
|
||||||
Участники конкурса будут добавлены в Telegram-группу, куда можно отправлять первый апдейт и получить обратную связь от жюри. Для команд-участников предусмотрена скидка 40% на конструктор программируемого квадрокоптера "Клевер".
|
|
||||||
|
|
||||||
> **Info** Ограничения по возрасту, образованию и количеству человек в команде отсутствуют.
|
|
||||||
|
|
||||||
## Конкурс статей участников проектов CopterHack 2023
|
|
||||||
|
|
||||||
Наши участники уже 2 года работают над передовыми проектами в области летающей робототехники. В этом году мы хотим ввести новый конкурс, стимулирующий участников презентовать результаты исследований, выполняющихся в рамках конкурса на престижных международных конференциях, а также публиковать их в российских и международных журналах по тематике конкурса.
|
|
||||||
|
|
||||||
На конкурс принимаются оригинальные статьи в следующих номинациях:
|
|
||||||
|
|
||||||
* $2000 за статью в журнале первого квартиля (Q1), индексируемом в Scopus, Web of Science.
|
|
||||||
* $1000 за статью журнале, индексируемом в Scopus, Web of Science.
|
|
||||||
* $500 за статью, опубликованную в сборнике материалов конференции (Conference Proceedings), индексируемые в Scopus, Web of Science.
|
|
||||||
|
|
||||||
> **Note** [Как узнать квартиль журнала в Scopus и WOS](http://russian-science.info/kak-uznat-kvartil-i-protsentil-zhurnala-v-scopus-i-wos).
|
|
||||||
|
|
||||||
Правила:
|
|
||||||
|
|
||||||
1. Статья должна отражать результаты проекта, разработанного в рамках CopterHack 2023.
|
|
||||||
2. Статья должна быть принята к печати к моменту подачи заявки на участие в конкурсе статей.
|
|
||||||
3. В acknowledgment следует указать, что работа выполнена в рамках конкурса.
|
|
||||||
|
|
||||||
**Прием заявок**: до 10 декабря 2023 года. Прием заявок осуществляется через [Google Форму](https://docs.google.com/forms/d/e/1FAIpQLSf52x0CTur-wUCG2URwY-p85gEUBUvgC0mPVNot0RHVjqcLZA/viewform).
|
|
||||||
|
|
||||||
**Объявление результатов**: 24 декабря 2023 года.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
По всем вопросам: [группа CopterHack в Telegram](https://t.me/CopterHack).
|
|
||||||
|
|
||||||
> **Info** Если вы хотите стать партнером конкурса или членом жюри, обращайтесь к [Олегу Понфиленку в Telegram](https://t.me/ponfilenok).
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
|Параметр|Значение|Примечание|
|
|Параметр|Значение|Примечание|
|
||||||
|-|-|-|
|
|-|-|-|
|
||||||
|`LPE_FUSION`|86|Чекбоксы: *flow* + *vis* + *land detector* + *gyro comp*. При полете над ровным полом возможно включение *pub agl as lpos down*. <br>Подробнее: [Optical Flow](optical_flow.md), [ArUco-маркеры](aruco_map.md), [GPS](gps.md).|
|
|`LPE_FUSION`|86|Чекбоксы: *flow* + *vis* + *land Detector* + *gyro comp*. При полете над ровным полом возможно включение *pub agl as lpos down*. <br>Подробнее: [Optical Flow](optical_flow.md), [ArUco-маркеры](aruco_map.md), [GPS](gps.md).|
|
||||||
|`LPE_VIS_DELAY`|0.0||
|
|`LPE_VIS_DELAY`|0.0||
|
||||||
|`LPE_VIS_Z`|0.1||
|
|`LPE_VIS_Z`|0.1||
|
||||||
|`LPE_FLW_SCALE`|1.0||
|
|`LPE_FLW_SCALE`|1.0||
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
> **Hint** Вы можете можете использовать готовый [образ виртуальной машины](simulation_vm.md) с инструментами для Клевера.
|
> **Hint** Вы можете можете использовать готовый [образ виртуальной машины](simulation_vm.md) с инструментами для Клевера.
|
||||||
|
|
||||||
На него необходимо установить пакет `ros-noetic-desktop-full` или `ros-noetic-desktop`, используя [документацию по установке](http://wiki.ros.org/noetic/Installation/Ubuntu).
|
На него необходимо установить пакет `ros-melodic-desktop-full` или `ros-melodic-desktop`, используя [документацию по установке](http://wiki.ros.org/melodic/Installation/Ubuntu).
|
||||||
|
|
||||||
Запуск rviz
|
Запуск rviz
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -132,12 +132,6 @@ roslaunch clover_simulation simulator.launch
|
|||||||
|
|
||||||
## Дополнительные шаги
|
## Дополнительные шаги
|
||||||
|
|
||||||
Для того, чтобы возможно было запускать среду симуляции Gazebo отдельно (команда `gazebo`), добавьте в `.bashrc` вызов соответствующего скрипта инициализации:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "source /usr/share/gazebo/setup.sh" >> ~/.bashrc
|
|
||||||
```
|
|
||||||
|
|
||||||
Опционально вы можете установить systemd-сервис для roscore для того, чтобы roscore был постоянно запущен в фоне:
|
Опционально вы можете установить systemd-сервис для roscore для того, чтобы roscore был постоянно запущен в фоне:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Установка виртуальной машины
|
# Установка виртуальной машины
|
||||||
|
|
||||||
Для работы с платформой Клевер рекомендуется иметь [установленное окружение ROS](ros.md) на своём компьютере. К сожалению, [установка ROS и симулятора](simulation_native.md) сопряжена с рядом трудностей: требуется использовать операционную систему Ubuntu 20.04, процесс установки длительный и требует выполнения большого количества команд в терминале.
|
Для работы с платформой Клевер рекомендуется иметь [установленное окружение ROS](ros.md) на своём компьютере. К сожалению, [установка ROS](ros-install.md) сопряжена с рядом трудностей: требуется использовать операционную систему Ubuntu 18.04, процесс установки длительный и требует выполнения большого количества команд в терминале.
|
||||||
|
|
||||||
Для облегчения процесса настройки окружения мы предлагаем использовать виртуальную машину со всем необходимым для работы с платформой Клевер. В состав виртуальной машины входят:
|
Для облегчения процесса настройки окружения мы предлагаем использовать виртуальную машину со всем необходимым для работы с платформой Клевер. В состав виртуальной машины входят:
|
||||||
|
|
||||||
* операционная система Ubuntu 20.04 с легковесной графической оболочкой XFCE;
|
* операционная система Ubuntu 18.04 с легковесной графической оболочкой XFCE;
|
||||||
* предустановленные пакеты ROS для работы с Клевером;
|
* предустановленные пакеты ROS для работы с Клевером;
|
||||||
* QGroundControl;
|
* QGroundControl;
|
||||||
* предварительно настроенный симулятор Gazebo;
|
* предварительно настроенный симулятор Gazebo;
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
Скачать текущую версию виртуальной машины можно [в релизах репозитория виртуальной машины](https://github.com/CopterExpress/clover_vm/releases/latest).
|
Скачать текущую версию виртуальной машины можно [в релизах репозитория виртуальной машины](https://github.com/CopterExpress/clover_vm/releases/latest).
|
||||||
|
|
||||||
|
> **Warning** Виртуальную машину следует использовать только в тех случаях, когда по каким-то причинам использование Ubuntu 18.04 напрямую невозможно. Производительность всех программ, особенно тех, которые используют 3D-графику - jMAVSim, Gazebo, rviz - будет существенно ниже; кроме того, в ряде случаев будут возникать графические ошибки, приводящие к частичной или полной неработоспособности указанных программ.
|
||||||
|
|
||||||
## Установка виртуальной машины
|
## Установка виртуальной машины
|
||||||
|
|
||||||
Для запуска виртуальной машины разработчика требуется использовать одну из совместимых сред виртуализации: [VirtualBox](https://www.virtualbox.org/wiki/Downloads), [VMware Player](https://www.vmware.com/products/workstation-player.html), [VMware Workstation](https://www.vmware.com/products/workstation-pro.html).
|
Для запуска виртуальной машины разработчика требуется использовать одну из совместимых сред виртуализации: [VirtualBox](https://www.virtualbox.org/wiki/Downloads), [VMware Player](https://www.vmware.com/products/workstation-player.html), [VMware Workstation](https://www.vmware.com/products/workstation-pro.html).
|
||||||
|
|||||||
@@ -401,26 +401,6 @@ rospy.sleep(5)
|
|||||||
flow_client.update_configuration({'enabled': True})
|
flow_client.update_configuration({'enabled': True})
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- markdownlint-disable MD044 -->
|
|
||||||
|
|
||||||
### # {#aruco-map-dynamic}
|
|
||||||
|
|
||||||
> **Info** Для [образа](image.md) версии > 0.23.
|
|
||||||
|
|
||||||
Динамически изменить используемый файл с [картой ArUco-маркеров](aruco_map.md):
|
|
||||||
|
|
||||||
<!-- markdownlint-enable MD044 -->
|
|
||||||
|
|
||||||
```python
|
|
||||||
import rospy
|
|
||||||
import dynamic_reconfigure.client
|
|
||||||
|
|
||||||
rospy.init_node('flight')
|
|
||||||
map_client = dynamic_reconfigure.client.Client('aruco_map')
|
|
||||||
|
|
||||||
map_client.update_configuration({'map': '/home/pi/catkin_ws/src/clover/aruco_pose/map/office.txt'})
|
|
||||||
```
|
|
||||||
|
|
||||||
### # {#wait-global-position}
|
### # {#wait-global-position}
|
||||||
|
|
||||||
Ожидать появления глобальной позиции (окончания инициализации [GPS-приемника](gps.md)):
|
Ожидать появления глобальной позиции (окончания инициализации [GPS-приемника](gps.md)):
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ http://192.168.11.1:8080/stream_viewer?topic=/main_camera/image_raw&type=mjpeg&q
|
|||||||
|
|
||||||
## Просмотр через rqt_image_view
|
## Просмотр через rqt_image_view
|
||||||
|
|
||||||
Для просмотра изображений через инструменты rqt необходим компьютер с установленной Ubuntu 20.04 и [ROS Noetic](http://wiki.ros.org/noetic/Installation/Ubuntu).
|
Для просмотра изображений через инструменты rqt необходим компьютер с установленной Ubuntu 18.04 и [ROS Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu).
|
||||||
|
|
||||||
[Подключитесь к Wi-Fi сети Клевера](wifi.md) и запустите `rqt_image_view` с указанием его IP-адреса:
|
[Подключитесь к Wi-Fi сети Клевера](wifi.md) и запустите `rqt_image_view` с указанием его IP-адреса:
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,6 @@
|
|||||||
{ "from": "connection/", "to": "en/connection.html" },
|
{ "from": "connection/", "to": "en/connection.html" },
|
||||||
{ "from": "clover_vm/", "to": "en/simulation_vm.html" },
|
{ "from": "clover_vm/", "to": "en/simulation_vm.html" },
|
||||||
{ "from": "gpio/", "to": "en/gpio.html" },
|
{ "from": "gpio/", "to": "en/gpio.html" },
|
||||||
{ "from": "blocks/", "to": "en/blocks.html" },
|
|
||||||
|
|
||||||
{ "from": "ru/microsd_images.html", "to": "image.html" },
|
{ "from": "ru/microsd_images.html", "to": "image.html" },
|
||||||
{ "from": "en/microsd_images.html", "to": "image.html" },
|
{ "from": "en/microsd_images.html", "to": "image.html" },
|
||||||
|
|||||||
Reference in New Issue
Block a user