Compare commits

...

108 Commits

Author SHA1 Message Date
Oleg Kalachev
f2820471bc mavros.launch: blacklisted wind_estimation plugin 2018-09-19 03:06:29 +03:00
Oleg Kalachev
fb7885ada2 optical flow: get fcu frame id from mavros params 2018-09-19 02:58:33 +03:00
Oleg Kalachev
f9f4dc5a92 simple_offboard: minor optimization 2018-09-19 02:56:59 +03:00
Oleg Kalachev
ffe4f562cc Code style 2018-09-19 02:53:16 +03:00
Oleg Kalachev
a906428734 image: add ROS packages for interactive markers 2018-09-19 01:42:08 +03:00
Oleg Kalachev
abc7e6fec1 Little fix 2018-09-19 01:30:51 +03:00
Oleg Kalachev
3b01cf3782 Experimental node for controlling the copter with rviz interactive markers 2018-09-19 00:13:11 +03:00
Oleg Kalachev
53d616fb16 image: add compressed_image_transport plugin 2018-09-18 04:39:27 +03:00
Oleg Kalachev
8168c1f201 docs: type 2018-09-17 19:57:44 +03:00
Oleg Kalachev
a0e1e032d6 docs: little fix 2018-09-17 19:57:15 +03:00
Andrei Korigodski
77eca7578f Use Copter Express Technologies as copyright holder 2018-09-17 19:51:20 +03:00
Andrei Korigodski
d13badca50 Improve copyright notices 2018-09-17 19:51:20 +03:00
Oleg Kalachev
acf4f84cae mavros.launch: fix copter_visualization params 2018-09-16 07:12:48 +03:00
Oleg Kalachev
c24d135815 docs: Pixhawk and Pixracer name themselves this way 2018-09-16 05:37:54 +03:00
Oleg Kalachev
0d64476b04 docs: spelling 2018-09-16 05:28:30 +03:00
Oleg Kalachev
091e110afd Move copter_visualization.launch to mavros.launch 2018-09-16 04:43:16 +03:00
Oleg Kalachev
de8ba52643 mavros.launch: fix aligning 2018-09-16 04:37:06 +03:00
Oleg Kalachev
8a2bb6eb32 mavros.launch: default connection is usb 2018-09-16 04:30:22 +03:00
Oleg Kalachev
ed649fd1b1 mavros: disable waypoint plugin 2018-09-16 04:30:07 +03:00
Oleg Kalachev
4cd4b99ae0 docs: add remark about plugin_blacklist usage in mavros 2018-09-16 04:13:37 +03:00
Oleg Kalachev
c903afa09d docs: small fix in snippets 2018-09-12 23:36:35 +03:00
Oleg Kalachev
8aeb11f771 snippet: correct formula for calculating angle to horizon 2018-09-12 23:35:53 +03:00
Oleg Kalachev
ed51b826a0 docs: add link to jsk-visualization plugins 2018-09-12 21:48:49 +03:00
Oleg Kalachev
bb84eeb35e docs: add some code smippets 2018-09-12 21:30:55 +03:00
Smirnov Artem
8a9fd2a97c Merge pull request #62 from urpylka/uart-article
Add UART article & new UART configure of image
2018-09-12 20:55:04 +03:00
Artem Smirnov
3b49f9a67f image_builder: new configure UART on RPi 2018-09-12 20:50:36 +03:00
Artem Smirnov
2a4faedf67 Add article about UART 2018-09-12 19:28:53 +03:00
Oleg Kalachev
82f7f82f54 Fix 2018-09-12 03:42:26 +03:00
Oleg Kalachev
276922104c Sane settings for rangefinders 2018-09-12 03:39:49 +03:00
Oleg Kalachev
3bd4a6673f Make camera markers node retrieve frame id from camera info 2018-09-12 02:50:36 +03:00
Oleg Kalachev
1909feceba Add experimental optical flow node 2018-09-11 19:30:11 +03:00
Oleg Kalachev
e585341933 Remove fpv_camera arg from sitl.launch 2018-09-11 06:54:08 +03:00
Oleg Kalachev
e87054f0d3 Respawn web server on failure 2018-09-11 04:35:37 +03:00
Oleg Kalachev
6b0bd77d49 selfcheck.py fixes 2018-09-11 04:02:36 +03:00
Oleg Kalachev
77f4cbcdd3 Remove unneeded 2018-09-08 23:40:30 +03:00
Oleg Kalachev
928c5938e9 Set up syntax highlighting in vim for .launch files 2018-09-08 23:38:51 +03:00
Oleg Kalachev
03500d70af selfcheck: add CPU usage checking 2018-09-08 23:37:31 +03:00
Oleg Kalachev
2c30a5361f selfcheck: add boot duration checking 2018-09-08 19:17:18 +03:00
Oleg Kalachev
c59d31fc21 Refactor selfcheck node 2018-09-08 18:45:58 +03:00
Oleg Kalachev
5115ba6d8a Update web_video_server version 2018-09-08 04:47:31 +03:00
Oleg Kalachev
4daab3d286 This is unneeded 2018-09-08 02:08:18 +03:00
Oleg Kalachev
34512e5e49 Deny byobu to check updates and take 100% CPU 2018-09-08 02:07:29 +03:00
Oleg Kalachev
0fddd90e1f clever.launch: remove viz argument from the header 2018-09-08 01:55:13 +03:00
Oleg Kalachev
29b6a58769 Set Monkey workers number to 1 2018-09-08 01:47:03 +03:00
Oleg Kalachev
549b2e3815 Add some plugins to mavros blacklist 2018-09-08 01:32:54 +03:00
Oleg Kalachev
88ef7d7eca Add butterfly web terminal 2018-09-08 01:32:05 +03:00
Oleg Kalachev
d70c3f92ad Remove FPV camera from clever.launch as it is not used 2018-09-08 00:18:21 +03:00
Oleg Kalachev
4a25fed9d5 Add camera visualisation markers node for aligning frame with rviz 2018-09-07 22:22:01 +03:00
Smirnov Artem
6fb4d43500 image_builder: change os version to 2018-06-27
Change base OS version to 2018-06-27-raspbian-stretch-lite
2018-09-06 15:56:15 +03:00
Oleg Kalachev
76dca88b62 image_builder: fix Monkey repository URL 2018-09-05 21:15:06 +03:00
Oleg Kalachev
bc7fb94d63 simple_offboard: fix yaw transformation 2018-09-05 20:30:37 +03:00
Smirnov Artem
2bedc6cd31 image_builder: Set max space for syslogs 2018-09-05 16:01:45 +03:00
Oleg Kalachev
c0f748756b docs: small fix 2018-09-04 22:44:35 +03:00
Oleg Kalachev
181a8aeb1b simple_offboard: default speed for navigate service 2018-09-04 02:23:28 +03:00
Oleg Kalachev
c45f7b8148 Don’t run web server in SITL 2018-09-04 01:52:23 +03:00
Oleg Kalachev
1d21665c16 Add Monkey web server 2018-09-04 01:30:30 +03:00
Oleg Kalachev
b87d3c612b Some fixes to selfcheck 2018-09-04 01:22:49 +03:00
Oleg Kalachev
d6757d67f8 Image builder: disable apt auto-updates 2018-09-03 20:15:11 +03:00
Oleg Kalachev
376e44ec6c simple_offboard: enable ‘navigate_after_armed’ by default 2018-09-01 02:48:53 +03:00
Oleg Kalachev
94402d96ad rc: new icon, version update 2018-08-24 00:36:13 +03:00
Oleg Kalachev
d3a1bf7eb6 Remove web server argument from sitl.launch 2018-08-22 20:50:43 +03:00
Oleg Kalachev
beb9370fc5 Remove web_server node 2018-08-22 18:08:48 +03:00
Oleg Kalachev
8dc4e6e0b9 docs 2018-08-19 19:07:49 +03:00
Oleg Kalachev
360ce5c77b docs: little improvements 2018-08-19 19:05:34 +03:00
Oleg Kalachev
4b6d630f5c docs: little improvements 2018-08-19 19:01:39 +03:00
Oleg Kalachev
47d4b3d8a8 docs: little improvements 2018-08-19 18:58:12 +03:00
Oleg Kalachev
162d9d05cc rc: use web for statustext notifications 2018-08-18 00:41:12 +03:00
Oleg Kalachev
4f114184bf Improvements to selfcheck node 2018-08-17 18:03:51 +03:00
Oleg Kalachev
810e44563c docs: small fixes 2018-08-15 21:14:59 +03:00
Oleg Kalachev
704aaf163c docs: add mavlink packet structure example 2018-08-15 21:07:16 +03:00
Smirnov Artem
55988650a6 Fix links 2018-08-13 22:55:24 +03:00
Smirnov Artem
eb499512ee docs: Fix links 2018-08-13 22:45:02 +03:00
Smirnov Artem
794310550c Update README.md 2018-08-13 21:19:14 +03:00
Oleg Kalachev
280db083b4 image: build clever package in Release mode 2018-08-13 16:50:10 +03:00
Oleg Kalachev
d5353a5bef docs: small fix 2018-08-11 05:30:04 +03:00
Oleg Kalachev
fc428d45b9 Add pymavlink library 2018-08-11 05:16:01 +03:00
Oleg Kalachev
19181facdb docs: small fixes 2018-08-11 05:09:21 +03:00
Oleg Kalachev
8813fce63f docs: small fixes 2018-08-11 05:06:51 +03:00
Oleg Kalachev
ac8090ae8b docs: small improvement 2018-08-11 00:38:55 +03:00
Oleg Kalachev
53e644a5f7 docs: add some capitalization info to markdownlint config 2018-08-10 22:20:40 +03:00
Oleg Kalachev
a325156e71 docs: add markdownlint config 2018-08-10 22:10:04 +03:00
Oleg Kalachev
05e1875eec docs: small fix 2018-08-10 21:15:25 +03:00
Oleg Kalachev
98d1ad8494 docs: small changes to ros.md 2018-08-10 21:14:54 +03:00
Oleg Kalachev
ef6b8727b9 docs: add info on /etc/clever_version file 2018-08-10 19:19:25 +03:00
Andrei Korigodski
d7ced0f9c4 docs: fix typo in ros.md 2018-08-10 18:41:18 +03:00
Oleg Kalachev
d76ef207fe Rough attempt to disable glossary links 2018-08-10 18:27:55 +03:00
Oleg Kalachev
fdf6eadfcd docs: disable glossary (attempt #2) 2018-08-10 18:10:16 +03:00
Oleg Kalachev
4e4f02404f Disable glossary links 2018-08-10 17:50:39 +03:00
Oleg Kalachev
42c942514f docs: add glossary 2018-08-10 17:27:38 +03:00
Oleg Kalachev
a6b0ac43e9 docs: small fixes 2018-08-10 01:21:43 +03:00
Oleg Kalachev
0893eb85bc docs: add some info on ROS 2018-08-10 01:17:48 +03:00
Oleg Kalachev
e817e3c7a5 docs: add some links 2018-08-10 00:39:27 +03:00
Oleg Kalachev
32f98fa70e docs: small fixes 2018-08-09 23:25:44 +03:00
Oleg Kalachev
66bdffc747 docs: add some info about MAVLink protocol 2018-08-09 22:59:45 +03:00
Oleg Kalachev
5d353125d2 docs: add some useful snippets 2018-08-09 22:59:45 +03:00
Smirnov Artem
7f2d4344e3 image_builder: fix doc 2018-08-09 13:18:57 +03:00
Oleg Kalachev
4736871524 rc: todo 2018-08-09 03:48:38 +03:00
Oleg Kalachev
bcd88d6d4d rc: fix low battery notification throttling 2018-08-09 03:48:21 +03:00
Oleg Kalachev
8ffe74b772 selfcheck: some todos 2018-08-06 20:33:12 +03:00
Oleg Kalachev
57ae4c304f Add experimental selfcheck node 2018-08-06 20:28:46 +03:00
Smirnov Artem
8be77ab7d9 image_builder: don't remove build-dir in catkin_ws 2018-08-06 16:56:19 +03:00
Oleg Kalachev
8c193b913f docs: fix params files links 2018-08-06 14:36:13 +03:00
Oleg Kalachev
4fac517a1e rc: fake GCS heartbeats to make PX4 send STATUSTEXT messages 2018-08-06 01:59:14 +03:00
Oleg Kalachev
4f7061351f rc: update clever logo 2018-08-02 20:29:29 +03:00
Oleg Kalachev
decc5ecae6 Force gitbook update 2018-07-31 14:01:01 +03:00
Oleg Kalachev
f06fae6885 docs: add link to App Store (RC) 2018-07-31 13:52:44 +03:00
Artem Smirnov
8d46f51c66 image_builder: add service symlink to /lib/systemd/system 2018-07-27 13:23:02 +03:00
Oleg Kalachev
601ef0848d rc: use /mavros/statustext/recv topic for STATUSTEXT messages 2018-07-25 23:01:52 +03:00
111 changed files with 1833 additions and 476 deletions

View File

@@ -5,7 +5,7 @@ end_of_line = lf
insert_final_newline = true insert_final_newline = true
charset = utf-8 charset = utf-8
[*.{py,cpp,h,swift,launch}] [*.{py,swift,launch}]
indent_style = space indent_style = space
indent_size = 4 indent_size = 4

22
.markdownlint.json Normal file
View File

@@ -0,0 +1,22 @@
{
"MD003": false,
"MD013": false,
"MD033": false,
"MD034": false,
"MD044": {
"names": [
"MAVLink",
"ROS",
"Python",
"C++",
"PX4",
"WireShark",
"Wi-Fi",
"Raspberry Pi",
"Pixhawk",
"Pixracer",
"ArUco"
],
"code_blocks": false
}
}

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018 Copter Express Copyright (c) 2018 Copter Express Technologies
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -9,6 +9,5 @@ target 'cleverrc' do
# Pods for cleverrc # Pods for cleverrc
pod 'SwiftSocket', '~> 2.0' pod 'SwiftSocket', '~> 2.0'
pod 'NotificationBannerSwift'
end end

View File

@@ -1,21 +1,12 @@
PODS: PODS:
- MarqueeLabel/Swift (3.1.4)
- NotificationBannerSwift (1.5.4):
- MarqueeLabel/Swift
- SnapKit (~> 4.0)
- SnapKit (4.0.0)
- SwiftSocket (2.0.2) - SwiftSocket (2.0.2)
DEPENDENCIES: DEPENDENCIES:
- NotificationBannerSwift
- SwiftSocket (~> 2.0) - SwiftSocket (~> 2.0)
SPEC CHECKSUMS: SPEC CHECKSUMS:
MarqueeLabel: bf768455fe88d427f71476ebb23f9092b660f40b
NotificationBannerSwift: 4f6666c8421dcf11be0812dd1093d932c15921af
SnapKit: a42d492c16e80209130a3379f73596c3454b7694
SwiftSocket: 6f4c9c63fbc5c1d61188936bb3c599fd546f40ae SwiftSocket: 6f4c9c63fbc5c1d61188936bb3c599fd546f40ae
PODFILE CHECKSUM: fd5199f69c3ee8c1fbc0dd582477d890c8b2a24f PODFILE CHECKSUM: 2044f57d00f536792fbc38c63ded4fa78dcc135c
COCOAPODS: 1.4.0 COCOAPODS: 1.4.0

View File

@@ -226,16 +226,10 @@
); );
inputPaths = ( inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc-frameworks.sh", "${SRCROOT}/Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/MarqueeLabel/MarqueeLabel.framework",
"${BUILT_PRODUCTS_DIR}/NotificationBannerSwift/NotificationBannerSwift.framework",
"${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework",
"${BUILT_PRODUCTS_DIR}/SwiftSocket/SwiftSocket.framework", "${BUILT_PRODUCTS_DIR}/SwiftSocket/SwiftSocket.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MarqueeLabel.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NotificationBannerSwift.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftSocket.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftSocket.framework",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -397,7 +391,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 7QY6KJ2672; DEVELOPMENT_TEAM = M8TDN3PAH2;
INFOPLIST_FILE = cleverrc/Info.plist; INFOPLIST_FILE = cleverrc/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = coex.cleverrc; PRODUCT_BUNDLE_IDENTIFIER = coex.cleverrc;
@@ -413,7 +407,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 7QY6KJ2672; DEVELOPMENT_TEAM = M8TDN3PAH2;
INFOPLIST_FILE = cleverrc/Info.plist; INFOPLIST_FILE = cleverrc/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = coex.cleverrc; PRODUCT_BUNDLE_IDENTIFIER = coex.cleverrc;

View File

@@ -3,7 +3,7 @@
// cleverrc // cleverrc
// //
// Created by Oleg Kalachev on 20.01.2018. // Created by Oleg Kalachev on 20.01.2018.
// Copyright © 2018 Copter Express. All rights reserved. // Copyright © 2018 Copter Express Technologies. All rights reserved.
// //
import UIKit import UIKit

View File

@@ -3,114 +3,176 @@
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "cleverrc40.png", "filename" : "Icon-App-20x20@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever60.png", "filename" : "Icon-App-20x20@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever58.png", "filename" : "Icon-App-29x29@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever87.png", "filename" : "Icon-App-29x29@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever80.png", "filename" : "Icon-App-40x40@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever120.png", "filename" : "Icon-App-40x40@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "60x60", "size" : "60x60",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever120-1.png", "filename" : "Icon-App-60x60@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "60x60", "size" : "60x60",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "clever180-1.png", "filename" : "Icon-App-60x60@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever20.png", "filename" : "Icon-App-20x20@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever40.png", "filename" : "Icon-App-20x20@2x-1.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever29.png", "filename" : "Icon-App-29x29@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever58-1.png", "filename" : "Icon-App-29x29@2x-1.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever40-1.png", "filename" : "Icon-App-40x40@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever80-1.png", "filename" : "Icon-App-40x40@2x-1.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "76x76", "size" : "76x76",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever76.png", "filename" : "Icon-App-76x76@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "76x76", "size" : "76x76",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever152.png", "filename" : "Icon-App-76x76@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "83.5x83.5", "size" : "83.5x83.5",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "clever167.png", "filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "1024x1024", "size" : "1024x1024",
"idiom" : "ios-marketing", "idiom" : "ios-marketing",
"filename" : "clever1024.png", "filename" : "ItunesArtwork@2x.png",
"scale" : "1x"
},
{
"size" : "24x24",
"idiom" : "watch",
"scale" : "2x",
"role" : "notificationCenter",
"subtype" : "38mm"
},
{
"size" : "27.5x27.5",
"idiom" : "watch",
"scale" : "2x",
"role" : "notificationCenter",
"subtype" : "42mm"
},
{
"size" : "29x29",
"idiom" : "watch",
"role" : "companionSettings",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "watch",
"role" : "companionSettings",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "watch",
"scale" : "2x",
"role" : "appLauncher",
"subtype" : "38mm"
},
{
"size" : "44x44",
"idiom" : "watch",
"scale" : "2x",
"role" : "longLook",
"subtype" : "42mm"
},
{
"size" : "86x86",
"idiom" : "watch",
"scale" : "2x",
"role" : "quickLook",
"subtype" : "38mm"
},
{
"size" : "98x98",
"idiom" : "watch",
"scale" : "2x",
"role" : "quickLook",
"subtype" : "42mm"
},
{
"idiom" : "watch-marketing",
"size" : "1024x1024",
"scale" : "1x" "scale" : "1x"
} }
], ],
"info" : { "info" : {
"version" : 1, "version" : 1,
"author" : "xcode" "author" : "xcode"
},
"properties" : {
"pre-rendered" : true
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

View File

@@ -1,20 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0</string> <string>1.1</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>3</string> <string>6</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>

View File

@@ -3,13 +3,12 @@
// cleverrc // cleverrc
// //
// Created by Oleg Kalachev on 20.01.2018. // Created by Oleg Kalachev on 20.01.2018.
// Copyright © 2018 Copter Express. All rights reserved. // Copyright © 2018 Copter Express Technologies. All rights reserved.
// //
import UIKit import UIKit
import WebKit import WebKit
import SwiftSocket import SwiftSocket
import NotificationBannerSwift
import AudioToolbox.AudioServices import AudioToolbox.AudioServices
class ViewController: UIViewController, WKScriptMessageHandler { class ViewController: UIViewController, WKScriptMessageHandler {
@@ -62,15 +61,7 @@ class ViewController: UIViewController, WKScriptMessageHandler {
} else if (message.name == "notification") { } else if (message.name == "notification") {
// Got notification message // Got notification message
print(message) print(message)
let m = message.body as! NSDictionary; tapticNotify()
let level = m["level"] as! Int
if level == 4 {
let banner = NotificationBanner(title: m["msg"] as! String, style: .warning)
banner.show()
} else {
let banner = NotificationBanner(title: m["msg"] as! String, style: .danger)
banner.show()
}
} }
} }

View File

@@ -1,84 +1,57 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg
viewBox="0 0 52.5 52.5" enable-background="new 0 0 52.5 52.5" xml:space="preserve"> xmlns:dc="http://purl.org/dc/elements/1.1/"
<g> xmlns:cc="http://creativecommons.org/ns#"
<path fill="white" fill-opacity="0.5" d="M35.7,17.2c0.3-0.3,0.5-0.7,0.7-1.1c0.2-0.4,0.3-0.9,0.3-1.4c0-0.5-0.1-1-0.3-1.4c-0.2-0.5-0.5-0.9-0.8-1.3 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
c-0.4-0.4-0.9-0.7-1.4-0.9c-0.6-0.2-1.2-0.3-1.8-0.2c-0.5,0.1-0.9,0.2-1.3,0.4c-0.2,0.1-0.4,0.3-0.6,0.4L30.2,12 xmlns:svg="http://www.w3.org/2000/svg"
c-0.1,0.1-0.1,0.1-0.2,0.1c-0.1,0.1-0.3,0.2-0.4,0.2c-0.1,0.1-0.3,0.1-0.4,0.2c-0.1,0-0.2,0.1-0.4,0.1c-0.1,0-0.2,0-0.3,0 xmlns="http://www.w3.org/2000/svg"
c-0.6,0.1-1.3-0.1-1.9-0.4c-0.2-0.1-0.4-0.2-0.6-0.4c0,0-0.1-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c0,0,0,0-0.1-0.1 viewBox="0 0 69.988266 69.987198"
c-0.1-0.1-0.1-0.2-0.1-0.3c0,0,0,0,0-0.1l0-6.5c-0.5-0.6-1.1-1.1-1.7-1.6c-0.9-0.7-1.9-1.4-3-1.8c-0.9-0.4-1.8-0.7-2.7-1 height="69.987198"
c-0.9-0.2-1.7-0.3-2.6-0.4c-0.9-0.1-1.8,0-2.7,0.1c-0.7,0.1-1.5,0.2-2.2,0.5C9.4,0.9,8.1,1.5,7,2.2C6.2,2.7,5.4,3.3,4.7,3.9 width="69.988266"
C4,4.6,3.4,5.3,2.8,6c-0.5,0.7-1,1.4-1.3,2.2C1.1,9,0.8,9.8,0.6,10.6c-0.2,0.7-0.4,1.4-0.4,2.1C0,13.7,0,14.6,0,15.6 xml:space="preserve"
c0,0.8,0.2,1.7,0.4,2.5c0.2,0.9,0.5,1.7,0.8,2.5C1.8,21.8,2.5,23,3.4,24c0.3,0.4,0.7,0.8,1,1.1c0.2,0.2,0.3,0.3,0.5,0.5H11 id="svg2"
c0.1-0.1,0.1-0.2,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2c0.1-0.4,0.2-0.8,0.1-1.1c0-0.1,0-0.1,0-0.2 version="1.1"><metadata
c0-0.1-0.1-0.1-0.1-0.2c0-0.1-0.1-0.2-0.2-0.2c0,0-0.1-0.1-0.1-0.1l0,0c0,0,0-0.1-0.1-0.1c0,0,0,0,0,0l-0.1-0.1 id="metadata8"><rdf:RDF><cc:Work
c-0.1-0.1-0.2-0.3-0.3-0.4c-0.2-0.3-0.4-0.7-0.5-1c-0.1-0.3-0.2-0.7-0.3-1c-0.1-0.6-0.1-1.1,0-1.7c0.1-0.5,0.3-1,0.5-1.5 rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
c0.3-0.5,0.6-0.9,1-1.3c0.4-0.4,0.9-0.7,1.4-0.9c0.6-0.2,1.2-0.4,1.8-0.4c0.7,0,1.3,0.1,1.9,0.3c0.7,0.2,1.3,0.6,1.8,1.1 rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
c0.5,0.5,1,1.1,1.3,1.8c0.2,0.4,0.3,0.7,0.3,1.1c0.1,0.4,0.1,0.8,0.1,1.3c0,0.4-0.1,0.8-0.2,1.1c-0.1,0.3-0.3,0.7-0.4,1 id="defs6"><clipPath
c-0.1,0.2-0.2,0.3-0.3,0.5c0,0.1-0.1,0.1-0.1,0.2l0,0l0,0l0,0.1c0,0,0,0.1-0.1,0.1l-0.1,0.1c0,0-0.1,0.1-0.1,0.1 id="clipPath18"
c-0.1,0.1-0.1,0.1-0.1,0.2c0,0.1-0.1,0.1-0.1,0.2c0,0.1,0,0.1,0,0.2c-0.1,0.3-0.1,0.7,0.1,1.1c0,0.1,0,0.1,0.1,0.2 clipPathUnits="userSpaceOnUse"><path
c0,0.1,0.1,0.1,0.1,0.2c0,0.1,0.1,0.2,0.2,0.3h7.2l0-7.5c0,0,0,0,0-0.1c0-0.1,0-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2 id="path16"
c0,0,0.1-0.1,0.1-0.1l0.1,0c0.1-0.1,0.2-0.1,0.3-0.2c0.5-0.3,1-0.5,1.6-0.6c0.2,0,0.3,0,0.5,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2,0 d="M 0,52.49 H 52.491 V 0 H 0 Z" /></clipPath></defs><g
c0.1,0,0.2,0,0.4,0.1c0.3,0.1,0.7,0.2,0.9,0.4c0.1,0.1,0.2,0.1,0.3,0.2c0,0,0.1,0.1,0.1,0.1l0,0l-0.1,0.1c0,0,0,0,0,0l0.1-0.1 transform="matrix(1.3333333,0,0,-1.3333333,0,69.9872)"
l0.2,0.2c0.1,0.1,0.2,0.2,0.4,0.2c0.2,0.1,0.5,0.3,0.8,0.4c0.7,0.2,1.4,0.3,2,0.1c0.4-0.1,0.7-0.2,1.1-0.4 id="g10"><g
C35.1,17.7,35.4,17.5,35.7,17.2z"/> id="g12"><g
<g> clip-path="url(#clipPath18)"
<polygon points="41.6,29.7 41.6,29.7 41.6,29.6 41.6,29.6 "/> id="g14"><g
<path fill="white" fill-opacity="0.5" d="M28.6,49.2c0.9,0.8,2,1.4,3,1.9c0.8,0.4,1.7,0.7,2.6,0.9c0.9,0.2,1.8,0.4,2.7,0.4c0.9,0.1,1.9,0,2.8-0.1 transform="translate(35.6531,35.3361)"
c0.7-0.1,1.4-0.2,2.1-0.4c1.3-0.4,2.5-0.9,3.6-1.6c0.8-0.5,1.6-1.1,2.3-1.7c0.7-0.7,1.4-1.4,2-2.2c0.5-0.6,0.9-1.3,1.2-2 id="g20"><path
c0.4-0.8,0.7-1.7,1-2.5c0.2-0.6,0.3-1.3,0.4-1.9c0.1-1,0.2-2,0.1-3c0-0.8-0.2-1.6-0.3-2.4c-0.2-0.9-0.5-1.7-0.8-2.6 id="path22"
c-0.5-1.2-1.2-2.4-2.1-3.4c-0.3-0.4-0.6-0.8-1-1.1l-0.5-0.5h-6.1l-0.2,0.3c0,0.1-0.1,0.1-0.1,0.2c0,0.1-0.1,0.1-0.1,0.2 style="fill:white;fill-opacity:0.5;fill-rule:nonzero;stroke:none"
c-0.1,0.4-0.2,0.8-0.1,1.1c0,0.1,0,0.1,0,0.2c0,0.1,0.1,0.1,0.1,0.2c0,0.1,0.1,0.2,0.2,0.3c0,0,0.1,0.1,0.1,0.1l0,0 d="M 0,0 C 0.279,0.322 0.5,0.686 0.657,1.081 0.827,1.513 0.914,1.968 0.917,2.434 0.92,2.924 0.829,3.403 0.647,3.857 0.458,4.329 0.165,4.77 -0.2,5.13 -0.587,5.512 -1.061,5.812 -1.571,5.995 -2.138,6.198 -2.756,6.262 -3.358,6.18 -3.821,6.115 -4.263,5.967 -4.671,5.739 -4.886,5.618 -5.094,5.472 -5.291,5.305 L -5.467,5.151 C -5.527,5.099 -5.587,5.049 -5.649,5.003 -5.775,4.909 -5.906,4.827 -6.04,4.759 -6.173,4.691 -6.314,4.633 -6.458,4.586 -6.575,4.549 -6.696,4.519 -6.819,4.496 -6.917,4.478 -7.017,4.465 -7.115,4.457 c -0.623,-0.052 -1.281,0.082 -1.9,0.385 -0.224,0.111 -0.439,0.241 -0.64,0.387 -0.042,0.03 -0.084,0.063 -0.127,0.095 -0.039,0.031 -0.069,0.054 -0.102,0.09 -0.023,0.025 -0.043,0.05 -0.061,0.077 -0.056,0.082 -0.093,0.176 -0.107,0.271 -0.004,0.022 -0.005,0.044 -0.006,0.066 l -0.002,6.486 c -0.534,0.589 -1.115,1.136 -1.728,1.626 -0.913,0.73 -1.913,1.352 -2.971,1.845 -0.867,0.405 -1.779,0.725 -2.711,0.952 -0.851,0.208 -1.731,0.34 -2.617,0.391 -0.912,0.053 -1.834,0.023 -2.741,-0.092 -0.741,-0.094 -1.479,-0.246 -2.194,-0.453 -1.274,-0.365 -2.494,-0.905 -3.628,-1.604 -0.824,-0.507 -1.603,-1.101 -2.316,-1.764 -0.687,-0.64 -1.317,-1.35 -1.871,-2.109 -0.505,-0.692 -0.951,-1.432 -1.327,-2.2 -0.375,-0.764 -0.684,-1.566 -0.919,-2.383 -0.201,-0.7 -0.351,-1.423 -0.446,-2.147 -0.12,-0.919 -0.153,-1.858 -0.099,-2.79 0.05,-0.838 0.171,-1.673 0.359,-2.482 0.201,-0.856 0.481,-1.7 0.833,-2.507 0.546,-1.253 1.265,-2.423 2.136,-3.479 0.317,-0.384 0.654,-0.753 1.002,-1.098 0.158,-0.157 0.32,-0.31 0.485,-0.459 h 6.121 c 0.051,0.08 0.099,0.161 0.143,0.245 0.037,0.071 0.072,0.144 0.104,0.218 0.026,0.062 0.05,0.128 0.073,0.193 0.132,0.394 0.159,0.784 0.077,1.127 -0.013,0.052 -0.028,0.105 -0.046,0.157 -0.024,0.068 -0.053,0.136 -0.087,0.201 -0.048,0.09 -0.105,0.174 -0.169,0.249 -0.035,0.041 -0.07,0.079 -0.107,0.116 l -0.024,0.026 c -0.025,0.029 -0.046,0.053 -0.066,0.079 -0.014,0.02 -0.02,0.029 -0.027,0.038 l -0.079,0.096 c -0.109,0.134 -0.212,0.277 -0.304,0.42 -0.207,0.318 -0.378,0.659 -0.506,1.013 -0.118,0.32 -0.202,0.651 -0.252,0.985 -0.085,0.571 -0.073,1.146 0.035,1.71 0.098,0.509 0.273,0.999 0.521,1.454 0.258,0.475 0.588,0.903 0.98,1.272 0.419,0.394 0.895,0.711 1.415,0.942 0.557,0.249 1.15,0.393 1.762,0.428 0.659,0.035 1.298,-0.05 1.914,-0.258 0.653,-0.221 1.268,-0.585 1.78,-1.05 0.541,-0.492 0.977,-1.106 1.261,-1.776 0.151,-0.357 0.26,-0.729 0.324,-1.106 0.072,-0.415 0.092,-0.843 0.058,-1.272 -0.031,-0.388 -0.108,-0.773 -0.227,-1.144 -0.11,-0.341 -0.257,-0.673 -0.441,-0.988 -0.103,-0.177 -0.216,-0.347 -0.335,-0.503 -0.037,-0.051 -0.077,-0.1 -0.117,-0.151 l -0.033,-0.04 -0.005,0.002 -0.049,-0.07 c -0.022,-0.028 -0.043,-0.054 -0.066,-0.08 l -0.076,-0.08 c -0.028,-0.03 -0.055,-0.062 -0.081,-0.094 -0.05,-0.063 -0.095,-0.131 -0.134,-0.202 -0.035,-0.064 -0.066,-0.131 -0.09,-0.199 -0.019,-0.053 -0.035,-0.105 -0.049,-0.158 -0.085,-0.34 -0.062,-0.729 0.066,-1.123 0.021,-0.066 0.045,-0.13 0.071,-0.193 0.03,-0.073 0.063,-0.145 0.1,-0.215 0.045,-0.088 0.096,-0.176 0.156,-0.269 h 7.162 l 0.002,7.527 c 10e-4,0.022 0.002,0.043 0.006,0.065 0.008,0.061 0.027,0.124 0.057,0.187 0.03,0.06 0.067,0.114 0.111,0.161 0.034,0.037 0.065,0.062 0.102,0.09 l 0.062,0.048 c 0.087,0.065 0.173,0.126 0.262,0.183 0.487,0.316 1.027,0.526 1.563,0.608 0.154,0.024 0.312,0.037 0.482,0.04 0.037,0.001 0.076,0 0.113,-0.001 0.062,-0.002 0.124,-0.005 0.186,-0.01 0.123,-0.011 0.247,-0.029 0.367,-0.053 0.338,-0.071 0.654,-0.2 0.939,-0.383 0.11,-0.07 0.214,-0.149 0.31,-0.231 0.031,-0.026 0.061,-0.053 0.09,-0.081 l 0.029,-0.028 -0.07,-0.106 c 0.003,-0.003 0.007,-0.007 0.01,-0.01 l 0.071,0.101 0.215,-0.169 c 0.13,-0.101 0.243,-0.179 0.358,-0.25 0.24,-0.146 0.497,-0.266 0.763,-0.355 0.656,-0.219 1.363,-0.253 2.04,-0.097 0.374,0.086 0.731,0.229 1.059,0.424 C -0.581,-0.571 -0.268,-0.309 0,0" /></g><g
c0,0,0,0.1,0.1,0.1l0,0.1l0.1-0.1l0,0l0,0l0,0l0,0l0,0l0.1,0.1c0.2,0.2,0.3,0.4,0.5,0.7c0.3,0.5,0.5,1,0.6,1.5 transform="translate(41.5882,22.8337)"
c0.1,0.7,0.1,1.5,0,2.2c-0.2,0.6-0.4,1.2-0.8,1.8c-0.3,0.4-0.7,0.8-1.1,1.1c-0.4,0.3-0.8,0.5-1.3,0.7c-0.5,0.2-1,0.3-1.5,0.3 id="g24"><path
c-0.5,0-0.9,0-1.3-0.1c-0.5-0.1-1-0.3-1.4-0.6c-0.5-0.3-1-0.7-1.3-1.1c-0.4-0.5-0.7-1-0.9-1.6c-0.2-0.6-0.3-1.3-0.2-2 id="path26"
c0-0.4,0.1-0.7,0.2-1c0.1-0.4,0.3-0.8,0.5-1.1c0.1-0.2,0.2-0.3,0.3-0.5c0-0.1,0.1-0.1,0.1-0.2l0.1,0c0,0,0,0,0,0l-0.1-0.1l0.1-0.1 style="fill:white;fill-opacity:0.5;fill-rule:nonzero;stroke:none"
c0,0,0-0.1,0.1-0.1l0.1-0.1c0,0,0.1-0.1,0.1-0.1c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0-0.1,0-0.2 d="M 0,0 V 0 L 0.053,0.044 0.013,0.018 Z" /></g><g
c0.1-0.3,0.1-0.7-0.1-1.1c0-0.1,0-0.1-0.1-0.2c0-0.1-0.1-0.2-0.1-0.2c0-0.1-0.1-0.2-0.1-0.2h-7.2l0,7.5c0,0,0,0,0,0.1 transform="translate(28.5515,3.2736)"
c0,0.1-0.1,0.2-0.1,0.3c0,0,0,0.1-0.1,0.1c0,0-0.1,0.1-0.1,0.1c0,0,0,0-0.1,0c-0.1,0.1-0.3,0.2-0.4,0.3c-0.6,0.4-1.3,0.6-1.9,0.6 id="g28"><path
c-0.1,0-0.2,0-0.3,0c-0.1,0-0.2,0-0.3,0c-0.4-0.1-0.7-0.2-1-0.4c-0.1-0.1-0.2-0.2-0.3-0.2c0,0-0.1-0.1-0.1-0.1h0l0,0l0,0 id="path30"
c0,0-0.1-0.1-0.1-0.1L22,34.8c-0.2-0.2-0.4-0.3-0.6-0.4c-0.4-0.2-0.9-0.3-1.3-0.4c-0.3,0-0.7,0-1,0.1c-0.3,0.1-0.5,0.1-0.8,0.2 style="fill:white;fill-opacity:0.5;fill-rule:nonzero;stroke:none"
c-0.5,0.2-1,0.5-1.3,0.9c-0.3,0.4-0.6,0.8-0.8,1.3C16,37,15.9,37.5,15.9,38c0,0.5,0.1,0.9,0.3,1.3c0.2,0.4,0.4,0.7,0.7,1 d="m 0,0 c 0.934,-0.757 1.959,-1.398 3.045,-1.906 0.84,-0.39 1.72,-0.702 2.615,-0.927 0.883,-0.222 1.796,-0.362 2.714,-0.416 0.944,-0.054 1.897,-0.019 2.832,0.106 0.707,0.094 1.414,0.242 2.102,0.439 1.276,0.368 2.496,0.908 3.628,1.605 0.798,0.492 1.556,1.065 2.251,1.704 0.724,0.666 1.384,1.408 1.962,2.205 0.468,0.646 0.886,1.334 1.242,2.044 0.409,0.815 0.742,1.672 0.99,2.547 0.179,0.628 0.316,1.274 0.409,1.921 0.14,0.979 0.182,1.98 0.123,2.973 -0.048,0.819 -0.165,1.638 -0.348,2.433 -0.2,0.872 -0.484,1.732 -0.843,2.556 -0.538,1.234 -1.247,2.392 -2.106,3.442 -0.313,0.381 -0.648,0.752 -0.998,1.1 l -0.52,0.493 H 12.982 L 12.831,22.068 C 12.797,22.003 12.763,21.931 12.732,21.857 12.705,21.794 12.681,21.73 12.659,21.665 12.527,21.268 12.5,20.878 12.582,20.536 c 0.012,-0.053 0.027,-0.105 0.045,-0.156 0.024,-0.069 0.054,-0.137 0.088,-0.202 0.046,-0.086 0.103,-0.171 0.169,-0.251 0.027,-0.032 0.056,-0.062 0.086,-0.093 l 0.045,-0.048 c 0.023,-0.025 0.044,-0.051 0.065,-0.078 l -0.046,-0.082 0.061,0.057 0.003,-0.002 0.022,-0.028 -10e-4,-10e-4 0.01,-0.015 0.004,0.003 0.05,-0.062 c 0.171,-0.212 0.322,-0.433 0.451,-0.659 0.275,-0.478 0.469,-0.996 0.575,-1.538 0.141,-0.718 0.124,-1.472 -0.05,-2.181 -0.152,-0.623 -0.431,-1.228 -0.807,-1.751 -0.303,-0.42 -0.667,-0.79 -1.082,-1.1 C 11.868,12.048 11.425,11.81 10.954,11.64 10.456,11.461 9.935,11.362 9.406,11.345 8.955,11.331 8.505,11.376 8.07,11.48 c -0.494,0.118 -0.965,0.308 -1.399,0.565 -0.509,0.301 -0.958,0.685 -1.333,1.14 -0.393,0.477 -0.692,1.014 -0.89,1.596 -0.218,0.645 -0.305,1.348 -0.25,2.031 0.029,0.355 0.095,0.704 0.194,1.037 0.114,0.383 0.273,0.751 0.474,1.095 0.095,0.164 0.207,0.334 0.334,0.503 0.038,0.051 0.078,0.102 0.118,0.151 L 5.45,19.56 v 0 l -0.101,0.074 0.055,0.073 c 0.023,0.028 0.045,0.054 0.066,0.078 l 0.076,0.08 c 0.03,0.031 0.057,0.062 0.082,0.095 0.05,0.063 0.095,0.131 0.135,0.203 0.034,0.063 0.065,0.13 0.09,0.199 0.019,0.052 0.034,0.103 0.047,0.156 0.086,0.341 0.063,0.73 -0.065,1.124 -0.021,0.065 -0.044,0.129 -0.071,0.193 -0.033,0.082 -0.071,0.162 -0.113,0.24 -0.044,0.084 -0.092,0.165 -0.143,0.244 h -7.162 l -0.002,-7.532 c -0.001,-0.02 -0.003,-0.041 -0.006,-0.06 -0.015,-0.099 -0.052,-0.192 -0.107,-0.272 -0.018,-0.027 -0.039,-0.052 -0.061,-0.076 -0.035,-0.037 -0.064,-0.061 -0.102,-0.09 -0.02,-0.016 -0.042,-0.033 -0.065,-0.05 -0.122,-0.091 -0.254,-0.181 -0.393,-0.264 -0.619,-0.37 -1.29,-0.565 -1.942,-0.565 -0.093,-0.003 -0.179,0.003 -0.268,0.011 -0.11,0.01 -0.221,0.025 -0.33,0.046 -0.36,0.071 -0.709,0.213 -1.008,0.411 -0.109,0.072 -0.213,0.152 -0.309,0.237 -0.029,0.026 -0.058,0.052 -0.085,0.079 h -0.026 l -0.022,0.042 -0.036,0.027 c -0.035,0.03 -0.061,0.051 -0.087,0.072 l -0.073,0.059 c -0.212,0.162 -0.427,0.296 -0.648,0.404 -0.416,0.204 -0.861,0.328 -1.324,0.367 -0.345,0.028 -0.695,0.012 -1.037,-0.053 -0.259,-0.05 -0.511,-0.126 -0.75,-0.228 -0.498,-0.211 -0.954,-0.534 -1.32,-0.936 -0.345,-0.381 -0.614,-0.838 -0.779,-1.322 -0.154,-0.455 -0.218,-0.933 -0.191,-1.421 0.026,-0.462 0.136,-0.909 0.326,-1.327 0.175,-0.386 0.412,-0.738 0.706,-1.047 0.283,-0.296 0.609,-0.543 0.97,-0.734 0.319,-0.168 0.661,-0.289 1.015,-0.36 0.449,-0.089 0.906,-0.095 1.357,-0.021 0.246,0.041 0.49,0.108 0.725,0.198 0.254,0.098 0.499,0.225 0.727,0.377 0.113,0.075 0.229,0.161 0.343,0.257 l 0.068,0.054 0.016,0.046 0.041,0.002 c 0.012,0.013 0.02,0.02 0.029,0.028 l 0.055,0.052 c 0.051,0.043 0.1,0.084 0.151,0.124 0.104,0.08 0.212,0.151 0.322,0.213 0.28,0.159 0.589,0.268 0.917,0.324 0.152,0.026 0.31,0.04 0.48,0.043 h 0.109 C -4.1,9.429 -3.938,9.414 -3.782,9.389 -3.261,9.303 -2.734,9.095 -2.256,8.787 -2.167,8.73 -2.08,8.668 -1.996,8.604 l 0.053,-0.04 c 0.048,-0.037 0.077,-0.061 0.111,-0.097 0.047,-0.05 0.084,-0.104 0.113,-0.162 0.029,-0.062 0.048,-0.125 0.057,-0.187 0.003,-0.02 0.005,-0.04 0.006,-0.06 L -1.654,8.021 V 1.566 C -1.142,1.001 -0.585,0.474 0,0" /></g><g
c0.3,0.3,0.6,0.5,1,0.7c0.3,0.2,0.7,0.3,1,0.4c0.4,0.1,0.9,0.1,1.4,0c0.2,0,0.5-0.1,0.7-0.2c0.3-0.1,0.5-0.2,0.7-0.4 transform="translate(22.2707,17.571)"
c0.1-0.1,0.2-0.2,0.3-0.3l0.1-0.1l0,0l0,0c0,0,0,0,0,0l0.1-0.1c0.1,0,0.1-0.1,0.2-0.1c0.1-0.1,0.2-0.2,0.3-0.2 id="g32"><path
c0.3-0.2,0.6-0.3,0.9-0.3c0.2,0,0.3,0,0.5,0h0.1c0.2,0,0.3,0,0.5,0c0.5,0.1,1,0.3,1.5,0.6c0.1,0.1,0.2,0.1,0.3,0.2l0.1,0 id="path34"
c0,0,0.1,0.1,0.1,0.1c0,0.1,0.1,0.1,0.1,0.2c0,0.1,0,0.1,0.1,0.2c0,0,0,0,0,0.1l0,0v6.5C27.4,48.2,28,48.7,28.6,49.2z"/> style="fill:white;fill-opacity:0.5;fill-rule:nonzero;stroke:none"
<polygon points="22.3,34.9 22.3,34.9 22.3,34.9 22.3,34.9 "/> d="m 0,0 v -0.008 l 0.011,0.019 v 0 z" /></g><g
</g> transform="translate(40.657,22.3049)"
<g> id="g36"><path
<polygon points="40.7,30.2 40.7,30.2 40.7,30.2 "/> id="path38"
<path fill="white" fill-opacity="0.5" d="M49.2,24c0.7-0.9,1.3-1.8,1.8-2.9c0.4-0.7,0.7-1.5,0.9-2.3c0.2-0.8,0.4-1.7,0.5-2.6c0.2-1.7,0.1-3.4-0.3-5 style="fill:white;fill-opacity:0.5;fill-rule:nonzero;stroke:none"
c-0.3-1.3-0.8-2.6-1.5-3.8c-0.4-0.7-0.9-1.4-1.4-2.1c-0.6-0.7-1.3-1.4-2-2c-0.6-0.5-1.3-1-2-1.4c-0.8-0.4-1.5-0.8-2.3-1.1 d="M 0,0 Z" /></g><g
c-1-0.4-2-0.6-3.1-0.7C39.3,0.1,38.9,0,38.5,0c-0.2,0-0.4,0-0.6,0h-0.1c-0.5,0-0.9,0-1.4,0.1c-0.8,0.1-1.7,0.2-2.5,0.4 transform="translate(49.1867,28.5134)"
c-0.9,0.2-1.7,0.6-2.5,0.9c-0.8,0.4-1.5,0.8-2.2,1.3c-0.6,0.4-1.1,0.9-1.6,1.4c-0.2,0.2-0.5,0.5-0.7,0.7V11 id="g40"><path
c0.1,0.1,0.2,0.1,0.2,0.1c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.1,0.1,0.2,0.1c0.4,0.1,0.8,0.2,1.1,0.1c0.1,0,0.1,0,0.2,0 id="path42"
c0.1,0,0.1-0.1,0.2-0.1c0.1,0,0.2-0.1,0.3-0.2c0,0,0.1-0.1,0.1-0.1l0,0c0,0,0.1,0,0.1-0.1l0.1-0.1c0.2-0.1,0.3-0.2,0.5-0.3 style="fill:white;fill-opacity:0.5;fill-rule:nonzero;stroke:none"
c0.3-0.2,0.7-0.4,1-0.5c0.3-0.1,0.6-0.2,1-0.2c0.6-0.1,1.1-0.1,1.7,0c0.5,0.1,1,0.3,1.5,0.5c0.5,0.3,0.9,0.6,1.3,1 d="m 0,0 c 0.721,0.884 1.337,1.848 1.832,2.865 0.359,0.739 0.659,1.516 0.89,2.311 0.244,0.839 0.413,1.706 0.503,2.579 0.173,1.678 0.063,3.352 -0.329,4.976 -0.323,1.339 -0.834,2.625 -1.518,3.823 -0.416,0.728 -0.898,1.425 -1.432,2.072 -0.597,0.724 -1.268,1.394 -1.993,1.994 -0.636,0.525 -1.32,0.999 -2.034,1.409 -0.75,0.431 -1.539,0.796 -2.345,1.086 -1,0.359 -2.041,0.609 -3.095,0.743 -0.401,0.051 -0.808,0.086 -1.209,0.104 -0.205,0.009 -0.41,0.014 -0.615,0.015 h -0.098 c -0.479,-0.003 -0.943,-0.026 -1.379,-0.069 -0.825,-0.08 -1.65,-0.231 -2.451,-0.45 -0.861,-0.235 -1.705,-0.551 -2.509,-0.941 -0.765,-0.371 -1.502,-0.811 -2.191,-1.308 -0.571,-0.411 -1.115,-0.866 -1.618,-1.352 -0.236,-0.227 -0.471,-0.469 -0.698,-0.72 v -6.121 c 0.079,-0.052 0.161,-0.1 0.245,-0.144 0.07,-0.037 0.143,-0.071 0.216,-0.102 0.064,-0.027 0.13,-0.051 0.195,-0.074 0.394,-0.132 0.784,-0.158 1.127,-0.077 0.053,0.012 0.105,0.027 0.156,0.045 0.069,0.024 0.136,0.054 0.201,0.088 0.088,0.047 0.173,0.104 0.251,0.169 0.04,0.034 0.078,0.071 0.116,0.107 l 0.029,0.028 c 0.035,0.029 0.055,0.046 0.077,0.063 l 0.107,0.085 c 0.164,0.132 0.314,0.24 0.466,0.338 0.319,0.205 0.662,0.373 1.018,0.502 0.317,0.115 0.649,0.198 0.987,0.245 0.56,0.082 1.126,0.068 1.681,-0.038 0.51,-0.098 1,-0.273 1.455,-0.521 0.473,-0.257 0.901,-0.587 1.272,-0.981 0.394,-0.418 0.711,-0.894 0.942,-1.414 0.248,-0.558 0.392,-1.151 0.427,-1.762 0.037,-0.645 -0.052,-1.307 -0.258,-1.914 -0.22,-0.652 -0.583,-1.267 -1.049,-1.781 -0.491,-0.54 -1.105,-0.976 -1.776,-1.26 -0.352,-0.149 -0.724,-0.259 -1.106,-0.325 -0.421,-0.072 -0.849,-0.091 -1.272,-0.057 -0.371,0.03 -0.739,0.1 -1.09,0.21 -0.365,0.113 -0.716,0.267 -1.042,0.458 -0.167,0.096 -0.336,0.209 -0.503,0.334 -0.051,0.039 -0.102,0.078 -0.151,0.118 l -0.108,0.086 c -0.028,0.022 -0.053,0.043 -0.079,0.065 -0.03,0.028 -0.056,0.054 -0.082,0.079 -0.029,0.026 -0.061,0.054 -0.094,0.081 -0.064,0.05 -0.132,0.095 -0.201,0.133 -0.064,0.035 -0.132,0.065 -0.201,0.091 -0.051,0.018 -0.101,0.034 -0.154,0.046 C -20.829,6.024 -21.219,6 -21.613,5.873 -21.677,5.852 -21.742,5.828 -21.806,5.802 -21.887,5.768 -21.967,5.73 -22.045,5.689 -22.129,5.645 -22.21,5.598 -22.289,5.546 v -7.162 l 7.532,-0.003 c 0.02,-0.001 0.04,-0.002 0.06,-0.005 0.098,-0.015 0.192,-0.052 0.272,-0.107 0.026,-0.018 0.053,-0.039 0.076,-0.062 0.035,-0.033 0.058,-0.061 0.085,-0.096 l 0.053,-0.068 c 0.094,-0.125 0.184,-0.257 0.267,-0.395 0.362,-0.608 0.557,-1.269 0.563,-1.912 0.002,-0.099 -0.002,-0.198 -0.01,-0.298 -0.009,-0.11 -0.025,-0.221 -0.046,-0.33 -0.072,-0.362 -0.213,-0.711 -0.41,-1.008 -0.074,-0.11 -0.153,-0.214 -0.238,-0.309 -0.026,-0.029 -0.053,-0.057 -0.08,-0.086 l -0.025,-0.026 v 10e-4 l -0.18,-0.227 c -0.083,-0.106 -0.161,-0.219 -0.23,-0.334 -0.143,-0.233 -0.26,-0.483 -0.349,-0.744 -0.223,-0.654 -0.261,-1.359 -0.109,-2.037 0.084,-0.378 0.229,-0.742 0.429,-1.083 0.208,-0.351 0.47,-0.665 0.779,-0.932 0.323,-0.28 0.687,-0.5 1.081,-0.656 0.429,-0.17 0.884,-0.257 1.352,-0.26 h 0.026 c 0.482,0 0.951,0.09 1.397,0.269 0.473,0.19 0.913,0.483 1.274,0.848 0.383,0.388 0.682,0.862 0.865,1.371 0.203,0.566 0.267,1.184 0.184,1.786 -0.066,0.477 -0.221,0.931 -0.461,1.349 -0.117,0.204 -0.256,0.4 -0.413,0.584 l -0.073,0.089 0.005,0.01 -0.002,0.006 0.007,0.002 0.017,0.033 0.035,0.065 -0.091,-0.085 -0.053,0.057 c -0.051,0.06 -0.101,0.12 -0.148,0.182 -0.091,0.121 -0.173,0.253 -0.243,0.391 -0.067,0.13 -0.125,0.27 -0.172,0.417 -0.038,0.116 -0.068,0.239 -0.091,0.363 -0.018,0.097 -0.031,0.196 -0.039,0.294 -0.052,0.624 0.082,1.281 0.385,1.901 0.109,0.221 0.239,0.436 0.386,0.639 0.031,0.043 0.064,0.085 0.096,0.127 0.032,0.041 0.055,0.069 0.09,0.102 0.025,0.023 0.051,0.045 0.078,0.063 0.079,0.054 0.172,0.091 0.27,0.106 0.02,0.003 0.04,0.004 0.06,0.005 l 0.038,0.003 h 6.454 C -0.981,-1.113 -0.465,-0.57 0,0" /></g>
c0.4,0.4,0.7,0.9,0.9,1.4c0.2,0.6,0.4,1.2,0.4,1.8c0,0.6-0.1,1.3-0.3,1.9c-0.2,0.7-0.6,1.3-1,1.8c-0.5,0.5-1.1,1-1.8,1.3 </g></g></g></svg>
c-0.4,0.1-0.7,0.3-1.1,0.3c-0.4,0.1-0.8,0.1-1.3,0.1c-0.4,0-0.7-0.1-1.1-0.2c-0.4-0.1-0.7-0.3-1-0.5c-0.2-0.1-0.3-0.2-0.5-0.3
c-0.1,0-0.1-0.1-0.2-0.1l-0.1-0.1c0,0-0.1,0-0.1-0.1c0,0-0.1-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c-0.1-0.1-0.1-0.1-0.2-0.1
c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1,0-0.2,0C28.4,18,28,18,27.6,18.1c-0.1,0-0.1,0-0.2,0.1c-0.1,0-0.2,0.1-0.2,0.1
c-0.1,0-0.2,0.1-0.2,0.1v7.2l7.5,0c0,0,0,0,0.1,0c0.1,0,0.2,0.1,0.3,0.1c0,0,0.1,0,0.1,0.1c0,0,0.1,0.1,0.1,0.1l0.1,0.1
c0.1,0.1,0.2,0.3,0.3,0.4c0.4,0.6,0.6,1.3,0.6,1.9c0,0.1,0,0.2,0,0.3c0,0.1,0,0.2,0,0.3c-0.1,0.4-0.2,0.7-0.4,1
c-0.1,0.1-0.2,0.2-0.2,0.3c0,0-0.1,0.1-0.1,0.1l0,0l0,0l-0.2,0.2c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.3,0.5-0.3,0.7
c-0.2,0.7-0.3,1.4-0.1,2c0.1,0.4,0.2,0.7,0.4,1.1c0.2,0.4,0.5,0.7,0.8,0.9c0.3,0.3,0.7,0.5,1.1,0.7c0.4,0.2,0.9,0.3,1.4,0.3
c0,0,0,0,0,0c0.5,0,1-0.1,1.4-0.3c0.5-0.2,0.9-0.5,1.3-0.8c0.4-0.4,0.7-0.9,0.9-1.4c0.2-0.6,0.3-1.2,0.2-1.8
c-0.1-0.5-0.2-0.9-0.5-1.3c-0.1-0.2-0.3-0.4-0.4-0.6l-0.1-0.1l0,0l0,0l0,0l0,0l0-0.1l0,0l-0.1,0.1l-0.1-0.1
c-0.1-0.1-0.1-0.1-0.1-0.2c-0.1-0.1-0.2-0.3-0.2-0.4c-0.1-0.1-0.1-0.3-0.2-0.4c0-0.1-0.1-0.2-0.1-0.4c0-0.1,0-0.2,0-0.3
c-0.1-0.6,0.1-1.3,0.4-1.9c0.1-0.2,0.2-0.4,0.4-0.6c0,0,0.1-0.1,0.1-0.1c0,0,0.1-0.1,0.1-0.1c0,0,0.1,0,0.1-0.1
c0.1-0.1,0.2-0.1,0.3-0.1c0,0,0,0,0.1,0l0,0h6.5C48.2,25.1,48.7,24.5,49.2,24z"/>
</g>
</g>
<g id="XMLID_14_">
</g>
<g id="XMLID_15_">
</g>
<g id="XMLID_16_">
</g>
<g id="XMLID_17_">
</g>
<g id="XMLID_18_">
</g>
<g id="XMLID_19_">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -17,6 +17,7 @@
<div class="stick-pointer"></div> <div class="stick-pointer"></div>
</div> </div>
</div> </div>
<div class="notifications"></div>
<script src="main.js" type="text/javascript"></script> <script src="main.js" type="text/javascript"></script>
<script src="telemetry.js" type="text/javascript"></script> <script src="telemetry.js" type="text/javascript"></script>
</body> </body>

View File

@@ -8,7 +8,7 @@ html, body {
} }
* { * {
user-select: none; user-select: none;
} }
.stick { .stick {
@@ -76,7 +76,8 @@ body.armed .telemetry .mode {
body.low-battery .battery { body.low-battery .battery {
color: #ff554b; color: #ff554b;
animation: scale 0.3s 1 ease-in-out} animation: scale 0.3s 1 ease-in-out
}
.logo { .logo {
position: absolute; position: absolute;
@@ -93,3 +94,32 @@ body.low-battery .battery {
user-select: none; user-select: none;
pointer-events: none; pointer-events: none;
} }
.notifications {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
right: 0;
color: white;
}
.notifications.hidden {
transform: translateY(-100%);
}
.notifications.anim {
transition: transform 0.2s ease;
}
.notifications .item {
font-size: 4mm;
-webkit-text-size-adjust: none;
background: #fca83a;
padding: 3mm;
padding-bottom: 1.5mm;
}
.notifications .item:last-child {
padding-bottom: 3mm;
}

View File

@@ -1,6 +1,7 @@
var url = 'ws://192.168.11.1:9090'; var url = 'ws://192.168.11.1:9090';
var modeEl = document.querySelector('.telemetry .mode'); var modeEl = document.querySelector('.telemetry .mode');
var batteryEl = document.querySelector('.battery'); var batteryEl = document.querySelector('.battery');
var notificationsEl = document.querySelector('.notifications');
var ros = new ROSLIB.Ros({ url: url }); var ros = new ROSLIB.Ros({ url: url });
@@ -35,10 +36,14 @@ new ROSLIB.Topic({
}); });
function notifyLowBattery() { function notifyLowBattery() {
console.log('low battery');
callNativeApp('lowBattery'); callNativeApp('lowBattery');
body.classList.remove('low-battery');
void body.offsetWidth; // trick for repeating animation
body.classList.add('low-battery');
} }
notifyLowBatteryThrottled = throttle(notifyLowBattery, 10000); notifyLowBatteryThrottled = throttle(notifyLowBattery, 15000);
new ROSLIB.Topic({ new ROSLIB.Topic({
ros: ros, ros: ros,
@@ -50,29 +55,50 @@ new ROSLIB.Topic({
batteryEl.innerHTML = (message.cell_voltage[0].toFixed(2) + ' V') || ''; batteryEl.innerHTML = (message.cell_voltage[0].toFixed(2) + ' V') || '';
if (message.cell_voltage[0] < LOW_BATTERY) { if (message.cell_voltage[0] < LOW_BATTERY) {
console.log('low battery'); notifyLowBatteryThrottled();
callNativeApp('lowBattery');
body.classList.remove('low-battery');
void body.offsetWidth; // trick for repeating animation
body.classList.add('low-battery');
} else { } else {
body.classList.remove('low-battery'); body.classList.remove('low-battery');
} }
}); });
var notificationHideTimer;
function notify(text, severity) {
var item = document.createElement('div');
item.innerHTML = text;
item.classList.add('item');
notificationsEl.prepend(item);
var itemHeight = item.offsetHeight;
notificationsEl.classList.remove('anim');
notificationsEl.style.transform = 'translateY(' + -itemHeight + 'px)';
setTimeout(function() {
notificationsEl.classList.add('anim');
notificationsEl.style.transform = 'translateY(0)';
}, 0);
clearTimeout(notificationHideTimer);
notificationHideTimer = setTimeout(function() {
notificationsEl.style.transform = '';
notificationsEl.classList.add('hidden');
setTimeout(function() {
notificationsEl.innerHTML = '';
}, 210);
}, 4000);
}
new ROSLIB.Topic({ new ROSLIB.Topic({
ros: ros, ros: ros,
name: '/rosout_agg', name: '/mavros/statustext/recv',
messageType: 'rosgraph_msgs/Log' messageType: 'mavros_msgs/StatusText'
}).subscribe(function(message) { }).subscribe(function(message) {
var BLACKLIST = ['CMD: ', 'PR: ', 'DROPPED', 'Clock skew detected', 'MANUAL CONTROL LOST']; var BLACKLIST = ['CMD: ', 'PR: ', 'DROPPED', 'Clock skew detected', 'MANUAL CONTROL LOST'];
if (message.level >= 4) { if (message.severity <= 4) {
if (BLACKLIST.some(function(e) { if (BLACKLIST.some(function(e) {
return message.msg.indexOf(e) != -1; return message.text.indexOf(e) != -1;
})) { })) {
console.log('Filtered out message ' + message.msg); console.log('Filtered out message ' + message.text);
return; return;
} }
notify(message.text, message.severity);
callNativeApp('notification', message); callNativeApp('notification', message);
} }
}); });

View File

@@ -15,5 +15,8 @@
"yametrika": { "yametrika": {
"id": 49359238 "id": 49359238
} }
},
"structure": {
"glossary": "_GLOSSARY.md"
} }
} }

View File

@@ -21,6 +21,9 @@ find_package(catkin REQUIRED COMPONENTS
tf tf
tf2 tf2
tf2_geometry_msgs tf2_geometry_msgs
tf2_ros
image_transport
cv_bridge
) )
@@ -121,7 +124,7 @@ generate_messages(
## DEPENDS: system dependencies of this project that dependent projects also need ## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package( catkin_package(
# INCLUDE_DIRS include # INCLUDE_DIRS include
# LIBRARIES clever LIBRARIES clever
# CATKIN_DEPENDS other_catkin_pkg # CATKIN_DEPENDS other_catkin_pkg
# DEPENDS system_lib # DEPENDS system_lib
) )
@@ -137,7 +140,11 @@ include_directories(
${catkin_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS}
) )
## Declare a C++ library # Declare a C++ library
add_library(clever
src/optical_flow.cpp
)
add_library(fcu_horiz add_library(fcu_horiz
src/fcu_horiz.cpp src/fcu_horiz.cpp
) )
@@ -156,8 +163,12 @@ add_library(aruco_vpe
## The recommended prefix ensures that target names across packages don't collide ## The recommended prefix ensures that target names across packages don't collide
add_executable(rc src/rc.cpp) add_executable(rc src/rc.cpp)
add_executable(camera_markers src/camera_markers.cpp)
target_link_libraries(rc ${catkin_LIBRARIES}) target_link_libraries(rc ${catkin_LIBRARIES})
target_link_libraries(camera_markers ${catkin_LIBRARIES})
## Rename C++ executable without prefix ## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the ## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use ## target back to the shorter version for ease of user use
@@ -169,6 +180,10 @@ target_link_libraries(rc ${catkin_LIBRARIES})
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against ## Specify libraries to link a library or executable target against
target_link_libraries(clever
${catkin_LIBRARIES}
)
target_link_libraries(fcu_horiz target_link_libraries(fcu_horiz
${catkin_LIBRARIES} ${catkin_LIBRARIES}
"/opt/ros/kinetic/lib/libtf2_ros.so" "/opt/ros/kinetic/lib/libtf2_ros.so"

View File

@@ -2,15 +2,13 @@
<arg name="fcu_conn" default="usb"/> <arg name="fcu_conn" default="usb"/>
<arg name="fcu_ip" default="127.0.0.1"/> <arg name="fcu_ip" default="127.0.0.1"/>
<arg name="gcs_bridge" default="tcp"/> <arg name="gcs_bridge" default="tcp"/>
<arg name="viz" default="true"/> <arg name="web_server" default="true"/>
<arg name="web_server" default="false"/>
<arg name="web_video_server" default="true"/> <arg name="web_video_server" default="true"/>
<arg name="rosbridge" default="true"/> <arg name="rosbridge" default="true"/>
<arg name="main_camera" default="true"/> <arg name="main_camera" default="true"/>
<arg name="optical_flow" default="false"/>
<arg name="aruco" default="false"/> <arg name="aruco" default="false"/>
<arg name="rc" value="true"/> <arg name="rc" value="true"/>
<arg name="fpv_camera" default="false"/>
<arg name="fpv_camera_device" default="/dev/v4l/by-id/usb-HD_Camera_Manufacturer_USB_2.0_Camera-video-index0"/>
<arg name="arduino" default="false"/> <arg name="arduino" default="false"/>
<!-- mavros --> <!-- mavros -->
@@ -18,11 +16,12 @@
<arg name="fcu_conn" value="$(arg fcu_conn)"/> <arg name="fcu_conn" value="$(arg fcu_conn)"/>
<arg name="fcu_ip" value="$(arg fcu_ip)"/> <arg name="fcu_ip" value="$(arg fcu_ip)"/>
<arg name="gcs_bridge" value="$(arg gcs_bridge)"/> <arg name="gcs_bridge" value="$(arg gcs_bridge)"/>
<arg name="viz" value="$(arg viz)"/> <arg name="viz" value="true"/>
</include> </include>
<!-- web server -->
<include file="$(find clever)/launch/web_server.launch" if="$(arg web_server)"/> <!-- web server, serving /home/pi/catkin_ws/src/clever/clever/static -->
<node name="web_server" pkg="clever" type="monkey" output="screen" if="$(arg web_server)" respawn="true" respawn_delay="5"/>
<!-- web video server --> <!-- web video server -->
<node name="web_video_server" pkg="web_video_server" type="web_video_server" if="$(arg web_video_server)" required="false" respawn="true" respawn_delay="5"/> <node name="web_video_server" pkg="web_video_server" type="web_video_server" if="$(arg web_video_server)" required="false" respawn="true" respawn_delay="5"/>
@@ -30,6 +29,12 @@
<!-- aruco vpe --> <!-- aruco vpe -->
<include file="$(find clever)/launch/aruco.launch" if="$(arg aruco)"/> <include file="$(find clever)/launch/aruco.launch" if="$(arg aruco)"/>
<!-- optical flow -->
<node pkg="nodelet" type="nodelet" name="optical_flow" args="load clever/optical_flow nodelet_manager" if="$(arg optical_flow)" clear_params="true">
<remap from="image" to="main_camera/image_raw"/>
<remap from="camera_info" to="main_camera/camera_info"/>
</node>
<!-- main nodelet manager --> <!-- main nodelet manager -->
<node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" clear_params="true"> <node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager" output="screen" clear_params="true">
<param name="num_worker_threads" value="2"/> <param name="num_worker_threads" value="2"/>
@@ -52,11 +57,6 @@
<!-- rc backend --> <!-- rc backend -->
<node name="rc" pkg="clever" type="rc" output="screen" if="$(arg rc)"/> <node name="rc" pkg="clever" type="rc" output="screen" if="$(arg rc)"/>
<!-- FPV video streaming -->
<include file="$(find clever)/launch/fpv_camera.launch" if="$(arg fpv_camera)">
<arg name="device" value="$(arg fpv_camera_device)"/>
</include>
<!-- Arduino bridge --> <!-- Arduino bridge -->
<include file="$(find clever)/launch/arduino.launch" if="$(arg arduino)"/> <include file="$(find clever)/launch/arduino.launch" if="$(arg arduino)"/>
</launch> </launch>

View File

@@ -1,12 +0,0 @@
<launch>
<remap to="mavros/local_position/pose" from="local_position"/>
<remap to="mavros/setpoint_position/local" from="local_setpoint"/>
<node name="copter_visualization" pkg="mavros_extras" type="copter_visualization"/>
<param name="copter_visualization/fixed_frame_id" value="local_origin"/>
<param name="copter_visualization/child_frame_id" value="fcu"/>
<param name="copter_visualization/marker_scale" value="1"/>
<param name="copter_visualization/max_track_size" value="500"/>
<param name="copter_visualization/num_rotors" value="4"/>
</launch>

View File

@@ -1,4 +1,7 @@
<launch> <launch>
<!-- Camera position and orientation are represented by fcu -> main_camera_optical transform -->
<!-- static_transform_publisher arguments: x y z yaw pitch roll frame_id child_frame_id -->
<!-- clever 2 --> <!-- clever 2 -->
<!--<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0 0 -0.07 -1.5707963 0 3.1415926 fcu main_camera_optical"/>--> <!--<node pkg="tf2_ros" type="static_transform_publisher" name="main_camera_frame" args="0 0 -0.07 -1.5707963 0 3.1415926 fcu main_camera_optical"/>-->
@@ -20,4 +23,9 @@
<param name="image_width" value="320"/> <param name="image_width" value="320"/>
<param name="image_height" value="240"/> <param name="image_height" value="240"/>
</node> </node>
<!-- camera visualization markers -->
<node pkg="clever" type="camera_markers" ns="main_camera" name="main_camera_markers">
<param name="scale" value="3.0"/>
</node>
</launch> </launch>

View File

@@ -1,58 +1,95 @@
<launch> <launch>
<arg name="fcu_conn" default="uart"/> <arg name="fcu_conn" default="usb"/>
<arg name="fcu_ip" default="127.0.0.1"/> <arg name="fcu_ip" default="127.0.0.1"/>
<arg name="gcs_bridge" default="tcp"/> <arg name="gcs_bridge" default="tcp"/>
<arg name="viz" default="true"/> <arg name="viz" default="true"/>
<arg name="respawn" default="true"/> <arg name="respawn" default="true"/>
<node pkg="mavros" type="mavros_node" name="mavros" required="false" clear_params="true" respawn="$(arg respawn)" respawn_delay="5" output="screen"> <node pkg="mavros" type="mavros_node" name="mavros" required="false" clear_params="true" respawn="$(arg respawn)" respawn_delay="5" output="screen">
<!-- UART connection --> <!-- UART connection -->
<param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/> <param name="fcu_url" value="/dev/ttyAMA0:921600" if="$(eval fcu_conn is None or fcu_conn == 'uart')"/>
<!-- USB connection --> <!-- USB connection -->
<param name="fcu_url" value="/dev/ttyACM0" if="$(eval fcu_conn == 'usb')"/> <param name="fcu_url" value="/dev/ttyACM0" if="$(eval fcu_conn == 'usb')"/>
<!-- sitl --> <!-- sitl -->
<param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/> <param name="fcu_url" value="udp://@$(arg fcu_ip):14557" if="$(eval fcu_conn == 'udp')"/>
<!-- gcs bridge --> <!-- gcs bridge -->
<param name="gcs_url" value="tcp-l://0.0.0.0:5760" if="$(eval gcs_bridge == 'tcp')"/> <param name="gcs_url" value="tcp-l://0.0.0.0:5760" if="$(eval gcs_bridge == 'tcp')"/>
<param name="gcs_url" value="udp://0.0.0.0:14550@14550" if="$(eval gcs_bridge == 'udp')"/> <param name="gcs_url" value="udp://0.0.0.0:14550@14550" if="$(eval gcs_bridge == 'udp')"/>
<param name="gcs_url" value="udp-b://$(env ROS_IP):14550@14550" if="$(eval gcs_bridge == 'udp-b')"/> <param name="gcs_url" value="udp-b://$(env ROS_IP):14550@14550" if="$(eval gcs_bridge == 'udp-b')"/>
<param name="gcs_url" value="udp-pb://$(env ROS_IP):14550@14550" if="$(eval gcs_bridge == 'udp-pb')"/> <param name="gcs_url" value="udp-pb://$(env ROS_IP):14550@14550" if="$(eval gcs_bridge == 'udp-pb')"/>
<param name="gcs_url" value="" if="$(eval not gcs_bridge)"/> <param name="gcs_url" value="" if="$(eval not gcs_bridge)"/>
<param name="gcs_quiet_mode" value="true"/> <param name="gcs_quiet_mode" value="true"/>
<param name="conn/timeout" value="8"/> <param name="conn/timeout" value="8"/>
<!-- default px4 params --> <!-- default px4 params -->
<rosparam command="load" file="$(find mavros)/launch/px4_config.yaml"/> <rosparam command="load" file="$(find mavros)/launch/px4_config.yaml"/>
<!-- additional params --> <!-- rangefinders -->
<param name="local_position/frame_id" value="local_origin"/> <rosparam>
<param name="local_position/tf/send" value="true"/> distance_sensor:
<param name="local_position/tf/frame_id" value="local_origin"/> rangefinder_0:
<param name="local_position/tf/child_frame_id" value="fcu"/> id: 0
<param name="global_position/tf/send" value="false"/> frame_id: "rangefinder"
<param name="imu/frame_id" value="fcu"/> orientation: PITCH_270
<rosparam param="plugin_blacklist"> field_of_view: 0.5
- safety_area rangefinder_1:
- image_pub id: 1
- vibration frame_id: "rangefinder"
- distance_sensor orientation: PITCH_270
- rangefinder field_of_view: 0.5
- 3dr_radio rangefinder_2_sub:
- actuator_control subscriber: true
- hil_controls id: 2
- vfr_hud orientation: PITCH_270
- px4flow rangefinder_3_sub:
- vision_speed_estimate subscriber: true
- fake_gps id: 3
- cam_imu_sync orientation: PITCH_270
- hil </rosparam>
- adsb
</rosparam> <!-- additional params -->
<param name="local_position/frame_id" value="local_origin"/>
<param name="local_position/tf/send" value="true"/>
<param name="local_position/tf/frame_id" value="local_origin"/>
<param name="local_position/tf/child_frame_id" value="fcu"/>
<param name="global_position/tf/send" value="false"/>
<param name="imu/frame_id" value="fcu"/>
<rosparam param="plugin_blacklist">
- safety_area
- image_pub
- vibration
- rangefinder
- 3dr_radio
- actuator_control
- hil_controls
- vfr_hud
- vision_speed_estimate
- fake_gps
- cam_imu_sync
- hil
- adsb
- waypoint
- obstacle_distance
- setpoint_accel
- trajectory
- wind_estimation
</rosparam>
</node> </node>
<!-- Rangefinders frame -->
<node pkg="tf2_ros" type="static_transform_publisher" name="rangefinder_frame" args="0 0 -0.05 0 1.5707963268 0 fcu rangefinder"/>
<!-- Copter visualization --> <!-- Copter visualization -->
<include file="$(find clever)/launch/copter_visualization.launch" if="$(arg viz)"/> <node name="copter_visualization" pkg="mavros_extras" type="copter_visualization" if="$(arg viz)">
<remap to="mavros/local_position/pose" from="local_position"/>
<remap to="mavros/setpoint_position/local" from="local_setpoint"/>
<param name="fixed_frame_id" value="local_origin"/>
<param name="child_frame_id" value="fcu"/>
<param name="marker_scale" value="1"/>
<param name="max_track_size" value="20"/>
<param name="num_rotors" value="4"/>
</node>
</launch> </launch>

View File

@@ -7,11 +7,11 @@
<arg name="fcu_conn" value="udp"/> <arg name="fcu_conn" value="udp"/>
<arg name="fcu_ip" value="$(arg ip)"/> <arg name="fcu_ip" value="$(arg ip)"/>
<arg name="gcs_bridge" value="false"/> <arg name="gcs_bridge" value="false"/>
<arg name="optical_flow" value="false"/>
<arg name="web_server" default="false"/>
<arg name="web_video_server" default="false"/> <arg name="web_video_server" default="false"/>
<arg name="main_camera" default="false"/> <arg name="main_camera" default="false"/>
<arg name="fpv_camera" default="false"/>
<arg name="rosbridge" value="$(arg rosbridge)"/> <arg name="rosbridge" value="$(arg rosbridge)"/>
<arg name="web_server" default="false"/>
<arg name="aruco" default="false"/> <arg name="aruco" default="false"/>
</include> </include>
</launch> </launch>

View File

@@ -1,5 +0,0 @@
<launch>
<node name="web_server" pkg="clever" type="web_server.py" output="screen">
<param name="path" value="$(find clever)/static"/>
</node>
</launch>

View File

@@ -1,3 +1,8 @@
<library path="lib/libclever">
<class name="clever/optical_flow" type="OpticalFlow" base_class_type="nodelet::Nodelet">
<description/>
</class>
</library>
<library path="lib/libfcu_horiz"> <library path="lib/libfcu_horiz">
<class name="clever/fcu_horiz" type="FcuHoriz" base_class_type="nodelet::Nodelet"> <class name="clever/fcu_horiz" type="FcuHoriz" base_class_type="nodelet::Nodelet">
<description/> <description/>

View File

@@ -1,2 +1,3 @@
flask==0.12.2 flask==0.12.2
geopy==1.11.0 geopy==1.11.0
pymavlink==2.2.10

View File

@@ -0,0 +1,101 @@
/*
* Visualization marker for camera alignment
* Copyright (C) 2018 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 <string>
#include <ros/ros.h>
#include <sensor_msgs/CameraInfo.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/MarkerArray.h>
using namespace visualization_msgs;
double markers_scale;
std::string camera_frame;
MarkerArray createMarkers() {
MarkerArray markers;
Marker lens;
lens.header.frame_id = camera_frame;
lens.ns = "camera_markers";
lens.id = 0;
lens.action = Marker::ADD;
lens.type = visualization_msgs::Marker::CYLINDER;
lens.frame_locked = true;
lens.scale.x = 0.013 * markers_scale;
lens.scale.y = 0.013 * markers_scale;
lens.scale.z = 0.015 * markers_scale;
lens.color.r = 0.3;
lens.color.g = 0.3;
lens.color.b = 0.3;
lens.color.a = 0.9;
lens.pose.position.z = 0.0075 * markers_scale;
lens.pose.orientation.w = 1;
Marker board;
board.header.frame_id = camera_frame;
board.ns = "camera_markers";
board.id = 1;
board.action = Marker::ADD;
board.type = Marker::CUBE;
board.frame_locked = true;
board.scale.x = 0.024 * markers_scale;
board.scale.y = 0.024 * markers_scale;
board.scale.z = 0.001 * markers_scale;
board.color.r = 0.0;
board.color.g = 0.8;
board.color.b = 0.0;
board.color.a = 0.9;
board.pose.orientation.w = 1;
Marker wire;
wire.header.frame_id = camera_frame;
wire.ns = "camera_markers";
wire.id = 2;
wire.action = Marker::ADD;
wire.type = Marker::CUBE;
wire.frame_locked = true;
wire.scale.x = 0.014 * markers_scale;
wire.scale.y = 0.04 * markers_scale;
wire.scale.z = 0.001 * markers_scale;
wire.color.r = 0.9;
wire.color.g = 0.9;
wire.color.b = 1.0;
wire.color.a = 0.8;
wire.pose.position.x = 0;
wire.pose.position.y = (0.01 + 0.02) * markers_scale;
wire.pose.position.z = 0.002 * markers_scale;
wire.pose.orientation.w = 1;
markers.markers.push_back(lens);
markers.markers.push_back(board);
markers.markers.push_back(wire);
return markers;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "camera_markers", ros::init_options::AnonymousName);
ros::NodeHandle nh, nh_priv("~");
nh_priv.param("scale", markers_scale, 1.0);
// wait for camera info
auto camera_info = ros::topic::waitForMessage<sensor_msgs::CameraInfo>("camera_info", nh);
camera_frame = camera_info->header.frame_id;
ros::Publisher markers_pub = nh.advertise<visualization_msgs::MarkerArray>("camera_markers", 1, true);
markers_pub.publish(createMarkers());
ROS_INFO("Camera markers initialized");
ros::spin();
}

85
clever/src/interactive.py Executable file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python
import copy
import rospy
import tf.transformations as t
from interactive_markers.interactive_marker_server import InteractiveMarkerServer
from visualization_msgs.msg import Marker, InteractiveMarker, InteractiveMarkerControl, InteractiveMarkerFeedback
from clever import srv
def make_box(msg):
marker = Marker()
marker.type = Marker.CUBE
marker.scale.x = msg.scale * 0.3
marker.scale.y = msg.scale * 0.3
marker.scale.z = msg.scale * 0.3
marker.color.r = 0.5
marker.color.g = 0.5
marker.color.b = 0.5
marker.color.a = 1.0
marker.pose.orientation.w = 1
return marker
def make_box_control(msg):
control = InteractiveMarkerControl()
control.always_visible = True
control.orientation.w = 1
control.markers.append(make_box(msg))
msg.controls.append(control)
return control
def make_quadcopter_marker():
marker = InteractiveMarker()
marker.header.frame_id = 'fcu'
marker.header.stamp = rospy.get_rostime()
marker.scale = 1
marker.pose.orientation.w = 1
marker.name = 'quadcopter'
marker.description = 'Quadcopter'
make_box_control(marker)
control = InteractiveMarkerControl()
control.orientation.w = 1
control.orientation.x = 0
control.orientation.y = 1
control.orientation.z = 0
control.interaction_mode = InteractiveMarkerControl.MOVE_ROTATE
marker.controls.append(copy.deepcopy(control))
control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS
marker.controls.append(control)
return marker
navigate = rospy.ServiceProxy('navigate', srv.Navigate)
def process_feedback(feedback):
if feedback.event_type != InteractiveMarkerFeedback.MOUSE_UP:
return
p = feedback.pose.position
o = feedback.pose.orientation
yaw = t.euler_from_quaternion((o.x, o.y, o.z, o.w), axes='rzyx')[0]
rospy.loginfo('Navigate to %s', p)
rospy.loginfo(navigate(x=p.x, y=p.y, z=p.z, yaw=yaw, speed=2,
frame_id=feedback.header.frame_id, auto_arm=True))
rospy.init_node('quadcopter_im')
server = InteractiveMarkerServer('quadcopter_im')
int_marker = make_quadcopter_marker()
server.insert(int_marker, process_feedback)
server.applyChanges()
rospy.loginfo('Interactive quadcopter marker initialized')
rospy.spin()

3
clever/src/monkey Executable file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
exec /home/pi/monkey/build/monkey --port 80 --workers 1

200
clever/src/optical_flow.cpp Normal file
View File

@@ -0,0 +1,200 @@
/*
* Optical Flow node for PX4
* Copyright (C) 2018 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 <vector>
#include <cmath>
#include <nodelet/nodelet.h>
#include <pluginlib/class_list_macros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <tf/transform_datatypes.h>
#include <tf2/exceptions.h>
#include <tf2/convert.h>
#include <tf2_ros/transform_listener.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#include <mavros_msgs/OpticalFlowRad.h>
#include <sensor_msgs/Imu.h>
#include <geometry_msgs/Vector3Stamped.h>
#include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/TwistStamped.h>
using cv::Mat;
class OpticalFlow : public nodelet::Nodelet
{
public:
OpticalFlow():
camera_matrix_(3, 3, CV_64F),
dist_coeffs_(8, 1, CV_64F),
tf_listener_(tf_buffer_)
{}
private:
ros::Publisher flow_pub_, velo_pub_, shift_pub_;
ros::Time prev_stamp_;
std::string fcu_frame_id_;
image_transport::CameraSubscriber img_sub_;
image_transport::Publisher img_pub_;
mavros_msgs::OpticalFlowRad flow_;
int roi_, roi_2_;
Mat hann_;
Mat prev_, curr_;
Mat camera_matrix_, dist_coeffs_;
tf2_ros::Buffer tf_buffer_;
tf2_ros::TransformListener tf_listener_;
void onInit()
{
ros::NodeHandle& nh = getNodeHandle();
ros::NodeHandle& nh_priv = getPrivateNodeHandle();
image_transport::ImageTransport it(nh);
image_transport::ImageTransport it_priv(nh_priv);
nh_priv.param<std::string>("mavros/local_position/tf/child_frame_id", fcu_frame_id_, "fcu");
nh_priv.param("roi", roi_, 128);
roi_2_ = roi_ / 2;
img_sub_ = it.subscribeCamera("image", 1, &OpticalFlow::flow, this);
img_pub_ = it_priv.advertise("debug", 1);
flow_pub_ = nh.advertise<mavros_msgs::OpticalFlowRad>("mavros/px4flow/raw/send", 1);
velo_pub_ = nh_priv.advertise<geometry_msgs::TwistStamped>("angular_velocity", 1);
shift_pub_ = nh_priv.advertise<geometry_msgs::Vector3Stamped>("shift", 1);
flow_.integrated_xgyro = NAN; // no IMU available
flow_.integrated_ygyro = NAN;
flow_.integrated_zgyro = NAN;
flow_.time_delta_distance_us = 0;
flow_.distance = -1; // no distance sensor available
flow_.temperature = 0;
ROS_INFO("Optical Flow initialized");
}
void parseCameraInfo(const sensor_msgs::CameraInfoConstPtr &cinfo) {
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
camera_matrix_.at<double>(i, j) = cinfo->K[3 * i + j];
}
}
for (int k = 0; k < cinfo->D.size(); k++) {
dist_coeffs_.at<double>(k) = cinfo->D[k];
}
}
void drawFlow(Mat& frame, double x, double y, double quality) const
{
double brightness = (1 - quality) * 25;;
cv::Scalar color(brightness, brightness, brightness);
double radius = std::sqrt(x * x + y * y);
// draw a circle and line indicating the shift direction...
cv::Point center(frame.cols >> 1, frame.rows >> 1);
cv::circle(frame, center, (int)(radius*5), color, 3, cv::LINE_AA);
cv::line(frame, center, cv::Point(center.x + (int)(x*5), center.y + (int)(y*5)), color, 3, cv::LINE_AA);
}
void flow(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr& cinfo)
{
parseCameraInfo(cinfo);
auto img = cv_bridge::toCvShare(msg, "mono8")->image;
// Apply ROI
if (roi_ != 0) {
img = img(cv::Rect((msg->width / 2 - roi_2_), (msg->height / 2 - roi_2_), roi_, roi_));
}
img.convertTo(curr_, CV_64F);
if (prev_.empty()) {
prev_ = curr_.clone();
prev_stamp_ = msg->header.stamp;
cv::createHanningWindow(hann_, curr_.size(), CV_64F);
} else {
double response;
cv::Point2d shift = cv::phaseCorrelate(prev_, curr_, hann_, &response);
// Publish raw shift in pixels
static geometry_msgs::Vector3Stamped shift_vec;
shift_vec.header.stamp = msg->header.stamp;
shift_vec.header.frame_id = msg->header.frame_id;
shift_vec.vector.x = shift.x;
shift_vec.vector.y = shift.y;
shift_pub_.publish(shift_vec);
// Undistort flow in pixels
uint32_t flow_center_x = msg->width / 2;
uint32_t flow_center_y = msg->height / 2;
shift.x += flow_center_x;
shift.y += flow_center_y;
std::vector<cv::Point2d> points_dist = { shift };
std::vector<cv::Point2d> points_undist(1);
cv::undistortPoints(points_dist, points_undist, camera_matrix_, dist_coeffs_, cv::noArray(), camera_matrix_);
points_undist[0].x -= flow_center_x;
points_undist[0].y -= flow_center_y;
// Calculate flow in radians
double focal_length_x = camera_matrix_.at<double>(0, 0);
double focal_length_y = camera_matrix_.at<double>(1, 1);
double flow_x = atan2(points_undist[0].x, focal_length_x);
double flow_y = atan2(points_undist[0].y, focal_length_y);
// // Convert to FCU frame
static geometry_msgs::Vector3Stamped flow_camera, flow_fcu;
flow_camera.header.frame_id = msg->header.frame_id;
flow_camera.header.stamp = msg->header.stamp;
flow_camera.vector.x = flow_y; // +y means counter-clockwise rotation around Y axis
flow_camera.vector.y = -flow_x; // +x means clockwise rotation around X axis
tf_buffer_.transform(flow_camera, flow_fcu, fcu_frame_id_);
// Calculate integration time
ros::Duration integration_time = msg->header.stamp - prev_stamp_;
uint32_t integration_time_us = integration_time.toSec() * 1.0e6;
// Publish flow in fcu frame
flow_.header.stamp = /*prev_stamp_*/ msg->header.stamp;
flow_.integration_time_us = integration_time_us;
flow_.integrated_x = flow_fcu.vector.x;
flow_.integrated_y = flow_fcu.vector.y;
flow_.quality = (uint8_t)(response * 255);
flow_pub_.publish(flow_);
// Publish debug image
if (img_pub_.getNumSubscribers() > 0) {
// publish debug image
drawFlow(img, shift_vec.vector.x, shift_vec.vector.y, response);
cv_bridge::CvImage out_msg;
out_msg.header.frame_id = msg->header.frame_id;
out_msg.header.stamp = msg->header.stamp;
out_msg.encoding = sensor_msgs::image_encodings::MONO8;
out_msg.image = img;
img_pub_.publish(out_msg.toImageMsg());
}
// Publish estimated angular velocity
static geometry_msgs::TwistStamped velo;
velo.header.stamp = msg->header.stamp;
velo.header.frame_id = fcu_frame_id_;
velo.twist.angular.x = flow_.integrated_x / integration_time.toSec();
velo.twist.angular.y = flow_.integrated_y / integration_time.toSec();
velo_pub_.publish(velo);
prev_ = curr_.clone();
prev_stamp_ = msg->header.stamp;
}
}
};
PLUGINLIB_EXPORT_CLASS(OpticalFlow, nodelet::Nodelet)

View File

@@ -10,6 +10,7 @@
#include "std_msgs/String.h" #include "std_msgs/String.h"
#include "mavros_msgs/State.h" #include "mavros_msgs/State.h"
#include "mavros_msgs/ManualControl.h" #include "mavros_msgs/ManualControl.h"
#include "mavros_msgs/Mavlink.h"
struct ControlMessage struct ControlMessage
{ {
@@ -27,6 +28,9 @@ public:
std::thread t(&RC::socketThread, this); std::thread t(&RC::socketThread, this);
t.detach(); t.detach();
std::thread gcst(&RC::fakeGCSThread, this);
gcst.detach();
initLatchedState(); initLatchedState();
} }
@@ -35,6 +39,7 @@ private:
ros::Subscriber state_sub; ros::Subscriber state_sub;
ros::Publisher state_pub; ros::Publisher state_pub;
ros::Timer state_timeout_timer; ros::Timer state_timeout_timer;
ros::Time last_manual_control{0};
mavros_msgs::StateConstPtr state_msg; mavros_msgs::StateConstPtr state_msg;
void handleState(const mavros_msgs::StateConstPtr& state) void handleState(const mavros_msgs::StateConstPtr& state)
@@ -70,6 +75,37 @@ private:
state_pub.publish(unknown_state); state_pub.publish(unknown_state);
} }
void fakeGCSThread()
{
// Awful workaround for fixing PX4 not sending STATUSTEXTs
// if there is no GCS hearbeats.
// TODO: use timer
// TODO: remove, when PX4 get this fixed.
ros::Publisher mavlink_pub = nh.advertise<mavros_msgs::Mavlink>("mavlink/to", 1);
// HEARTBEAT from GCS message
mavros_msgs::Mavlink hb;
hb.framing_status = mavros_msgs::Mavlink::FRAMING_OK;
hb.magic = mavros_msgs::Mavlink::MAVLINK_V20;
hb.len = 9;
hb.incompat_flags = 0;
hb.compat_flags = 0;
hb.seq = 0;
hb.sysid = 255;
hb.compid = 0;
hb.checksum = 26460;
hb.payload64.push_back(342282393542983680);
hb.payload64.push_back(3);
ros::Rate rate(1);
while (ros::ok()) {
if (ros::Time::now() - last_manual_control < ros::Duration(8)) {
mavlink_pub.publish(hb);
}
rate.sleep();
}
}
int createSocket(int port) int createSocket(int port)
{ {
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -123,6 +159,8 @@ private:
manual_control_msg.z = msg->z; manual_control_msg.z = msg->z;
manual_control_msg.r = msg->r; manual_control_msg.r = msg->r;
manual_control_pub.publish(manual_control_msg); manual_control_pub.publish(manual_control_msg);
last_manual_control = ros::Time::now();
} }
} }
}; };

173
clever/src/selfcheck.py Executable file
View File

@@ -0,0 +1,173 @@
#!/usr/bin/env python
import math
from subprocess import Popen, PIPE
import re
import traceback
import rospy
from std_srvs.srv import Trigger
from sensor_msgs.msg import Image, CameraInfo, NavSatFix, Imu
from mavros_msgs.msg import State
from geometry_msgs.msg import PoseStamped, TwistStamped
# TODO: roscore is running
# TODO: disk free space
# TODO: local_origin, fcu, fcu_horiz
# TODO: rc service
# TODO: perform commander check in PX4
# TODO: check if FCU params setter succeed
# TODO: selfcheck ROS service (with blacklists for checks)
rospy.init_node('selfcheck')
failures = []
def failure(text, *args):
failures.append(text % args)
def check(name):
def inner(fn):
def wrapper(*args, **kwargs):
failures[:] = []
try:
fn(*args, **kwargs)
for f in failures:
rospy.logwarn('%s: %s', name, f)
except Exception as e:
traceback.print_exc()
rospy.logwarn('%s: exception occured', name)
return
if not failures:
rospy.loginfo('%s: OK', name)
return wrapper
return inner
@check('FCU')
def check_fcu():
try:
state = rospy.wait_for_message('mavros/state', State, timeout=3)
if not state.connected:
failure('No connection to the FCU')
except rospy.ROSException:
failure('No MAVROS state')
@check('Camera')
def check_camera(name):
try:
rospy.wait_for_message(name + '/image_raw', Image, timeout=1)
except rospy.ROSException:
failure('No %s camera images' % name)
try:
rospy.wait_for_message(name + '/camera_info', CameraInfo, timeout=3)
except rospy.ROSException:
failure('No %s camera camera info' % name)
@check('Aruco detector')
def check_aruco():
try:
rospy.wait_for_message('aruco_pose/debug', Image, timeout=1)
except rospy.ROSException:
failure('No aruco_pose/debug messages')
@check('Simple offboard node')
def check_simpleoffboard():
try:
rospy.wait_for_service('navigate', timeout=3)
rospy.wait_for_service('get_telemetry', timeout=3)
rospy.wait_for_service('land', timeout=3)
except rospy.ROSException:
failure('No simple_offboard services')
@check('IMU')
def check_imu():
try:
rospy.wait_for_message('mavros/imu/data', Imu, timeout=1)
except rospy.ROSException:
failure('No IMU data')
@check('Local position')
def check_local_position():
try:
rospy.wait_for_message('mavros/local_position/pose', PoseStamped, timeout=1)
except rospy.ROSException:
failure('No local position')
@check('Velocity estimation')
def check_velocity():
try:
velocity = rospy.wait_for_message('mavros/local_position/velocity', TwistStamped, timeout=1)
horiz = math.hypot(velocity.twist.linear.x, velocity.twist.linear.y)
vert = velocity.twist.linear.z
if abs(horiz) > 0.1:
failure('Horizontal velocity estimation is %s m/s; is the copter staying still?' % horiz)
if abs(vert) > 0.1:
failure('Vertical velocity estimation is %s m/s; is the copter staying still?' % vert)
except rospy.ROSException:
failure('No velocity estimation')
@check('Global position (GPS)')
def check_global_position():
try:
rospy.wait_for_message('mavros/global_position/global', NavSatFix, timeout=2)
except rospy.ROSException:
failure('No global position')
@check('Boot duration')
def check_boot_duration():
proc = Popen('systemd-analyze', stdout=PIPE)
proc.wait()
output = proc.communicate()[0]
r = re.compile(r'([\d\.]+)s$')
duration = float(r.search(output).groups()[0])
if duration > 15:
failure('long Raspbian boot duration: %ss', duration)
@check('CPU usage')
def check_cpu_usage():
WHITELIST = 'nodelet',
CMD = "top -n 1 -b -i | tail -n +8 | awk '{ printf(\"%-8s\\t%-8s\\t%-8s\\n\", $1, $9, $12); }'"
proc = Popen(CMD, stdout=PIPE, shell=True)
proc.wait()
output = proc.communicate()[0]
processes = output.split('\n')
for process in processes:
if not process:
continue
pid, cpu, cmd = process.split('\t')
if cmd.strip() not in WHITELIST and float(cpu) > 30:
failure('High CPU usage (%s%%) detected: %s (PID %s)',
cpu.strip(), cmd.strip(), pid.strip())
def selfcheck():
check_fcu()
check_imu()
check_local_position()
check_velocity()
check_global_position()
check_camera('main_camera')
check_aruco()
check_simpleoffboard()
check_cpu_usage()
check_boot_duration()
if __name__ == '__main__':
rospy.loginfo('Performing selfcheck...')
selfcheck()

View File

@@ -83,12 +83,13 @@ AUTO_ARM = AUTO_OFFBOARD and rospy.get_param('~auto_arm', True)
OFFBOARD_TIMEOUT = rospy.Duration(rospy.get_param('~offboard_timeout', 3)) OFFBOARD_TIMEOUT = rospy.Duration(rospy.get_param('~offboard_timeout', 3))
ARM_TIMEOUT = rospy.Duration(rospy.get_param('~arm_timeout', 5)) ARM_TIMEOUT = rospy.Duration(rospy.get_param('~arm_timeout', 5))
LOCAL_POSITION_TIMEOUT = rospy.Duration(rospy.get_param('~local_position_timeout', 0.5)) LOCAL_POSITION_TIMEOUT = rospy.Duration(rospy.get_param('~local_position_timeout', 0.5))
NAVIGATE_AFTER_ARMED = rospy.Duration(rospy.get_param('~navigate_after_armed', False)) NAVIGATE_AFTER_ARMED = rospy.Duration(rospy.get_param('~navigate_after_armed', True))
TRANSFORM_TIMEOUT = rospy.Duration(rospy.get_param('~transform_timeout', 3)) TRANSFORM_TIMEOUT = rospy.Duration(rospy.get_param('~transform_timeout', 3))
SETPOINT_RATE = rospy.get_param('~setpoint_rate', 30) SETPOINT_RATE = rospy.get_param('~setpoint_rate', 30)
LOCAL_FRAME = rospy.get_param('~local_frame', 'local_origin') LOCAL_FRAME = rospy.get_param('~local_frame', 'local_origin')
LAND_MODE = rospy.get_param('~land_mode', 'AUTO.LAND') LAND_MODE = rospy.get_param('~land_mode', 'AUTO.LAND')
LAND_TIMEOUT = rospy.Duration(rospy.get_param('~land_timeout', 2)) LAND_TIMEOUT = rospy.Duration(rospy.get_param('~land_timeout', 2))
DEFAULT_SPEED = rospy.get_param('~default_speed', 0.5)
def offboard_and_arm(): def offboard_and_arm():
@@ -120,6 +121,8 @@ def offboard_and_arm():
ps = PoseStamped() ps = PoseStamped()
vs = Vector3Stamped() vs = Vector3Stamped()
pt = PositionTarget()
at = AttitudeTarget()
BRAKE_TIME = rospy.Duration(0) BRAKE_TIME = rospy.Duration(0)
@@ -164,7 +167,7 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True):
if update_frame: if update_frame:
ps.header.frame_id = req.frame_id or LOCAL_FRAME ps.header.frame_id = req.frame_id or LOCAL_FRAME
ps.pose.position = Point(getattr(req, 'x', 0), getattr(req, 'y', 0), req.z) ps.pose.position = Point(getattr(req, 'x', 0), getattr(req, 'y', 0), req.z)
ps.pose.orientation = orientation_from_euler(0, 0, req.yaw) ps.pose.orientation = orientation_from_euler(0, 0, req.yaw, axes='sxyz')
current_nav_finish = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) current_nav_finish = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT)
if isinstance(req, srv.NavigateGlobalRequest): if isinstance(req, srv.NavigateGlobalRequest):
@@ -183,13 +186,14 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True):
current_nav_start_stamp, req.speed) current_nav_start_stamp, req.speed)
yaw_rate_flag = math.isnan(req.yaw) yaw_rate_flag = math.isnan(req.yaw)
msg = PositionTarget(coordinate_frame=PT.FRAME_LOCAL_NED, msg = pt
type_mask=PT.IGNORE_VX + PT.IGNORE_VY + PT.IGNORE_VZ + msg.coordinate_frame = PT.FRAME_LOCAL_NED
PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + msg.type_mask = PT.IGNORE_VX + PT.IGNORE_VY + PT.IGNORE_VZ + \
(PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE), PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + \
position=setpoint, (PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE)
yaw=euler_from_orientation(current_nav_finish.pose.orientation, 'szyx')[2] - math.pi / 2, msg.position = setpoint
yaw_rate=req.yaw_rate) msg.yaw = euler_from_orientation(current_nav_finish.pose.orientation, 'sxyz')[2]
msg.yaw_rate = req.yaw_rate
return position_pub, msg return position_pub, msg
elif isinstance(req, (srv.SetPositionRequest, srv.SetPositionGlobalRequest)): elif isinstance(req, (srv.SetPositionRequest, srv.SetPositionGlobalRequest)):
@@ -202,13 +206,14 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True):
pose_local.pose.position.x, pose_local.pose.position.y = global_to_local(req.lat, req.lon) pose_local.pose.position.x, pose_local.pose.position.y = global_to_local(req.lat, req.lon)
yaw_rate_flag = math.isnan(req.yaw) yaw_rate_flag = math.isnan(req.yaw)
msg = PositionTarget(coordinate_frame=PT.FRAME_LOCAL_NED, msg = pt
type_mask=PT.IGNORE_VX + PT.IGNORE_VY + PT.IGNORE_VZ + msg.coordinate_frame = PT.FRAME_LOCAL_NED
PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + msg.type_mask = PT.IGNORE_VX + PT.IGNORE_VY + PT.IGNORE_VZ + \
(PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE), PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + \
position=pose_local.pose.position, (PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE)
yaw=euler_from_orientation(pose_local.pose.orientation, 'szyx')[2] - math.pi / 2, msg.position = pose_local.pose.position
yaw_rate=req.yaw_rate) msg.yaw = euler_from_orientation(pose_local.pose.orientation, 'sxyz')[2]
msg.yaw_rate = req.yaw_rate
return position_pub, msg return position_pub, msg
elif isinstance(req, srv.SetVelocityRequest): elif isinstance(req, srv.SetVelocityRequest):
@@ -220,28 +225,33 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True):
vector_local = tf_buffer.transform(vs, LOCAL_FRAME, TRANSFORM_TIMEOUT) vector_local = tf_buffer.transform(vs, LOCAL_FRAME, TRANSFORM_TIMEOUT)
yaw_rate_flag = math.isnan(req.yaw) yaw_rate_flag = math.isnan(req.yaw)
msg = PositionTarget(coordinate_frame=PT.FRAME_LOCAL_NED, msg = pt
type_mask=PT.IGNORE_PX + PT.IGNORE_PY + PT.IGNORE_PZ + msg.coordinate_frame = PT.FRAME_LOCAL_NED
PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + msg.type_mask = PT.IGNORE_PX + PT.IGNORE_PY + PT.IGNORE_PZ + \
(PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE), PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + \
velocity=vector_local.vector, (PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE)
yaw=euler_from_orientation(pose_local.pose.orientation, 'szyx')[2] - math.pi / 2, msg.velocity = vector_local.vector
yaw_rate=req.yaw_rate) msg.yaw = euler_from_orientation(pose_local.pose.orientation, 'sxyz')[2]
msg.yaw_rate = req.yaw_rate
return position_pub, msg return position_pub, msg
elif isinstance(req, srv.SetAttitudeRequest): elif isinstance(req, srv.SetAttitudeRequest):
ps.header.frame_id = req.frame_id or LOCAL_FRAME ps.header.frame_id = req.frame_id or LOCAL_FRAME
ps.pose.orientation = orientation_from_euler(req.roll, req.pitch, req.yaw) ps.pose.orientation = orientation_from_euler(req.roll, req.pitch, req.yaw)
pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT)
msg = AttitudeTarget(orientation=pose_local.pose.orientation, msg = at
thrust=req.thrust, msg.orientation = pose_local.pose.orientation
type_mask=AT.IGNORE_YAW_RATE + AT.IGNORE_PITCH_RATE + AT.IGNORE_ROLL_RATE) msg.thrust = req.thrust
msg.type_mask = AT.IGNORE_YAW_RATE + AT.IGNORE_PITCH_RATE + AT.IGNORE_ROLL_RATE
return attitude_pub, msg return attitude_pub, msg
elif isinstance(req, srv.SetRatesRequest): elif isinstance(req, srv.SetRatesRequest):
msg = AttitudeTarget(thrust=req.thrust, msg = at
type_mask=AttitudeTarget.IGNORE_ATTITUDE, msg.thrust = req.thrust
body_rate=Vector3(req.roll_rate, req.pitch_rate, req.yaw_rate)) msg.type_mask = AT.IGNORE_ATTITUDE
msg.body_rate.x = req.roll_rate
msg.body_rate.y = req.pitch_rate
msg.body_rate.z = req.yaw_rate
return attitude_pub, msg return attitude_pub, msg
@@ -261,9 +271,12 @@ def handle(req):
rospy.logwarn('No connection to the FCU') rospy.logwarn('No connection to the FCU')
return {'message': 'No connection to the FCU'} return {'message': 'No connection to the FCU'}
if isinstance(req, (srv.NavigateRequest, srv.NavigateGlobalRequest)) and req.speed <= 0: if isinstance(req, (srv.NavigateRequest, srv.NavigateGlobalRequest)):
rospy.logwarn('Navigate speed must be greater than zero, %s passed') if req.speed < 0:
return {'message': 'Navigate speed must be greater than zero, %s passed' % req.speed} rospy.logwarn('Navigate speed must be positive, %s passed')
return {'message': 'Navigate speed must be positive, %s passed' % req.speed}
elif req.speed == 0:
req.speed = DEFAULT_SPEED
if isinstance(req, (srv.NavigateRequest, srv.NavigateGlobalRequest)) and \ if isinstance(req, (srv.NavigateRequest, srv.NavigateGlobalRequest)) and \
(pose is None or rospy.get_rostime() - pose.header.stamp > LOCAL_POSITION_TIMEOUT): (pose is None or rospy.get_rostime() - pose.header.stamp > LOCAL_POSITION_TIMEOUT):
@@ -280,13 +293,13 @@ def handle(req):
try: try:
with handle_lock: with handle_lock:
stamp = rospy.get_rostime() stamp = rospy.get_rostime()
current_req = req current_req = req
current_pub, current_msg = get_publisher_and_message(req, stamp, False) current_pub, current_msg = get_publisher_and_message(req, stamp, False)
rospy.loginfo('Topic: %s, message: %s', current_pub.name, current_msg) rospy.loginfo('Topic: %s, message: %s', current_pub.name, current_msg)
current_msg.header.stamp = stamp current_msg.header.stamp = stamp
current_pub.publish(current_msg) current_pub.publish(current_msg)
if req.auto_arm: if req.auto_arm:
offboard_and_arm() offboard_and_arm()

View File

@@ -1,60 +0,0 @@
#!/usr/bin/env python
import rospy
import subprocess
import re
from flask import Flask, send_from_directory, send_file, request, jsonify
rospy.init_node('web_server', disable_signals=True)
port = rospy.get_param('~port', 7070)
host = rospy.get_param('~host', '0.0.0.0')
serve_path = rospy.get_param('~path')
app = Flask(__name__)
@app.route('/')
def serve_index():
return send_from_directory(serve_path, 'index.html')
@app.route('/<path:path>')
def serve_static(path):
print serve_path, path
return send_from_directory(serve_path, path)
@app.route('/wifi_data/')
def get_wifi_data():
cur_ip = request.remote_addr
ip_signal = get_ip_signal()
return jsonify({'ip': cur_ip, 'signal': ip_signal[cur_ip]}), 200
def get_ip_signal():
wlan_interface = 'wlan0'
# Getting info about wifi client connected to access point. From here we know MAC and signal level
iwl = subprocess.check_output(['sudo', 'iw', 'dev', 'wlan0', 'station', 'dump']).splitlines()
mac_signal = {}
cur_client = ''
for line in iwl:
if line.find('Station') != -1:
cur_client = re.search(r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})', line, re.I).group()
if line.find('signal') != -1:
sg = re.search(r'(\[-?\d*\])', line, re.I).group()
mac_signal[cur_client] = re.sub(r'[\[\]]', '', sg)
ip_signal = {}
# Getting ip-mac mapping
ip_mac = subprocess.check_output(['arp', '-i', wlan_interface]).splitlines()
for line in ip_mac:
mac = re.search(r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})', line, re.I)
if mac is not None:
mac = mac.group()
if mac in mac_signal:
ips = re.search(r'((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9])', line, re.I).group()
ip_signal[ips] = mac_signal[mac]
return ip_signal
rospy.loginfo('Serving on %s:%s', host, port)
app.run(host=host, port=port, threaded=True)

13
clever/static/index.html Normal file
View File

@@ -0,0 +1,13 @@
<h1>CLEVER Drone Kit Tools</h1>
<ul>
<!-- <li><a href="">View user reference</a> (<a href="http://clever.copterexpress.com">http://clever.copterexpress.com</a> snapshot)</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> -->
</ul>
<script type="text/javascript">
document.querySelector("#wvs").href = location.origin + ':8080';
document.querySelector("#butterfly").href = location.origin + ':57575';
</script>

6
deploy/butterfly.service Normal file
View File

@@ -0,0 +1,6 @@
[Unit]
Description=Butterfly Terminal Server
[Service]
ExecStart=/usr/local/bin/butterfly.server.py --host="0.0.0.0" --unsecure
User=pi

5
deploy/butterfly.socket Normal file
View File

@@ -0,0 +1,5 @@
[Socket]
ListenStream=57575
[Install]
WantedBy=sockets.target

57
deploy/monkey Normal file
View File

@@ -0,0 +1,57 @@
# Default Host - Configuration
# ============================
# Here the variable principals of the program are defined in respect
# to the configuration of the different types of directives.
[HOST]
# ServerName:
# -----------
# Allow you to set a host and domain name (e.g monkey.linuxchile.cl). If
# you are working in a local network just set your IP address or if you
# are working like localhost set your loopback address (127.0.0.1).
ServerName 0.0.0.0
# DocumentRoot:
# -------------
# This variable corresponds to the location of the main server directory
# of the web pages, where the files of your site are located.
#
# Example:
# DocumentRoot /home/krypton/htdocs
DocumentRoot /home/pi/catkin_ws/src/clever/clever/static
# Redirect:
# ---------
# Under specific conditions, you may want the server performs a HTTP
# redirect when this Virtual Host is reach. If that is the case, append
# to the Redirect key the value of the address where to redirect the
# HTTP client.
#
# Redirect http://monkey-project.com
[LOGGER]
# AccessLog:
# ----------
# Registration file of correct request.
AccessLog /home/pi/monkey/build/log/access.log
# ErrorLog:
# ---------
# Registration file of incorrect request.
ErrorLog /home/pi/monkey/build/log/error.log
[ERROR_PAGES]
404 404.html
[HANDLERS]
# FastCGI
# =======
# Match /.*\.php fastcgi
# CGI
# ===
# Match /cgi-bin/.*\.cgi cgi

View File

@@ -1,4 +1,6 @@
Использование внешнего 3G-модема Использование внешнего 3G-модема
=== ===
Использование внешнего 3G-модема на Raspberry возможно с помощью пакета `sakis3g`.
TODO TODO

View File

@@ -5,15 +5,15 @@
«Клевер» — это учебный конструктор программируемого квадрокоптера, состоящего из популярных открытых компонентов, а также набор необходимой документации и библиотек для работы с ним. «Клевер» — это учебный конструктор программируемого квадрокоптера, состоящего из популярных открытых компонентов, а также набор необходимой документации и библиотек для работы с ним.
Набор включает в себя полетный контроллер PixHawk/PixRacer с полетным стеком PX4, Raspberry Pi 3 в качестве управлящего бортового компьютера, модуль камеры для реализации полетов с использованием компьютерного зрения, а также набор различных датчиков и другой периферии. Набор включает в себя полетный контроллер Pixhawk/Pixracer с полетным стеком PX4, Raspberry Pi 3 в качестве управлящего бортового компьютера, модуль камеры для реализации полетов с использованием компьютерного зрения, а также набор различных датчиков и другой периферии.
На базе точно такой же платформы были созданы многие «большие» проекты компании Copter Express, например, дроны для [пиар-акций по автономной доставке пиццы](https://www.youtube.com/watch?v=hmkAoZOtF58) (Самара, Казань); дрон-доставщик кофе в Сколково, мониторинговый дрон с зарядной станцией, дроны-победители на полевых испытаниях «[Робокросс-2016](https://www.youtube.com/watch?v=dGbDaz_VmYU)», «[Робокросс-2017](https://youtu.be/AQnd2CRczbQ)» и многие другие. На базе точно такой же платформы были созданы многие «большие» проекты компании Copter Express, например, дроны для [пиар-акций по автономной доставке пиццы](https://www.youtube.com/watch?v=hmkAoZOtF58) (Самара, Казань); дрон-доставщик кофе в Сколково, мониторинговый дрон с зарядной станцией, дроны-победители на полевых испытаниях «[Робокросс-2016](https://www.youtube.com/watch?v=dGbDaz_VmYU)», «[Робокросс-2017](https://youtu.be/AQnd2CRczbQ)» и многие другие.
Для того, чтобы научиться собирать, настраивать, пилотировать и программировать автономный дрон «Клевер», воспользуйтесь этим учебником. Для того, чтобы научиться собирать, настраивать, пилотировать и программировать автономный дрон «Клевер», воспользуйтесь этим учебником.
Если вы детально изучили наш gitbook, но так и не нашли ответа на свой вопрос, напишите в чат техподдержки и наши специалисты вам с радостью ответят https://t.me/COEXHelpdesk . Если вы детально изучили наш gitbook, но так и не нашли ответа на свой вопрос, напишите в чат техподдержки и наши специалисты вам с радостью ответят: https://t.me/COEXHelpdesk.
Также, у нас есть чат для программистов, которые разрабатывают под PX4, автономную навигацию в помещениях и рои дронов https://t.me/DroneCode . Также у нас есть чат для программистов, которые разрабатывают под PX4, автономную навигацию в помещениях и рои дронов https://t.me/DroneCode.
Образ для Raspberry Pi Образ для Raspberry Pi
---------------------- ----------------------
@@ -24,7 +24,7 @@
* Raspbian Stretch * Raspbian Stretch
* ROS Kinetic * ROS Kinetic
* Настроенную работу с сетью * Настроенную [работу с сетью](network.md)
* OpenCV * OpenCV
* mavros * mavros
* Набор ПО для работы с Клевером * Набор ПО для работы с Клевером

View File

@@ -1,17 +1,19 @@
# Summary # Summary
* [Введение](README.md) * [Введение](README.md)
* [Глоссарий](glossary.md)
* [Сборка](assemble.md) * [Сборка](assemble.md)
* [Первоначальная настройка](setup.md) * [Первоначальная настройка](setup.md)
* [Полетные режимы](modes.md) * [Полетные режимы](modes.md)
* [Raspberry Pi](raspberry.md) * [Raspberry Pi](raspberry.md)
* [Образ операционной системы на RPi](microsd_images.md) * [Образ операционной системы на RPi](microsd_images.md)
* [Подключение Raspberry Pi к PixHawk](connection.md) * [Подключение Raspberry Pi к Pixhawk](connection.md)
* [Подключение по Wi-Fi](wifi.md) * [Подключение по Wi-Fi](wifi.md)
* [Работа с QGroundControl через Wi-Fi](gcs_bridge.md) * [Работа с QGroundControl через Wi-Fi](gcs_bridge.md)
* [Прошивка PixHawk/PixRacer](firmware.md) * [Прошивка Pixhawk/Pixracer](firmware.md)
* [Пилотирование со смартфона](rc.md) * [Пилотирование со смартфона](rc.md)
* [SSH-доступ](ssh.md) * [SSH-доступ](ssh.md)
* [Устройство UART](uart.md)
* [Неисправности радиоаппаратуры](radioerrors.md) * [Неисправности радиоаппаратуры](radioerrors.md)
* [Безопасность](safety.md) * [Безопасность](safety.md)
* [Техника безопасности по пайке](tb.md) * [Техника безопасности по пайке](tb.md)
@@ -32,6 +34,10 @@
* [Использование 3G-модема](3g.md) * [Использование 3G-модема](3g.md)
* [Устройство сети RPi](network.md) * [Устройство сети RPi](network.md)
* [Работа с логами PX4](flight_logs.md) * [Работа с логами PX4](flight_logs.md)
* [Протокол MAVLink](mavlink.md)
* [Типы силовых разъемов](connectortypes.md)
* [Ошибки радиоаппаратуры](radioerrors1.md)
* [Настройка PID](calibratePID.md)
* Учебник * Учебник
* [Теория и видеоуроки](lessons.md) * [Теория и видеоуроки](lessons.md)
* [Учебно-методическое пособие](metod.md) * [Учебно-методическое пособие](metod.md)

View File

@@ -110,7 +110,7 @@ _Примечание_: указанное выше определение пр
Для правильной работы Vision Position Estimation необходимо \(через [QGroundControl](gcs_bridge.md)\) убедиться, что: Для правильной работы Vision Position Estimation необходимо \(через [QGroundControl](gcs_bridge.md)\) убедиться, что:
* Для PixHawk: Установлена прошивка с LPE \(local position estimator\). Для PixHawk необходимо [скачать прошивку `px4fmu-v2_lpe.px4`](https://github.com/PX4/Firmware/releases). Для PixRacer параметр `SYS_MC_EST_GROUP` должен быть установлен в `local_position_estimator, attitude_estimator_q`. * Для Pixhawk: Установлена прошивка с LPE \(local position estimator\). Для Pixhawk необходимо [скачать прошивку `px4fmu-v2_lpe.px4`](https://github.com/PX4/Firmware/releases). Для Pixracer параметр `SYS_MC_EST_GROUP` должен быть установлен в `local_position_estimator, attitude_estimator_q`.
* В параметре `LPE_FUSION` включены **только** флажки `vision position`, `vision yaw`, `land detector`. Итоговое значение _28_. * В параметре `LPE_FUSION` включены **только** флажки `vision position`, `vision yaw`, `land detector`. Итоговое значение _28_.
* Выключен компас: `ATT_W_MAG` = 0 * Выключен компас: `ATT_W_MAG` = 0
* Вес угла по рысканью по зрению: `ATT_W_EXT_HDG` = 0.5 * Вес угла по рысканью по зрению: `ATT_W_EXT_HDG` = 0.5
@@ -122,7 +122,7 @@ _Примечание_: указанное выше определение пр
* `LNDMC_THR_RANGE` = 0.5 * `LNDMC_THR_RANGE` = 0.5
* `LNDMC_Z_VEL_MAX` = 1 m/s * `LNDMC_Z_VEL_MAX` = 1 m/s
Для простоты настройки можно воспользоваться готовым файлом настроек для [Clever 2](https://github.com/CopterExpress/clever/blob/masterassets/Clever2LPE_160118.params) или для [Clever 3](https://github.com/CopterExpress/clever/blob/masterassets/Clever3_LPE_020218.params) и вгрузить его в контроллер с помощью меню Tools - Load from file из раздела Parameters в QGroundControl. Для простоты настройки можно воспользоваться готовым файлом настроек для [Clever 2](https://github.com/CopterExpress/clever/blob/master/docs/assets/Clever2LPE_160118.params) или для [Clever 3](https://github.com/CopterExpress/clever/blob/master/docs/assets/Clever3_LPE_020218.params) и вгрузить его в контроллер с помощью меню Tools - Load from file из раздела Parameters в QGroundControl.
![](assets/Screenshot from 2018-02-27 22-30-50.png) ![](assets/Screenshot from 2018-02-27 22-30-50.png)

46
docs/assets/appstore.svg Executable file
View File

@@ -0,0 +1,46 @@
<svg id="livetype" xmlns="http://www.w3.org/2000/svg" width="119.66407" height="40" viewBox="0 0 119.66407 40">
<title>Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917</title>
<g>
<g>
<g>
<path d="M110.13477,0H9.53468c-.3667,0-.729,0-1.09473.002-.30615.002-.60986.00781-.91895.0127A13.21476,13.21476,0,0,0,5.5171.19141a6.66509,6.66509,0,0,0-1.90088.627A6.43779,6.43779,0,0,0,1.99757,1.99707,6.25844,6.25844,0,0,0,.81935,3.61816a6.60119,6.60119,0,0,0-.625,1.90332,12.993,12.993,0,0,0-.1792,2.002C.00587,7.83008.00489,8.1377,0,8.44434V31.5586c.00489.3105.00587.6113.01515.9219a12.99232,12.99232,0,0,0,.1792,2.0019,6.58756,6.58756,0,0,0,.625,1.9043A6.20778,6.20778,0,0,0,1.99757,38.001a6.27445,6.27445,0,0,0,1.61865,1.1787,6.70082,6.70082,0,0,0,1.90088.6308,13.45514,13.45514,0,0,0,2.0039.1768c.30909.0068.6128.0107.91895.0107C8.80567,40,9.168,40,9.53468,40H110.13477c.3594,0,.7246,0,1.084-.002.3047,0,.6172-.0039.9219-.0107a13.279,13.279,0,0,0,2-.1768,6.80432,6.80432,0,0,0,1.9082-.6308,6.27742,6.27742,0,0,0,1.6172-1.1787,6.39482,6.39482,0,0,0,1.1816-1.6143,6.60413,6.60413,0,0,0,.6191-1.9043,13.50643,13.50643,0,0,0,.1856-2.0019c.0039-.3106.0039-.6114.0039-.9219.0078-.3633.0078-.7246.0078-1.0938V9.53613c0-.36621,0-.72949-.0078-1.09179,0-.30664,0-.61426-.0039-.9209a13.5071,13.5071,0,0,0-.1856-2.002,6.6177,6.6177,0,0,0-.6191-1.90332,6.46619,6.46619,0,0,0-2.7988-2.7998,6.76754,6.76754,0,0,0-1.9082-.627,13.04394,13.04394,0,0,0-2-.17676c-.3047-.00488-.6172-.01074-.9219-.01269-.3594-.002-.7246-.002-1.084-.002Z" style="fill: #a6a6a6"/>
<path d="M8.44483,39.125c-.30468,0-.602-.0039-.90429-.0107a12.68714,12.68714,0,0,1-1.86914-.1631,5.88381,5.88381,0,0,1-1.65674-.5479,5.40573,5.40573,0,0,1-1.397-1.0166,5.32082,5.32082,0,0,1-1.02051-1.3965,5.72186,5.72186,0,0,1-.543-1.6572,12.41351,12.41351,0,0,1-.1665-1.875c-.00634-.2109-.01464-.9131-.01464-.9131V8.44434S.88185,7.75293.8877,7.5498a12.37039,12.37039,0,0,1,.16553-1.87207,5.7555,5.7555,0,0,1,.54346-1.6621A5.37349,5.37349,0,0,1,2.61183,2.61768,5.56543,5.56543,0,0,1,4.01417,1.59521a5.82309,5.82309,0,0,1,1.65332-.54394A12.58589,12.58589,0,0,1,7.543.88721L8.44532.875H111.21387l.9131.0127a12.38493,12.38493,0,0,1,1.8584.16259,5.93833,5.93833,0,0,1,1.6709.54785,5.59374,5.59374,0,0,1,2.415,2.41993,5.76267,5.76267,0,0,1,.5352,1.64892,12.995,12.995,0,0,1,.1738,1.88721c.0029.2832.0029.5874.0029.89014.0079.375.0079.73193.0079,1.09179V30.4648c0,.3633,0,.7178-.0079,1.0752,0,.3252,0,.6231-.0039.9297a12.73126,12.73126,0,0,1-.1709,1.8535,5.739,5.739,0,0,1-.54,1.67,5.48029,5.48029,0,0,1-1.0156,1.3857,5.4129,5.4129,0,0,1-1.3994,1.0225,5.86168,5.86168,0,0,1-1.668.5498,12.54218,12.54218,0,0,1-1.8692.1631c-.2929.0068-.5996.0107-.8974.0107l-1.084.002Z"/>
</g>
<g id="_Group_" data-name="&lt;Group&gt;">
<g id="_Group_2" data-name="&lt;Group&gt;">
<g id="_Group_3" data-name="&lt;Group&gt;">
<path id="_Path_" data-name="&lt;Path&gt;" d="M24.76888,20.30068a4.94881,4.94881,0,0,1,2.35656-4.15206,5.06566,5.06566,0,0,0-3.99116-2.15768c-1.67924-.17626-3.30719,1.00483-4.1629,1.00483-.87227,0-2.18977-.98733-3.6085-.95814a5.31529,5.31529,0,0,0-4.47292,2.72787c-1.934,3.34842-.49141,8.26947,1.3612,10.97608.9269,1.32535,2.01018,2.8058,3.42763,2.7533,1.38706-.05753,1.9051-.88448,3.5794-.88448,1.65876,0,2.14479.88448,3.591.8511,1.48838-.02416,2.42613-1.33124,3.32051-2.66914a10.962,10.962,0,0,0,1.51842-3.09251A4.78205,4.78205,0,0,1,24.76888,20.30068Z" style="fill: #fff"/>
<path id="_Path_2" data-name="&lt;Path&gt;" d="M22.03725,12.21089a4.87248,4.87248,0,0,0,1.11452-3.49062,4.95746,4.95746,0,0,0-3.20758,1.65961,4.63634,4.63634,0,0,0-1.14371,3.36139A4.09905,4.09905,0,0,0,22.03725,12.21089Z" style="fill: #fff"/>
</g>
</g>
<g>
<path d="M42.30227,27.13965h-4.7334l-1.13672,3.35645H34.42727l4.4834-12.418h2.083l4.4834,12.418H43.438ZM38.0591,25.59082h3.752l-1.84961-5.44727h-.05176Z" style="fill: #fff"/>
<path d="M55.15969,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238H48.4302v1.50586h.03418a3.21162,3.21162,0,0,1,2.88281-1.60059C53.645,21.34766,55.15969,23.16406,55.15969,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C52.30227,29.01563,53.24953,27.81934,53.24953,25.96973Z" style="fill: #fff"/>
<path d="M65.12453,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238H58.395v1.50586h.03418A3.21162,3.21162,0,0,1,61.312,21.34766C63.60988,21.34766,65.12453,23.16406,65.12453,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C62.26711,29.01563,63.21438,27.81934,63.21438,25.96973Z" style="fill: #fff"/>
<path d="M71.71047,27.03613c.1377,1.23145,1.334,2.04,2.96875,2.04,1.56641,0,2.69336-.80859,2.69336-1.91895,0-.96387-.67969-1.541-2.28906-1.93652l-1.60937-.3877c-2.28027-.55078-3.33887-1.61719-3.33887-3.34766,0-2.14258,1.86719-3.61426,4.51855-3.61426,2.624,0,4.42285,1.47168,4.4834,3.61426h-1.876c-.1123-1.23926-1.13672-1.9873-2.63379-1.9873s-2.52148.75684-2.52148,1.8584c0,.87793.6543,1.39453,2.25488,1.79l1.36816.33594c2.54785.60254,3.60645,1.626,3.60645,3.44238,0,2.32324-1.85059,3.77832-4.79395,3.77832-2.75391,0-4.61328-1.4209-4.7334-3.667Z" style="fill: #fff"/>
<path d="M83.34621,19.2998v2.14258h1.72168v1.47168H83.34621v4.99121c0,.77539.34473,1.13672,1.10156,1.13672a5.80752,5.80752,0,0,0,.61133-.043v1.46289a5.10351,5.10351,0,0,1-1.03223.08594c-1.833,0-2.54785-.68848-2.54785-2.44434V22.91406H80.16262V21.44238H81.479V19.2998Z" style="fill: #fff"/>
<path d="M86.065,25.96973c0-2.84863,1.67773-4.63867,4.29395-4.63867,2.625,0,4.29492,1.79,4.29492,4.63867,0,2.85645-1.66113,4.63867-4.29492,4.63867C87.72609,30.6084,86.065,28.82617,86.065,25.96973Zm6.69531,0c0-1.9541-.89551-3.10742-2.40137-3.10742s-2.40039,1.16211-2.40039,3.10742c0,1.96191.89453,3.10645,2.40039,3.10645S92.76027,27.93164,92.76027,25.96973Z" style="fill: #fff"/>
<path d="M96.18606,21.44238h1.77246v1.541h.043a2.1594,2.1594,0,0,1,2.17773-1.63574,2.86616,2.86616,0,0,1,.63672.06934v1.73828a2.59794,2.59794,0,0,0-.835-.1123,1.87264,1.87264,0,0,0-1.93652,2.083v5.37012h-1.8584Z" style="fill: #fff"/>
<path d="M109.3843,27.83691c-.25,1.64355-1.85059,2.77148-3.89844,2.77148-2.63379,0-4.26855-1.76465-4.26855-4.5957,0-2.83984,1.64355-4.68164,4.19043-4.68164,2.50488,0,4.08008,1.7207,4.08008,4.46582v.63672h-6.39453v.1123a2.358,2.358,0,0,0,2.43555,2.56445,2.04834,2.04834,0,0,0,2.09082-1.27344Zm-6.28223-2.70215h4.52637a2.1773,2.1773,0,0,0-2.2207-2.29785A2.292,2.292,0,0,0,103.10207,25.13477Z" style="fill: #fff"/>
</g>
</g>
</g>
<g id="_Group_4" data-name="&lt;Group&gt;">
<g>
<path d="M37.82619,8.731a2.63964,2.63964,0,0,1,2.80762,2.96484c0,1.90625-1.03027,3.002-2.80762,3.002H35.67092V8.731Zm-1.22852,5.123h1.125a1.87588,1.87588,0,0,0,1.96777-2.146,1.881,1.881,0,0,0-1.96777-2.13379h-1.125Z" style="fill: #fff"/>
<path d="M41.68068,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C44.57522,13.99463,45.01369,13.42432,45.01369,12.44434Z" style="fill: #fff"/>
<path d="M51.57326,14.69775h-.92187l-.93066-3.31641h-.07031l-.92676,3.31641h-.91309l-1.24121-4.50293h.90137l.80664,3.436h.06641l.92578-3.436h.85254l.92578,3.436h.07031l.80273-3.436h.88867Z" style="fill: #fff"/>
<path d="M53.85354,10.19482H54.709v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915h-.88867V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
<path d="M59.09377,8.437h.88867v6.26074h-.88867Z" style="fill: #fff"/>
<path d="M61.21779,12.44434a2.13346,2.13346,0,1,1,4.24756,0,2.1338,2.1338,0,1,1-4.24756,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C64.11232,13.99463,64.5508,13.42432,64.5508,12.44434Z" style="fill: #fff"/>
<path d="M66.4009,13.42432c0-.81055.60352-1.27783,1.6748-1.34424l1.21973-.07031v-.38867c0-.47559-.31445-.74414-.92187-.74414-.49609,0-.83984.18213-.93848.50049h-.86035c.09082-.77344.81836-1.26953,1.83984-1.26953,1.12891,0,1.76563.562,1.76563,1.51318v3.07666h-.85547v-.63281h-.07031a1.515,1.515,0,0,1-1.35254.707A1.36026,1.36026,0,0,1,66.4009,13.42432Zm2.89453-.38477v-.37646l-1.09961.07031c-.62012.0415-.90137.25244-.90137.64941,0,.40527.35156.64111.835.64111A1.0615,1.0615,0,0,0,69.29543,13.03955Z" style="fill: #fff"/>
<path d="M71.34816,12.44434c0-1.42285.73145-2.32422,1.86914-2.32422a1.484,1.484,0,0,1,1.38086.79h.06641V8.437h.88867v6.26074h-.85156v-.71143h-.07031a1.56284,1.56284,0,0,1-1.41406.78564C72.0718,14.772,71.34816,13.87061,71.34816,12.44434Zm.918,0c0,.95508.4502,1.52979,1.20313,1.52979.749,0,1.21191-.583,1.21191-1.52588,0-.93848-.46777-1.52979-1.21191-1.52979C72.72121,10.91846,72.26613,11.49707,72.26613,12.44434Z" style="fill: #fff"/>
<path d="M79.23,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C82.12453,13.99463,82.563,13.42432,82.563,12.44434Z" style="fill: #fff"/>
<path d="M84.66945,10.19482h.85547v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915H87.605V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
<path d="M93.51516,9.07373v1.1416h.97559v.74854h-.97559V13.2793c0,.47168.19434.67822.63672.67822a2.96657,2.96657,0,0,0,.33887-.02051v.74023a2.9155,2.9155,0,0,1-.4834.04541c-.98828,0-1.38184-.34766-1.38184-1.21582v-2.543h-.71484v-.74854h.71484V9.07373Z" style="fill: #fff"/>
<path d="M95.70461,8.437h.88086v2.48145h.07031a1.3856,1.3856,0,0,1,1.373-.80664,1.48339,1.48339,0,0,1,1.55078,1.67871v2.90723H98.69v-2.688c0-.71924-.335-1.0835-.96289-1.0835a1.05194,1.05194,0,0,0-1.13379,1.1416v2.62988h-.88867Z" style="fill: #fff"/>
<path d="M104.76125,13.48193a1.828,1.828,0,0,1-1.95117,1.30273A2.04531,2.04531,0,0,1,100.73,12.46045a2.07685,2.07685,0,0,1,2.07617-2.35254c1.25293,0,2.00879.856,2.00879,2.27V12.688h-3.17969v.0498a1.1902,1.1902,0,0,0,1.19922,1.29,1.07934,1.07934,0,0,0,1.07129-.5459Zm-3.126-1.45117h2.27441a1.08647,1.08647,0,0,0-1.1084-1.1665A1.15162,1.15162,0,0,0,101.63527,12.03076Z" style="fill: #fff"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -26,6 +26,6 @@
* ОС [Raspbian Jessie](https://www.raspberrypi.org/downloads/raspbian/) * ОС [Raspbian Jessie](https://www.raspberrypi.org/downloads/raspbian/)
* Фреймворк [ROS](ros.md) * Фреймворк [ROS](ros.md)
* Пакет [MAVROS](mavros.md) для связи с PixHawk по MAVLINK * Пакет [MAVROS](mavros.md) для связи с Pixhawk по [MAVLink](mavlink.md)
* Дополнительные пакеты ROS: web_video_server, usb_cam, rosbridge_suite и другие * Дополнительные пакеты ROS: web_video_server, usb_cam, rosbridge_suite и другие
* Пакет программ clever_bundle * Пакет программ clever_bundle

View File

@@ -13,9 +13,10 @@
``` ```
Фрейм камеры задается таким образом, что: Фрейм камеры задается таким образом, что:
* x указывает направо на изображении;
* y указывает вниз на изображении; * **<font color=red>x</font>** указывает направо на изображении;
* z указывает от плоскости матрицы камеры. * **<font color=green>y</font>** указывает вниз на изображении;
* **<font color=blue>z</font>** указывает от плоскости матрицы камеры.
Сдвиги задаются в метрах, углы задаются в радианах. Корректность установленной трансформации может быть проверена с использованием [rviz](rviz.md). Сдвиги задаются в метрах, углы задаются в радианах. Корректность установленной трансформации может быть проверена с использованием [rviz](rviz.md).

View File

@@ -1,21 +1,20 @@
Подключение PixHawk/PixRacer к Raspberry Pi Подключение Pixhawk/Pixracer к Raspberry Pi
=== ===
Для программирования [автономных полетов](simple_offboard.md), [работы с PixHawk по Wi-Fi](gcs_bridge.md), использования [веб-пульта](web_rc.md) и других функций необходимо подсоединить Raspberry Pi к PixHawk. Для программирования [автономных полетов](simple_offboard.md), [работы с Pixhawk по Wi-Fi](gcs_bridge.md), использования [веб-пульта](web_rc.md) и других функций необходимо подсоединить Raspberry Pi к Pixhawk.
Убедиться в работоспособности подключения, выполнив на Raspberry Pi: Убедиться в работоспособности подключения, выполнив на Raspberry Pi:
``` ```bash
rostopic echo /mavros/state rostopic echo /mavros/state
``` ```
Поле `connected` должно содержать значение `True`. Поле `connected` должно содержать значение `True`.
Подключение по USB Подключение по USB
--- ---
Соедините PixHawk/PixRacer и Raspberry Pi micro-USB to USB кабелем. Соедините Pixhawk/Pixracer и Raspberry Pi micro-USB to USB кабелем.
Необходимо убедиться, что в launch-файле Клевера (`~/catkin_ws/src/clever/clever/launch/clever.launch`) тип подключения установлен на USB: Необходимо убедиться, что в launch-файле Клевера (`~/catkin_ws/src/clever/clever/launch/clever.launch`) тип подключения установлен на USB:
@@ -29,7 +28,7 @@ rostopic echo /mavros/state
sudo systemctl restart clever sudo systemctl restart clever
``` ```
> **Hint** Для корректной работы подключения Raspberry Pi и PixHawk по USB необходимо установить значение параметра `CBRK_USB_CHK` на 197848. > **Hint** Для корректной работы подключения Raspberry Pi и Pixhawk по USB необходимо установить значение параметра `CBRK_USB_CHK` на 197848.
Подключение по UART Подключение по UART
--- ---
@@ -48,7 +47,7 @@ TODO схема подключения
sudo systemctl restart clever sudo systemctl restart clever
``` ```
> **Hint** Для корректной работы подключения Raspberry Pi и PixHawk по UART необходимо установить значение параметра `SYS_COMPANION` на 921600. > **Hint** Для корректной работы подключения Raspberry Pi и Pixhawk по UART необходимо установить значение параметра `SYS_COMPANION` на 921600.
Подключение к SITL Подключение к SITL
--- ---

View File

@@ -2,40 +2,40 @@
Хорошая статья, которая объясняет принцип работы ESC \(Electric speed controller\) регуляторов: [http://www.avmodels.ru/engines/electric/esc.html](http://www.avmodels.ru/engines/electric/esc.html) Хорошая статья, которая объясняет принцип работы ESC \(Electric speed controller\) регуляторов: [http://www.avmodels.ru/engines/electric/esc.html](http://www.avmodels.ru/engines/electric/esc.html)
#### Зачем перепрошивать? ## Зачем перепрошивать?
Иногда требуется поменять один из параметров регулятора, например направление вращения мотора, минимальная и максимальная скважности PPM сигнала на входе контроллера, уровень громкости звуковых сигналов, издаваемых мотором или время, через которое регулятор начинает напоминать, что он включён. Иногда требуется поменять один из параметров регулятора, например направление вращения мотора, минимальная и максимальная скважности PPM сигнала на входе контроллера, уровень громкости звуковых сигналов, издаваемых мотором или время, через которое регулятор начинает напоминать, что он включён.
#### Программа для прошивки регуляторов ## Программа для прошивки регуляторов
Для прошивки самых разнообразных ESC регуляторов существует программа [BLHeliSuite](https://github.com/4712/BLHeliSuite) \(для Windows\). Для прошивки самых разнообразных ESC регуляторов существует программа [BLHeliSuite](https://github.com/4712/BLHeliSuite) \(для Windows\).
Для запуска программы \(BLHeliSuite.exe\) необходимо распаковать архивы BLHeliAtmelHEX.zip и BLHeliSilabsHEX.zip в папку с программой. Для запуска программы \(BLHeliSuite.exe\) необходимо распаковать архивы BLHeliAtmelHEX.zip и BLHeliSilabsHEX.zip в папку с программой.
#### Программатор для прошивки регуляторов. ## Программатор для прошивки регуляторов
Чтобы прошить регулятор, необходим программатор, который умеет общаться с контроллером регулятора по 1-wire протоколу. Один из способов добыть программатор - взять подвернувшуюся под руку ардуинку и прошить её специальной прошивкой. В BLHeliSuite есть инструмент для создания интерфейсов программаторов. Чтобы прошить регулятор, необходим программатор, который умеет общаться с контроллером регулятора по 1-wire протоколу. Один из способов добыть программатор - взять подвернувшуюся под руку ардуинку и прошить её специальной прошивкой. В BLHeliSuite есть инструмент для создания интерфейсов программаторов.
Создание программатора на примере Arduino Mega. Создание программатора на примере Arduino Mega.
1. Запустите программу BLHeliSuite и выберите вкладку Make interfaces. 1. Запустите программу BLHeliSuite и выберите вкладку Make interfaces.
![](assets/BLHeliSuite_SiLabs_ESC_Setup_2.png) ![](assets/BLHeliSuite_SiLabs_ESC_Setup_2.png)
2. Подключите Arduino к компьютеру, при необходимости посмотрите в диспетчере устройств номер COM порта, к которому подключена плата. 2. Подключите Arduino к компьютеру, при необходимости посмотрите в диспетчере устройств номер COM порта, к которому подключена плата.
3. Нажмите Arduino 4way-interface в разделе Make Arduino Interface Boards и выберите файл прошивки. После выбора файла начнётся прошивка контроллера. 3. Нажмите Arduino 4way-interface в разделе Make Arduino Interface Boards и выберите файл прошивки. После выбора файла начнётся прошивка контроллера.
![](assets/BLHeliSuite_Make_Interfaces.png) ![](assets/BLHeliSuite_Make_Interfaces.png)
![](assets/BLHeliSuite_Interface_Options.png) ![](assets/BLHeliSuite_Interface_Options.png)
![](assets/BLHeliSuite_Arduino_Select_Firmware.png) ![](assets/BLHeliSuite_Arduino_Select_Firmware.png)
4. После прошивки Arduino вернитесь на вкладку Silabs ESC Setup и подключитесь к Arduino, предварительно выбрав интерфейс программатора 4way-if и COM порт Arduino. 4. После прошивки Arduino вернитесь на вкладку Silabs ESC Setup и подключитесь к Arduino, предварительно выбрав интерфейс программатора 4way-if и COM порт Arduino.
![](assets/BLHeliSuite_4way-if_Select.png) ![](assets/BLHeliSuite_4way-if_Select.png)
![](assets/BLHeliSuite_ESC_Setup_Connect.png) ![](assets/BLHeliSuite_ESC_Setup_Connect.png)
#### Подключение ESC регуляторов к Arduino. ## Подключение ESC регуляторов к Arduino
Для прошивки или изменения настроек регуляторов необходимо подключить сигнальные порты (обычно белого цвета) ESC регуляторов к портам Arduino, предварительно посмотрев в мануале (см. рисунок ниже), какие порты используются для соединения с регуляторами. Так же нужно соединить GND Arduino с землёй одного из регуляторов (обычно черного цвета). Регуляторы должны быть подключены к питанию, а если к регуляторам подключены моторы, **на них не должно быть винтов**. Для прошивки или изменения настроек регуляторов необходимо подключить сигнальные порты (обычно белого цвета) ESC регуляторов к портам Arduino, предварительно посмотрев в мануале (см. рисунок ниже), какие порты используются для соединения с регуляторами. Так же нужно соединить GND Arduino с землёй одного из регуляторов (обычно черного цвета). Регуляторы должны быть подключены к питанию, а если к регуляторам подключены моторы, **на них не должно быть винтов**.
@@ -43,7 +43,7 @@
В случае с Arduino Mega, сигнальные порты регуляторов подключаются к портам D43-D49 и D51. В случае с Arduino Mega, сигнальные порты регуляторов подключаются к портам D43-D49 и D51.
#### Изменение настроек ESC регуляторов. ## Изменение настроек ESC регуляторов
Для загрузки информации о версии прошивки и настроек регуляторов нужно нажать на кнопку Check. Для загрузки информации о версии прошивки и настроек регуляторов нужно нажать на кнопку Check.
@@ -64,15 +64,15 @@
Для отображения настроек со всех регуляторов одновременно можно воспользоваться вкладкой ESC Overview. Для отображения настроек со всех регуляторов одновременно можно воспользоваться вкладкой ESC Overview.
#### Прошивка ESC регуляторов. ## Прошивка ESC регуляторов
Файлы с прошивками регуляторов находятся [здесь](https://github.com/cleanflight/blheli-multishot/tree/master/BLHeli_S%20SiLabs/Hex%20Files). Файлы с прошивками регуляторов находятся [здесь](https://github.com/cleanflight/blheli-multishot/tree/master/BLHeli_S%20SiLabs/Hex%20Files).
Для перепрошивки регуляторов нужно нажать на кнопку Flash BLHeli и выбрать файл прошивки с типом контроллера, название которого указано в рамке названия прошивки и находится сверху во вкладке Silabs ESC Setup (в случае контроллера, который используется в конструкторе Клевер 2, это A-H-70). Для перепрошивки регуляторов нужно нажать на кнопку Flash BLHeli и выбрать файл прошивки с типом контроллера, название которого указано в рамке названия прошивки и находится сверху во вкладке Silabs ESC Setup (в случае контроллера, который используется в конструкторе Клевер 2, это A-H-70).
Для перепрошивки отдельного регулятора нужно сделать все остальные неактивными. Для перепрошивки отдельного регулятора нужно сделать все остальные неактивными.
#### Видеоинструкция по перепрошивке ESC регуляторов ## Видеоинструкция по перепрошивке ESC регуляторов
Для лучшего понимания того, что описано в статье, рекомендуем посмотреть наглядное руководство по подключению электроники и прошивке регуляторов на английском языке на [youtube](https://www.youtube.com/watch?v=i6lhMcQLRSU&feature=youtu.be). Для лучшего понимания того, что описано в статье, рекомендуем посмотреть наглядное руководство по подключению электроники и прошивке регуляторов на английском языке на [youtube](https://www.youtube.com/watch?v=i6lhMcQLRSU&feature=youtu.be).

View File

@@ -1,16 +1,16 @@
Прошивка PixHawk / PixRacer Прошивка Pixhawk / Pixracer
=== ===
PixHawk или PixRacer можно прошить, используя QGroundControl или утилиты командной строки. Pixhawk или Pixracer можно прошить, используя QGroundControl или утилиты командной строки.
Различные варианты сборок стабильных прошивок PX4 можно скачать в разделе [Releases на GitHub](https://github.com/PX4/Firmware/releases). Различные варианты сборок стабильных прошивок PX4 можно скачать в разделе [Releases на GitHub](https://github.com/PX4/Firmware/releases).
В названии файла прошивки кодируется информации о целевой плате и варианте сборки. Примеры: В названии файла прошивки кодируется информации о целевой плате и варианте сборки. Примеры:
* `px4fmu-v2_default.px4` — прошивка для PixHawk с EKF2. * `px4fmu-v2_default.px4` — прошивка для Pixhawk с EKF2.
* `px4fmu-v2_lpe.px4` — прошивка для PixHawk с LPE. * `px4fmu-v2_lpe.px4` — прошивка для Pixhawk с LPE.
* `px4fmu-v4_default.px4` — прошивка для PixRacer с EKF2 и LPE (*Клевер 3*). * `px4fmu-v4_default.px4` — прошивка для Pixracer с EKF2 и LPE (*Клевер 3*).
* `px4fmu-v3_default.px4` — прошивка для более новых версий PixHawk (чип ревизии 3, см. илл. + Bootloader v5) с EKF2 и LPE. * `px4fmu-v3_default.px4` — прошивка для более новых версий Pixhawk (чип ревизии 3, см. илл. + Bootloader v5) с EKF2 и LPE.
![](assets/stmrev.jpg) ![](assets/stmrev.jpg)
@@ -19,9 +19,9 @@ PixHawk или PixRacer можно прошить, используя QGroundCon
QGroundControl QGroundControl
--- ---
В QGroundControl откройте раздел Firmware. **После** этого подключите PixHawk / PixRacer по USB. В QGroundControl откройте раздел Firmware. **После** этого подключите Pixhawk / Pixracer по USB.
Выберите PX4 Flight Stack. Для скачивания и загрузки стандартной прошивки (вариант с EKF2 для PixHawk) выберите пункт меню "Standard Version", для загрузки собственного файла прошивки выберите пункт "Custom firmware file...", затем нажмите OK. Выберите PX4 Flight Stack. Для скачивания и загрузки стандартной прошивки (вариант с EKF2 для Pixhawk) выберите пункт меню "Standard Version", для загрузки собственного файла прошивки выберите пункт "Custom firmware file...", затем нажмите OK.
> **Warning** Не отключайте USB-кабель до окончания процесса прошивки. > **Warning** Не отключайте USB-кабель до окончания процесса прошивки.
@@ -46,7 +46,7 @@ make px4fmu-v4_default upload
Где `px4fmu-v4_default` – требуемый вариант прошивки. Где `px4fmu-v4_default` – требуемый вариант прошивки.
Для загрузки прошивки `v3` в PixHawk может понадобиться команда `force_upload`: Для загрузки прошивки `v3` в Pixhawk может понадобиться команда `force_upload`:
``` ```
make px4fmu-v3_default force-upload make px4fmu-v3_default force-upload

View File

@@ -38,7 +38,7 @@
Мониторинг топиков в режиме реального времени Мониторинг топиков в режиме реального времени
--- ---
Для более новых версий платы PixHawk (`px4fmu-v3`), а также для плат PixRacer, в прошивку включен модуль `topic_listener`, который позволяет просматривать значения топиков в режиме реального времени (в том числе в полете). Для более новых версий платы Pixhawk (`px4fmu-v3`), а также для плат Pixracer, в прошивку включен модуль `topic_listener`, который позволяет просматривать значения топиков в режиме реального времени (в том числе в полете).
Для ее использования нужно выбрать вкладку Mavlink Console в QGroundControl: Для ее использования нужно выбрать вкладку Mavlink Console в QGroundControl:

View File

@@ -18,6 +18,7 @@ TCP-бридж
--- ---
Изменить параметр `gcs_bridge` в launch-файле: Изменить параметр `gcs_bridge` в launch-файле:
```xml ```xml
<arg name="gcs_bridge" default="tcp"/> <arg name="gcs_bridge" default="tcp"/>
``` ```
@@ -32,6 +33,7 @@ UDP бридж (с автоматическим подключением)
--- ---
Изменить параметр gcs_bridge в launch-файле: Изменить параметр gcs_bridge в launch-файле:
```xml ```xml
<arg name="gcs_bridge" default="udp-b"/> <arg name="gcs_bridge" default="udp-b"/>
``` ```

70
docs/glossary.md Normal file
View File

@@ -0,0 +1,70 @@
# Глоссарий
## Квадрокоптер
Беспилотный летательный аппарат с 4-мя винтами и электронной системной стабилизации.
## Мультикоптер
Беспилотный летательный аппарат с электронной системой стабилизации и числом винтов, равным 3 (трикоптер), 4 (квадрокоптер), 6 (гексакоптер), 8 (октокоптер) или более.
## Полетный контроллер / автопилот
**1\.** Специализированная плата, спроектированная для управления мультикоптером, самолетом или другим аппаратом. Примеры:
Pixhawk, Ardupilot, Naze32, CC3D.
**2\.** Программное обеспечение для платы управления мультикоптером. Примеры: PX4, APM, CleanFlight.
## Мотор
Электродвигатель, который вращает винты мультикоптера. Обычно используются бесколлекторные электродвигатели. Такие двигатели подключаются к ESC.
## ESC / регулятор двигателя / "регуль"
Electronic Speed Controller. Специализированная плата, которая управляет скоростью вращения бесколлекторного электродвигателя. Управляется полетным контроллером при помощи широтно-импульсной модуляции (ШИМ).
ESC имеет прошивку, которая определяет особенности его работы.
## Пульт / аппаратура радиоуправления / "аппа"
Пульт для управления квадрокоптером, работающий по радиоканалу. Для работы пульта к полетном контроллеру необходимо подключить ресивер.
Клевером, также, можно [управлять со смартфона](rc.md).
## Телеметрия
**1\.** Передача данных о состоянии квадрокоптера или другого аппарата на расстояние.
**2\.** Совокупность данных о состоянии аппарата, так таковая (высота, ориентация, глобальные координаты и т. д.).
**3\.** Система для передачи данных о состоянии аппарата или команд для него по воздуху. Примеры: радиомодемы (RFD900, 3DR Radio Modem), Wi-Fi модули (ESP-07). Raspberry Pi на Клевере также может быть использован в качестве модуля для телемерии: [использование QGroundControl через Wi-Fi](gcs_bridge.md).
## Арминг
Armed состояние коптера готовности к полету. При поднятии стика газа либо при посылке внешней команды с целевой точкой – коптер полетит. Обычно коптер начинает вращать винтами при переходе в состояние "armed" даже если стик газа находится внизу.
Противолположным состоянием является Disarmed.
## PX4
Популярный полетный контроллер с открытым исходным кодом, работащий на платах Pixhawk, Pixracer и других. PX4 рекомендуется для использования на Клевере.
## APM / ArduPilot
Полетный контроллер с открытым исходным кодом, изначально созданный для платы Arduino. Впоследствии был портирован на Pixhawk, Pixracer и другие платы.
## MAVLink
Протокол для взаимодействия дронов, наземных станций и других аппаратов по радиоканалам. Обычно именно этот протокол используется для телеметрии.
## ROS
Популярный фреймворк для написания сложных роботехнических приложений.
## MAVROS
Библиотека-связующее звено между аппаратом, работающем по протоколу MAVLink, и ROS.
## UART
Последовательный асинхронный интерфейс передачи данных, применяемый во многих устройствах. Например GPS антенны, Wi-Fi роутеры или Pixhawk.

View File

@@ -1,6 +1,6 @@
## Работа со светодиодной лентой на Raspberry 3 # Работа со светодиодной лентой на Raspberry 3
#### Подключение и определение типа ленты ## Подключение и определение типа ленты
Есть два основных типа адресуемых светодиодов: WS2812 и WS2812B. Принцип управления один и тот же, однако тайминги разные. Найдите на ленте чип светодиода и определите сколько у него ножек: 6 или 4. Если ножек 6, то это WS2812, если 4 - то WS2812B или его аналог SK6812. Есть два основных типа адресуемых светодиодов: WS2812 и WS2812B. Принцип управления один и тот же, однако тайминги разные. Найдите на ленте чип светодиода и определите сколько у него ножек: 6 или 4. Если ножек 6, то это WS2812, если 4 - то WS2812B или его аналог SK6812.
@@ -16,7 +16,7 @@
Типы лент для обозначения ленты в коде описаны в [файле](https://github.com/jgarff/rpi_ws281x/blob/master/ws2811.h). Основные типы лент - это WS2812\_STRIP \(для WS2812\) и SK6812\_STRIP \(для WS2812B или SK6812\). Типы лент для обозначения ленты в коде описаны в [файле](https://github.com/jgarff/rpi_ws281x/blob/master/ws2811.h). Основные типы лент - это WS2812\_STRIP \(для WS2812\) и SK6812\_STRIP \(для WS2812B или SK6812\).
#### Установка библиотеки для работы со светодиодной лентой ## Установка библиотеки для работы со светодиодной лентой
Определите папку, в которой будут находиться файлы библиотеки, и открыть путь к этой папке в терминале. По-умолчанию можно использовать домашнюю папку, для перехода в неё нужно выполнить команду Определите папку, в которой будут находиться файлы библиотеки, и открыть путь к этой папке в терминале. По-умолчанию можно использовать домашнюю папку, для перехода в неё нужно выполнить команду
@@ -51,7 +51,7 @@ sudo python ./setup.py build
sudo python ./setup.py install sudo python ./setup.py install
``` ```
#### Пример программы для светодиодной ленты на RPI3 ## Пример программы для светодиодной ленты на RPI3
Откройте в текстовом редакторе файл strandtest.py из папки python/examples \(находится в папке с библиотекой\) Откройте в текстовом редакторе файл strandtest.py из папки python/examples \(находится в папке с библиотекой\)
@@ -96,7 +96,7 @@ sudo python strandtest.py
Права администратора необходимы для выполнения скрипта, т.к. без них нет доступа к функциям прерывания, которые использует библиотека для работы с лентой. Права администратора необходимы для выполнения скрипта, т.к. без них нет доступа к функциям прерывания, которые использует библиотека для работы с лентой.
#### Совместимость с ROS и python ## Совместимость с ROS и python
При запуске программы с помощью sudo пользовательское окружение изменяется и появляются ошибки импорта библиотек, т.к. в окружении отсутствуют необходимые пути. Чтобы добавить в окружение пути к библиотекам python и пакетам ROS, необходимо добавить в файл /etc/sudoers следующие строки: При запуске программы с помощью sudo пользовательское окружение изменяется и появляются ошибки импорта библиотек, т.к. в окружении отсутствуют необходимые пути. Чтобы добавить в окружение пути к библиотекам python и пакетам ROS, необходимо добавить в файл /etc/sudoers следующие строки:
@@ -107,7 +107,7 @@ Defaults env_keep += "ROS_ROOT"
Defaults env_keep += "ROS_MASTER_URI" Defaults env_keep += "ROS_MASTER_URI"
``` ```
#### Функции для работы со светодиодной лентой ## Функции для работы со светодиодной лентой
Для подключения библиотеки и её корректной работы требуется подключить следующие модули: neopixels - для работы ленты, time - для управления задержками, sys и signal для прерываний и формирования управляющего сигнала. Для подключения библиотеки и её корректной работы требуется подключить следующие модули: neopixels - для работы ленты, time - для управления задержками, sys и signal для прерываний и формирования управляющего сигнала.
@@ -144,23 +144,23 @@ pydoc neopixel
```(bash) ```(bash)
Help on module neopixel: Help on module neopixel:
NAME NAME
neopixel neopixel
DESCRIPTION DESCRIPTION
# Adafruit NeoPixel library port to the rpi_ws281x library. # Adafruit NeoPixel library port to the rpi_ws281x library.
# Author: Tony DiCola (tony@tonydicola.com) # Author: Tony DiCola (tony@tonydicola.com)
CLASSES CLASSES
__builtin__.object __builtin__.object
Adafruit_NeoPixel Adafruit_NeoPixel
class Adafruit_NeoPixel(__builtin__.object) class Adafruit_NeoPixel(__builtin__.object)
| Methods defined here: | Methods defined here:
| |
| __del__(self) | __del__(self)
| |
| __init__(self, num, pin, freq_hz=800000, dma=5, invert=False) | __init__(self, num, pin, freq_hz=800000, dma=5, invert=False)
| Class to represent a NeoPixel/WS281x LED display. Num should be the | Class to represent a NeoPixel/WS281x LED display. Num should be the
| number of pixels in the display, and pin should be the GPIO pin connected | number of pixels in the display, and pin should be the GPIO pin connected
@@ -168,38 +168,38 @@ pydoc neopixel
| parameters are freq, the frequency of the display signal in hertz (default | parameters are freq, the frequency of the display signal in hertz (default
| 800khz), dma, the DMA channel to use (default 5), and invert, a boolean | 800khz), dma, the DMA channel to use (default 5), and invert, a boolean
| specifying if the signal line should be inverted (default False). | specifying if the signal line should be inverted (default False).
| |
| begin(self) | begin(self)
| Initialize library, must be called once before other functions are | Initialize library, must be called once before other functions are
| called. | called.
| |
| getPixelColor(self, n) | getPixelColor(self, n)
| Get the 24-bit RGB color value for the LED at position n. | Get the 24-bit RGB color value for the LED at position n.
| |
| getPixels(self) | getPixels(self)
| Return an object which allows access to the LED display data as if | Return an object which allows access to the LED display data as if
| it were a sequence of 24-bit RGB values. | it were a sequence of 24-bit RGB values.
| |
| numPixels(self) | numPixels(self)
| Return the number of pixels in the display. | Return the number of pixels in the display.
| |
| setBrightness(self, brightness) | setBrightness(self, brightness)
| Scale each LED in the buffer by the provided brightness. A brightness | Scale each LED in the buffer by the provided brightness. A brightness
| of 0 is the darkest and 255 is the brightest. Note that scaling can have | of 0 is the darkest and 255 is the brightest. Note that scaling can have
| quantization issues (i.e. blowing out to white or black) if used repeatedly! | quantization issues (i.e. blowing out to white or black) if used repeatedly!
| |
| setPixelColor(self, n, color) | setPixelColor(self, n, color)
| Set LED at position n to the provided 24-bit color value (in RGB order). | Set LED at position n to the provided 24-bit color value (in RGB order).
| |
| setPixelColorRGB(self, n, red, green, blue) | setPixelColorRGB(self, n, red, green, blue)
| Set LED at position n to the provided red, green, and blue color. | Set LED at position n to the provided red, green, and blue color.
| Each color component should be a value from 0 to 255 (where 0 is the | Each color component should be a value from 0 to 255 (where 0 is the
| lowest intensity and 255 is the highest intensity). | lowest intensity and 255 is the highest intensity).
| |
| show(self) | show(self)
| Update the display with the data from the LED buffer. | Update the display with the data from the LED buffer.
| |
FUNCTIONS FUNCTIONS
Color(red, green, blue) Color(red, green, blue)
Convert the provided red, green, blue color to a 24-bit color value. Convert the provided red, green, blue color to a 24-bit color value.
@@ -207,7 +207,7 @@ pydoc neopixel
and 255 is the highest intensity. and 255 is the highest intensity.
``` ```
#### Почему именно так и можно ли по-другому? ## Почему именно так и можно ли по-другому?
Основные типы лент, которые используются для Clever3, это WS2812, WS2812B и SK6812 \(аналог WS2812B\). Они управляются по одному и тому же принципу: для массива светодиодов в ленте отправляется пакет данных по 24 бита на светодиод; каждый светодиод считывает первые 24 бита из пришедших к нему данных и устанавливает соответствующий цвет, остальные данные он отправляет следующему светодиоду в ленте. Нули и единицы задаются разными сочетаниями длительностей высокого и низкого уровня в импульсе. Основные типы лент, которые используются для Clever3, это WS2812, WS2812B и SK6812 \(аналог WS2812B\). Они управляются по одному и тому же принципу: для массива светодиодов в ленте отправляется пакет данных по 24 бита на светодиод; каждый светодиод считывает первые 24 бита из пришедших к нему данных и устанавливает соответствующий цвет, остальные данные он отправляет следующему светодиоду в ленте. Нули и единицы задаются разными сочетаниями длительностей высокого и низкого уровня в импульсе.
@@ -227,4 +227,3 @@ pydoc neopixel
3. Если нам важна и работа аудио, и подключение к SPI устройств кроме лед ленты, то можно управлять лентой по каналу PCM \(GPIO 21 или 31\). При этом никаких дополнительных манипуляций с распберри не требуется. 3. Если нам важна и работа аудио, и подключение к SPI устройств кроме лед ленты, то можно управлять лентой по каналу PCM \(GPIO 21 или 31\). При этом никаких дополнительных манипуляций с распберри не требуется.
Исходя из вышеперечисленных способов управления лентой, наилучшим вариантом, позволяющим управлять лентой, сохранить работоспособность встроенной аудиосистемы и возможность подключения всяческих устройств и датчиков по SPI, является управление по каналу PCM \(GPIO 21\) с использованием 10 канала DMA. Исходя из вышеперечисленных способов управления лентой, наилучшим вариантом, позволяющим управлять лентой, сохранить работоспособность встроенной аудиосистемы и возможность подключения всяческих устройств и датчиков по SPI, является управление по каналу PCM \(GPIO 21\) с использованием 10 канала DMA.

179
docs/mavlink.md Normal file
View File

@@ -0,0 +1,179 @@
# MAVLink
Основная документация: https://mavlink.io/en/.
MAVLink – это протокол для организации связи между автономными летательными и транспортными системами (дронами, самолетами, автомобилями). Проктол MAVLink лежит в основе взаимодействия между Pixhawk и Raspberry Pi.
В Клевер включено 2 обертки над этим протоколом: [MAVROS](mavros.md) и [simple_offboard](simple_offboard.md).
Код для отправки произвольного MAVLink сообщения можно найти в [примерах](snippets.md).
## Основные концепции
### Канал связи
Протокол MAVLink может быть использован поверх следующих каналов связи:
* последовательное соединение (UART, USB и др.);
* UDP (Wi-Fi, Ethernet, 3G, LTE);
* TCP (Wi-Fi, Ethernet, 3G, LTE).
### Сообщение
MAVLink-сообщение это отдельная "порция" данных, передаваемая между устройствами. Отдельное MAVLink-сообщение содержит информацию о состоянии дрона (или другого устройства) или команду для дрона.
Примеры MAVLink-сообщений:
* `ATTITUDE`, `ATTITUDE_QUATERNION` ориентация квадрокоптера в пространстве;
* `LOCAL_POSITION_NED` локальная позиция квадрокоптера;
* `GLOBAL_POSITION_INT` глобальная позиция квадрокоптера (широта/долгота/высота);
* `COMMAND_LONG` команда для квадрокоптера (взлететь, сесть, переключить режим и т. д.).
Полный список MAVLink-сообщений можно посмотреть в [документации MAVLink](http://mavlink.org/messages/common).
### Система, компонент системы
Каждое устройство (дрон, базовая станция и т. д.) имеет ID в сети MAVLink. В PX4 MAVLink ID менятся с помощью параметра `MAV_SYS_ID`. Каждое MAVLink сообщение содержит поле с ID системы-отправителя. Кроме того, некоторые сообщения (например, `COMMAND_LONG`) содержат также ID системы-получателя.
Помимо ID систем, сообщения могут содержать ID компонента-отправителя и компонента-получателя. Примеры компонентов системы: полетный контроллер, внешняя камера, управляющий бортовой компьютер (Raspberry Pi в случае Клевера) и т. д.
### Пример пакета
Пример структуры MAVLink-пакета с сообщением `COMMAND_LONG`:
<table>
<tr>
<th></th>
<th>Поле</th>
<th>Длина</th>
<th>Имя</th>
<th>Комментарий</th>
</tr>
<tr>
<td rowspan="8"><div style="transform: rotate(-90deg)">Заголовок</div></td>
<td><code>magic</code></td>
<td>1 байт</td>
<td>Метка начала</td>
<td>0xFD для MAVLink 2.0</td>
</tr>
<tr>
<td><code>len</code></td>
<td>1 байт</td>
<td>Размер данных</td>
<td></td>
</tr>
<tr>
<td><code>incompat_flags</code></td>
<td>1 байт</td>
<td>Обратно несовместимые флаги</td>
<td>На данный момент не используется</td>
</tr>
<tr>
<td><code>compat_flags</code></td>
<td>1 байт</td>
<td>Обратно совместимые флаги</td>
<td>На данный момент не используется</td>
</tr>
<tr>
<td><code>seq</code></td>
<td>1 байт</td>
<td>Порядковый номер сообщения</td>
<td></td>
</tr>
<tr>
<td><code>sysid</code></td>
<td>1 байт</td>
<td>ID системы-отправителя</td>
<td></td>
</tr>
<tr>
<td><code>compid</code></td>
<td>1 байт</td>
<td>ID компонента-отправителя</td>
<td></td>
</tr>
<tr>
<td><code>msgid</code></td>
<td>3 байта</td>
<td>ID сообщения</td>
<td></td>
</tr>
<tr style="background: #fffee6">
<td rowspan="11"><div style="transform: rotate(-90deg)">Данные (пример)</div></td>
<td><code>target_system</code></td>
<td>1 байт</td>
<td>ID системы-получателя</td>
<td></td>
</tr>
<tr style="background: #fffee6">
<td><code>target_component</code></td>
<td>1 байт</td>
<td>ID компонента–получателя</td>
<td></td>
</tr>
<tr style="background: #fffee6">
<td><code>command</code></td>
<td>2 байта</td>
<td>ID команды</td>
<td></td>
</tr>
<tr style="background: #fffee6">
<td><code>confirmation</code></td>
<td>1 байт</td>
<td>Номер для подтверждения</td>
<td></td>
</tr>
<tr style="background: #fffee6">
<td><code>param1</code></td>
<td>4 байта</td>
<td>Параметр 1</td>
<td rowspan="7">Число с плавающей точкой одинарной точности</td>
</tr>
<tr style="background: #fffee6">
<td><code>param2</code></td>
<td>4 байта</td>
<td>Параметр 2</td>
</tr>
<tr style="background: #fffee6">
<td><code>param3</code></td>
<td>4 байта</td>
<td>Параметр 3</td>
</tr>
<tr style="background: #fffee6">
<td><code>param4</code></td>
<td>4 байта</td>
<td>Параметр 4</td>
</tr>
<tr style="background: #fffee6">
<td><code>param5</code></td>
<td>4 байта</td>
<td>Параметр 5</td>
</tr>
<tr style="background: #fffee6">
<td><code>param6</code></td>
<td>4 байта</td>
<td>Параметр 6</td>
</tr>
<tr style="background: #fffee6">
<td><code>param7</code></td>
<td>4 байта</td>
<td>Параметр 7</td>
</tr>
<tr>
<td></td>
<td><code>checksum</code></td>
<td>2 байта</td>
<td>Контрольная сумма</td>
<td></td>
</tr>
<tr>
<td></td>
<td><code>signature</code></td>
<td>13 байт</td>
<td>Сигнатура (опционально)</td>
<td>Позволяет убедиться, что пакет не был скомпроментирован.
Обычно не используется.</td>
</tr>
</table>
<span style="background: #fffee6">Желтым</span> цветом выделены поля данных (полезной нагрузки). Для каждого типа сообщения существует свой набор таких полей.

View File

@@ -1,12 +1,16 @@
# MAVROS # MAVROS
Основная статья: [http://wiki.ros.org/mavros](http://wiki.ros.org/mavros) Основная документация: [http://wiki.ros.org/mavros](http://wiki.ros.org/mavros)
MAVROS \(MAVLink + ROS\) — это пакет для ROS, предоставляющий возможность управлять беспилотниками по протоколу MAVLink. MAVROS поддерживает полетные стеки PX4 и APM. Связь организовывается по UART, USB, TCP или UDP. MAVROS \(MAVLink + ROS\) — это пакет для ROS, предоставляющий возможность управлять беспилотниками по протоколу [MAVLink](mavlink.md). MAVROS поддерживает полетные стеки PX4 и APM. Связь организовывается по UART, USB, TCP или UDP.
MAVROS подписывается определенные ROS-топики в ожидании команд, публикует в другие топики телеметрию, и предоставляет сервисы. MAVROS подписывается определенные ROS-топики в ожидании команд, публикует в другие топики телеметрию, и предоставляет сервисы.
Узел mavros автоматически запускается в launch-файле Клевера. Для [настройки типа подключения](connection.md) см. аргумент `fcu_conn`. Нода MAVROS автоматически запускается в launch-файле Клевера. Для [настройки типа подключения](connection.md) см. аргумент `fcu_conn`.
> **Hint** Упрощенное взаимодействие с коптером возможно с использованием пакета [`simple_offboard`](simple_offboard.md).
> **Note** В пакете `clever` некоторые плагины MAVROS отключены (в целях сохранения ресурсов). Подробнее см. параметр `plugin_blacklist` в файле `/home/pi/catkin_ws/src/clever/clever/launch/mavros.launch`.
## Основные сервисы ## Основные сервисы
@@ -18,7 +22,7 @@ MAVROS подписывается определенные ROS-топики в
`/mavros/state` — статус подключения к полетному контроллеру. Режим полетного контроллера. `/mavros/state` — статус подключения к полетному контроллеру. Режим полетного контроллера.
`/mavros/local_position/pose` — локальная позиция коптера в системе координат ENU. `/mavros/local_position/pose` — локальная позиция коптера в системе координат ENU и его ориентация.
`/mavros/local_position/velocity` — текущая скорость в локальных координатах. Угловые скорости. `/mavros/local_position/velocity` — текущая скорость в локальных координатах. Угловые скорости.
@@ -28,6 +32,8 @@ MAVROS подписывается определенные ROS-топики в
`/mavros/global_position/rel_alt` — относительная высота \(относительно высоты включения моторов\). `/mavros/global_position/rel_alt` — относительная высота \(относительно высоты включения моторов\).
Просмотр сообщений, публикуемых в топики возможен с помощью утилиты `rostopic`, например `rostopic echo /mavros/state`. Подробнее см. [работа с ROS](ros.md).
## Основные топики для публикации ## Основные топики для публикации
`/mavros/setpoint_position/local` — установить целевую позицию и рысканье \(yaw\) беспилотника \(в системе координат ENU\). `/mavros/setpoint_position/local` — установить целевую позицию и рысканье \(yaw\) беспилотника \(в системе координат ENU\).
@@ -45,6 +51,3 @@ MAVROS подписывается определенные ROS-топики в
`/mavros/setpoint_raw/attitude` — отправка пакета [SET\_ATTITUDE\_TARGET](https://pixhawk.ethz.ch/mavlink/#SET_ATTITUDE_TARGET). Позвлояет установить целевую ориенатацию /угловые скорости и уровень газа. Выбор устанавливаемых величин осуществляется с помощью поля `type_mask` `/mavros/setpoint_raw/attitude` — отправка пакета [SET\_ATTITUDE\_TARGET](https://pixhawk.ethz.ch/mavlink/#SET_ATTITUDE_TARGET). Позвлояет установить целевую ориенатацию /угловые скорости и уровень газа. Выбор устанавливаемых величин осуществляется с помощью поля `type_mask`
`/mavros/setpoint_raw/global` — отправка пакета [SET\_POSITION\_TARGET\_GLOBAL\_INT](https://pixhawk.ethz.ch/mavlink/#SET_POSITION_TARGET_GLOBAL_INT). Позволяет установить целевую позицию в глобальных координатах \(ширина, долгота, высота\), а также скорости полета. **Не поддерживается в PX4** \([issue](https://github.com/PX4/Firmware/issues/7552)\). `/mavros/setpoint_raw/global` — отправка пакета [SET\_POSITION\_TARGET\_GLOBAL\_INT](https://pixhawk.ethz.ch/mavlink/#SET_POSITION_TARGET_GLOBAL_INT). Позволяет установить целевую позицию в глобальных координатах \(ширина, долгота, высота\), а также скорости полета. **Не поддерживается в PX4** \([issue](https://github.com/PX4/Firmware/issues/7552)\).
[Упрощенное управление коптером с помощью Simple Offboard](simple_offboard.md).

View File

@@ -7,47 +7,47 @@
Учебно-методическое пособие Учебно-методическое пособие
--------------------------- ---------------------------
[Урок 1. «Знакомство. Принципы проектирования и строение мультикоптеров»](https://github.com/CopterExpress/clever/blob/master/docs/ https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 1. «Знакомство. Принципы проектирования и строение мультикоптеров»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 2. «Основы электричества»](https://github.com/CopterExpress/clever/blob/master/docs/ https://github.com/CopterExpress/clever/blob/master/docs/ https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 2. «Основы электричества»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 3. «Теория пайки»]( https://github.com/CopterExpress/clever/blob/master/docs/ https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 3. «Теория пайки»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 4. «Аэродинамика полета. Пропеллер»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 4. «Аэродинамика полета. Пропеллер»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 5. «Основы электромагнетизма. Типы двигателей»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 5. «Основы электромагнетизма. Типы двигателей»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 6. «Бесколлекторные двигатели и регуляторы их хода»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 6. «Бесколлекторные двигатели и регуляторы их хода»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 7. «Принцип работы, типы и устройство аккумуляторов»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 7. «Принцип работы, типы и устройство аккумуляторов»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 8. «Управление полётом мультикоптера. Принцип функционирования полетного контроллера. ПИД регуляторы»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 8. «Управление полётом мультикоптера. Принцип функционирования полетного контроллера. ПИД регуляторы»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 9. «Основы радиосвязи. Принцип работы радиоаппаратуры управления»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 9. «Основы радиосвязи. Принцип работы радиоаппаратуры управления»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 10. «Аналоговая и цифровая видеотрансляция. Применяемые камеры, радиопередатчики и приёмники»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 10. «Аналоговая и цифровая видеотрансляция. Применяемые камеры, радиопередатчики и приёмники»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 11. «Техника безопасности при сборке и настройке коптеров, при подготовке к вылету. Техника безопасности при работе с аккумуляторами»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 11. «Техника безопасности при сборке и настройке коптеров, при подготовке к вылету. Техника безопасности при работе с аккумуляторами»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 12. «Теория ручного визуального пилотирования»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 12. «Теория ручного визуального пилотирования»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 13. «Техника безопасности при летной эксплуатации коптера»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 13. «Техника безопасности при летной эксплуатации коптера»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 14. «Обучение лётному мастерству»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 14. «Обучение лётному мастерству»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 15. «Основы радиоэлектроники, схемотехники и макетирования электрических схем»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 15. «Основы радиоэлектроники, схемотехники и макетирования электрических схем»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 16. «Основы работы с аналоговым и цифровым сигналом»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 16. «Основы работы с аналоговым и цифровым сигналом»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 17. «Основы работы с лабораторным оборудованием»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 17. «Основы работы с лабораторным оборудованием»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 18. «Теория FPV полетов»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 18. «Теория FPV полетов»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 19. «История автономных полетов. Развитие автопилотов в авиации»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 19. «История автономных полетов. Развитие автопилотов в авиации»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 20. «Основы программирование на языке Python»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 20. «Основы программирование на языке Python»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 21. «Знакомство с компьютером Raspberry Pi»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 21. «Знакомство с компьютером Raspberry Pi»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)
[Урок 22. «Управление автономным дроном: теория»]( https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md) [Урок 22. «Управление автономным дроном: теория»](https://github.com/CopterExpress/clever/blob/master/docs/metodmaterials.md)

View File

@@ -50,7 +50,7 @@
**Подведение итогов** **Подведение итогов**
Ниже предложен один из вариантов подведения итогов курса. Ниже предложен один из вариантов подведения итогов курса.
Финальное мероприятие включает 3 раздела: Финальное мероприятие включает 3 раздела:
@@ -155,7 +155,7 @@
| 5 | Заключение | Подвести итоги занятия, спросить, есть ли у класса вопросы. Спросить, что из изученного на занятии было для них интереснее всего. Попросить учеников ответить на контрольные вопросы. Предложить ученикам по желанию провести в интернете дополнительное исследование на пройденную тему. Сообщить ученикам, какую тему они будут проходить на следующем занятии. | | 5 | Заключение | Подвести итоги занятия, спросить, есть ли у класса вопросы. Спросить, что из изученного на занятии было для них интереснее всего. Попросить учеников ответить на контрольные вопросы. Предложить ученикам по желанию провести в интернете дополнительное исследование на пройденную тему. Сообщить ученикам, какую тему они будут проходить на следующем занятии. |
| 6 | Резервное время | Показать видео и рассказать классу интересные факты по пройденной теме, не вошедшие в программу. | | 6 | Резервное время | Показать видео и рассказать классу интересные факты по пройденной теме, не вошедшие в программу. |
## Урок №6. Тема: «Бесколлекторные двигатели и регуляторы их хода» ## Урок №6. Тема: «Бесколлекторные двигатели и регуляторы их хода»
**Цель урока:** закрепить теоретические знания о строении и работе бесколлекторных **Цель урока:** закрепить теоретические знания о строении и работе бесколлекторных
электродвигателей. Сформировать знания о работе и настройке регуляторов хода, электродвигателей. Сформировать знания о работе и настройке регуляторов хода,
@@ -381,7 +381,7 @@
| 5 | Меняем SSID | Рассказать, что такое SSID. Научить изменять имя wi-fi сети. Объяснить что такое демоны и в какой момент они запускаются. Проработать с конфигурацией одного из них. | | 5 | Меняем SSID | Рассказать, что такое SSID. Научить изменять имя wi-fi сети. Объяснить что такое демоны и в какой момент они запускаются. Проработать с конфигурацией одного из них. |
| 6 | Используем права суперпользователя | Рассказать о типах и правах пользователей системы. Показать примеры использования sudo. | | 6 | Используем права суперпользователя | Рассказать о типах и правах пользователей системы. Показать примеры использования sudo. |
| 7 | Подготовка коптера к автономным полетам | Проверить подключенное оборудование для автономных полетов. Убедиться в работоспособности подключения можно выполнив на Raspberry Pi: rostopic echo /mavros/state | | 7 | Подготовка коптера к автономным полетам | Проверить подключенное оборудование для автономных полетов. Убедиться в работоспособности подключения можно выполнив на Raspberry Pi: rostopic echo /mavros/state |
| 8 | Использование QGroundControl через Wi-Fi | Настроить беспроводное соединение для работы с PixHawk в QGroundControl. Предложить учащимся установить новую прошивку, которая подходит для автономных полетов и откалибровать коптер при беспроводном подключении. | | 8 | Использование QGroundControl через Wi-Fi | Настроить беспроводное соединение для работы с Pixhawk в QGroundControl. Предложить учащимся установить новую прошивку, которая подходит для автономных полетов и откалибровать коптер при беспроводном подключении. |
| 9 | Заключение | Подвести итоги занятия, спросить, есть ли у класса вопросы, их должно быть много, нужно заранее продумать ответы на них. Попросить учеников ответить на контрольные вопросы. Предложить ученикам по желанию провести в интернете дополнительное исследование на пройденную тему. Сообщить ученикам, какую тему они будут проходить на следующем занятии.| | 9 | Заключение | Подвести итоги занятия, спросить, есть ли у класса вопросы, их должно быть много, нужно заранее продумать ответы на них. Попросить учеников ответить на контрольные вопросы. Предложить ученикам по желанию провести в интернете дополнительное исследование на пройденную тему. Сообщить ученикам, какую тему они будут проходить на следующем занятии.|
| 10 | | | | 10 | | |

View File

@@ -13,3 +13,11 @@
Для установки образа воспользуйтесь утилитой [Etcher](https://etcher.io). Для установки образа воспользуйтесь утилитой [Etcher](https://etcher.io).
[![Etcher](https://etcher.io/static/screenshot.gif)](https://etcher.io) [![Etcher](https://etcher.io/static/screenshot.gif)](https://etcher.io)
## Версия образа
Версию установленного образа можно узнать в файле `/etc/clever_version`:
```bash
cat /etc/clever_version
```

View File

@@ -31,7 +31,7 @@ PX4
В режиме автоматического полета квадрокоптер игнорирует сигналы с пульта. В режиме автоматического полета квадрокоптер игнорирует сигналы с пульта.
* **AUTO.MISSION** PX4 выполняет заранее загруженную в квадрокоптер миссию (миссия загружается с помощью QGroundControl, или по MAVLINK используя MAVROS). * **AUTO.MISSION** PX4 выполняет заранее загруженную в квадрокоптер миссию (миссия загружается с помощью QGroundControl, или по [MAVLink](mavlink.md) используя [MAVROS](mavros.md).
* **AUTO.RTL** – коптер автоматически вовращается в точку взлета. * **AUTO.RTL** – коптер автоматически вовращается в точку взлета.
* **AUTO.LAND** – коптер выполняет посадку. * **AUTO.LAND** – коптер выполняет посадку.

View File

@@ -1,10 +1,11 @@
# Настройка Wi-Fi # Настройка Wi-Fi
Wi-Fi адаптер на Raspberry Pi имеет два основных режима работы: Wi-Fi адаптер на Raspberry Pi имеет два основных режима работы:
1. **Режим клиента** RPi подключается к существующей Wi-Fi сети. 1. **Режим клиента** RPi подключается к существующей Wi-Fi сети.
2. **Режим точки доступа** RPi создает Wi-Fi сеть, к которой вы можете подключиться. 2. **Режим точки доступа** RPi создает Wi-Fi сеть, к которой вы можете подключиться.
При использовании [образа для RPi](microsd_images.md) по умолчанию Wi-Fi адаптер работает в режиме точки доступа. При использовании [образа для RPi](microsd_images.md) по умолчанию Wi-Fi адаптер работает в [режиме точки доступа](wifi.md).
## Инструкция для переключения адаптера в режим клиента ## Инструкция для переключения адаптера в режим клиента
@@ -116,7 +117,9 @@ ___
Ниже вы можете узнать больше о том, как устроена работа с сетью на RPi. Ниже вы можете узнать больше о том, как устроена работа с сетью на RPi.
# Устройство сети RPi # Устройство сети RPi
Работа сети на образе **2017-11-29-raspbian-stretch-lite** поддерживается двумя предустановленными службами: Работа сети на образе **2017-11-29-raspbian-stretch-lite** поддерживается двумя предустановленными службами:
* **networking** — служба включает все сетевые интерфейсы в момент запуска [5]. * **networking** — служба включает все сетевые интерфейсы в момент запуска [5].
* **dhcpcd** — служба обеспечивает настройку адресации и маршрутризации на интерфейсах, полученных динамически или указаных в файле настроек статически. * **dhcpcd** — служба обеспечивает настройку адресации и маршрутризации на интерфейсах, полученных динамически или указаных в файле настроек статически.
@@ -188,9 +191,11 @@ network={
```bash ```bash
sudo systemctl restart dhcpcd sudo systemctl restart dhcpcd
``` ```
## DHCP сервер ## DHCP сервер
### dnsmasq-base ### dnsmasq-base
`dnsmasq-base` консольная утилита, не являющаяся службой, для использования dnsmasq как службы надо установить пакет `dnsmasq`. `dnsmasq-base` консольная утилита, не являющаяся службой, для использования dnsmasq как службы надо установить пакет `dnsmasq`.
```bash ```bash
@@ -264,7 +269,6 @@ fi
EOF EOF
``` ```
## Ссылки ## Ссылки
1. [habr.com: Linux WiFi из командной строки с wpa_supplicant](https://habr.com/post/315960/) 1. [habr.com: Linux WiFi из командной строки с wpa_supplicant](https://habr.com/post/315960/)

View File

@@ -9,13 +9,14 @@ Raspberry Pi означает «малиновый пирог». Этот сво
* оперативная память 512 Мб; * оперативная память 512 Мб;
* есть USB -разъемы (один или два в зависимости от модели); м * есть USB -разъемы (один или два в зависимости от модели); м
* наиболее применяемая модель мини-компьютера Raspberry Pi модель В - это модель В на с поддержкой Ethernet. * наиболее применяемая модель мини-компьютера Raspberry Pi модель В - это модель В на с поддержкой Ethernet.
Сферы применения компьютера Raspberry Pi достаточно широки, ведь это всё-таки вполне полноценный компьютер. Если вам нужна машина для решения несложных задач, которые не требуют применения мощных ресурсов в плане вычисления, то вы смело можете подключать к устройству Raspberry Pi стандартные элементы компьютера: монитор; мышь; клавиатуру; Сферы применения компьютера Raspberry Pi достаточно широки, ведь это всё-таки вполне полноценный компьютер. Если вам нужна машина для решения несложных задач, которые не требуют применения мощных ресурсов в плане вычисления, то вы смело можете подключать к устройству Raspberry Pi стандартные элементы компьютера: монитор; мышь; клавиатуру;
Вообще, Raspberry Pi очень популярная платформа, на которой можно реализовать множество проектов, таких как Вообще, Raspberry Pi очень популярная платформа, на которой можно реализовать множество проектов, таких как
* сервер домашней автоматизации (или система «умный дом») * сервер домашней автоматизации (или система «умный дом»)
* сервер хранения данных (NAS) * сервер хранения данных (NAS)
* домашний медиа-сервер * домашний медиа-сервер
* «мозговой центр» для автоматизированных станков или роботов * «мозговой центр» для автоматизированных станков или роботов
Собственно, в последнем качестве мы и будем его использовать, благодаря возможности подключения его к автопилоту Pixhawk. Собственно, в последнем качестве мы и будем его использовать, благодаря возможности подключения его к автопилоту Pixhawk.

View File

@@ -1,9 +1,9 @@
Управление Клевером со смартфона Управление Клевером со смартфона
=== ===
**WORK-IN-PROGRESS** <a href="https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8"><img src="assets/appstore.svg"></a>
Для управления Клевером со смартфона через Wi-Fi необходимо установить приложение  iOS (TODO), Android (TODO). Для управления Клевером со смартфона через Wi-Fi необходимо установить приложение  [iOS](https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8), Android (*work-in-progress*).
![](assets/IMG_4397.PNG) ![](assets/IMG_4397.PNG)
@@ -16,7 +16,7 @@
> **Note** Мобильный пульт конфликтует с реальной аппаратурой радиоуправления. Во время использования мобильного пульта она должна быть выключена. > **Note** Мобильный пульт конфликтует с реальной аппаратурой радиоуправления. Во время использования мобильного пульта она должна быть выключена.
Установите [образ Clever на RPi](microsd_images.md), а также включите `rosbridge` и `rc` в launch-файле (`~/catkin_ws/src/clever/clever/launch/clever.launch`): Установите [образ Clever на RPi](microsd_images.md). Для работы приложения параметры `rosbridge` и `rc` в launch-файле (`~/catkin_ws/src/clever/clever/launch/clever.launch`) должны быть включены:
```xml ```xml
<arg name="rosbridge" default="true"/> <arg name="rosbridge" default="true"/>
@@ -34,7 +34,7 @@ sudo systemctl restart clever
Также необходимо убедиться, что PX4-параметр `COM_RC_IN_MODE` установлен в значение `0` (RC Transmitter). Также необходимо убедиться, что PX4-параметр `COM_RC_IN_MODE` установлен в значение `0` (RC Transmitter).
Дополнительные параметры: Дополнительные параметры PX4:
* `COM_RC_LOSS_T` таймаут для определения потери сигнала пульта (мобильного или физического). Рекомендуется увеличение таймаута до нескольких секунд. * `COM_RC_LOSS_T` таймаут для определения потери сигнала пульта (мобильного или физического). Рекомендуется увеличение таймаута до нескольких секунд.
* `NAV_RCL_ACT` действие при потере сигнала пульта. * `NAV_RCL_ACT` действие при потере сигнала пульта.
@@ -53,4 +53,4 @@ sudo systemctl restart clever
* Если интерфейс пульта отображает явно неправильное напряжение (напр. > 5 V), проверьте, что значение PX4-параметра `BAT_N_CELLS` соответствует реальному количество элементов батареи. Если отображаемое напряжение все равно неверно, откалибруйте батарею (TODO: ссылка). * Если интерфейс пульта отображает явно неправильное напряжение (напр. > 5 V), проверьте, что значение PX4-параметра `BAT_N_CELLS` соответствует реальному количество элементов батареи. Если отображаемое напряжение все равно неверно, откалибруйте батарею (TODO: ссылка).
* Если вместо режима PX4 отображается текст "DISCONNECTED FROM FCU", проверьте [подключение Raspberry Pi к PixHawk](connection.md). * Если вместо режима PX4 отображается текст "DISCONNECTED FROM FCU", проверьте [подключение Raspberry Pi к Pixhawk](connection.md).

View File

@@ -1,15 +1,19 @@
ROS: основные концепции ROS
==== ===
Основная статья: http://wiki.ros.org Основная статья: http://wiki.ros.org
TODO ROS – это широко используемый фреймворк для создания сложных и распределенных роботехнических систем.
Установка Установка
--- ---
Основная статья: http://wiki.ros.org/kinetic/Installation/Ubuntu Основная статья: http://wiki.ros.org/kinetic/Installation/Ubuntu
ROS уже установлен на [образе для RPi](microsd_images.md).
Для использования ROS на компьютере рекомендуется ОС Ubuntu Linux (либо виртуальная машина, например [Parallels Desktop Lite](https://itunes.apple.com/ru/app/parallels-desktop-lite/id1085114709?mt=12) или [VirtualBox](https://www.virtualbox.org)).
Концепции Концепции
--- ---
@@ -17,15 +21,86 @@ TODO
Основная статья: http://wiki.ros.org/Nodes Основная статья: http://wiki.ros.org/Nodes
ROS-нода это специальная программа (обычно написанная на Python или C++), которая взаимодействует с другими нодами посредством ROS-топиков и ROS-сервисов. Разделение сложных роботехнических систем на изолированные ноды дает определеные преимущества: понижается связанность кода, повышается переиспользуемость и надежность.
Очень многие роботехнические библиотеки и драйвера выполнены именно в виде ROS-нод.
Для того, чтобы превратить обычную программу в ROS-ноду, необходимо подключить к ней библиотеку `rospy` или `roscpp` и добавить инициализирующий код.
Пример ROS-ноды на языке Python:
```python
import rospy
rospy.init_node('my_ros_node') # имя ROS-ноды
rospy.spin() # входим в бесонечный цикл...
```
### Топики ### Топики
Основная статья: http://wiki.ros.org/Topics Основная статья: http://wiki.ros.org/Topics
Топик это именованная шина данных, по которой ноды обмениваются сообщениями. Любая нода может *опубликовать* сообщение в произвольный топик, а также *подписаться* на произвольный топик.
Пример публикации сообщения типа [`std_msgs/String`](http://docs.ros.org/api/std_msgs/html/msg/String.html) (строка) в топик `/foo` на языке Python:
```python
from std_msgs.msg import String
# ...
foo_pub = rospy.Publisher('/foo', String, queue_size=1) # создаем Publisher'а
foo_pub.publish(data='Hello, world!') # публикуем сообщение
```
Пример подписки на топик `/foo`:
```python
def foo_callback(msg):
print msg.data
# Подписываемся. При получении сообщения в топик /foo будет вызвана функция foo_callback.
rospy.Subscriber('/foo', String, foo_callback)
```
Также, существует возможность работы с топиками с помощью утилиты `rostopic`. Например, с помощью следующей команды можно просматривать сообщения, публикуемые в топик `/mavros/state`:
```bash
rostopic echo /mavros/state
```
### Сервисы ### Сервисы
Основная статья: http://wiki.ros.org/Services Основная статья: http://wiki.ros.org/Services
Mavros Сервис – это некоторый аналог функции, которая может быть вызвана из одной ноды, а обработана в другой. У сервиса есть имя, аналогичное имени топика, и 2 типа сообщений: тип запроса и тип ответа.
Пример вызова ROS-сервиса из языка Python:
```python
from clever.srv import GetTelemetry
# ...
# Создаем обертку над сервисом get_telemetry пакета clever с типом GetTelemetry:
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
# Вызываем сервис и получаем телеметрию квадрокоптера:
telemetry = get_telemetry()
```
С сервисами можно также работать при помощи утилиты `rosservice`. Так можно вызвать сервис `/get_telemetry` из командной строки:
```bash
rosservice call /get_telemetry "{frame_id: ''}"
```
Больше примеров использования сервисов для автономных полетов квадрокоптера Клевер можно посмотреть в [документации ноды simple_offboard](simple_offboard.md).
Работа на нескольких машинах
--- ---
Основная статья: http://wiki.ros.org/mavros Преимуществом использования ROS явлется возможность распределения нод на несколько машин в сети. Например, ноду, осуществляющую распознование образом на изображении можно запустить на более мощном компьютере; ноду, управляющую коптером можно запустить непосредствено на Raspberry Pi, подключенном к полетому контроллеру и т. д.
Для запуска ноды

View File

@@ -30,3 +30,9 @@ export ROS_IP=192.168.11.1
В качестве reference frame рекомендуется установить фрейм `local_origin`. Для визуализации коптера можно добавить визуализационные маркеры из топика `/vehicle_markers`. Можно просмотреть картинку с дополненной реальностью из топика основной камеры `/main_camera/image_raw`. В качестве reference frame рекомендуется установить фрейм `local_origin`. Для визуализации коптера можно добавить визуализационные маркеры из топика `/vehicle_markers`. Можно просмотреть картинку с дополненной реальностью из топика основной камеры `/main_camera/image_raw`.
Axis или Grid настроенный на фрейм `aruco_map` будут визуализировать расположение [карты ArUco-меток](aruco.md). Axis или Grid настроенный на фрейм `aruco_map` будут визуализировать расположение [карты ArUco-меток](aruco.md).
Рекомендуется также установка набора дополнительных полезных плагинов [jsk_rviz_plugins](https://jsk-docs.readthedocs.io/en/latest/jsk_visualization/doc/jsk_rviz_plugins/index.html). Это набор позволяет визуализировать топики типа `TwistStamped` (скорость), `CameraInfo`, `PolygonArray` и многое другое. Для установки используйте команду:
```bash
sudo apt-get install ros-kinetic-jsk-visualization
```

View File

@@ -282,4 +282,4 @@
Далее: [Настройка-полетного-контролера](aruco.md#Настройка-полетного-контролера) Далее: [Настройка-полетного-контролера](aruco.md#Настройка-полетного-контролера)
Далее: [Подключение Raspberry Pi к PixHawk](connection.md). Далее: [Подключение Raspberry Pi к Pixhawk](connection.md).

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