Compare commits
98 Commits
sitl-tests
...
vpe-publis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb772d9ce0 | ||
|
|
a6bdedbfc1 | ||
|
|
68fc2fee1a | ||
|
|
a4fa53ba1b | ||
|
|
3ba4ebf3a2 | ||
|
|
5c2441e2e8 | ||
|
|
45356b19a9 | ||
|
|
e1a11bd70a | ||
|
|
035384cd6f | ||
|
|
16a2ecef2e | ||
|
|
727fde82a8 | ||
|
|
fc1df980ff | ||
|
|
2e7bcde38e | ||
|
|
5a8ce0cf0c | ||
|
|
e78c57a734 | ||
|
|
9581cc6496 | ||
|
|
eddec45259 | ||
|
|
2e903b45a3 | ||
|
|
50739a3ea8 | ||
|
|
fb5f8e5078 | ||
|
|
ba9d968b44 | ||
|
|
0a4b398c90 | ||
|
|
86938a1afe | ||
|
|
1af20c0869 | ||
|
|
fda030e539 | ||
|
|
91e1d3c8f3 | ||
|
|
5071139d09 | ||
|
|
d2c201dba4 | ||
|
|
f9620b241d | ||
|
|
291b4a17e4 | ||
|
|
8696ad14a5 | ||
|
|
4b0605fcbb | ||
|
|
6b56e45ef9 | ||
|
|
506568ebd8 | ||
|
|
2b671d9c18 | ||
|
|
a1ada2d55c | ||
|
|
c711446e49 | ||
|
|
588ccaf314 | ||
|
|
d8128bfebc | ||
|
|
1be06b8cee | ||
|
|
1533092d67 | ||
|
|
100f697691 | ||
|
|
2d4e835089 | ||
|
|
cd63afe268 | ||
|
|
0f27928631 | ||
|
|
4acf45e97d | ||
|
|
67392a8f1e | ||
|
|
059f932951 | ||
|
|
f9b1a82b5e | ||
|
|
1773a1ccae | ||
|
|
e254472f3d | ||
|
|
fc89f80388 | ||
|
|
e710c7fdb1 | ||
|
|
663a302ebd | ||
|
|
01d382331a | ||
|
|
5c973f044b | ||
|
|
a2f1ad2bcb | ||
|
|
892dc8dba2 | ||
|
|
b5f4ebde66 | ||
|
|
86d84e5c0a | ||
|
|
cd34cc077b | ||
|
|
61e9239241 | ||
|
|
5d1f38888c | ||
|
|
b8a27fcc98 | ||
|
|
c6182bc9ac | ||
|
|
8253fc3b1a | ||
|
|
8f5017532f | ||
|
|
d6722fb84a | ||
|
|
7f642da02f | ||
|
|
6cf36d5a0a | ||
|
|
56e42a1cef | ||
|
|
35bf315227 | ||
|
|
2859f7c68d | ||
|
|
783937c5e8 | ||
|
|
d73e1dd72a | ||
|
|
dd7946a9bb | ||
|
|
81d0282d11 | ||
|
|
8c5309c753 | ||
|
|
2b50b9bd8c | ||
|
|
a4ba3a6030 | ||
|
|
5808647971 | ||
|
|
e72db1775f | ||
|
|
04ca1f2631 | ||
|
|
a926c0b93d | ||
|
|
fb3d8c9747 | ||
|
|
f64b9f5225 | ||
|
|
9614216bb3 | ||
|
|
8c6a9d010b | ||
|
|
4c4b0ba6fa | ||
|
|
fc1a12f13e | ||
|
|
8c50ca3a9e | ||
|
|
76ab7f46a6 | ||
|
|
e3d0837403 | ||
|
|
84c81b8ad8 | ||
|
|
17dbc5b4fb | ||
|
|
95784b11be | ||
|
|
4d59748dea | ||
|
|
7238eed4ef |
@@ -103,7 +103,8 @@
|
||||
"SDA",
|
||||
"TCP",
|
||||
"UDP",
|
||||
"QR"
|
||||
"QR",
|
||||
"Li-ion"
|
||||
],
|
||||
"code_blocks": false
|
||||
},
|
||||
|
||||
@@ -62,7 +62,8 @@ jobs:
|
||||
- markdownlint -V
|
||||
script:
|
||||
- markdownlint docs
|
||||
- ./check_files_size.py
|
||||
- ./check_assets_size.py
|
||||
- ./check_unused_assets.py
|
||||
- gitbook install
|
||||
- gitbook build
|
||||
deploy:
|
||||
@@ -72,8 +73,8 @@ jobs:
|
||||
github-token: ${GITHUB_OAUTH_TOKEN}
|
||||
keep-history: true
|
||||
target-branch: master
|
||||
repo: CopterExpress/clever-gitbook
|
||||
fqdn: clever.copterexpress.com
|
||||
repo: CopterExpress/clever.coex.tech
|
||||
fqdn: clever.coex.tech
|
||||
verbose: true
|
||||
on:
|
||||
branch: master
|
||||
|
||||
12
README.md
@@ -1,12 +1,12 @@
|
||||
# CLEVER
|
||||
|
||||
<img src="docs/assets/clever3.png" align="right" width="300px" alt="CLEVER drone">
|
||||
<img src="docs/assets/clever4-front-white.png" align="right" width="400px" alt="CLEVER drone">
|
||||
|
||||
CLEVER (Russian: *"Клевер"*, meaning *"Clover"*) is an educational programmable drone kit consisting of an unassembled quadcopter, open source software and documentation. The kit includes Pixhawk/Pixracer autopilot running PX4 firmware, Raspberry Pi 3 as companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices.
|
||||
|
||||
Copter Express has implemented a large number of different autonomous drone projects using exactly the same platform: [automated pizza delivery](https://www.youtube.com/watch?v=hmkAoZOtF58) in Samara and Kazan, coffee delivery in Skolkovo Innovation Center, [autonomous quadcopter with charging station](https://www.youtube.com/watch?v=RjX6nUqw1mI) for site monitoring and security, winning drones on [Robocross-2016](https://www.youtube.com/watch?v=dGbDaz_VmYU) and [Robocross-2017](https://youtu.be/AQnd2CRczbQ) competitions and many others.
|
||||
|
||||
**The main documentation in Russian is available [on our Gitbook](https://clever.copterexpress.com/).**
|
||||
**The main documentation is available [on Gitbook](https://clever.coex.tech/).**
|
||||
|
||||
Use it to learn how to assemble, configure, pilot and program autonomous CLEVER drone.
|
||||
|
||||
@@ -26,7 +26,7 @@ Image includes:
|
||||
* Periphery drivers (`pigpiod`, `rpi_ws281x`, etc)
|
||||
* CLEVER software bundle for autonomous drone control
|
||||
|
||||
API description (in Russian) for autonomous flights is available [on GitBook](https://clever.copterexpress.com/simple_offboard.html).
|
||||
API description (in Russian) for autonomous flights is available [on GitBook](https://clever.coex.tech/simple_offboard.html).
|
||||
|
||||
## Manual installation
|
||||
|
||||
@@ -73,7 +73,7 @@ Alternatively you may change the `fcu_url` property in `mavros.launch` file to p
|
||||
Enable systemd service `roscore` (if not running):
|
||||
|
||||
```bash
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clever/deploy/roscore.service
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clever/builder/assets/roscore.service
|
||||
sudo systemctl start roscore
|
||||
```
|
||||
|
||||
@@ -97,3 +97,7 @@ Also, you can enable and start the systemd service:
|
||||
sudo systemctl enable /home/<username>/catkin_ws/src/clever/deploy/clever.service
|
||||
sudo systemctl start clever
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
While the Clever platform source code is available under the MIT License, note, that the [documentation](docs/) is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <ros/ros.h>
|
||||
#include <nodelet/nodelet.h>
|
||||
#include <pluginlib/class_list_macros.h>
|
||||
@@ -62,12 +63,14 @@ private:
|
||||
image_transport::Publisher debug_pub_;
|
||||
image_transport::CameraSubscriber img_sub_;
|
||||
ros::Publisher markers_pub_, vis_markers_pub_;
|
||||
ros::Subscriber map_markers_sub_;
|
||||
bool estimate_poses_, send_tf_, auto_flip_;
|
||||
double length_;
|
||||
std::unordered_map<int, double> length_override_;
|
||||
std::string frame_id_prefix_, known_tilt_;
|
||||
Mat camera_matrix_, dist_coeffs_;
|
||||
aruco_pose::MarkerArray array_;
|
||||
std::unordered_set<int> map_markers_ids_;
|
||||
visualization_msgs::MarkerArray vis_array_;
|
||||
|
||||
public:
|
||||
@@ -81,7 +84,7 @@ public:
|
||||
nh_priv_.param("estimate_poses", estimate_poses_, true);
|
||||
nh_priv_.param("send_tf", send_tf_, true);
|
||||
if (estimate_poses_ && !nh_priv_.getParam("length", length_)) {
|
||||
ROS_FATAL("aruco_detect: can't estimate marker's poses as ~length parameter is not defined");
|
||||
NODELET_FATAL("can't estimate marker's poses as ~length parameter is not defined");
|
||||
ros::shutdown();
|
||||
}
|
||||
readLengthOverride();
|
||||
@@ -101,12 +104,13 @@ public:
|
||||
image_transport::ImageTransport it(nh_);
|
||||
image_transport::ImageTransport it_priv(nh_priv_);
|
||||
|
||||
map_markers_sub_ = nh_.subscribe("map_markers", 1, &ArucoDetect::mapMarkersCallback, this);
|
||||
debug_pub_ = it_priv.advertise("debug", 1);
|
||||
markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1);
|
||||
vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1);
|
||||
img_sub_ = it.subscribeCamera("image_raw", 1, &ArucoDetect::imageCallback, this);
|
||||
|
||||
ROS_INFO("aruco_detect: ready");
|
||||
NODELET_INFO("ready");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -158,7 +162,7 @@ private:
|
||||
snap_to = tf_buffer_.lookupTransform(msg->header.frame_id, known_tilt_,
|
||||
msg->header.stamp, ros::Duration(0.02));
|
||||
} catch (const tf2::TransformException& e) {
|
||||
ROS_WARN_THROTTLE(5, "aruco_detect: can't snap: %s", e.what());
|
||||
NODELET_WARN_THROTTLE(5, "can't snap: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,8 +190,8 @@ private:
|
||||
if (send_tf_) {
|
||||
transform.child_frame_id = getChildFrameId(ids[i]);
|
||||
|
||||
// check if such static transform exists
|
||||
if (!tf_buffer_.canTransform(transform.header.frame_id, transform.child_frame_id, transform.header.stamp)) {
|
||||
// check if such static transform is in the map
|
||||
if (map_markers_ids_.find(ids[i]) == map_markers_ids_.end()) {
|
||||
transform.transform.rotation = marker.pose.orientation;
|
||||
fillTranslation(transform.transform.translation, tvecs[i]);
|
||||
br_.sendTransform(transform);
|
||||
@@ -329,6 +333,14 @@ private:
|
||||
return length_;
|
||||
}
|
||||
}
|
||||
|
||||
void mapMarkersCallback(const aruco_pose::MarkerArray& msg)
|
||||
{
|
||||
map_markers_ids_.clear();
|
||||
for (auto const& marker : msg.markers) {
|
||||
map_markers_ids_.insert(marker.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PLUGINLIB_EXPORT_CLASS(ArucoDetect, nodelet::Nodelet)
|
||||
|
||||
@@ -59,7 +59,7 @@ typedef message_filters::sync_policies::ExactTime<Image, CameraInfo, MarkerArray
|
||||
class ArucoMap : public nodelet::Nodelet {
|
||||
private:
|
||||
ros::NodeHandle nh_, nh_priv_;
|
||||
ros::Publisher img_pub_, pose_pub_, vis_markers_pub_;
|
||||
ros::Publisher img_pub_, pose_pub_, markers_pub_, vis_markers_pub_;
|
||||
image_transport::Publisher debug_pub_;
|
||||
message_filters::Subscriber<Image> image_sub_;
|
||||
message_filters::Subscriber<CameraInfo> info_sub_;
|
||||
@@ -70,6 +70,7 @@ private:
|
||||
geometry_msgs::TransformStamped transform_;
|
||||
geometry_msgs::PoseWithCovarianceStamped pose_;
|
||||
vector<geometry_msgs::TransformStamped> markers_transforms_;
|
||||
aruco_pose::MarkerArray markers_;
|
||||
tf2_ros::TransformBroadcaster br_;
|
||||
tf2_ros::StaticTransformBroadcaster static_br_;
|
||||
tf2_ros::Buffer tf_buffer_;
|
||||
@@ -89,6 +90,7 @@ public:
|
||||
|
||||
// TODO: why image_transport doesn't work here?
|
||||
img_pub_ = nh_priv_.advertise<sensor_msgs::Image>("image", 1, true);
|
||||
markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1, true);
|
||||
|
||||
board_ = cv::makePtr<cv::aruco::Board>();
|
||||
board_->dictionary = cv::aruco::getPredefinedDictionary(
|
||||
@@ -116,7 +118,7 @@ public:
|
||||
} else if (type == "gridboard") {
|
||||
createGridBoard();
|
||||
} else {
|
||||
ROS_FATAL("aruco_map: unknown type: %s", type.c_str());
|
||||
NODELET_FATAL("unknown type: %s", type.c_str());
|
||||
ros::shutdown();
|
||||
}
|
||||
|
||||
@@ -132,10 +134,11 @@ public:
|
||||
sync_->registerCallback(boost::bind(&ArucoMap::callback, this, _1, _2, _3));
|
||||
|
||||
publishMarkersFrames();
|
||||
publishMarkers();
|
||||
publishMapImage();
|
||||
vis_markers_pub_.publish(vis_array_);
|
||||
|
||||
ROS_INFO("aruco_map: ready");
|
||||
NODELET_INFO("ready");
|
||||
}
|
||||
|
||||
void callback(const sensor_msgs::ImageConstPtr& image,
|
||||
@@ -195,7 +198,7 @@ public:
|
||||
known_tilt_, markers->header.stamp, ros::Duration(0.02));
|
||||
snapOrientation(transform_.transform.rotation, snap_to.transform.rotation, auto_flip_);
|
||||
} catch (const tf2::TransformException& e) {
|
||||
ROS_WARN_THROTTLE(1, "aruco_map: can't snap: %s", e.what());
|
||||
NODELET_WARN_THROTTLE(1, "can't snap: %s", e.what());
|
||||
}
|
||||
|
||||
geometry_msgs::TransformStamped shift;
|
||||
@@ -268,7 +271,7 @@ publish_debug:
|
||||
std::string line;
|
||||
|
||||
if (!f.good()) {
|
||||
ROS_FATAL("aruco_map: %s - %s", strerror(errno), filename.c_str());
|
||||
NODELET_FATAL("%s - %s", strerror(errno), filename.c_str());
|
||||
ros::shutdown();
|
||||
}
|
||||
|
||||
@@ -286,7 +289,7 @@ publish_debug:
|
||||
}
|
||||
|
||||
if (first == '#') {
|
||||
ROS_DEBUG("aruco_map: Skipping line as a comment: %s", line.c_str());
|
||||
NODELET_DEBUG("Skipping line as a comment: %s", line.c_str());
|
||||
continue;
|
||||
} else if (isdigit(first)) {
|
||||
// Put the digit back into the stream
|
||||
@@ -295,43 +298,43 @@ publish_debug:
|
||||
s.putback(first);
|
||||
} else {
|
||||
// Probably garbage data; inform user and throw an exception, possibly killing nodelet
|
||||
ROS_FATAL("aruco_map: Malformed input: %s", line.c_str());
|
||||
NODELET_FATAL("Malformed input: %s", line.c_str());
|
||||
ros::shutdown();
|
||||
throw std::runtime_error("Malformed input");
|
||||
}
|
||||
|
||||
if (!(s >> id >> length >> x >> y)) {
|
||||
ROS_ERROR("aruco_map: Not enough data in line: %s; "
|
||||
NODELET_ERROR("Not enough data in line: %s; "
|
||||
"Each marker must have at least id, length, x, y fields", line.c_str());
|
||||
continue;
|
||||
}
|
||||
// Be less strict about z, yaw, pitch roll
|
||||
if (!(s >> z)) {
|
||||
ROS_DEBUG("aruco_map: No z coordinate provided for marker %d, assuming 0", id);
|
||||
NODELET_DEBUG("No z coordinate provided for marker %d, assuming 0", id);
|
||||
z = 0;
|
||||
}
|
||||
if (!(s >> yaw)) {
|
||||
ROS_DEBUG("aruco_map: No yaw provided for marker %d, assuming 0", id);
|
||||
NODELET_DEBUG("No yaw provided for marker %d, assuming 0", id);
|
||||
yaw = 0;
|
||||
}
|
||||
if (!(s >> pitch)) {
|
||||
ROS_DEBUG("aruco_map: No pitch provided for marker %d, assuming 0", id);
|
||||
NODELET_DEBUG("No pitch provided for marker %d, assuming 0", id);
|
||||
pitch = 0;
|
||||
}
|
||||
if (!(s >> roll)) {
|
||||
ROS_DEBUG("aruco_map: No roll provided for marker %d, assuming 0", id);
|
||||
NODELET_DEBUG("No roll provided for marker %d, assuming 0", id);
|
||||
roll = 0;
|
||||
}
|
||||
addMarker(id, length, x, y, z, yaw, pitch, roll);
|
||||
}
|
||||
|
||||
ROS_INFO("aruco_map: 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 createGridBoard()
|
||||
{
|
||||
ROS_INFO("aruco_map: generate gridboard");
|
||||
ROS_WARN("aruco_map: gridboard maps are deprecated");
|
||||
NODELET_INFO("generate gridboard");
|
||||
NODELET_WARN("gridboard maps are deprecated");
|
||||
|
||||
int markers_x, markers_y, first_marker;
|
||||
double markers_side, markers_sep_x, markers_sep_y;
|
||||
@@ -346,7 +349,7 @@ publish_debug:
|
||||
|
||||
if (nh_priv_.getParam("marker_ids", marker_ids)) {
|
||||
if ((unsigned int)(markers_x * markers_y) != marker_ids.size()) {
|
||||
ROS_FATAL("~marker_ids length should be equal to ~markers_x * ~markers_y");
|
||||
NODELET_FATAL("~marker_ids length should be equal to ~markers_x * ~markers_y");
|
||||
ros::shutdown();
|
||||
}
|
||||
} else {
|
||||
@@ -363,7 +366,7 @@ publish_debug:
|
||||
for(int x = 0; x < markers_x; x++) {
|
||||
double x_pos = x * (markers_side + markers_sep_x);
|
||||
double y_pos = max_y - y * (markers_side + markers_sep_y) - markers_side;
|
||||
ROS_INFO("add marker %d %g %g", marker_ids[y * markers_y + x], x_pos, y_pos);
|
||||
NODELET_INFO("add marker %d %g %g", marker_ids[y * markers_y + x], x_pos, y_pos);
|
||||
addMarker(marker_ids[y * markers_y + x], markers_side, x_pos, y_pos, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -390,14 +393,14 @@ publish_debug:
|
||||
// Check whether the id is in range for current dictionary
|
||||
int num_markers = board_->dictionary->bytesList.rows;
|
||||
if (num_markers <= id) {
|
||||
ROS_ERROR("aruco_map: Marker id %d is not in dictionary; current dictionary contains %d markers. "
|
||||
"Please see https://github.com/CopterExpress/clever/blob/master/aruco_pose/README.md#parameters for details",
|
||||
NODELET_ERROR("Marker id %d is not in dictionary; current dictionary contains %d markers. "
|
||||
"Please see https://github.com/CopterExpress/clever/blob/master/aruco_pose/README.md#parameters for details",
|
||||
id, num_markers);
|
||||
return;
|
||||
}
|
||||
// Check if marker is already in the board
|
||||
if (std::count(board_->ids.begin(), board_->ids.end(), id) > 0) {
|
||||
ROS_ERROR("aruco_map: Marker id %d is already in the map", id);
|
||||
NODELET_ERROR("Marker id %d is already in the map", id);
|
||||
return;
|
||||
}
|
||||
// Create transform
|
||||
@@ -438,27 +441,36 @@ publish_debug:
|
||||
markers_transforms_.push_back(marker_transform);
|
||||
}
|
||||
|
||||
// Add visualization marker
|
||||
visualization_msgs::Marker marker;
|
||||
marker.header.frame_id = transform_.child_frame_id;
|
||||
// marker.header.stamp = stamp;
|
||||
marker.action = visualization_msgs::Marker::ADD;
|
||||
marker.id = vis_array_.markers.size();
|
||||
marker.ns = "aruco_map_marker";
|
||||
marker.type = visualization_msgs::Marker::CUBE;
|
||||
marker.scale.x = length;
|
||||
marker.scale.y = length;
|
||||
marker.scale.z = 0.001;
|
||||
marker.color.r = 1;
|
||||
marker.color.g = 0.5;
|
||||
marker.color.b = 0.5;
|
||||
marker.color.a = 0.8;
|
||||
// Add marker to array
|
||||
aruco_pose::Marker marker;
|
||||
marker.id = id;
|
||||
marker.length = length;
|
||||
marker.pose.position.x = x;
|
||||
marker.pose.position.y = y;
|
||||
marker.pose.position.z = z;
|
||||
tf::quaternionTFToMsg(q, marker.pose.orientation);
|
||||
marker.frame_locked = true;
|
||||
vis_array_.markers.push_back(marker);
|
||||
markers_.markers.push_back(marker);
|
||||
|
||||
// Add visualization marker
|
||||
visualization_msgs::Marker vis_marker;
|
||||
vis_marker.header.frame_id = transform_.child_frame_id;
|
||||
vis_marker.action = visualization_msgs::Marker::ADD;
|
||||
vis_marker.id = vis_array_.markers.size();
|
||||
vis_marker.ns = "aruco_map_marker";
|
||||
vis_marker.type = visualization_msgs::Marker::CUBE;
|
||||
vis_marker.scale.x = length;
|
||||
vis_marker.scale.y = length;
|
||||
vis_marker.scale.z = 0.001;
|
||||
vis_marker.color.r = 1;
|
||||
vis_marker.color.g = 0.5;
|
||||
vis_marker.color.b = 0.5;
|
||||
vis_marker.color.a = 0.8;
|
||||
vis_marker.pose.position.x = x;
|
||||
vis_marker.pose.position.y = y;
|
||||
vis_marker.pose.position.z = z;
|
||||
tf::quaternionTFToMsg(q, marker.pose.orientation);
|
||||
vis_marker.frame_locked = true;
|
||||
vis_array_.markers.push_back(vis_marker);
|
||||
|
||||
// Add linking line
|
||||
// geometry_msgs::Point p;
|
||||
@@ -475,6 +487,11 @@ publish_debug:
|
||||
}
|
||||
}
|
||||
|
||||
void publishMarkers()
|
||||
{
|
||||
markers_pub_.publish(markers_);
|
||||
}
|
||||
|
||||
void publishMapImage()
|
||||
{
|
||||
cv::Size size(image_width_, image_height_);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// with some improvements and fixes
|
||||
|
||||
#include "draw.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::aruco;
|
||||
@@ -112,9 +113,32 @@ void _drawPlanarBoard(Board *_board, Size outSize, OutputArray _img, int marginS
|
||||
auto out_copy = _img.getMat();
|
||||
|
||||
cv::Point center(ofs.x - minX / sizeX * float(out.cols), ofs.y + out.rows + minY / sizeY * float(out.rows));
|
||||
line(out_copy, center, center + Point(300, 0), Scalar(255, 0, 0), 10); // x axis
|
||||
line(out_copy, center, center + Point(0, -300), Scalar(0, 255, 0), 10); // y axis
|
||||
line(out_copy, center, center + Point(-200, 200), Scalar(0, 0, 255), 10); // z axis
|
||||
|
||||
int axis_points[3][2] = {{300, 0}, {0, -300}, {-150, 150}};
|
||||
Point axis_names[3] = {Point(270, 50), Point(25, -270), Point(-160, 115)};
|
||||
Scalar colors[] = {Scalar(255, 0, 0), Scalar(0, 255, 0), Scalar(0, 0, 255)};
|
||||
String names[] = {"X", "Y", "Z"};
|
||||
|
||||
int r_half = 14;
|
||||
int height = 55;
|
||||
|
||||
for(int poly = 2; poly >= 0; poly--){
|
||||
double alpha = atan2(0 - axis_points[poly][0], 0 - axis_points[poly][1]);
|
||||
float x_delta = r_half * cos(alpha);
|
||||
float y_delta = r_half * sin(alpha);
|
||||
|
||||
Point polygon_vertices[1][3];
|
||||
polygon_vertices[0][0] = center + Point(axis_points[poly][0] + x_delta, axis_points[poly][1] - y_delta);
|
||||
polygon_vertices[0][1] = center + Point(axis_points[poly][0] - x_delta, axis_points[poly][1] + y_delta);
|
||||
polygon_vertices[0][2] = center + Point(axis_points[poly][0] - sin(alpha) * height, axis_points[poly][1] - cos(alpha) * height);
|
||||
|
||||
const Point* ppt[1] = {polygon_vertices[0]};
|
||||
int npt[] = {3};
|
||||
|
||||
fillPoly(out_copy, ppt, npt, 1, colors[poly]);
|
||||
putText(out_copy, names[poly], center + axis_names[poly], FONT_HERSHEY_SIMPLEX, 1.2, colors[poly], 7);
|
||||
line(out_copy, center, center + Point(axis_points[poly][0], axis_points[poly][1]), colors[poly], 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,62 @@ def test_map_image(node):
|
||||
img = rospy.wait_for_message('aruco_map/image', Image, timeout=5)
|
||||
assert img.width == 2000
|
||||
assert img.height == 2000
|
||||
assert img.encoding == 'mono8'
|
||||
assert img.encoding in ('mono8', 'rgb8')
|
||||
|
||||
def test_map_markers(node):
|
||||
markers = rospy.wait_for_message('aruco_map/markers', MarkerArray, timeout=5)
|
||||
assert markers.markers[0].id == 1
|
||||
assert markers.markers[1].id == 2
|
||||
assert markers.markers[2].id == 3
|
||||
assert markers.markers[3].id == 4
|
||||
assert markers.markers[4].id == 10
|
||||
assert markers.markers[5].id == 11
|
||||
assert markers.markers[6].id == 12
|
||||
|
||||
assert markers.markers[0].pose.position.x == 0
|
||||
assert markers.markers[0].pose.position.y == 0
|
||||
assert markers.markers[0].pose.position.z == 0
|
||||
assert markers.markers[0].pose.orientation.x == 0
|
||||
assert markers.markers[0].pose.orientation.y == 0
|
||||
assert markers.markers[0].pose.orientation.z == 0
|
||||
assert markers.markers[0].pose.orientation.w == 1
|
||||
assert markers.markers[0].length == approx(0.33)
|
||||
|
||||
assert markers.markers[1].pose.position.x == 1
|
||||
assert markers.markers[1].pose.position.y == 0
|
||||
assert markers.markers[1].pose.position.z == 0
|
||||
assert markers.markers[1].pose.orientation.x == 0
|
||||
assert markers.markers[1].pose.orientation.y == 0
|
||||
assert markers.markers[1].pose.orientation.z == 0
|
||||
assert markers.markers[1].pose.orientation.w == 1
|
||||
assert markers.markers[1].length == approx(0.33)
|
||||
|
||||
assert markers.markers[2].pose.position.x == 0
|
||||
assert markers.markers[2].pose.position.y == 1
|
||||
assert markers.markers[2].pose.position.z == 0
|
||||
assert markers.markers[2].pose.orientation.x == 0
|
||||
assert markers.markers[2].pose.orientation.y == 0
|
||||
assert markers.markers[2].pose.orientation.z == 0
|
||||
assert markers.markers[2].pose.orientation.w == 1
|
||||
assert markers.markers[2].length == approx(0.33)
|
||||
|
||||
assert markers.markers[3].pose.position.x == 1
|
||||
assert markers.markers[3].pose.position.y == 1
|
||||
assert markers.markers[3].pose.position.z == 0
|
||||
assert markers.markers[3].pose.orientation.x == 0
|
||||
assert markers.markers[3].pose.orientation.y == 0
|
||||
assert markers.markers[3].pose.orientation.z == 0
|
||||
assert markers.markers[3].pose.orientation.w == 1
|
||||
assert markers.markers[3].length == approx(0.33)
|
||||
|
||||
assert markers.markers[4].pose.position.x == approx(0.5)
|
||||
assert markers.markers[4].pose.position.y == 2
|
||||
assert markers.markers[4].pose.position.z == 0
|
||||
assert markers.markers[4].pose.orientation.x == 0
|
||||
assert markers.markers[4].pose.orientation.y == 0
|
||||
assert markers.markers[4].pose.orientation.z == approx(0.5646424733950354)
|
||||
assert markers.markers[4].pose.orientation.w == approx(0.8253356149096783)
|
||||
assert markers.markers[4].length == approx(0.5)
|
||||
|
||||
def test_map_visualization(node):
|
||||
vis = rospy.wait_for_message('aruco_map/visualization', VisMarkerArray, timeout=5)
|
||||
|
||||
@@ -17,7 +17,7 @@ class TestArucoPose(unittest.TestCase):
|
||||
img = rospy.wait_for_message('aruco_map/image', Image, timeout=5)
|
||||
self.assertEqual(img.width, 2000)
|
||||
self.assertEqual(img.height, 2000)
|
||||
self.assertEqual(img.encoding, 'mono8')
|
||||
self.assertIn(img.encoding, ('mono8', 'rgb8'))
|
||||
|
||||
def test_map_visualization(self):
|
||||
vis = rospy.wait_for_message('aruco_map/visualization', VisMarkerArray, timeout=5)
|
||||
|
||||
@@ -58,4 +58,4 @@ def test_map_image(node):
|
||||
img = rospy.wait_for_message('aruco_map/image', Image, timeout=5)
|
||||
assert img.width == 2000
|
||||
assert img.height == 2000
|
||||
assert img.encoding == 'mono8'
|
||||
assert img.encoding in ('mono8', 'rgb8')
|
||||
|
||||
43
book.json
@@ -2,17 +2,21 @@
|
||||
"title": "Clever",
|
||||
"description": "Конструктор квадрокоптера «Клевер»",
|
||||
"author": "Copter Express",
|
||||
"language": "ru",
|
||||
"language": "en",
|
||||
"root": "docs/",
|
||||
"gitbook": "^3.2.2",
|
||||
"plugins": [
|
||||
"youtube",
|
||||
"richquotes@https://github.com/okalachev/gitbook-plugin-richquotes.git",
|
||||
"yametrika",
|
||||
"anchors",
|
||||
"validate-links",
|
||||
"bulk-redirect@https://github.com/okalachev/gitbook-plugin-bulk-redirect.git",
|
||||
"sitemap@https://github.com/okalachev/plugin-sitemap.git"
|
||||
"sitemap@https://github.com/okalachev/plugin-sitemap.git",
|
||||
"toolbar@https://github.com/hamishwillee/gitbook-plugin-toolbar.git",
|
||||
"addcssjs",
|
||||
"localized-footer@https://github.com/okalachev/gitbook-plugin-localized-footer.git",
|
||||
"image-zoom@https://github.com/okalachev/gitbook-plugin-image-zoom.git",
|
||||
"language-picker@https://github.com/okalachev/gitbook-plugin-language-picker.git"
|
||||
],
|
||||
"pluginsConfig": {
|
||||
"yametrika": {
|
||||
@@ -20,10 +24,39 @@
|
||||
},
|
||||
"bulk-redirect": {
|
||||
"basepath": "",
|
||||
"redirectsFile": "redirects.json"
|
||||
"redirectsFile": "redirects.json",
|
||||
"blank": true
|
||||
},
|
||||
"sitemap": {
|
||||
"hostname": "https://clever.copterexpress.com"
|
||||
"hostname": "https://clever.coex.tech"
|
||||
},
|
||||
"toolbar": {
|
||||
"buttons":
|
||||
[
|
||||
{
|
||||
"label": "Edit page on github",
|
||||
"icon": "fa fa-pencil-square-o",
|
||||
"position" : "left",
|
||||
"url": "https://github.com/CopterExpress/clever/edit/master/docs/{{filepath_lang}}"
|
||||
},
|
||||
{
|
||||
"label": "GitHub",
|
||||
"icon": "fa fa-github",
|
||||
"position" : "left",
|
||||
"url": "https://github.com/CopterExpress/clever"
|
||||
}
|
||||
]
|
||||
},
|
||||
"addcssjs": {
|
||||
"css": ["../clever.css"],
|
||||
"js": ["../clever.js"]
|
||||
},
|
||||
"language-picker": {
|
||||
"languages": [["ru", "Russian"], ["en", "English"]]
|
||||
},
|
||||
"localized-footer": {
|
||||
"hline": false,
|
||||
"filename": "./FOOTER.md"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
User=pi
|
||||
ExecStart=/bin/sh -c ". /home/pi/catkin_ws/devel/setup.sh; \
|
||||
ROS_HOSTNAME=`hostname`.local exec roslaunch clever clever.launch --wait --screen --skip-log-check"
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
ExecStart=/bin/bash -c ". /home/pi/catkin_ws/devel/setup.sh; \
|
||||
ROS_HOSTNAME=`hostname`.local exec stdbuf -o L roslaunch clever clever.launch --wait --screen --skip-log-check \
|
||||
2> >(tee /tmp/clever.err)"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -35,14 +35,15 @@ echo_stamp() {
|
||||
echo -e ${TEXT}
|
||||
}
|
||||
|
||||
echo_stamp "Rename SSID"
|
||||
NEW_SSID='CLEVER-'$(head -c 100 /dev/urandom | xxd -ps -c 100 | sed -e "s/[^0-9]//g" | cut -c 1-4)
|
||||
echo_stamp "Setting SSID to ${NEW_SSID}"
|
||||
sudo sed -i.OLD "s/CLEVER/${NEW_SSID}/" /etc/wpa_supplicant/wpa_supplicant.conf
|
||||
|
||||
echo_stamp "Rename hostname to $NEW_SSID"
|
||||
hostnamectl set-hostname $NEW_SSID
|
||||
sed -i 's/127\.0\.1\.1.*/127.0.1.1\t'${NEW_SSID}' '${NEW_SSID}'.local/g' /etc/hosts
|
||||
# .local (mdns) hostname added to make it accesable when wlan and ethernet interfaces down
|
||||
NEW_HOSTNAME=$(echo ${NEW_SSID} | tr '[:upper:]' '[:lower:]')
|
||||
echo_stamp "Setting hostname to $NEW_HOSTNAME"
|
||||
hostnamectl set-hostname $NEW_HOSTNAME
|
||||
sed -i 's/127\.0\.1\.1.*/127.0.1.1\t'${NEW_HOSTNAME}' '${NEW_HOSTNAME}'.local/g' /etc/hosts
|
||||
# .local (mdns) hostname added to make it accesable when wlan and ethernet interfaces are down
|
||||
|
||||
echo_stamp "Harware setup"
|
||||
/root/hardware_setup.sh
|
||||
|
||||
@@ -529,6 +529,12 @@ libogg:
|
||||
vl53l1x:
|
||||
debian:
|
||||
stretch: [ros-kinetic-vl53l1x]
|
||||
ws281x:
|
||||
debian:
|
||||
stretch: [ros-kinetic-ws281x]
|
||||
led_msgs:
|
||||
debian:
|
||||
stretch: [ros-kinetic-led-msgs]
|
||||
interactive_markers:
|
||||
debian:
|
||||
stretch: [ros-kinetic-interactive-markers]
|
||||
|
||||
22
builder/assets/launch.nanorc
Normal file
@@ -0,0 +1,22 @@
|
||||
## ROS .launch files (which are actually xml files)
|
||||
|
||||
syntax "launch" "\.(launch)$"
|
||||
header "<\?xml.*version=.*\?>"
|
||||
magic "(XML|SGML) (sub)?document"
|
||||
comment "<!--|-->"
|
||||
|
||||
# The entire content of the tag:
|
||||
color green start="<" end=">"
|
||||
|
||||
# The start and the end of the tag:
|
||||
color cyan "<[^> ]+" ">"
|
||||
|
||||
# The strings inside the tag:
|
||||
color magenta "\"[^"]*\""
|
||||
|
||||
# Comments:
|
||||
color yellow start="<!DOCTYPE" end="[/]?>"
|
||||
color yellow start="<!--" end="-->"
|
||||
|
||||
# Escapes:
|
||||
color red "&[^;]*;"
|
||||
@@ -113,6 +113,7 @@ ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/roscore
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/kinetic-rosdep-clever.yaml' '/etc/ros/rosdep/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/ros_python_paths' '/etc/sudoers.d/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/pigpiod.service' '/lib/systemd/system/'
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/launch.nanorc' '/usr/share/nano/'
|
||||
# ${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${SCRIPTS_DIR}'/assets/kinetic-ros-clever.rosinstall' '/home/pi/ros_catkin_ws/'
|
||||
# Add PX4 udev rules
|
||||
${BUILDER_DIR}/image-chroot.sh ${IMAGE_PATH} copy ${REPO_DIR}'/clever/config/99-px4fmu.rules' '/lib/udev/rules.d/'
|
||||
|
||||
@@ -174,6 +174,7 @@ apt-get install -y --no-install-recommends \
|
||||
ros-kinetic-rosserial \
|
||||
ros-kinetic-usb-cam \
|
||||
ros-kinetic-vl53l1x \
|
||||
ros-kinetic-ws281x \
|
||||
ros-kinetic-opencv3=3.3.19-0stretch \
|
||||
ros-kinetic-rosshow
|
||||
|
||||
@@ -182,6 +183,7 @@ echo_stamp "Install GeographicLib datasets (needed for mavros)" \
|
||||
&& wget -qO- https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh | bash
|
||||
|
||||
echo_stamp "Running tests"
|
||||
cd /home/pi/catkin_ws
|
||||
catkin_make run_tests && catkin_test_results
|
||||
|
||||
echo_stamp "Change permissions for catkin_ws"
|
||||
|
||||
@@ -60,14 +60,14 @@ my_travis_retry() {
|
||||
echo_stamp "Install apt keys & repos"
|
||||
|
||||
# TODO: This STDOUT consist 'OK'
|
||||
curl http://repo.coex.space/aptly_repo_signing.key 2> /dev/null | apt-key add -
|
||||
curl http://deb.coex.tech/aptly_repo_signing.key 2> /dev/null | apt-key add -
|
||||
apt-get update \
|
||||
&& apt-get install --no-install-recommends -y -qq dirmngr=2.1.18-8~deb9u4 > /dev/null \
|
||||
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
|
||||
|
||||
echo "deb http://packages.ros.org/ros/ubuntu stretch main" > /etc/apt/sources.list.d/ros-latest.list
|
||||
echo "deb http://repo.coex.space/rpi-ros-kinetic stretch main" > /etc/apt/sources.list.d/rpi-ros-kinetic.list
|
||||
echo "deb http://repo.coex.space/clever stretch main" > /etc/apt/sources.list.d/clever.list
|
||||
echo "deb http://deb.coex.tech/rpi-ros-kinetic stretch main" > /etc/apt/sources.list.d/rpi-ros-kinetic.list
|
||||
echo "deb http://deb.coex.tech/clever stretch main" > /etc/apt/sources.list.d/clever.list
|
||||
|
||||
echo_stamp "Update apt cache"
|
||||
|
||||
@@ -107,18 +107,17 @@ espeak espeak-data python-espeak \
|
||||
ntpdate \
|
||||
python-dev \
|
||||
python3-dev \
|
||||
python-systemd \
|
||||
mjpg-streamer=2.0 \
|
||||
&& echo_stamp "Everything was installed!" "SUCCESS" \
|
||||
|| (echo_stamp "Some packages wasn't installed!" "ERROR"; exit 1)
|
||||
|
||||
echo_stamp "Updating kernel to fix camera bug"
|
||||
apt-get install --no-install-recommends -y \
|
||||
raspberrypi-kernel=1.20190709~stretch-1 \
|
||||
raspberrypi-bootloader=1.20190709~stretch-1 \
|
||||
libraspberrypi-bin=1.20190709~stretch-1 \
|
||||
libraspberrypi-dev=1.20190709~stretch-1 \
|
||||
libraspberrypi0=1.20190709~stretch-1 \
|
||||
raspberrypi-kernel=1.20190819~stretch-1 \
|
||||
raspberrypi-bootloader=1.20190819~stretch-1 \
|
||||
libraspberrypi-bin=1.20190819~stretch-1 \
|
||||
libraspberrypi-dev=1.20190819~stretch-1 \
|
||||
libraspberrypi0=1.20190819~stretch-1 \
|
||||
wireless-regdb=2018.05.09-0~rpt1 \
|
||||
wpasupplicant=2:2.6-21~bpo9~rpt1
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ from mavros_msgs.srv import CommandBool, CommandLong, SetMode
|
||||
|
||||
from std_srvs.srv import Trigger
|
||||
from clever.srv import GetTelemetry, Navigate, NavigateGlobal, SetPosition, SetVelocity, \
|
||||
SetAttitude, SetRates
|
||||
SetAttitude, SetRates, SetLEDEffect
|
||||
|
||||
import tf2_ros
|
||||
import tf2_geometry_msgs
|
||||
|
||||
@@ -10,11 +10,14 @@ def human_size(num, suffix='B'):
|
||||
num /= 1024.0
|
||||
return "%.1f %s%s" % (num, 'Yi', suffix)
|
||||
|
||||
SIZE_LIMIT = 600 * 1024
|
||||
SIZE_LIMIT = 800 * 1024
|
||||
EXCLUDE = 'rviz.png', 'ssid.png', 'sitl_docker_demo.png', 'qgc-params.png', 'butterfly.png', \
|
||||
'Clever main.png', 'fpv_3.png', '1_4.png', 'fpv_4.png', 'detal1.png', 'lockradio.png', \
|
||||
'qground.png', 'allElements.png', 'download-log.png', 'explosion.png', 'rqt.png', \
|
||||
'cl3_mountBEC.JPG', 'cl3_mountRpiCamera.JPG'
|
||||
'cl3_mountBEC.JPG', 'cl3_mountRpiCamera.JPG', 'clever4-front-black-large.png', \
|
||||
'qgc-battery.png', 'qgc-radio.png', 'qgc-cal-acc.png', 'qgc-esc.png', 'qgc-cal-compass.png', \
|
||||
'qgc.png', 'qgc-parameters.png', 'clever4-front-white-large.png', 'qgc-modes.png', \
|
||||
'qgc-requires-setup.png', 'clever4-front-white.png', 'clever4-kit-white.png', '26_1.png'
|
||||
|
||||
code = 0
|
||||
|
||||
22
check_unused_assets.py
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
EXCLUDE = ('clever4-front-white.png', '.DS_Store', 'clever4-front-black-large.png')
|
||||
code = 0
|
||||
|
||||
os.chdir('./docs')
|
||||
|
||||
for root, dirs, files in os.walk('assets'):
|
||||
for f in files:
|
||||
if f not in EXCLUDE:
|
||||
path = os.path.join(root, f)
|
||||
try:
|
||||
subprocess.check_output(['grep', '-F', '-r', path, './ru', './en'])
|
||||
except subprocess.CalledProcessError:
|
||||
print('\x1b[1;31mAssets file {} is not used\x1b[0m'.format(path))
|
||||
code = 1
|
||||
|
||||
sys.exit(code)
|
||||
@@ -80,6 +80,7 @@ add_service_files(
|
||||
SetVelocity.srv
|
||||
SetAttitude.srv
|
||||
SetRates.srv
|
||||
SetLEDEffect.srv
|
||||
)
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
@@ -164,6 +165,8 @@ add_executable(camera_markers src/camera_markers.cpp)
|
||||
|
||||
add_executable(vpe_publisher src/vpe_publisher.cpp)
|
||||
|
||||
add_executable(led src/led.cpp)
|
||||
|
||||
target_link_libraries(simple_offboard
|
||||
${catkin_LIBRARIES}
|
||||
${GeographicLib_LIBRARIES}
|
||||
@@ -175,8 +178,12 @@ target_link_libraries(camera_markers ${catkin_LIBRARIES})
|
||||
|
||||
target_link_libraries(vpe_publisher ${catkin_LIBRARIES})
|
||||
|
||||
target_link_libraries(led ${catkin_LIBRARIES})
|
||||
|
||||
add_dependencies(simple_offboard clever_generate_messages_cpp)
|
||||
|
||||
add_dependencies(led clever_generate_messages_cpp)
|
||||
|
||||
## Rename C++ executable without prefix
|
||||
## The above recommended prefix causes long target names, the following renames the
|
||||
## target back to the shorter version for ease of user use
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
<arg name="aruco_map" default="false"/>
|
||||
<arg name="aruco_vpe" default="false"/>
|
||||
|
||||
<!-- For additional help go to https://clever.copterexpress.com/aruco.html -->
|
||||
<!-- For additional help go to https://clever.coex.tech/aruco -->
|
||||
|
||||
<!-- aruco_detect: detect aruco markers, estimate poses -->
|
||||
<node name="aruco_detect" pkg="nodelet" if="$(arg aruco_detect)" type="nodelet" args="load aruco_pose/aruco_detect nodelet_manager" output="screen" clear_params="true">
|
||||
<remap from="image_raw" to="main_camera/image_raw"/>
|
||||
<remap from="camera_info" to="main_camera/camera_info"/>
|
||||
<remap from="map_markers" to="aruco_map/markers" if="$(arg aruco_map)"/>
|
||||
<param name="estimate_poses" value="true"/>
|
||||
<param name="send_tf" value="true"/>
|
||||
<param name="known_tilt" value="map"/>
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
<arg name="main_camera" default="true"/>
|
||||
<arg name="optical_flow" default="false"/>
|
||||
<arg name="aruco" default="false"/>
|
||||
<arg name="rc" default="true"/>
|
||||
<arg name="rangefinder_vl53l1x" default="false"/>
|
||||
<arg name="led" default="false"/>
|
||||
<arg name="rc" default="true"/>
|
||||
|
||||
<!-- log formatting -->
|
||||
<env name="ROSCONSOLE_FORMAT" value="[${severity}] [${time}]: ${logger}: ${message}"/>
|
||||
|
||||
<!-- mavros -->
|
||||
<include file="$(find clever)/launch/mavros.launch">
|
||||
@@ -44,6 +48,7 @@
|
||||
<node name="simple_offboard" pkg="clever" type="simple_offboard" output="screen" clear_params="true">
|
||||
<param name="reference_frames/body" value="map"/>
|
||||
<param name="reference_frames/base_link" value="map"/>
|
||||
<param name="reference_frames/navigate_target" value="map"/>
|
||||
</node>
|
||||
|
||||
<!-- main camera -->
|
||||
@@ -56,11 +61,13 @@
|
||||
<node name="tf2_web_republisher" pkg="tf2_web_republisher" type="tf2_web_republisher" output="screen" if="$(arg rosbridge)"/>
|
||||
|
||||
<!-- vl53l1x ToF rangefinder -->
|
||||
<node name="vl53l1x" pkg="vl53l1x" type="vl53l1x_node" output="screen" if="$(arg rangefinder_vl53l1x)">
|
||||
<node name="rangefinder" pkg="vl53l1x" type="vl53l1x_node" output="screen" if="$(arg rangefinder_vl53l1x)">
|
||||
<param name="frame_id" value="rangefinder"/>
|
||||
<remap from="~range" to="mavros/distance_sensor/rangefinder_sub"/> <!-- redirect data to FCU -->
|
||||
</node>
|
||||
|
||||
<!-- led strip -->
|
||||
<include file="$(find clever)/launch/led.launch" if="$(arg led)"/>
|
||||
|
||||
<!-- rc backend -->
|
||||
<node name="rc" pkg="clever" type="rc" output="screen" if="$(arg rc)"/>
|
||||
</launch>
|
||||
|
||||
38
clever/launch/led.launch
Normal file
@@ -0,0 +1,38 @@
|
||||
<launch>
|
||||
<arg name="ws281x" default="true"/>
|
||||
<arg name="led_effect" default="true"/>
|
||||
<arg name="led_notify" default="true"/>
|
||||
|
||||
<!-- For additional help go to https://clever.coex.tech/led -->
|
||||
|
||||
<!-- ws281x led strip driver -->
|
||||
<node pkg="ws281x" name="led" type="ws281x_node" clear_params="true" output="screen" if="$(arg ws281x)">
|
||||
<param name="led_count" value="58"/>
|
||||
<param name="gpio_pin" value="21"/>
|
||||
<param name="brightness" value="100"/>
|
||||
<param name="strip_type" value="WS2811_STRIP_GRB"/>
|
||||
<param name="target_frequency" value="800000"/>
|
||||
<param name="dma" value="10"/>
|
||||
<param name="invert" value="false"/>
|
||||
</node>
|
||||
|
||||
<!-- high level led effects control, events notification with leds -->
|
||||
<node pkg="clever" name="led_effect" type="led" ns="led" clear_params="true" output="screen" if="$(arg led_effect)">
|
||||
<param name="blink_rate" value="2"/>
|
||||
<param name="fade_period" value="0.5"/>
|
||||
<param name="rainbow_period" value="5"/>
|
||||
<!-- events effects table -->
|
||||
<rosparam param="notify" if="$(arg led_notify)">
|
||||
startup: { r: 255, g: 255, b: 255 }
|
||||
connected: { effect: rainbow }
|
||||
disconnected: { effect: blink, r: 255, g: 50, b: 50 }
|
||||
acro: { r: 245, g: 155, b: 0 }
|
||||
stabilized: { r: 30, g: 180, b: 50 }
|
||||
altctl: { r: 255, g: 255, b: 40 }
|
||||
posctl: { r: 50, g: 100, b: 220 }
|
||||
offboard: { r: 220, g: 20, b: 250 }
|
||||
low_battery: { threshold: 3.7, effect: blink_fast, r: 255, g: 0, b: 0 }
|
||||
error: { effect: flash, r: 255, g: 0, b: 0 }
|
||||
</rosparam>
|
||||
</node>
|
||||
</launch>
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- Camera position and orientation are represented by base_link -> main_camera_optical transform -->
|
||||
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
|
||||
|
||||
<!-- article about camera setup: https://clever.copterexpress.com/camera_frame.html -->
|
||||
<!-- article about camera setup: https://clever.coex.tech/camera_frame -->
|
||||
|
||||
<!-- camera is oriented downward, camera cable goes backward [option 1] -->
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0.05 0 -0.07 -1.5707963 0 3.1415926 base_link main_camera_optical"/>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<arg name="gcs_bridge" default="tcp"/>
|
||||
<arg name="viz" default="true"/>
|
||||
<arg name="respawn" default="true"/>
|
||||
<arg name="distance_sensor_remap" default="rangefinder/range"/>
|
||||
|
||||
<node pkg="mavros" type="mavros_node" name="mavros" required="false" clear_params="true" respawn="$(arg respawn)" unless="$(eval fcu_conn == 'none')" respawn_delay="1" output="screen">
|
||||
<!-- UART connection -->
|
||||
@@ -27,6 +28,9 @@
|
||||
<!-- basic params -->
|
||||
<rosparam command="load" file="$(find clever)/launch/mavros_config.yaml"/>
|
||||
|
||||
<!-- remap rangefinder -->
|
||||
<remap from="mavros/distance_sensor/rangefinder_sub" to="rangefinder/range"/>
|
||||
|
||||
<rosparam param="plugin_whitelist">
|
||||
- altitude
|
||||
- command
|
||||
@@ -52,6 +56,14 @@
|
||||
</rosparam>
|
||||
</node>
|
||||
|
||||
<!-- remapped distance_sensor config -->
|
||||
<rosparam param="$(arg distance_sensor_remap)" if="$(eval bool(distance_sensor_remap))">
|
||||
subscriber: true
|
||||
id: 1
|
||||
orientation: PITCH_270
|
||||
covariance: 1 # cm
|
||||
</rosparam>
|
||||
|
||||
<!-- Rangefinders frame -->
|
||||
<node pkg="tf2_ros" type="static_transform_publisher" name="rangefinder_frame" args="0 0 -0.05 0 1.5707963268 0 base_link rangefinder"/>
|
||||
|
||||
|
||||
@@ -77,9 +77,6 @@ distance_sensor:
|
||||
field_of_view: 0.5
|
||||
rangefinder_sub:
|
||||
subscriber: true
|
||||
id: 1
|
||||
orientation: PITCH_270
|
||||
covariance: 1 # cm
|
||||
|
||||
# fake_gps
|
||||
fake_gps:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<maintainer email="okalachev@gmail.com">Oleg Kalachev</maintainer>
|
||||
<license>MIT</license>
|
||||
|
||||
<url type="website">https://clever.copterexpress.com/</url>
|
||||
<url type="website">https://clever.coex.tech/</url>
|
||||
<author email="okalachev@gmail.com">Oleg Kalachev</author>
|
||||
<author email="urpylka@gmail.com">Artem Smirnov</author>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<depend>geometry_msgs</depend>
|
||||
<depend>sensor_msgs</depend>
|
||||
<depend>visualization_msgs</depend>
|
||||
<depend>led_msgs</depend>
|
||||
<depend>geographiclib</depend>
|
||||
<depend>nodelet</depend>
|
||||
<depend>mavros</depend>
|
||||
|
||||
321
clever/src/led.cpp
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* High level control for the LED strip
|
||||
* Indicate flight events with the LED strip
|
||||
* Copyright (C) 2019 Copter Express Technologies
|
||||
*
|
||||
* Author: Oleg Kalachev <okalachev@gmail.com>
|
||||
*
|
||||
* Distributed under MIT License (available at https://opensource.org/licenses/MIT).
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
#include <ros/ros.h>
|
||||
#include <string>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <clever/SetLEDEffect.h>
|
||||
#include <led_msgs/SetLEDs.h>
|
||||
#include <led_msgs/LEDState.h>
|
||||
#include <led_msgs/LEDStateArray.h>
|
||||
|
||||
#include <sensor_msgs/BatteryState.h>
|
||||
#include <mavros_msgs/State.h>
|
||||
#include <rosgraph_msgs/Log.h>
|
||||
|
||||
clever::SetLEDEffect::Request current_effect;
|
||||
int led_count;
|
||||
ros::Timer timer;
|
||||
ros::Time start_time;
|
||||
double blink_rate, blink_fast_rate, flash_delay, fade_period, wipe_period, rainbow_period;
|
||||
double low_battery_threshold;
|
||||
bool blink_state;
|
||||
led_msgs::SetLEDs set_leds;
|
||||
led_msgs::LEDStateArray state, start_state;
|
||||
ros::ServiceClient set_leds_srv;
|
||||
mavros_msgs::State mavros_state;
|
||||
int counter;
|
||||
|
||||
void callSetLeds()
|
||||
{
|
||||
bool res = set_leds_srv.call(set_leds);
|
||||
if (!res) {
|
||||
ROS_WARN_THROTTLE(5, "Error calling set_leds service");
|
||||
} else if (!set_leds.response.success) {
|
||||
ROS_WARN_THROTTLE(5, "Calling set_leds failed: %s", set_leds.response.message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void rainbow(uint8_t n, uint8_t& r, uint8_t& g, uint8_t& b)
|
||||
{
|
||||
if (n < 255 / 3) {
|
||||
r = n * 3;
|
||||
g = 255 - n * 3;
|
||||
b = 0;
|
||||
} else if (n < 255 / 3 * 2) {
|
||||
n -= 255 / 3;
|
||||
r = 255 - n * 3;
|
||||
g = 0;
|
||||
b = n * 3;
|
||||
} else {
|
||||
n -= 255 / 3 * 2;
|
||||
r = 0;
|
||||
g = n * 3;
|
||||
b = 255 - n * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void fill(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
set_leds.request.leds.resize(led_count);
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
set_leds.request.leds[i].index = i;
|
||||
set_leds.request.leds[i].r = r;
|
||||
set_leds.request.leds[i].g = g;
|
||||
set_leds.request.leds[i].b = b;
|
||||
}
|
||||
callSetLeds();
|
||||
}
|
||||
|
||||
void proceed(const ros::TimerEvent& event)
|
||||
{
|
||||
counter++;
|
||||
uint8_t r, g, b;
|
||||
set_leds.request.leds.clear();
|
||||
set_leds.request.leds.resize(led_count);
|
||||
|
||||
if (current_effect.effect == "blink" || current_effect.effect == "blink_fast") {
|
||||
blink_state = !blink_state;
|
||||
// toggle all leds
|
||||
if (blink_state) {
|
||||
fill(current_effect.r, current_effect.g, current_effect.b);
|
||||
} else {
|
||||
fill(0, 0, 0);
|
||||
}
|
||||
|
||||
} else if (current_effect.effect == "fade") {
|
||||
// fade all leds from starting state
|
||||
double passed = std::min((event.current_real - start_time).toSec() / fade_period, 1.0);
|
||||
double one_minus_passed = 1 - passed;
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
set_leds.request.leds[i].index = i;
|
||||
set_leds.request.leds[i].r = one_minus_passed * start_state.leds[i].r + passed * current_effect.r;
|
||||
set_leds.request.leds[i].g = one_minus_passed * start_state.leds[i].g + passed * current_effect.g;
|
||||
set_leds.request.leds[i].b = one_minus_passed * start_state.leds[i].b + passed * current_effect.b;
|
||||
}
|
||||
callSetLeds();
|
||||
if (passed >= 1.0) {
|
||||
// fade finished
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
} else if (current_effect.effect == "wipe") {
|
||||
set_leds.request.leds.resize(1);
|
||||
set_leds.request.leds[0].index = counter - 1;
|
||||
set_leds.request.leds[0].r = current_effect.r;
|
||||
set_leds.request.leds[0].g = current_effect.g;
|
||||
set_leds.request.leds[0].b = current_effect.b;
|
||||
callSetLeds();
|
||||
if (counter == led_count) {
|
||||
// wipe finished
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
} else if (current_effect.effect == "rainbow_fill") {
|
||||
rainbow(counter % 255, r, g, b);
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
set_leds.request.leds[i].index = i;
|
||||
set_leds.request.leds[i].r = r;
|
||||
set_leds.request.leds[i].g = g;
|
||||
set_leds.request.leds[i].b = b;
|
||||
}
|
||||
callSetLeds();
|
||||
|
||||
} else if (current_effect.effect == "rainbow") {
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
int pos = (int)round(counter + (255.0 * i / led_count)) % 255;
|
||||
rainbow(pos % 255, r, g, b);
|
||||
set_leds.request.leds[i].index = i;
|
||||
set_leds.request.leds[i].r = r;
|
||||
set_leds.request.leds[i].g = g;
|
||||
set_leds.request.leds[i].b = b;
|
||||
}
|
||||
callSetLeds();
|
||||
}
|
||||
}
|
||||
|
||||
bool setEffect(clever::SetLEDEffect::Request& req, clever::SetLEDEffect::Response& res)
|
||||
{
|
||||
res.success = true;
|
||||
|
||||
if (req.effect == "") {
|
||||
req.effect = "fill";
|
||||
}
|
||||
|
||||
if (req.effect != "flash" && req.effect != "fill" && current_effect.effect == req.effect &&
|
||||
current_effect.r == req.r && current_effect.g == req.g && current_effect.b == req.b) {
|
||||
res.message = "Effect already set, skip";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (req.effect == "fill") {
|
||||
fill(req.r, req.g, req.b);
|
||||
|
||||
} else if (req.effect == "blink") {
|
||||
timer.setPeriod(ros::Duration(1 / blink_rate), true);
|
||||
timer.start();
|
||||
|
||||
} else if (req.effect == "blink_fast") {
|
||||
timer.setPeriod(ros::Duration(1 / blink_fast_rate), true);
|
||||
timer.start();
|
||||
|
||||
} else if (req.effect == "fade") {
|
||||
timer.setPeriod(ros::Duration(0.05), true);
|
||||
timer.start();
|
||||
|
||||
} else if (req.effect == "wipe") {
|
||||
timer.setPeriod(ros::Duration(wipe_period / led_count), true);
|
||||
timer.start();
|
||||
|
||||
} else if (req.effect == "flash") {
|
||||
ros::Duration delay(flash_delay);
|
||||
fill(0, 0, 0);
|
||||
delay.sleep();
|
||||
fill(req.r, req.g, req.b);
|
||||
delay.sleep();
|
||||
fill(0, 0, 0);
|
||||
delay.sleep();
|
||||
fill(req.r, req.g, req.b);
|
||||
delay.sleep();
|
||||
fill(0, 0, 0);
|
||||
delay.sleep();
|
||||
if (current_effect.effect == "fill"||
|
||||
current_effect.effect == "fade" ||
|
||||
current_effect.effect == "wipe") {
|
||||
// restore previous filling
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
fill(current_effect.r, current_effect.g, current_effect.b);
|
||||
}
|
||||
callSetLeds();
|
||||
}
|
||||
return true; // this effect happens only once
|
||||
|
||||
} else if (req.effect == "rainbow_fill") {
|
||||
timer.setPeriod(ros::Duration(rainbow_period / 255), true);
|
||||
timer.start();
|
||||
|
||||
} else if (req.effect == "rainbow") {
|
||||
timer.setPeriod(ros::Duration(rainbow_period / 255), true);
|
||||
timer.start();
|
||||
|
||||
} else {
|
||||
res.message = "Unknown effect: " + req.effect + ". Available effects are fill, fade, wipe, blink, blink_fast, flash, rainbow, rainbow_fill.";
|
||||
ROS_ERROR("%s", res.message.c_str());
|
||||
res.success = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// set current effect
|
||||
current_effect = req;
|
||||
counter = 0;
|
||||
start_state = state;
|
||||
start_time = ros::Time::now();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleState(const led_msgs::LEDStateArray& msg)
|
||||
{
|
||||
state = msg;
|
||||
led_count = state.leds.size();
|
||||
}
|
||||
|
||||
bool notify(const std::string& event)
|
||||
{
|
||||
if (ros::param::has("~notify/" + event + "/effect") ||
|
||||
ros::param::has("~notify/" + event + "/r") ||
|
||||
ros::param::has("~notify/" + event + "/g") ||
|
||||
ros::param::has("~notify/" + event + "/b")) {
|
||||
ROS_INFO_THROTTLE(5, "led: notify %s", event.c_str());
|
||||
clever::SetLEDEffect effect;
|
||||
effect.request.effect = ros::param::param("~notify/" + event + "/effect", std::string(""));
|
||||
effect.request.r = ros::param::param("~notify/" + event + "/r", 0);
|
||||
effect.request.g = ros::param::param("~notify/" + event + "/g", 0);
|
||||
effect.request.b = ros::param::param("~notify/" + event + "/b", 0);
|
||||
setEffect(effect.request, effect.response);
|
||||
}
|
||||
}
|
||||
|
||||
void handleMavrosState(const mavros_msgs::State& msg)
|
||||
{
|
||||
if (msg.connected && !mavros_state.connected) {
|
||||
notify("connected");
|
||||
} else if (!msg.connected && mavros_state.connected) {
|
||||
notify("disconnected");
|
||||
} else if (msg.armed && !mavros_state.armed) {
|
||||
notify("armed");
|
||||
} else if (!msg.armed && mavros_state.armed) {
|
||||
notify("disarmed");
|
||||
} else if (msg.mode != mavros_state.mode) {
|
||||
// mode changed
|
||||
std::string mode = boost::algorithm::to_lower_copy(msg.mode);
|
||||
if (mode.find(".") != std::string::npos) {
|
||||
// remove the part before "."
|
||||
mode = mode.substr(mode.find(".") + 1);
|
||||
}
|
||||
notify(mode);
|
||||
}
|
||||
mavros_state = msg;
|
||||
}
|
||||
|
||||
void handleLog(const rosgraph_msgs::Log& log)
|
||||
{
|
||||
if (log.level >= rosgraph_msgs::Log::ERROR) {
|
||||
notify("error");
|
||||
}
|
||||
}
|
||||
|
||||
void handleBattery(const sensor_msgs::BatteryState& msg)
|
||||
{
|
||||
for (auto const& voltage : msg.cell_voltage) {
|
||||
if (voltage < low_battery_threshold) {
|
||||
// notify low battery every time
|
||||
notify("low_battery");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "led");
|
||||
ros::NodeHandle nh, nh_priv("~");
|
||||
|
||||
nh_priv.param("blink_rate", blink_rate, 2.0);
|
||||
nh_priv.param("blink_fast_rate", blink_fast_rate, blink_rate * 2);
|
||||
nh_priv.param("fade_period", fade_period, 0.5);
|
||||
nh_priv.param("wipe_period", wipe_period, 0.5);
|
||||
nh_priv.param("flash_delay", flash_delay, 0.1);
|
||||
nh_priv.param("rainbow_period", rainbow_period, 5.0);
|
||||
|
||||
nh_priv.param("notify/low_battery/threshold", low_battery_threshold, 3.7);
|
||||
|
||||
ros::service::waitForService("set_leds"); // cannot work without set_leds service
|
||||
set_leds_srv = nh.serviceClient<led_msgs::SetLEDs>("set_leds", true);
|
||||
|
||||
// wait for leds count info
|
||||
handleState(*ros::topic::waitForMessage<led_msgs::LEDStateArray>("state", nh));
|
||||
|
||||
auto state_sub = nh.subscribe("state", 1, &handleState);
|
||||
|
||||
auto set_effect = nh.advertiseService("set_effect", &setEffect);
|
||||
|
||||
auto mavros_state_sub = nh.subscribe("/mavros/state", 1, &handleMavrosState);
|
||||
auto battery_sub = nh.subscribe("/mavros/battery", 1, &handleBattery);
|
||||
auto rosout_sub = nh.subscribe("/rosout_agg", 1, &handleLog);
|
||||
|
||||
timer = nh.createTimer(ros::Duration(0), &proceed, false, false);
|
||||
|
||||
ROS_INFO("ready");
|
||||
notify("startup");
|
||||
ros::spin();
|
||||
}
|
||||
@@ -80,7 +80,7 @@ private:
|
||||
flow_.distance = -1; // no distance sensor available
|
||||
flow_.temperature = 0;
|
||||
|
||||
ROS_INFO("Optical Flow initialized");
|
||||
NODELET_INFO("Optical Flow initialized");
|
||||
}
|
||||
|
||||
void parseCameraInfo(const sensor_msgs::CameraInfoConstPtr &cinfo) {
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
import math
|
||||
import subprocess
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
import traceback
|
||||
from threading import Event
|
||||
import numpy
|
||||
import rospy
|
||||
from systemd import journal
|
||||
import tf2_ros
|
||||
import tf2_geometry_msgs
|
||||
from pymavlink import mavutil
|
||||
from std_srvs.srv import Trigger
|
||||
from sensor_msgs.msg import Image, CameraInfo, NavSatFix, Imu, Range
|
||||
from sensor_msgs.msg import BatteryState, Image, CameraInfo, NavSatFix, Imu, Range
|
||||
from mavros_msgs.msg import State, OpticalFlowRad, Mavlink
|
||||
from mavros_msgs.srv import ParamGet
|
||||
from geometry_msgs.msg import PoseStamped, TwistStamped, PoseWithCovarianceStamped, Vector3Stamped
|
||||
@@ -209,7 +209,7 @@ def check_fcu():
|
||||
is_clever_firmware = True
|
||||
|
||||
if not is_clever_firmware:
|
||||
failure('not running Clever PX4 firmware, check http://clever.copterexpress.com/firmware.html')
|
||||
failure('not running Clever PX4 firmware, https://clever.coex.tech/firmware')
|
||||
|
||||
est = get_param('SYS_MC_EST_GROUP')
|
||||
if est == 1:
|
||||
@@ -236,6 +236,20 @@ def check_fcu():
|
||||
except KeyError:
|
||||
failure('unknown board rotation %s', rot)
|
||||
|
||||
cbrk_usb_chk = get_param('CBRK_USB_CHK')
|
||||
if cbrk_usb_chk != 197848:
|
||||
failure('Set parameter CBRK_USB_CHK to 197848 for flying with USB connected')
|
||||
|
||||
try:
|
||||
battery = rospy.wait_for_message('mavros/battery', BatteryState, timeout=3)
|
||||
cell = battery.cell_voltage[0]
|
||||
if cell > 4.3 or cell < 3.0:
|
||||
failure('Incorrect cell voltage: %.2f V, https://clever.coex.tech/power', cell)
|
||||
elif cell < 3.7:
|
||||
failure('Critically low cell voltage: %.2f V, recharge battery', cell)
|
||||
except rospy.ROSException:
|
||||
failure('no battery state')
|
||||
|
||||
except rospy.ROSException:
|
||||
failure('no MAVROS state (check wiring)')
|
||||
|
||||
@@ -463,7 +477,7 @@ def check_local_position():
|
||||
@check('Velocity estimation')
|
||||
def check_velocity():
|
||||
try:
|
||||
velocity = rospy.wait_for_message('mavros/local_position/velocity', TwistStamped, timeout=1)
|
||||
velocity = rospy.wait_for_message('mavros/local_position/velocity_local', TwistStamped, timeout=1)
|
||||
horiz = math.hypot(velocity.twist.linear.x, velocity.twist.linear.y)
|
||||
vert = velocity.twist.linear.z
|
||||
if abs(horiz) > 0.1:
|
||||
@@ -471,6 +485,7 @@ def check_velocity():
|
||||
if abs(vert) > 0.1:
|
||||
failure('vertical velocity estimation is %.2f m/s; is copter staying still?' % vert)
|
||||
|
||||
velocity = rospy.wait_for_message('mavros/local_position/velocity_body', TwistStamped, timeout=1)
|
||||
angular = velocity.twist.angular
|
||||
ANGULAR_VELOCITY_LIMIT = 0.1
|
||||
if abs(angular.x) > ANGULAR_VELOCITY_LIMIT:
|
||||
@@ -544,7 +559,7 @@ def check_rangefinder():
|
||||
# TODO: check FPS!
|
||||
rng = False
|
||||
try:
|
||||
rospy.wait_for_message('mavros/distance_sensor/rangefinder_sub', Range, timeout=4)
|
||||
rospy.wait_for_message('rangefinder/range', Range, timeout=4)
|
||||
rng = True
|
||||
except rospy.ROSException:
|
||||
failure('no rangefinder data from Raspberry')
|
||||
@@ -613,27 +628,33 @@ def check_clever_service():
|
||||
failure('systemctl returned %s: %s', e.returncode, e.output)
|
||||
return
|
||||
if 'inactive' in output:
|
||||
failure('clever.service is not running, try sudo systemctl restart clever')
|
||||
failure('service is not running, try sudo systemctl restart clever')
|
||||
return
|
||||
elif 'failed' in output:
|
||||
failure('service failed to run, check your launch-files')
|
||||
|
||||
j = journal.Reader()
|
||||
j.this_boot()
|
||||
j.add_match(_SYSTEMD_UNIT='clever.service')
|
||||
j.add_disjunction()
|
||||
j.add_match(UNIT='clever.service')
|
||||
node_errors = []
|
||||
r = re.compile(r'^(.*)\[(FATAL|ERROR)\] \[\d+.\d+\]: (.*)$')
|
||||
for event in j:
|
||||
msg = event['MESSAGE']
|
||||
if ('Stopped Clever ROS package' in msg) or ('Started Clever ROS package' in msg):
|
||||
node_errors = []
|
||||
elif ('[ERROR]' in msg) or ('[FATAL]' in msg):
|
||||
msg = r.search(msg).groups()[2]
|
||||
if msg in node_errors:
|
||||
continue
|
||||
node_errors.append(msg)
|
||||
for error in node_errors:
|
||||
failure(error)
|
||||
r = re.compile(r'^(.*)\[(FATAL|ERROR)\] \[\d+.\d+\]: (.*?)(\x1b(.*))?$')
|
||||
error_count = OrderedDict()
|
||||
try:
|
||||
for line in open('/tmp/clever.err', 'r'):
|
||||
node_error = r.search(line)
|
||||
if node_error:
|
||||
msg = node_error.groups()[1] + ': ' + node_error.groups()[2]
|
||||
if msg in error_count:
|
||||
error_count[msg] += 1
|
||||
else:
|
||||
error_count.update({msg: 1})
|
||||
else:
|
||||
error_count.update({line.strip(): 1})
|
||||
|
||||
for error in error_count:
|
||||
if error_count[error] == 1:
|
||||
failure(error)
|
||||
else:
|
||||
failure('%s (%d)', error, error_count[error])
|
||||
|
||||
except IOError as e:
|
||||
failure('%s', e)
|
||||
|
||||
|
||||
@check('Image')
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <tf2/utils.h>
|
||||
#include <tf2_ros/transform_listener.h>
|
||||
#include <tf2_ros/transform_broadcaster.h>
|
||||
#include <tf2_ros/static_transform_broadcaster.h>
|
||||
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
|
||||
#include <std_srvs/Trigger.h>
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
@@ -55,6 +56,7 @@ using mavros_msgs::Thrust;
|
||||
// tf2
|
||||
tf2_ros::Buffer tf_buffer;
|
||||
std::shared_ptr<tf2_ros::TransformBroadcaster> transform_broadcaster;
|
||||
std::shared_ptr<tf2_ros::StaticTransformBroadcaster> static_transform_broadcaster;
|
||||
|
||||
// Parameters
|
||||
string local_frame;
|
||||
@@ -71,7 +73,7 @@ ros::Duration global_position_timeout;
|
||||
ros::Duration battery_timeout;
|
||||
float default_speed;
|
||||
bool auto_release;
|
||||
bool land_only_in_offboard;
|
||||
bool land_only_in_offboard, nav_from_sp;
|
||||
std::map<string, string> reference_frames;
|
||||
|
||||
// Publishers
|
||||
@@ -100,6 +102,7 @@ float setpoint_yaw_rate;
|
||||
float nav_speed;
|
||||
bool busy = false;
|
||||
bool wait_armed = false;
|
||||
bool nav_from_sp_flag = false;
|
||||
|
||||
enum setpoint_type_t {
|
||||
NONE,
|
||||
@@ -130,6 +133,15 @@ void handleMessage(const T& msg)
|
||||
STORAGE = msg;
|
||||
}
|
||||
|
||||
void handleState(const mavros_msgs::State& s)
|
||||
{
|
||||
state = s;
|
||||
if (s.mode != "OFFBOARD") {
|
||||
// flight intercepted
|
||||
nav_from_sp_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void publishBodyFrame()
|
||||
{
|
||||
if (body.child_frame_id.empty()) return;
|
||||
@@ -214,7 +226,7 @@ bool getTelemetry(GetTelemetry::Request& req, GetTelemetry::Response& res)
|
||||
res.pitch = pitch;
|
||||
res.roll = roll;
|
||||
} catch (const tf2::TransformException& e) {
|
||||
ROS_DEBUG("simple_offboard: %s", e.what());
|
||||
ROS_DEBUG("%s", e.what());
|
||||
}
|
||||
|
||||
if (!TIMEOUT(velocity, velocity_timeout)) {
|
||||
@@ -261,7 +273,7 @@ void offboardAndArm()
|
||||
|
||||
if (state.mode != "OFFBOARD") {
|
||||
auto start = ros::Time::now();
|
||||
ROS_INFO("simple_offboard: switch to OFFBOARD");
|
||||
ROS_INFO("switch to OFFBOARD");
|
||||
static mavros_msgs::SetMode sm;
|
||||
sm.request.custom_mode = "OFFBOARD";
|
||||
|
||||
@@ -286,7 +298,7 @@ void offboardAndArm()
|
||||
|
||||
if (!state.armed) {
|
||||
ros::Time start = ros::Time::now();
|
||||
ROS_INFO("simple_offboard: arming");
|
||||
ROS_INFO("arming");
|
||||
mavros_msgs::CommandBool srv;
|
||||
srv.request.value = true;
|
||||
if (!arming.call(srv)) {
|
||||
@@ -386,18 +398,7 @@ void publish(const ros::Time stamp)
|
||||
}
|
||||
|
||||
} catch (const tf2::TransformException& e) {
|
||||
ROS_WARN_THROTTLE(10, "simple_offboard: can't transform");
|
||||
}
|
||||
|
||||
if (!target.child_frame_id.empty()) {
|
||||
if (setpoint_type == NAVIGATE || setpoint_type == NAVIGATE_GLOBAL || setpoint_type == POSITION) {
|
||||
target.header = setpoint_position_transformed.header;
|
||||
target.transform.translation.x = setpoint_position_transformed.pose.position.x;
|
||||
target.transform.translation.y = setpoint_position_transformed.pose.position.y;
|
||||
target.transform.translation.z = setpoint_position_transformed.pose.position.z;
|
||||
target.transform.rotation = setpoint_position_transformed.pose.orientation;
|
||||
transform_broadcaster->sendTransform(target);
|
||||
}
|
||||
ROS_WARN_THROTTLE(10, "can't transform");
|
||||
}
|
||||
|
||||
if (setpoint_type == NAVIGATE || setpoint_type == NAVIGATE_GLOBAL) {
|
||||
@@ -478,7 +479,7 @@ inline void checkState()
|
||||
throw std::runtime_error("State timeout, check mavros settings");
|
||||
|
||||
if (!state.connected)
|
||||
throw std::runtime_error("No connection to FCU, https://clever.copterexpress.com/connection.html");
|
||||
throw std::runtime_error("No connection to FCU, https://clever.coex.tech/connection");
|
||||
}
|
||||
|
||||
#define ENSURE_FINITE(var) { if (!std::isfinite(var)) throw std::runtime_error(#var " argument cannot be NaN or Inf"); }
|
||||
@@ -567,10 +568,20 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
|
||||
// Everything fine - switch setpoint type
|
||||
setpoint_type = sp_type;
|
||||
|
||||
if (sp_type != NAVIGATE && sp_type != NAVIGATE_GLOBAL) {
|
||||
nav_from_sp_flag = false;
|
||||
}
|
||||
|
||||
if (sp_type == NAVIGATE || sp_type == NAVIGATE_GLOBAL) {
|
||||
// starting point
|
||||
nav_start = local_position;
|
||||
if (nav_from_sp && nav_from_sp_flag) {
|
||||
message = "Navigating from current setpoint";
|
||||
nav_start = position_msg;
|
||||
} else {
|
||||
nav_start = local_position;
|
||||
}
|
||||
nav_speed = speed;
|
||||
nav_from_sp_flag = true;
|
||||
}
|
||||
|
||||
// if (sp_type == NAVIGATE || sp_type == NAVIGATE_GLOBAL || sp_type == POSITION || sp_type == VELOCITY) {
|
||||
@@ -632,6 +643,19 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
|
||||
publish(stamp); // calculate initial transformed messages first
|
||||
setpoint_timer.start();
|
||||
|
||||
// publish target frame
|
||||
if (!target.child_frame_id.empty()) {
|
||||
if (setpoint_type == NAVIGATE || setpoint_type == NAVIGATE_GLOBAL || setpoint_type == POSITION) {
|
||||
target.header.frame_id = setpoint_position.header.frame_id;
|
||||
target.header.stamp = stamp;
|
||||
target.transform.translation.x = setpoint_position.pose.position.x;
|
||||
target.transform.translation.y = setpoint_position.pose.position.y;
|
||||
target.transform.translation.z = setpoint_position.pose.position.z;
|
||||
target.transform.rotation = setpoint_position.pose.orientation;
|
||||
static_transform_broadcaster->sendTransform(target);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto_arm) {
|
||||
offboardAndArm();
|
||||
wait_armed = false;
|
||||
@@ -645,7 +669,7 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
message = e.what();
|
||||
ROS_INFO("simple_offboard: %s", message.c_str());
|
||||
ROS_INFO("%s", message.c_str());
|
||||
busy = false;
|
||||
return true;
|
||||
}
|
||||
@@ -721,7 +745,7 @@ bool land(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
res.message = e.what();
|
||||
ROS_INFO("simple_offboard: %s", e.what());
|
||||
ROS_INFO("%s", e.what());
|
||||
busy = false;
|
||||
return true;
|
||||
}
|
||||
@@ -734,6 +758,7 @@ int main(int argc, char **argv)
|
||||
|
||||
tf2_ros::TransformListener tf_listener(tf_buffer);
|
||||
transform_broadcaster = std::make_shared<tf2_ros::TransformBroadcaster>();
|
||||
static_transform_broadcaster = std::make_shared<tf2_ros::StaticTransformBroadcaster>();
|
||||
|
||||
// Params
|
||||
nh.param<string>("mavros/local_position/tf/frame_id", local_frame, "map");
|
||||
@@ -741,6 +766,7 @@ int main(int argc, char **argv)
|
||||
nh_priv.param("target_frame", target.child_frame_id, string("navigate_target"));
|
||||
nh_priv.param("auto_release", auto_release, true);
|
||||
nh_priv.param("land_only_in_offboard", land_only_in_offboard, true);
|
||||
nh_priv.param("nav_from_sp", nav_from_sp, true);
|
||||
nh_priv.param("default_speed", default_speed, 0.5f);
|
||||
nh_priv.param<string>("body_frame", body.child_frame_id, "body");
|
||||
nh_priv.getParam("reference_frames", reference_frames);
|
||||
@@ -762,7 +788,7 @@ int main(int argc, char **argv)
|
||||
set_mode = nh.serviceClient<mavros_msgs::SetMode>("mavros/set_mode");
|
||||
|
||||
// Telemetry subscribers
|
||||
auto state_sub = nh.subscribe("mavros/state", 1, &handleMessage<mavros_msgs::State, state>);
|
||||
auto state_sub = nh.subscribe("mavros/state", 1, &handleState);
|
||||
auto velocity_sub = nh.subscribe("mavros/local_position/velocity_body", 1, &handleMessage<TwistStamped, velocity>);
|
||||
auto global_position_sub = nh.subscribe("mavros/global_position/global", 1, &handleMessage<NavSatFix, global_position>);
|
||||
auto battery_sub = nh.subscribe("mavros/battery", 1, &handleMessage<BatteryState, battery>);
|
||||
@@ -795,6 +821,6 @@ int main(int argc, char **argv)
|
||||
position_raw_msg.coordinate_frame = PositionTarget::FRAME_LOCAL_NED;
|
||||
rates_msg.header.frame_id = fcu_frame;
|
||||
|
||||
ROS_INFO("simple_offboard: ready");
|
||||
ROS_INFO("ready");
|
||||
ros::spin();
|
||||
}
|
||||
|
||||
@@ -14,16 +14,21 @@
|
||||
#include <tf2/transform_datatypes.h>
|
||||
#include <tf2_ros/buffer.h>
|
||||
#include <tf2_ros/transform_listener.h>
|
||||
#include <tf2_ros/transform_broadcaster.h>
|
||||
#include <tf2_ros/static_transform_broadcaster.h>
|
||||
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
|
||||
#include <geometry_msgs/TransformStamped.h>
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
#include <geometry_msgs/PoseWithCovarianceStamped.h>
|
||||
#include <nav_msgs/Odometry.h>
|
||||
#include <std_srvs/Trigger.h>
|
||||
// #include <aruco_pose/MarkerArray.h>
|
||||
|
||||
using std::string;
|
||||
using namespace geometry_msgs;
|
||||
|
||||
bool use_tf;
|
||||
bool reset_flag = false;
|
||||
string local_frame_id, frame_id, child_frame_id, offset_frame_id;
|
||||
tf2_ros::Buffer tf_buffer;
|
||||
ros::Publisher vpe_pub;
|
||||
@@ -34,13 +39,35 @@ ros::Time got_local_pos(0);
|
||||
ros::Duration publish_zero_timout, publish_zero_duration, offset_timeout;
|
||||
TransformStamped offset;
|
||||
|
||||
inline geometry_msgs::TransformStamped poseToTransform(const geometry_msgs::PoseStamped& pose)
|
||||
{
|
||||
geometry_msgs::TransformStamped result;
|
||||
result.header.frame_id = pose.header.frame_id;
|
||||
result.header.stamp = pose.header.stamp;
|
||||
result.transform.translation.x = pose.pose.position.x;
|
||||
result.transform.translation.y = pose.pose.position.y;
|
||||
result.transform.translation.z = pose.pose.position.z;
|
||||
result.transform.rotation = pose.pose.orientation;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline geometry_msgs::Transform poseToTransform(const geometry_msgs::Pose& pose)
|
||||
{
|
||||
geometry_msgs::Transform result;
|
||||
result.translation.x = pose.position.x;
|
||||
result.translation.y = pose.position.y;
|
||||
result.translation.z = pose.position.z;
|
||||
result.rotation = pose.orientation;
|
||||
return result;
|
||||
}
|
||||
|
||||
void publishZero(const ros::TimerEvent& e)
|
||||
{
|
||||
if (e.current_real - vpe.header.stamp < publish_zero_timout) return; // have vpe
|
||||
|
||||
if (e.current_real - pose.header.stamp < publish_zero_timout) { // have local position
|
||||
if (got_local_pos.isZero()) {
|
||||
ROS_INFO("vpe_publisher: got local position");
|
||||
ROS_INFO("got local position");
|
||||
got_local_pos = e.current_real;
|
||||
}
|
||||
|
||||
@@ -50,7 +77,7 @@ void publishZero(const ros::TimerEvent& e)
|
||||
got_local_pos = ros::Time(0);
|
||||
}
|
||||
|
||||
ROS_INFO_THROTTLE(10, "vpe_publisher: publish zero");
|
||||
ROS_INFO_THROTTLE(10, "publish zero");
|
||||
static geometry_msgs::PoseStamped zero;
|
||||
zero.header.frame_id = local_frame_id;
|
||||
zero.header.stamp = e.current_real;
|
||||
@@ -64,68 +91,91 @@ inline Pose getPose(const PoseStampedConstPtr& pose) { return pose->pose; }
|
||||
|
||||
inline Pose getPose(const PoseWithCovarianceStampedConstPtr& pose) { return pose->pose.pose; }
|
||||
|
||||
inline Pose getPose(const nav_msgs::OdometryConstPtr& pose) { return pose->pose.pose; }
|
||||
|
||||
template <typename T>
|
||||
void callback(const T& msg)
|
||||
{
|
||||
static tf2_ros::StaticTransformBroadcaster br;
|
||||
|
||||
try {
|
||||
if (!frame_id.empty()) {
|
||||
// get VPE transform from TF
|
||||
auto transform = tf_buffer.lookupTransform(frame_id, child_frame_id,
|
||||
msg->header.stamp, ros::Duration(0.02));
|
||||
vpe.pose.position.x = transform.transform.translation.x;
|
||||
vpe.pose.position.y = transform.transform.translation.y;
|
||||
vpe.pose.position.z = transform.transform.translation.z;
|
||||
vpe.pose.orientation = transform.transform.rotation;
|
||||
} else {
|
||||
vpe.pose = getPose(msg);
|
||||
if (!use_tf) {
|
||||
// republish transform from pose for convenience
|
||||
static tf2_ros::TransformBroadcaster tr_br;
|
||||
tf2::Transform pose;
|
||||
tf2::fromMsg(poseToTransform(getPose(msg)), pose);
|
||||
pose = pose.inverse();
|
||||
TransformStamped transform;
|
||||
transform.transform = tf2::toMsg(pose);
|
||||
transform.header.stamp = msg->header.stamp;
|
||||
transform.header.frame_id = child_frame_id;
|
||||
transform.child_frame_id = frame_id;
|
||||
tr_br.sendTransform(transform);
|
||||
}
|
||||
|
||||
// get VPE transform from TF
|
||||
auto transform = tf_buffer.lookupTransform(frame_id, child_frame_id,
|
||||
msg->header.stamp, ros::Duration(0.02));
|
||||
vpe.pose.position.x = transform.transform.translation.x;
|
||||
vpe.pose.position.y = transform.transform.translation.y;
|
||||
vpe.pose.position.z = transform.transform.translation.z;
|
||||
vpe.pose.orientation = transform.transform.rotation;
|
||||
|
||||
// offset
|
||||
if (!offset_frame_id.empty()) {
|
||||
if (msg->header.stamp - vpe.header.stamp > offset_timeout) {
|
||||
if (reset_flag || msg->header.stamp - vpe.header.stamp > offset_timeout) {
|
||||
// calculate the offset
|
||||
offset = tf_buffer.lookupTransform(local_frame_id, frame_id,
|
||||
msg->header.stamp, ros::Duration(0.02));
|
||||
// offset.header.frame_id = vpe.header.frame_id;
|
||||
offset.child_frame_id = offset_frame_id;
|
||||
br.sendTransform(offset);
|
||||
ROS_INFO("vpe_publisher: offset reset");
|
||||
reset_flag = false;
|
||||
ROS_INFO("offset reset");
|
||||
}
|
||||
// apply the offset
|
||||
tf2::doTransform(vpe, vpe, offset);
|
||||
}
|
||||
|
||||
vpe.header.frame_id = local_frame_id;
|
||||
vpe.header.stamp = msg->header.stamp;
|
||||
vpe.header.stamp = ros::Time::now();//msg->header.stamp;
|
||||
vpe_pub.publish(vpe);
|
||||
|
||||
} catch (const tf2::TransformException& e) {
|
||||
ROS_WARN_THROTTLE(5, "vpe_publisher: %s", e.what());
|
||||
ROS_WARN_THROTTLE(5, "%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool reset(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
||||
{
|
||||
reset_flag = true;
|
||||
res.success = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ros::init(argc, argv, "vpe_publisher");
|
||||
ros::NodeHandle nh, nh_priv("~");
|
||||
|
||||
tf2_ros::TransformListener tf_listener(tf_buffer);
|
||||
|
||||
string base_link;
|
||||
nh_priv.param<string>("frame_id", frame_id, "");
|
||||
nh_priv.param<string>("offset_frame_id", offset_frame_id, "");
|
||||
nh_priv.param<string>("mavros/local_position/frame_id", local_frame_id, "map");
|
||||
nh_priv.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", base_link, "base_link");
|
||||
nh_priv.param<string>("child_frame_id", child_frame_id, base_link);
|
||||
offset_timeout = ros::Duration(nh_priv.param("offset_timeout", 3.0));
|
||||
|
||||
if (!frame_id.empty()) {
|
||||
ROS_INFO("vpe_publisher: using data from TF");
|
||||
if (use_tf) {
|
||||
ROS_INFO("using data from TF");
|
||||
} else {
|
||||
ROS_INFO("vpe_publisher: using data topic");
|
||||
ROS_INFO("using data topic");
|
||||
}
|
||||
|
||||
auto pose_sub = nh_priv.subscribe<PoseStamped>("pose", 1, &callback);
|
||||
auto pose_cov_sub = nh_priv.subscribe<PoseWithCovarianceStamped>("pose_cov", 1, &callback);
|
||||
auto odom_sub = nh_priv.subscribe<nav_msgs::Odometry>("odom", 1, &callback, ros::TransportHints().tcpNoDelay());
|
||||
//auto markers_sub = nh_priv.subscribe<aruco_pose::MarkerArray>("markers", 1, &callback);
|
||||
|
||||
vpe_pub = nh_priv.advertise<PoseStamped>("vpe", 1);
|
||||
@@ -139,6 +189,8 @@ int main(int argc, char **argv) {
|
||||
local_position_sub = nh.subscribe("mavros/local_position/pose", 1, &localPositionCallback);
|
||||
}
|
||||
|
||||
ROS_INFO("vpe_publisher: ready");
|
||||
auto reset_serv = nh_priv.advertiseService("reset", &reset);
|
||||
|
||||
ROS_INFO("ready");
|
||||
ros::spin();
|
||||
}
|
||||
|
||||
7
clever/srv/SetLEDEffect.srv
Normal file
@@ -0,0 +1,7 @@
|
||||
string effect
|
||||
uint8 r
|
||||
uint8 g
|
||||
uint8 b
|
||||
---
|
||||
bool success
|
||||
string message
|
||||
@@ -32,6 +32,10 @@
|
||||
|
||||
<node name="rc" pkg="clever" type="rc" required="true" output="screen"/>
|
||||
|
||||
<node pkg="clever" name="led_effect" type="led" ns="led" clear_params="true" output="screen" required="true">
|
||||
<rosparam param="notify">startup: { r: 255, g: 255, b: 255 }</rosparam>
|
||||
</node>
|
||||
|
||||
<param name="test_module" value="$(find clever)/test/basic.py"/>
|
||||
<test test-name="basic_test" pkg="ros_pytest" type="ros_pytest_runner"/>
|
||||
</launch>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h1>CLEVER Drone Kit Tools</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="docs">View documentation</a> (snapshot of <a href="http://clever.copterexpress.com">clever.copterexpress.com</a>)</li>
|
||||
<li><a href="docs">View documentation</a> (snapshot of <a href="https://clever.coex.tech">clever.coex.tech</a>)</li>
|
||||
<li><a href="" id="wvs">View image topics</a> (<code>web_video_server</code>)</li>
|
||||
<li><a href="" id="butterfly">Open web terminal</a> (<code>Butterfly</code>)</li>
|
||||
<li><a href="viz.html">View 3D visualization</a> (<code>ros3djs</code>)</li>
|
||||
|
||||
437
docs/LICENSE
Normal file
@@ -0,0 +1,437 @@
|
||||
Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
Public License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
||||
("Public License"). To the extent this Public License may be
|
||||
interpreted as a contract, You are granted the Licensed Rights in
|
||||
consideration of Your acceptance of these terms and conditions, and the
|
||||
Licensor grants You such rights in consideration of benefits the
|
||||
Licensor receives from making the Licensed Material available under
|
||||
these terms and conditions.
|
||||
|
||||
|
||||
Section 1 -- Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
|
||||
c. BY-NC-SA Compatible License means a license listed at
|
||||
creativecommons.org/compatiblelicenses, approved by Creative
|
||||
Commons as essentially the equivalent of this Public License.
|
||||
|
||||
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
|
||||
e. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
|
||||
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
|
||||
g. License Elements means the license attributes listed in the name
|
||||
of a Creative Commons Public License. The License Elements of this
|
||||
Public License are Attribution, NonCommercial, and ShareAlike.
|
||||
|
||||
h. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
|
||||
i. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
|
||||
k. NonCommercial means not primarily intended for or directed towards
|
||||
commercial advantage or monetary compensation. For purposes of
|
||||
this Public License, the exchange of the Licensed Material for
|
||||
other material subject to Copyright and Similar Rights by digital
|
||||
file-sharing or similar means is NonCommercial provided there is
|
||||
no payment of monetary compensation in connection with the
|
||||
exchange.
|
||||
|
||||
l. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
|
||||
m. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
|
||||
n. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
|
||||
|
||||
Section 2 -- Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part, for NonCommercial purposes only; and
|
||||
|
||||
b. produce, reproduce, and Share Adapted Material for
|
||||
NonCommercial purposes only.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
|
||||
b. Additional offer from the Licensor -- Adapted Material.
|
||||
Every recipient of Adapted Material from You
|
||||
automatically receives an offer from the Licensor to
|
||||
exercise the Licensed Rights in the Adapted Material
|
||||
under the conditions of the Adapter's License You apply.
|
||||
|
||||
c. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties, including when
|
||||
the Licensed Material is used other than for NonCommercial
|
||||
purposes.
|
||||
|
||||
|
||||
Section 3 -- License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
|
||||
b. ShareAlike.
|
||||
|
||||
In addition to the conditions in Section 3(a), if You Share
|
||||
Adapted Material You produce, the following conditions also apply.
|
||||
|
||||
1. The Adapter's License You apply must be a Creative Commons
|
||||
license with the same License Elements, this version or
|
||||
later, or a BY-NC-SA Compatible License.
|
||||
|
||||
2. You must include the text of, or the URI or hyperlink to, the
|
||||
Adapter's License You apply. You may satisfy this condition
|
||||
in any reasonable manner based on the medium, means, and
|
||||
context in which You Share Adapted Material.
|
||||
|
||||
3. You may not offer or impose any additional or different terms
|
||||
or conditions on, or apply any Effective Technological
|
||||
Measures to, Adapted Material that restrict exercise of the
|
||||
rights granted under the Adapter's License You apply.
|
||||
|
||||
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of the database for NonCommercial purposes
|
||||
only;
|
||||
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material,
|
||||
including for purposes of Section 3(b); and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
|
||||
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
|
||||
|
||||
Section 6 -- Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
|
||||
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
|
||||
|
||||
Section 8 -- Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
BIN
docs/assets/0.gif
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
docs/assets/4/01.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
docs/assets/4/02.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
docs/assets/4/03.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
docs/assets/4/03_1.png
Normal file
|
After Width: | Height: | Size: 254 KiB |
BIN
docs/assets/4/04.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
docs/assets/4/05.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
docs/assets/4/07.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
docs/assets/4/07_1.png
Normal file
|
After Width: | Height: | Size: 374 KiB |
BIN
docs/assets/4/08.png
Normal file
|
After Width: | Height: | Size: 452 KiB |
BIN
docs/assets/4/08_1.png
Normal file
|
After Width: | Height: | Size: 496 KiB |
BIN
docs/assets/4/09.png
Normal file
|
After Width: | Height: | Size: 491 KiB |
BIN
docs/assets/4/10.png
Normal file
|
After Width: | Height: | Size: 433 KiB |
BIN
docs/assets/4/10_1.png
Normal file
|
After Width: | Height: | Size: 496 KiB |
BIN
docs/assets/4/12_1.png
Normal file
|
After Width: | Height: | Size: 790 KiB |
BIN
docs/assets/4/13.png
Normal file
|
After Width: | Height: | Size: 365 KiB |
BIN
docs/assets/4/13_1.png
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
docs/assets/4/14.png
Normal file
|
After Width: | Height: | Size: 502 KiB |
BIN
docs/assets/4/15.png
Normal file
|
After Width: | Height: | Size: 513 KiB |
BIN
docs/assets/4/16.png
Normal file
|
After Width: | Height: | Size: 513 KiB |
BIN
docs/assets/4/18.png
Normal file
|
After Width: | Height: | Size: 577 KiB |
BIN
docs/assets/4/18_1.png
Normal file
|
After Width: | Height: | Size: 572 KiB |
BIN
docs/assets/4/19.png
Normal file
|
After Width: | Height: | Size: 463 KiB |
BIN
docs/assets/4/19_1.png
Normal file
|
After Width: | Height: | Size: 537 KiB |
BIN
docs/assets/4/20.png
Normal file
|
After Width: | Height: | Size: 709 KiB |
BIN
docs/assets/4/20_1.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
docs/assets/4/21.png
Normal file
|
After Width: | Height: | Size: 518 KiB |
BIN
docs/assets/4/21_1.png
Normal file
|
After Width: | Height: | Size: 524 KiB |
BIN
docs/assets/4/22.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
docs/assets/4/23.png
Normal file
|
After Width: | Height: | Size: 423 KiB |
BIN
docs/assets/4/24.png
Normal file
|
After Width: | Height: | Size: 474 KiB |
BIN
docs/assets/4/26.png
Normal file
|
After Width: | Height: | Size: 463 KiB |
BIN
docs/assets/4/26_1.png
Normal file
|
After Width: | Height: | Size: 812 KiB |
BIN
docs/assets/4/27.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/assets/4/27_1.png
Normal file
|
After Width: | Height: | Size: 378 KiB |
BIN
docs/assets/4/28.png
Normal file
|
After Width: | Height: | Size: 550 KiB |
BIN
docs/assets/4/31_1.png
Normal file
|
After Width: | Height: | Size: 523 KiB |
BIN
docs/assets/4/32.png
Normal file
|
After Width: | Height: | Size: 763 KiB |
BIN
docs/assets/4/33.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
docs/assets/4/33_1.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
docs/assets/4/34.png
Normal file
|
After Width: | Height: | Size: 223 KiB |
BIN
docs/assets/4/35.png
Normal file
|
After Width: | Height: | Size: 500 KiB |
BIN
docs/assets/4/36.png
Normal file
|
After Width: | Height: | Size: 792 KiB |
BIN
docs/assets/4/37.png
Normal file
|
After Width: | Height: | Size: 336 KiB |
BIN
docs/assets/4/38.png
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
docs/assets/4/39.png
Normal file
|
After Width: | Height: | Size: 610 KiB |
BIN
docs/assets/4/40.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
docs/assets/4/41.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
docs/assets/4/42.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
BIN
docs/assets/4/42_1.png
Normal file
|
After Width: | Height: | Size: 430 KiB |
BIN
docs/assets/4/47_1.png
Normal file
|
After Width: | Height: | Size: 678 KiB |
BIN
docs/assets/4/47_2.png
Normal file
|
After Width: | Height: | Size: 688 KiB |
BIN
docs/assets/4/48.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
docs/assets/4/49.png
Normal file
|
After Width: | Height: | Size: 448 KiB |
BIN
docs/assets/4/50.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
docs/assets/4/radio/base.png
Normal file
|
After Width: | Height: | Size: 408 KiB |
BIN
docs/assets/4/radio/binding.png
Normal file
|
After Width: | Height: | Size: 430 KiB |
BIN
docs/assets/CS.jpg
Normal file
|
After Width: | Height: | Size: 319 KiB |
@@ -1,562 +0,0 @@
|
||||
# Onboard parameters for Vehicle 1
|
||||
#
|
||||
# Stack: PX4 Pro
|
||||
# Vehicle: Multi-Rotor
|
||||
# Version: 1.7.3
|
||||
# Git Revision: 50bd148f53f1aeca
|
||||
#
|
||||
# Vehicle-Id Component-Id Name Value Type
|
||||
1 1 ATT_ACC_COMP 1 6
|
||||
1 1 ATT_BIAS_MAX 0.050000000745058060 9
|
||||
1 1 ATT_EXT_HDG_M 2 6
|
||||
1 1 ATT_MAG_DECL 0.000000000000000000 9
|
||||
1 1 ATT_MAG_DECL_A 1 6
|
||||
1 1 ATT_W_ACC 0.200000002980232239 9
|
||||
1 1 ATT_W_EXT_HDG 0.500000000000000000 9
|
||||
1 1 ATT_W_GYRO_BIAS 0.100000001490116119 9
|
||||
1 1 ATT_W_MAG 0.000000000000000000 9
|
||||
1 1 BAT_A_PER_V 36.367515563964843750 9
|
||||
1 1 BAT_CAPACITY -1.000000000000000000 9
|
||||
1 1 BAT_CNT_V_CURR 0.000805664050858468 9
|
||||
1 1 BAT_CNT_V_VOLT 0.000805664050858468 9
|
||||
1 1 BAT_CRIT_THR 0.070000000298023224 9
|
||||
1 1 BAT_EMERGEN_THR 0.050000000745058060 9
|
||||
1 1 BAT_LOW_THR 0.150000005960464478 9
|
||||
1 1 BAT_N_CELLS 3 6
|
||||
1 1 BAT_R_INTERNAL -1.000000000000000000 9
|
||||
1 1 BAT_SOURCE 0 6
|
||||
1 1 BAT_V_CHARGED 4.199999809265136719 9
|
||||
1 1 BAT_V_DIV 11.074123382568359375 9
|
||||
1 1 BAT_V_EMPTY 3.400000095367431641 9
|
||||
1 1 BAT_V_LOAD_DROP 0.300000011920928955 9
|
||||
1 1 BAT_V_OFFS_CURR 0.000000000000000000 9
|
||||
1 1 CAL_ACC0_EN 1 6
|
||||
1 1 CAL_ACC0_ID 3737098 6
|
||||
1 1 CAL_ACC0_XOFF -0.098434448242187500 9
|
||||
1 1 CAL_ACC0_XSCALE 0.997351467609405518 9
|
||||
1 1 CAL_ACC0_YOFF 1.317526340484619141 9
|
||||
1 1 CAL_ACC0_YSCALE 1.046252608299255371 9
|
||||
1 1 CAL_ACC0_ZOFF -0.126798629760742188 9
|
||||
1 1 CAL_ACC0_ZSCALE 1.000259757041931152 9
|
||||
1 1 CAL_ACC1_EN 1 6
|
||||
1 1 CAL_ACC1_ID 1442826 6
|
||||
1 1 CAL_ACC1_XOFF -0.081950664520263672 9
|
||||
1 1 CAL_ACC1_XSCALE 1.000148773193359375 9
|
||||
1 1 CAL_ACC1_YOFF 0.202856063842773438 9
|
||||
1 1 CAL_ACC1_YSCALE 0.997385859489440918 9
|
||||
1 1 CAL_ACC1_ZOFF 0.050376892089843750 9
|
||||
1 1 CAL_ACC1_ZSCALE 0.988558351993560791 9
|
||||
1 1 CAL_ACC2_XOFF 0.000000000000000000 9
|
||||
1 1 CAL_ACC2_XSCALE 1.000000000000000000 9
|
||||
1 1 CAL_ACC2_YOFF 0.000000000000000000 9
|
||||
1 1 CAL_ACC2_YSCALE 1.000000000000000000 9
|
||||
1 1 CAL_ACC2_ZOFF 0.000000000000000000 9
|
||||
1 1 CAL_ACC2_ZSCALE 1.000000000000000000 9
|
||||
1 1 CAL_ACC_PRIME 3737098 6
|
||||
1 1 CAL_AIR_CMODEL 0 6
|
||||
1 1 CAL_AIR_TUBED_MM 1.500000000000000000 9
|
||||
1 1 CAL_AIR_TUBELEN 0.200000002980232239 9
|
||||
1 1 CAL_BARO_PRIME 0 6
|
||||
1 1 CAL_GYRO0_EN 1 6
|
||||
1 1 CAL_GYRO0_ID 3802634 6
|
||||
1 1 CAL_GYRO0_XOFF -0.000510273908730596 9
|
||||
1 1 CAL_GYRO0_XSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO0_YOFF -0.002145451959222555 9
|
||||
1 1 CAL_GYRO0_YSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO0_ZOFF -0.005362632218748331 9
|
||||
1 1 CAL_GYRO0_ZSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO1_EN 1 6
|
||||
1 1 CAL_GYRO1_ID 2360330 6
|
||||
1 1 CAL_GYRO1_XOFF 0.011787598021328449 9
|
||||
1 1 CAL_GYRO1_XSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO1_YOFF -0.009070184081792831 9
|
||||
1 1 CAL_GYRO1_YSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO1_ZOFF 0.010833776555955410 9
|
||||
1 1 CAL_GYRO1_ZSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO2_XOFF 0.000000000000000000 9
|
||||
1 1 CAL_GYRO2_XSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO2_YOFF 0.000000000000000000 9
|
||||
1 1 CAL_GYRO2_YSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO2_ZOFF 0.000000000000000000 9
|
||||
1 1 CAL_GYRO2_ZSCALE 1.000000000000000000 9
|
||||
1 1 CAL_GYRO_PRIME 3802634 6
|
||||
1 1 CAL_MAG0_EN 1 6
|
||||
1 1 CAL_MAG0_ID 66826 6
|
||||
1 1 CAL_MAG0_ROT -1 6
|
||||
1 1 CAL_MAG0_XOFF -0.095534555613994598 9
|
||||
1 1 CAL_MAG0_XSCALE 1.375232458114624023 9
|
||||
1 1 CAL_MAG0_YOFF -0.516776323318481445 9
|
||||
1 1 CAL_MAG0_YSCALE 1.035408258438110352 9
|
||||
1 1 CAL_MAG0_ZOFF 0.725963234901428223 9
|
||||
1 1 CAL_MAG0_ZSCALE 0.721308171749114990 9
|
||||
1 1 CAL_MAG1_EN 1 6
|
||||
1 1 CAL_MAG1_ID 263178 6
|
||||
1 1 CAL_MAG1_ROT -1 6
|
||||
1 1 CAL_MAG1_XOFF -0.375689446926116943 9
|
||||
1 1 CAL_MAG1_XSCALE 1.188240885734558105 9
|
||||
1 1 CAL_MAG1_YOFF 0.270963609218597412 9
|
||||
1 1 CAL_MAG1_YSCALE 0.958104193210601807 9
|
||||
1 1 CAL_MAG1_ZOFF 0.543377697467803955 9
|
||||
1 1 CAL_MAG1_ZSCALE 0.874348759651184082 9
|
||||
1 1 CAL_MAG2_ID 0 6
|
||||
1 1 CAL_MAG2_ROT -1 6
|
||||
1 1 CAL_MAG2_XOFF 0.000000000000000000 9
|
||||
1 1 CAL_MAG2_XSCALE 1.000000000000000000 9
|
||||
1 1 CAL_MAG2_YOFF 0.000000000000000000 9
|
||||
1 1 CAL_MAG2_YSCALE 1.000000000000000000 9
|
||||
1 1 CAL_MAG2_ZOFF 0.000000000000000000 9
|
||||
1 1 CAL_MAG2_ZSCALE 1.000000000000000000 9
|
||||
1 1 CAL_MAG3_ID 0 6
|
||||
1 1 CAL_MAG3_ROT -1 6
|
||||
1 1 CAL_MAG3_XOFF 0.000000000000000000 9
|
||||
1 1 CAL_MAG3_XSCALE 1.000000000000000000 9
|
||||
1 1 CAL_MAG3_YOFF 0.000000000000000000 9
|
||||
1 1 CAL_MAG3_YSCALE 1.000000000000000000 9
|
||||
1 1 CAL_MAG3_ZOFF 0.000000000000000000 9
|
||||
1 1 CAL_MAG3_ZSCALE 1.000000000000000000 9
|
||||
1 1 CAL_MAG_PRIME 66826 6
|
||||
1 1 CAL_MAG_SIDES 63 6
|
||||
1 1 CBRK_AIRSPD_CHK 0 6
|
||||
1 1 CBRK_ENGINEFAIL 284953 6
|
||||
1 1 CBRK_FLIGHTTERM 121212 6
|
||||
1 1 CBRK_GPSFAIL 240024 6
|
||||
1 1 CBRK_IO_SAFETY 22027 6
|
||||
1 1 CBRK_RATE_CTRL 0 6
|
||||
1 1 CBRK_SUPPLY_CHK 0 6
|
||||
1 1 CBRK_USB_CHK 197848 6
|
||||
1 1 CBRK_VELPOSERR 0 6
|
||||
1 1 COM_ARM_AUTH 256010 6
|
||||
1 1 COM_ARM_EKF_AB 0.002400000113993883 9
|
||||
1 1 COM_ARM_EKF_GB 0.000869999988935888 9
|
||||
1 1 COM_ARM_EKF_HGT 1.000000000000000000 9
|
||||
1 1 COM_ARM_EKF_POS 0.500000000000000000 9
|
||||
1 1 COM_ARM_EKF_VEL 0.500000000000000000 9
|
||||
1 1 COM_ARM_EKF_YAW 0.500000000000000000 9
|
||||
1 1 COM_ARM_IMU_ACC 0.699999988079071045 9
|
||||
1 1 COM_ARM_IMU_GYR 0.250000000000000000 9
|
||||
1 1 COM_ARM_MAG 0.150000005960464478 9
|
||||
1 1 COM_ARM_MIS_REQ 0 6
|
||||
1 1 COM_ARM_SWISBTN 0 6
|
||||
1 1 COM_ARM_WO_GPS 1 6
|
||||
1 1 COM_DISARM_LAND 1 6
|
||||
1 1 COM_DL_LOSS_T 10 6
|
||||
1 1 COM_DL_REG_T 0 6
|
||||
1 1 COM_EF_C2T 5.000000000000000000 9
|
||||
1 1 COM_EF_THROT 0.500000000000000000 9
|
||||
1 1 COM_EF_TIME 10.000000000000000000 9
|
||||
1 1 COM_FLIGHT_UUID 182 6
|
||||
1 1 COM_FLTMODE1 8 6
|
||||
1 1 COM_FLTMODE2 1 6
|
||||
1 1 COM_FLTMODE3 2 6
|
||||
1 1 COM_FLTMODE4 -1 6
|
||||
1 1 COM_FLTMODE5 -1 6
|
||||
1 1 COM_FLTMODE6 -1 6
|
||||
1 1 COM_HOME_H_T 5.000000000000000000 9
|
||||
1 1 COM_HOME_V_T 10.000000000000000000 9
|
||||
1 1 COM_LOW_BAT_ACT 0 6
|
||||
1 1 COM_OBL_ACT 0 6
|
||||
1 1 COM_OBL_RC_ACT 0 6
|
||||
1 1 COM_OF_LOSS_T 0.000000000000000000 9
|
||||
1 1 COM_POSCTL_NAVL 0 6
|
||||
1 1 COM_POS_FS_DELAY 1 6
|
||||
1 1 COM_POS_FS_GAIN 10 6
|
||||
1 1 COM_POS_FS_PROB 30 6
|
||||
1 1 COM_RC_ARM_HYST 1000 6
|
||||
1 1 COM_RC_IN_MODE 0 6
|
||||
1 1 COM_RC_LOSS_T 0.500000000000000000 9
|
||||
1 1 COM_RC_OVERRIDE 0 6
|
||||
1 1 COM_RC_STICK_OV 12.000000000000000000 9
|
||||
1 1 COM_TAKEOFF_ACT 0 6
|
||||
1 1 FW_CLMBOUT_DIFF 10.000000000000000000 9
|
||||
1 1 GF_ACTION 1 6
|
||||
1 1 GF_ALTMODE 0 6
|
||||
1 1 GF_COUNT -1 6
|
||||
1 1 GF_MAX_HOR_DIST 0.000000000000000000 9
|
||||
1 1 GF_MAX_VER_DIST 0.000000000000000000 9
|
||||
1 1 GF_SOURCE 0 6
|
||||
1 1 GPS_DUMP_COMM 0 6
|
||||
1 1 GPS_UBX_DYNMODEL 7 6
|
||||
1 1 IMU_ACCEL_CUTOFF 30.000000000000000000 9
|
||||
1 1 IMU_GYRO_CUTOFF 30.000000000000000000 9
|
||||
1 1 LNDMC_ALT_MAX -1.000000000000000000 9
|
||||
1 1 LNDMC_FFALL_THR 2.000000000000000000 9
|
||||
1 1 LNDMC_FFALL_TTRI 0.300000011920928955 9
|
||||
1 1 LNDMC_ROT_MAX 45.000000000000000000 9
|
||||
1 1 LNDMC_THR_RANGE 0.500000000000000000 9
|
||||
1 1 LNDMC_XY_VEL_MAX 0.500000000000000000 9
|
||||
1 1 LNDMC_Z_VEL_MAX 1.000000000000000000 9
|
||||
1 1 LND_FLIGHT_T_HI 0 6
|
||||
1 1 LND_FLIGHT_T_LO -807089101 6
|
||||
1 1 LPE_ACC_XY 0.012000000104308128 9
|
||||
1 1 LPE_ACC_Z 0.019999999552965164 9
|
||||
1 1 LPE_BAR_Z 3.000000000000000000 9
|
||||
1 1 LPE_EPH_MAX 3.000000000000000000 9
|
||||
1 1 LPE_EPV_MAX 5.000000000000000000 9
|
||||
1 1 LPE_FAKE_ORIGIN 1 6
|
||||
1 1 LPE_FGYRO_HP 0.001000000047497451 9
|
||||
1 1 LPE_FLW_OFF_Z 0.000000000000000000 9
|
||||
1 1 LPE_FLW_QMIN 150 6
|
||||
1 1 LPE_FLW_R 7.000000000000000000 9
|
||||
1 1 LPE_FLW_RR 7.000000000000000000 9
|
||||
1 1 LPE_FLW_SCALE 1.299999952316284180 9
|
||||
1 1 LPE_FUSION 28 6
|
||||
1 1 LPE_GPS_DELAY 0.289999991655349731 9
|
||||
1 1 LPE_GPS_VXY 0.250000000000000000 9
|
||||
1 1 LPE_GPS_VZ 0.250000000000000000 9
|
||||
1 1 LPE_GPS_XY 1.000000000000000000 9
|
||||
1 1 LPE_GPS_Z 3.000000000000000000 9
|
||||
1 1 LPE_LAND_VXY 0.050000000745058060 9
|
||||
1 1 LPE_LAND_Z 0.029999999329447746 9
|
||||
1 1 LPE_LAT 47.397743225097656250 9
|
||||
1 1 LPE_LDR_OFF_Z 0.000000000000000000 9
|
||||
1 1 LPE_LDR_Z 0.029999999329447746 9
|
||||
1 1 LPE_LON 8.545594215393066406 9
|
||||
1 1 LPE_PN_B 0.001000000047497451 9
|
||||
1 1 LPE_PN_P 0.100000001490116119 9
|
||||
1 1 LPE_PN_T 0.001000000047497451 9
|
||||
1 1 LPE_PN_V 0.100000001490116119 9
|
||||
1 1 LPE_SNR_OFF_Z 0.000000000000000000 9
|
||||
1 1 LPE_SNR_Z 0.050000000745058060 9
|
||||
1 1 LPE_T_MAX_GRADE 1.000000000000000000 9
|
||||
1 1 LPE_VIC_P 0.001000000047497451 9
|
||||
1 1 LPE_VIS_DELAY 0.000000000000000000 9
|
||||
1 1 LPE_VIS_XY 0.100000001490116119 9
|
||||
1 1 LPE_VIS_Z 0.150000005960464478 9
|
||||
1 1 LPE_VXY_PUB 0.300000011920928955 9
|
||||
1 1 LPE_X_LP 5.000000000000000000 9
|
||||
1 1 LPE_Z_PUB 1.000000000000000000 9
|
||||
1 1 MAV_BROADCAST 0 6
|
||||
1 1 MAV_COMP_ID 1 6
|
||||
1 1 MAV_FWDEXTSP 1 6
|
||||
1 1 MAV_PROTO_VER 0 6
|
||||
1 1 MAV_RADIO_ID 0 6
|
||||
1 1 MAV_SYS_ID 1 6
|
||||
1 1 MAV_TEST_PAR 1 6
|
||||
1 1 MAV_TYPE 2 6
|
||||
1 1 MAV_USEHILGPS 0 6
|
||||
1 1 MC_ACRO_EXPO 0.689999997615814209 9
|
||||
1 1 MC_ACRO_P_MAX 720.000000000000000000 9
|
||||
1 1 MC_ACRO_R_MAX 720.000000000000000000 9
|
||||
1 1 MC_ACRO_SUPEXPO 0.699999988079071045 9
|
||||
1 1 MC_ACRO_Y_MAX 540.000000000000000000 9
|
||||
1 1 MC_BAT_SCALE_EN 0 6
|
||||
1 1 MC_PITCHRATE_D 0.003000000026077032 9
|
||||
1 1 MC_PITCHRATE_FF 0.000000000000000000 9
|
||||
1 1 MC_PITCHRATE_I 0.050000000745058060 9
|
||||
1 1 MC_PITCHRATE_MAX 220.000000000000000000 9
|
||||
1 1 MC_PITCHRATE_P 0.150000005960464478 9
|
||||
1 1 MC_PITCH_P 4.500000000000000000 9
|
||||
1 1 MC_PITCH_TC 0.250000000000000000 9
|
||||
1 1 MC_PR_INT_LIM 0.300000011920928955 9
|
||||
1 1 MC_RATT_TH 0.800000011920928955 9
|
||||
1 1 MC_ROLLRATE_D 0.003000000026077032 9
|
||||
1 1 MC_ROLLRATE_FF 0.000000000000000000 9
|
||||
1 1 MC_ROLLRATE_I 0.050000000745058060 9
|
||||
1 1 MC_ROLLRATE_MAX 220.000000000000000000 9
|
||||
1 1 MC_ROLLRATE_P 0.150000005960464478 9
|
||||
1 1 MC_ROLL_P 4.500000000000000000 9
|
||||
1 1 MC_ROLL_TC 0.250000000000000000 9
|
||||
1 1 MC_RR_INT_LIM 0.300000011920928955 9
|
||||
1 1 MC_TPA_BREAK_D 1.000000000000000000 9
|
||||
1 1 MC_TPA_BREAK_I 1.000000000000000000 9
|
||||
1 1 MC_TPA_BREAK_P 1.000000000000000000 9
|
||||
1 1 MC_TPA_RATE_D 0.000000000000000000 9
|
||||
1 1 MC_TPA_RATE_I 0.000000000000000000 9
|
||||
1 1 MC_TPA_RATE_P 0.000000000000000000 9
|
||||
1 1 MC_YAWRATE_D 0.000000000000000000 9
|
||||
1 1 MC_YAWRATE_FF 0.000000000000000000 9
|
||||
1 1 MC_YAWRATE_I 0.100000001490116119 9
|
||||
1 1 MC_YAWRATE_MAX 200.000000000000000000 9
|
||||
1 1 MC_YAWRATE_P 0.200000002980232239 9
|
||||
1 1 MC_YAWRAUTO_MAX 45.000000000000000000 9
|
||||
1 1 MC_YAW_FF 0.500000000000000000 9
|
||||
1 1 MC_YAW_P 4.800000190734863281 9
|
||||
1 1 MC_YR_INT_LIM 0.300000011920928955 9
|
||||
1 1 MIS_ALTMODE 1 6
|
||||
1 1 MIS_DIST_1WP 900.000000000000000000 9
|
||||
1 1 MIS_DIST_WPS 900.000000000000000000 9
|
||||
1 1 MIS_LTRMIN_ALT -1.000000000000000000 9
|
||||
1 1 MIS_ONBOARD_EN 1 6
|
||||
1 1 MIS_TAKEOFF_ALT 2.500000000000000000 9
|
||||
1 1 MIS_YAWMODE 1 6
|
||||
1 1 MIS_YAW_ERR 12.000000000000000000 9
|
||||
1 1 MIS_YAW_TMT -1.000000000000000000 9
|
||||
1 1 MNT_MODE_IN -1 6
|
||||
1 1 MOT_SLEW_MAX 0.000000000000000000 9
|
||||
1 1 MPC_ACC_DOWN_MAX 10.000000000000000000 9
|
||||
1 1 MPC_ACC_HOR 5.000000000000000000 9
|
||||
1 1 MPC_ACC_HOR_MAX 10.000000000000000000 9
|
||||
1 1 MPC_ACC_UP_MAX 10.000000000000000000 9
|
||||
1 1 MPC_ALT_MODE 0 6
|
||||
1 1 MPC_CRUISE_90 3.000000000000000000 9
|
||||
1 1 MPC_DEC_HOR_SLOW 5.000000000000000000 9
|
||||
1 1 MPC_HOLD_DZ 0.100000001490116119 9
|
||||
1 1 MPC_HOLD_MAX_XY 0.800000011920928955 9
|
||||
1 1 MPC_HOLD_MAX_Z 0.600000023841857910 9
|
||||
1 1 MPC_JERK_MAX 0.000000000000000000 9
|
||||
1 1 MPC_JERK_MIN 1.000000000000000000 9
|
||||
1 1 MPC_LAND_ALT1 10.000000000000000000 9
|
||||
1 1 MPC_LAND_ALT2 5.000000000000000000 9
|
||||
1 1 MPC_LAND_SPEED 0.699999988079071045 9
|
||||
1 1 MPC_MANTHR_MAX 0.899999976158142090 9
|
||||
1 1 MPC_MANTHR_MIN 0.079999998211860657 9
|
||||
1 1 MPC_MAN_TILT_MAX 35.000000000000000000 9
|
||||
1 1 MPC_MAN_Y_MAX 200.000000000000000000 9
|
||||
1 1 MPC_THR_HOVER 0.500000000000000000 9
|
||||
1 1 MPC_THR_MAX 0.899999976158142090 9
|
||||
1 1 MPC_THR_MIN 0.119999997317790985 9
|
||||
1 1 MPC_TILTMAX_AIR 45.000000000000000000 9
|
||||
1 1 MPC_TILTMAX_LND 12.000000000000000000 9
|
||||
1 1 MPC_TKO_RAMP_T 0.400000005960464478 9
|
||||
1 1 MPC_TKO_SPEED 1.500000000000000000 9
|
||||
1 1 MPC_VELD_LP 5.000000000000000000 9
|
||||
1 1 MPC_VEL_MANUAL 10.000000000000000000 9
|
||||
1 1 MPC_XY_CRUISE 5.000000000000000000 9
|
||||
1 1 MPC_XY_MAN_EXPO 0.000000000000000000 9
|
||||
1 1 MPC_XY_P 0.949999988079071045 9
|
||||
1 1 MPC_XY_VEL_D 0.009999999776482582 9
|
||||
1 1 MPC_XY_VEL_I 0.019999999552965164 9
|
||||
1 1 MPC_XY_VEL_MAX 3.000000000000000000 9
|
||||
1 1 MPC_XY_VEL_P 0.150000005960464478 9
|
||||
1 1 MPC_Z_MAN_EXPO 0.000000000000000000 9
|
||||
1 1 MPC_Z_P 1.000000000000000000 9
|
||||
1 1 MPC_Z_VEL_D 0.000000000000000000 9
|
||||
1 1 MPC_Z_VEL_I 0.019999999552965164 9
|
||||
1 1 MPC_Z_VEL_MAX_DN 1.000000000000000000 9
|
||||
1 1 MPC_Z_VEL_MAX_UP 1.000000000000000000 9
|
||||
1 1 MPC_Z_VEL_P 0.200000002980232239 9
|
||||
1 1 NAV_ACC_RAD 2.000000000000000000 9
|
||||
1 1 NAV_AH_ALT 600.000000000000000000 9
|
||||
1 1 NAV_AH_LAT -265847810 6
|
||||
1 1 NAV_AH_LON 1518423250 6
|
||||
1 1 NAV_DLL_ACT 0 6
|
||||
1 1 NAV_DLL_AH_T 120.000000000000000000 9
|
||||
1 1 NAV_DLL_CHSK 0 6
|
||||
1 1 NAV_DLL_CH_ALT 600.000000000000000000 9
|
||||
1 1 NAV_DLL_CH_LAT -266072120 6
|
||||
1 1 NAV_DLL_CH_LON 1518453890 6
|
||||
1 1 NAV_DLL_CH_T 120.000000000000000000 9
|
||||
1 1 NAV_DLL_N 2 6
|
||||
1 1 NAV_FORCE_VT 1 6
|
||||
1 1 NAV_FT_DST 8.000000000000000000 9
|
||||
1 1 NAV_FT_FS 1 6
|
||||
1 1 NAV_FT_RS 0.500000000000000000 9
|
||||
1 1 NAV_FW_ALT_RAD 10.000000000000000000 9
|
||||
1 1 NAV_GPSF_LT 0.000000000000000000 9
|
||||
1 1 NAV_GPSF_P 0.000000000000000000 9
|
||||
1 1 NAV_GPSF_R 15.000000000000000000 9
|
||||
1 1 NAV_GPSF_TR 0.000000000000000000 9
|
||||
1 1 NAV_LOITER_RAD 50.000000000000000000 9
|
||||
1 1 NAV_MC_ALT_RAD 0.800000011920928955 9
|
||||
1 1 NAV_MIN_FT_HT 8.000000000000000000 9
|
||||
1 1 NAV_RCL_ACT 0 6
|
||||
1 1 NAV_RCL_LT 120.000000000000000000 9
|
||||
1 1 NAV_TRAFF_AVOID 1 6
|
||||
1 1 PWM_AUX_DISARMED 1500 6
|
||||
1 1 PWM_AUX_MAX 2000 6
|
||||
1 1 PWM_AUX_MIN 1000 6
|
||||
1 1 PWM_AUX_REV1 0 6
|
||||
1 1 PWM_AUX_REV2 0 6
|
||||
1 1 PWM_AUX_REV3 0 6
|
||||
1 1 PWM_AUX_REV4 0 6
|
||||
1 1 PWM_AUX_REV5 0 6
|
||||
1 1 PWM_AUX_REV6 0 6
|
||||
1 1 PWM_AUX_TRIM1 0.000000000000000000 9
|
||||
1 1 PWM_AUX_TRIM2 0.000000000000000000 9
|
||||
1 1 PWM_AUX_TRIM3 0.000000000000000000 9
|
||||
1 1 PWM_AUX_TRIM4 0.000000000000000000 9
|
||||
1 1 PWM_AUX_TRIM5 0.000000000000000000 9
|
||||
1 1 PWM_AUX_TRIM6 0.000000000000000000 9
|
||||
1 1 PWM_DISARMED 950 6
|
||||
1 1 PWM_MAIN_DIS1 -1 6
|
||||
1 1 PWM_MAIN_DIS2 -1 6
|
||||
1 1 PWM_MAIN_DIS3 -1 6
|
||||
1 1 PWM_MAIN_DIS4 -1 6
|
||||
1 1 PWM_MAIN_DIS5 -1 6
|
||||
1 1 PWM_MAIN_DIS6 -1 6
|
||||
1 1 PWM_MAIN_DIS7 -1 6
|
||||
1 1 PWM_MAIN_DIS8 -1 6
|
||||
1 1 PWM_MAX 1950 6
|
||||
1 1 PWM_MIN 1075 6
|
||||
1 1 PWM_RATE 490 6
|
||||
1 1 RC10_DZ 0.000000000000000000 9
|
||||
1 1 RC10_MAX 2000.000000000000000000 9
|
||||
1 1 RC10_MIN 1000.000000000000000000 9
|
||||
1 1 RC10_REV 1.000000000000000000 9
|
||||
1 1 RC10_TRIM 1500.000000000000000000 9
|
||||
1 1 RC11_DZ 0.000000000000000000 9
|
||||
1 1 RC11_MAX 2000.000000000000000000 9
|
||||
1 1 RC11_MIN 1000.000000000000000000 9
|
||||
1 1 RC11_REV 1.000000000000000000 9
|
||||
1 1 RC11_TRIM 1500.000000000000000000 9
|
||||
1 1 RC12_DZ 0.000000000000000000 9
|
||||
1 1 RC12_MAX 2000.000000000000000000 9
|
||||
1 1 RC12_MIN 1000.000000000000000000 9
|
||||
1 1 RC12_REV 1.000000000000000000 9
|
||||
1 1 RC12_TRIM 1500.000000000000000000 9
|
||||
1 1 RC13_DZ 0.000000000000000000 9
|
||||
1 1 RC13_MAX 2000.000000000000000000 9
|
||||
1 1 RC13_MIN 1000.000000000000000000 9
|
||||
1 1 RC13_REV 1.000000000000000000 9
|
||||
1 1 RC13_TRIM 1500.000000000000000000 9
|
||||
1 1 RC14_DZ 0.000000000000000000 9
|
||||
1 1 RC14_MAX 2000.000000000000000000 9
|
||||
1 1 RC14_MIN 1000.000000000000000000 9
|
||||
1 1 RC14_REV 1.000000000000000000 9
|
||||
1 1 RC14_TRIM 1500.000000000000000000 9
|
||||
1 1 RC15_DZ 0.000000000000000000 9
|
||||
1 1 RC15_MAX 2000.000000000000000000 9
|
||||
1 1 RC15_MIN 1000.000000000000000000 9
|
||||
1 1 RC15_REV 1.000000000000000000 9
|
||||
1 1 RC15_TRIM 1500.000000000000000000 9
|
||||
1 1 RC16_DZ 0.000000000000000000 9
|
||||
1 1 RC16_MAX 2000.000000000000000000 9
|
||||
1 1 RC16_MIN 1000.000000000000000000 9
|
||||
1 1 RC16_REV 1.000000000000000000 9
|
||||
1 1 RC16_TRIM 1500.000000000000000000 9
|
||||
1 1 RC17_DZ 0.000000000000000000 9
|
||||
1 1 RC17_MAX 2000.000000000000000000 9
|
||||
1 1 RC17_MIN 1000.000000000000000000 9
|
||||
1 1 RC17_REV 1.000000000000000000 9
|
||||
1 1 RC17_TRIM 1500.000000000000000000 9
|
||||
1 1 RC18_DZ 0.000000000000000000 9
|
||||
1 1 RC18_MAX 2000.000000000000000000 9
|
||||
1 1 RC18_MIN 1000.000000000000000000 9
|
||||
1 1 RC18_REV 1.000000000000000000 9
|
||||
1 1 RC18_TRIM 1500.000000000000000000 9
|
||||
1 1 RC1_DZ 10.000000000000000000 9
|
||||
1 1 RC1_MAX 1993.000000000000000000 9
|
||||
1 1 RC1_MIN 1012.000000000000000000 9
|
||||
1 1 RC1_REV 1.000000000000000000 9
|
||||
1 1 RC1_TRIM 1475.000000000000000000 9
|
||||
1 1 RC2_DZ 10.000000000000000000 9
|
||||
1 1 RC2_MAX 1993.000000000000000000 9
|
||||
1 1 RC2_MIN 995.000000000000000000 9
|
||||
1 1 RC2_REV 1.000000000000000000 9
|
||||
1 1 RC2_TRIM 1493.000000000000000000 9
|
||||
1 1 RC3_DZ 10.000000000000000000 9
|
||||
1 1 RC3_MAX 1993.000000000000000000 9
|
||||
1 1 RC3_MIN 995.000000000000000000 9
|
||||
1 1 RC3_REV 1.000000000000000000 9
|
||||
1 1 RC3_TRIM 995.000000000000000000 9
|
||||
1 1 RC4_DZ 10.000000000000000000 9
|
||||
1 1 RC4_MAX 1993.000000000000000000 9
|
||||
1 1 RC4_MIN 995.000000000000000000 9
|
||||
1 1 RC4_REV 1.000000000000000000 9
|
||||
1 1 RC4_TRIM 1494.000000000000000000 9
|
||||
1 1 RC5_DZ 10.000000000000000000 9
|
||||
1 1 RC5_MAX 1993.000000000000000000 9
|
||||
1 1 RC5_MIN 995.000000000000000000 9
|
||||
1 1 RC5_REV 1.000000000000000000 9
|
||||
1 1 RC5_TRIM 1494.000000000000000000 9
|
||||
1 1 RC6_DZ 10.000000000000000000 9
|
||||
1 1 RC6_MAX 1993.000000000000000000 9
|
||||
1 1 RC6_MIN 995.000000000000000000 9
|
||||
1 1 RC6_REV 1.000000000000000000 9
|
||||
1 1 RC6_TRIM 1494.000000000000000000 9
|
||||
1 1 RC7_DZ 10.000000000000000000 9
|
||||
1 1 RC7_MAX 2000.000000000000000000 9
|
||||
1 1 RC7_MIN 1000.000000000000000000 9
|
||||
1 1 RC7_REV 1.000000000000000000 9
|
||||
1 1 RC7_TRIM 1500.000000000000000000 9
|
||||
1 1 RC8_DZ 10.000000000000000000 9
|
||||
1 1 RC8_MAX 2000.000000000000000000 9
|
||||
1 1 RC8_MIN 1000.000000000000000000 9
|
||||
1 1 RC8_REV 1.000000000000000000 9
|
||||
1 1 RC8_TRIM 1500.000000000000000000 9
|
||||
1 1 RC9_DZ 0.000000000000000000 9
|
||||
1 1 RC9_MAX 2000.000000000000000000 9
|
||||
1 1 RC9_MIN 1000.000000000000000000 9
|
||||
1 1 RC9_REV 1.000000000000000000 9
|
||||
1 1 RC9_TRIM 1500.000000000000000000 9
|
||||
1 1 RC_ACRO_TH 0.500000000000000000 9
|
||||
1 1 RC_ARMSWITCH_TH 0.250000000000000000 9
|
||||
1 1 RC_ASSIST_TH 0.250000000000000000 9
|
||||
1 1 RC_AUTO_TH 0.750000000000000000 9
|
||||
1 1 RC_CHAN_CNT 18 6
|
||||
1 1 RC_FAILS_THR 0 6
|
||||
1 1 RC_FLT_CUTOFF 10.000000000000000000 9
|
||||
1 1 RC_FLT_SMP_RATE 50.000000000000000000 9
|
||||
1 1 RC_GEAR_TH 0.250000000000000000 9
|
||||
1 1 RC_KILLSWITCH_TH 0.250000000000000000 9
|
||||
1 1 RC_LOITER_TH 0.500000000000000000 9
|
||||
1 1 RC_MAN_TH 0.500000000000000000 9
|
||||
1 1 RC_MAP_ACRO_SW 0 6
|
||||
1 1 RC_MAP_ARM_SW 0 6
|
||||
1 1 RC_MAP_AUX1 0 6
|
||||
1 1 RC_MAP_AUX2 0 6
|
||||
1 1 RC_MAP_AUX3 0 6
|
||||
1 1 RC_MAP_AUX4 0 6
|
||||
1 1 RC_MAP_AUX5 0 6
|
||||
1 1 RC_MAP_FAILSAFE 0 6
|
||||
1 1 RC_MAP_FLAPS 0 6
|
||||
1 1 RC_MAP_FLTMODE 5 6
|
||||
1 1 RC_MAP_GEAR_SW 0 6
|
||||
1 1 RC_MAP_KILL_SW 0 6
|
||||
1 1 RC_MAP_LOITER_SW 0 6
|
||||
1 1 RC_MAP_MAN_SW 0 6
|
||||
1 1 RC_MAP_MODE_SW 0 6
|
||||
1 1 RC_MAP_OFFB_SW 0 6
|
||||
1 1 RC_MAP_PARAM1 0 6
|
||||
1 1 RC_MAP_PARAM2 0 6
|
||||
1 1 RC_MAP_PARAM3 0 6
|
||||
1 1 RC_MAP_PITCH 2 6
|
||||
1 1 RC_MAP_POSCTL_SW 0 6
|
||||
1 1 RC_MAP_RATT_SW 0 6
|
||||
1 1 RC_MAP_RETURN_SW 0 6
|
||||
1 1 RC_MAP_ROLL 1 6
|
||||
1 1 RC_MAP_STAB_SW 0 6
|
||||
1 1 RC_MAP_THROTTLE 3 6
|
||||
1 1 RC_MAP_TRANS_SW 0 6
|
||||
1 1 RC_MAP_YAW 4 6
|
||||
1 1 RC_OFFB_TH 0.500000000000000000 9
|
||||
1 1 RC_POSCTL_TH 0.500000000000000000 9
|
||||
1 1 RC_RATT_TH 0.500000000000000000 9
|
||||
1 1 RC_RETURN_TH 0.500000000000000000 9
|
||||
1 1 RC_STAB_TH 0.500000000000000000 9
|
||||
1 1 RC_TRANS_TH 0.250000000000000000 9
|
||||
1 1 RTL_DESCEND_ALT 10.000000000000000000 9
|
||||
1 1 RTL_LAND_DELAY 0.000000000000000000 9
|
||||
1 1 RTL_LAND_TYPE 0 6
|
||||
1 1 RTL_MIN_DIST 5.000000000000000000 9
|
||||
1 1 RTL_RETURN_ALT 30.000000000000000000 9
|
||||
1 1 SDLOG_DIRS_MAX 0 6
|
||||
1 1 SDLOG_MODE 0 6
|
||||
1 1 SDLOG_PROFILE 3 6
|
||||
1 1 SDLOG_UTC_OFFSET 0 6
|
||||
1 1 SENS_BARO_QNH 1013.250000000000000000 9
|
||||
1 1 SENS_BOARD_ROT 0 6
|
||||
1 1 SENS_BOARD_X_OFF -0.288025468587875366 9
|
||||
1 1 SENS_BOARD_Y_OFF -0.865298211574554443 9
|
||||
1 1 SENS_BOARD_Z_OFF 0.000000000000000000 9
|
||||
1 1 SENS_DPRES_OFF 0.000000000000000000 9
|
||||
1 1 SENS_EN_LL40LS 0 6
|
||||
1 1 SENS_EN_MB12XX 0 6
|
||||
1 1 SENS_EN_SF0X 0 6
|
||||
1 1 SENS_EN_SF1XX 0 6
|
||||
1 1 SENS_EN_TFMINI 0 6
|
||||
1 1 SENS_EN_TRANGER 0 6
|
||||
1 1 SYS_AUTOCONFIG 0 6
|
||||
1 1 SYS_AUTOSTART 4001 6
|
||||
1 1 SYS_CAL_ACCEL 0 6
|
||||
1 1 SYS_CAL_BARO 0 6
|
||||
1 1 SYS_CAL_GYRO 0 6
|
||||
1 1 SYS_CAL_TDEL 24 6
|
||||
1 1 SYS_CAL_TMAX 10 6
|
||||
1 1 SYS_CAL_TMIN 5 6
|
||||
1 1 SYS_COMPANION 157600 6
|
||||
1 1 SYS_FMU_TASK 1 6
|
||||
1 1 SYS_HITL 0 6
|
||||
1 1 SYS_LOGGER 1 6
|
||||
1 1 SYS_MC_EST_GROUP 1 6
|
||||
1 1 SYS_PARAM_VER 1 6
|
||||
1 1 SYS_RESTART_TYPE 2 6
|
||||
1 1 SYS_STCK_EN 1 6
|
||||
1 1 TC_A_ENABLE 0 6
|
||||
1 1 TC_B_ENABLE 0 6
|
||||
1 1 TC_G_ENABLE 0 6
|
||||
1 1 THR_MDL_FAC 0.000000000000000000 9
|
||||
1 1 TRIG_MODE 0 6
|
||||
1 1 UAVCAN_ENABLE 0 6
|
||||
1 1 VT_B_DEC_MSS 2.000000000000000000 9
|
||||
1 1 VT_B_REV_DEL 0.000000000000000000 9
|
||||
|
Before Width: | Height: | Size: 18 KiB |
BIN
docs/assets/TrainerCable_Pinout.jpg
Normal file
|
After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 174 KiB |
0
docs/assets/appstore.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |