Compare commits

..

229 Commits

Author SHA1 Message Date
Oleg Kalachev
6f96c9e3ff Fix build, attempt #2 2018-09-19 07:04:34 +03:00
Oleg Kalachev
9aca12e0a5 Little fix in byobu installation 2018-09-19 04:40:20 +03:00
Oleg Kalachev
ead55fe0e3 image: add ltrace utility 2018-09-19 03:22:31 +03:00
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
Oleg Kalachev
3b0dd46ca6 Decrease conn/timeout to 8 seconds 2018-07-25 15:40:38 +03:00
Oleg Kalachev
16b2e1903a Fix udp and udp-b bridge settings 2018-07-25 15:40:38 +03:00
Smirnov Artem
36d7a95d34 Merge pull request #58 from urpylka/rm_mount_point
image_builder: fix pack 4
2018-07-25 14:33:11 +04:00
Artem Smirnov
1d82e195ec image_builder: add checkout to GWBT_REF 2018-07-25 12:55:18 +03:00
Artem Smirnov
78cae0c69a image_builder: fix vars syntax 2018-07-25 12:55:18 +03:00
Oleg Kalachev
2b46ee27f2 docs: small fix 2018-07-25 12:26:43 +03:00
Oleg Kalachev
de44400749 Merge branch 'master' of github.com:CopterExpress/clever 2018-07-25 12:01:47 +03:00
Oleg Kalachev
55e40bd6c3 docs: add mobile rc page [wip] 2018-07-25 12:01:38 +03:00
Artem Smirnov
124950d7e4 image_builder: remove MOUNT_POINT
I changed CONST-PATH to dynamic dir by mktemp
2018-07-24 19:05:04 +03:00
Smirnov Artem
199104ca83 Merge pull request #57 from urpylka/master
image_builder: fix pack
2018-07-24 16:33:19 +04:00
Artem Smirnov
e5552e0a4b image_builder: replace old archive 2018-07-24 15:16:56 +03:00
Oleg Kalachev
bfb0aa7961 Force gitbook update 2018-07-16 23:34:00 +03:00
Smirnov Artem
44d83bdcf8 Merge pull request #56 from Yuliya1404/master
added description of project and links to telegtam chats
2018-07-11 22:41:12 +03:00
Yuliya1404
d960e57cf9 docs: small fix 2018-07-11 15:47:38 +03:00
Yuliya1404
30ec03ef4d docs: added description of project and links on telegram chat 2018-07-11 15:28:34 +03:00
Smirnov Artem
c2c27b1577 docs: added build status icon 2018-07-08 15:09:51 +03:00
Oleg Kalachev
c0449ccf59 docs update 2018-07-07 17:58:33 +03:00
Oleg Kalachev
ea933ce3d1 docs: small fix 2018-07-07 17:57:02 +03:00
Oleg Kalachev
327666385b docs: small fix 2018-07-07 17:55:54 +03:00
Oleg Kalachev
8ea511b293 docs: firmware.md fixes 2018-07-07 17:54:09 +03:00
Oleg Kalachev
c510fe5cf0 Merge branch 'master' of github.com:CopterExpress/clever 2018-07-07 17:50:47 +03:00
Oleg Kalachev
dab70937f5 docs: add article about px4 firmware uploading 2018-07-07 17:50:42 +03:00
Smirnov Artem
fec4859cfe image_builder: enable the lirc-rpi module for uart 2018-07-06 22:10:58 +03:00
Oleg Kalachev
63ecc3b713 image: fix libpoco-dev version 2018-07-06 22:02:53 +03:00
Oleg Kalachev
d3a08c60d7 Merge pull request #54 from Yuliya1404/master
docs: changed metod materials
2018-07-06 17:25:51 +03:00
Oleg Kalachev
322eb1e255 image: add tcpdump and libpoco-dev 2018-07-06 04:37:00 +03:00
Oleg Kalachev
22d4f3c3e7 docs: small fixes 2018-07-05 03:07:52 +03:00
Oleg Kalachev
008750b1d9 docs: add systemd/roslaunch documentation 2018-07-05 03:03:16 +03:00
Oleg Kalachev
506767f32f docs: add some info to gps article 2018-07-05 02:50:45 +03:00
Oleg Kalachev
aaa673de92 simple_offboard: add global alt to get_telemetry service 2018-07-05 02:50:35 +03:00
Oleg Kalachev
43237d8ff4 GCS bridges config and documentation improvements 2018-07-05 02:10:53 +03:00
Oleg Kalachev
9681fc9a87 Merge branch 'master' of github.com:CopterExpress/clever 2018-07-04 20:29:45 +03:00
Oleg Kalachev
76c3e96f76 Enable mavros respawn by default 2018-07-04 20:26:47 +03:00
shish1404
1e66afa6a4 docs: changed test 2018-06-29 22:14:46 +03:00
shish1404
41c59e8e49 docs: added videos 2018-06-29 18:49:22 +03:00
shish1404
225e3d7936 docs: changed label 2018-06-29 18:48:53 +03:00
Artem Smirnov
204dd97b00 image_builder: remove date from image name 2018-06-26 19:49:42 +03:00
Artem Smirnov
27bfecc737 image_builder: add information about new partitions 2018-06-25 19:33:11 +03:00
Smirnov Artem
8cdb131a19 Merge pull request #53 from urpylka/master
image_builder: fix pack
2018-06-25 14:53:51 +03:00
Artem Smirnov
c9042588f0 image_builder: enable shrinker by default 2018-06-25 13:28:44 +03:00
Oleg Kalachev
342eaec49a gitbook: fix ya-metrika 2018-06-25 03:13:17 +03:00
Oleg Kalachev
77b3d28e3b gitbook: add ya-metrika 2018-06-25 03:00:04 +03:00
Smirnov Artem
357b38b5e7 image_builder: add text for /etc/fstab 2018-06-23 21:12:06 +03:00
Artem Smirnov
a99a1c7540 image_builder: change PARTUUID to /dev/mmcblk0p2 2018-06-23 20:44:30 +03:00
Artem Smirnov
6742ba332a image_builder: add fixed version for deb-packages 2018-06-22 15:31:26 +03:00
Smirnov Artem
c5916fea7c Merge pull request #52 from urpylka/master
image_builder fix-pack
2018-06-21 23:44:08 +03:00
Smirnov Artem
7a4958f8e9 Merge branch 'master' into master 2018-06-21 23:43:35 +03:00
Artem Smirnov
b71a96faee image_builder: add param for discover packages 2018-06-21 21:54:47 +03:00
Artem Smirnov
24e79f0169 image_builder: add autosizer.sh to build.Jenkinsfile 2018-06-21 18:24:02 +03:00
Artem Smirnov
76e887407a image_builder: add argument for set FREE SPACE 2018-06-21 18:24:02 +03:00
Artem Smirnov
0d0c8e54f4 image_builder: add image-shrinker 2018-06-21 18:24:02 +03:00
Artem Smirnov
06a01f7e32 image_builder: return devel dir to catkin_ws
needed for roscd
2018-06-21 18:24:02 +03:00
Artem Smirnov
f564d20c5b image_builder: add fixed rosinstall file 2018-06-21 18:24:02 +03:00
Artem Smirnov
85afded6b4 image_builder: move install mjpg-streamer to soft-install 2018-06-19 15:51:26 +03:00
Artem Smirnov
7e84853c37 image_builder: small echo fix 2018-06-19 13:39:37 +03:00
Artem Smirnov
c3c324158f image_builder: fix for add environment 2018-06-18 20:51:29 +03:00
Artem Smirnov
1e2fd40c05 image_builder: remove build & devel dirs 2018-06-18 20:42:47 +03:00
Artem Smirnov
6a7f78a218 image_builder: add "yes" flag 2018-06-18 20:42:47 +03:00
Smirnov Artem
0b637e56d7 image_builder: change param to const 2018-06-18 20:42:47 +03:00
Artem Smirnov
63f44a5a3f image_builder: remove unused code from image_config.sh 2018-06-18 20:42:47 +03:00
Artem Smirnov
83ce14e31b image_builder: merge arguments in resize_fs 2018-06-18 20:42:47 +03:00
Artem Smirnov
8162357ce6 image_builder: catkin_init_workspace not needed 2018-06-18 20:42:47 +03:00
Oleg Kalachev
ba0e9cf9c5 Change udp connection timeout to 10 2018-06-18 19:40:34 +03:00
Oleg Kalachev
8d1072d97d docs: add info about virtual joustick in qgroundcontrol 2018-06-14 02:04:22 +03:00
Oleg Kalachev
ffd4fdf2dc docs: add illustration to listener command usage 2018-06-14 01:01:17 +03:00
Oleg Kalachev
d279f04a1f docs: more 2018-06-13 16:39:48 +03:00
Oleg Kalachev
77e8c858a0 docs: another fixes 2018-06-13 16:34:57 +03:00
Oleg Kalachev
f6edf15011 docs: little fixes 2018-06-13 16:33:52 +03:00
Oleg Kalachev
b50c34b19c docs: add flight logs article 2018-06-13 16:29:55 +03:00
Oleg Kalachev
874f206e2a Somes fixes to iOS app 2018-06-09 20:33:40 +03:00
Oleg Kalachev
fd262fdb6a Add .editorconfig 2018-06-09 20:26:18 +03:00
Oleg Kalachev
2cb17985d4 Merge branch 'master' of github.com:CopterExpress/clever 2018-06-09 19:21:11 +03:00
Oleg Kalachev
2daa6f108a Update to iOS app 2018-06-09 16:12:57 +03:00
Oleg Kalachev
2e0d92c0d5 image: restore .vimrc 2018-06-09 03:41:41 +03:00
Oleg Kalachev
1a0d61af7c docs: small fixes 2018-06-09 02:28:45 +03:00
Oleg Kalachev
eb9fc6140b Merge branch 'master' of github.com:CopterExpress/clever 2018-06-08 20:14:43 +03:00
Oleg Kalachev
b0d72030fa docs: working on rc docs 2018-06-08 20:13:42 +03:00
Oleg Kalachev
db27d422ae docs: working on rc docs 2018-06-08 20:06:44 +03:00
Oleg Kalachev
d6ec597fe2 docs: working on rc docs 2018-06-08 00:52:12 +03:00
Oleg Kalachev
0fe319f430 Set udp bridge connection timeout to 20 2018-06-06 18:17:24 +03:00
Oleg Kalachev
2616b49e82 Merge branch 'master' of github.com:CopterExpress/clever 2018-06-06 18:09:47 +03:00
Oleg Kalachev
c2fd26db56 Support mavros udp-pb bridge 2018-06-06 18:09:38 +03:00
Artem Smirnov
71bd59fe3d image_builder: change "catkin init" to "catkin_init_workspace" 2018-06-05 17:41:38 +03:00
Oleg Kalachev
5b84fe63dd docs: remove disquss 2018-06-03 15:11:24 +03:00
Smirnov Artem
40782063c4 image_builder: Added GWBT_URL parameter
Added GWBT_URL parameter for automatic insert that to field on manual run of build
2018-06-02 14:55:53 +03:00
Smirnov Artem
580eb2400c docs: update wifi.md 2018-05-31 17:12:15 +03:00
Smirnov Artem
4666e443cb Update microsd_images.md 2018-05-31 16:54:41 +03:00
Smirnov Artem
d52c1701e4 Merge pull request #49 from urpylka/wifi_doc
docs: add network & wifi conf
2018-05-31 16:24:50 +03:00
Smirnov Artem
4a543c75f7 image_builder: use dnsmasq as default dhcp-server (#48) 2018-05-31 16:22:45 +03:00
Smirnov Artem
0b15f4ffd5 Update network.md 2018-05-31 16:16:06 +03:00
Oleg Kalachev
0f6e24d07f Changes to network.md 2018-05-31 16:15:51 +03:00
Artem Smirnov
7110ef1420 docs: add network & wifi conf 2018-05-31 16:04:35 +03:00
Oleg Kalachev
a56cef65d5 docs: modes changes 2018-05-30 16:35:09 +03:00
Oleg Kalachev
f58be1ff6f docs: small change 2018-05-30 16:11:07 +03:00
Oleg Kalachev
b1a788864c docs: some styling 2018-05-30 16:09:06 +03:00
Oleg Kalachev
fe468d911b docs: small change 2018-05-30 16:05:45 +03:00
Oleg Kalachev
ef8e1c0478 docs: some styling 2018-05-30 16:04:14 +03:00
Oleg Kalachev
710c4fb33e docs: add some units 2018-05-30 15:56:18 +03:00
Oleg Kalachev
3ef8656bcd docs: add link to px4 releases page 2018-05-30 15:50:53 +03:00
Oleg Kalachev
251e15f503 docs: add some units 2018-05-30 15:44:03 +03:00
Smirnov Artem
eb2f9d9c2b docs: add UDP support to GCS-bridge (#47) 2018-05-18 18:12:54 +03:00
Oleg Kalachev
dfcd3ea693 Merge branch 'master' of github.com:CopterExpress/clever 2018-05-13 23:01:14 +03:00
Oleg Kalachev
7260128dfd docs: note about yaw=NaN 2018-05-13 23:01:06 +03:00
Oleg Kalachev
d4e783c96f snippets: get_distance_global 2018-05-13 20:10:41 +03:00
Oleg Kalachev
c57a342053 Fix to readme 2018-05-12 17:03:25 +03:00
Oleg Kalachev
9ed9af2d04 Some fixes to readme 2018-05-12 17:02:48 +03:00
Oleg Kalachev
295b9c98d1 docs: rework images article 2018-05-12 16:58:54 +03:00
Oleg Kalachev
8f4de0e08f Merge branch 'master' of github.com:CopterExpress/clever 2018-05-10 22:33:16 +03:00
Oleg Kalachev
8f53301b79 simple_offboard: correct axes for calculating yaw for setpoints 2018-05-10 22:32:45 +03:00
Oleg Kalachev
6372ef8c22 simple_offboard: Tait-Bryan z-y-x angles for pitch, roll and yaw 2018-05-10 22:31:56 +03:00
Oleg Kalachev
a91f9e5a6b Change image size to from 8G to 7G 2018-05-10 16:40:05 +03:00
Oleg Kalachev
6b74f75616 Merge branch 'master' of github.com:CopterExpress/clever 2018-05-09 19:50:46 +03:00
Oleg Kalachev
9cd9babb83 simple_offboard: yaw_rate, pitch_rate, roll_rate in get_telemetry 2018-05-09 19:50:18 +03:00
Smirnov Artem
380c14da56 image_buider: enable hardware uart with raspi-config (#43)
Signed-off-by: Artem Smirnov <urpylka@gmail.com>
2018-05-05 20:36:22 +03:00
urpylka
32c1c18af2 image_builder: fix syntax
Signed-off-by: Artem Smirnov <urpylka@gmail.com>
2018-05-05 16:50:36 +03:00
urpylka
b7077339a1 image_builder: add sha256sum to release message
Signed-off-by: Artem Smirnov <urpylka@gmail.com>
2018-05-03 22:33:57 +03:00
urpylka
52fd505ffc image_builder: change spaces
Signed-off-by: Artem Smirnov <urpylka@gmail.com>
2018-05-03 22:33:57 +03:00
urpylka
b911b7a3dd image_builder: fix syntax
Signed-off-by: Artem Smirnov <urpylka@gmail.com>
2018-05-03 22:01:29 +03:00
126 changed files with 4509 additions and 2027 deletions

13
.editorconfig Normal file
View File

@@ -0,0 +1,13 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
[*.{py,swift,launch}]
indent_style = space
indent_size = 4
[*.{js,html}]
indent_style = tab

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

@@ -4,16 +4,17 @@
CLEVER is an educational programmable drone kit consisting of an unassembled quadcopter, open source software and documentation. The kit includes Pixhawk/Pixracer autopilot running PX4 firmware, Raspberry Pi 3 as companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices. CLEVER is an educational programmable drone kit consisting of an unassembled quadcopter, open source software and documentation. The kit includes Pixhawk/Pixracer autopilot running PX4 firmware, Raspberry Pi 3 as companion computer, a camera for computer vision navigation as well as additional sensors and peripheral devices.
Copter Express has implemented a large number of different autonomous drone projects using exactly the same platform: [automated pizza delivery](https://www.youtube.com/watch?v=hmkAoZOtF58) in Samara and Kazan, coffee delivery in Skolkovo Innovation Center, [autonomous quadcopter with charging station](https://www.youtube.com/watch?v=RjX6nUqw1mI) for site monitoring and security, winning drones on [Robokross-2016](https://www.youtube.com/watch?v=dGbDaz_VmYU) and [Robokross-2017](https://youtu.be/AQnd2CRczbQ) competitions and many others. Copter Express has implemented a large number of different autonomous drone projects using exactly the same platform: [automated pizza delivery](https://www.youtube.com/watch?v=hmkAoZOtF58) in Samara and Kazan, coffee delivery in Skolkovo Innovation Center, [autonomous quadcopter with charging station](https://www.youtube.com/watch?v=RjX6nUqw1mI) for site monitoring and security, winning drones on [Robocross-2016](https://www.youtube.com/watch?v=dGbDaz_VmYU) and [Robocross-2017](https://youtu.be/AQnd2CRczbQ) competitions and many others.
**The main documentation in Russian is available on our Gitbook:** **The main documentation in Russian is available [on our Gitbook](https://clever.copterexpress.com/).**
**https://copterexpress.gitbooks.io/clever/content/**
Use it to learn how to assemble, configure, pilot and program autonomous CLEVER drone. Use it to learn how to assemble, configure, pilot and program autonomous CLEVER drone.
## Preconfigured RPi 3 image ## Preconfigured RPi 3 image
Preconfigured image for Raspberry Pi 3 with installed and configured software, ready to fly, is available [here](https://copterexpress.gitbooks.io/clever/content/docs/microsd_images.html). **Preconfigured image for Raspberry Pi 3 with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clever/releases).**
[![Build Status](http://builder.coex.space/job/CopterExpress---clever/badge/icon)](http://builder.coex.space/job/CopterExpress---clever/)
Image includes: Image includes:
@@ -24,7 +25,7 @@ Image includes:
* mavros * mavros
* CLEVER software bundle for autonomous drone control * CLEVER software bundle for autonomous drone control
API description in Russian for autonomous flights is available [here](https://copterexpress.gitbooks.io/clever/simple_offboard.html). API description (in Russian) for autonomous flights is available [on GitBook](https://copterexpress.gitbooks.io/clever/simple_offboard.html).
## Manual installation ## Manual installation

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

@@ -139,7 +139,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 0920; LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Copter Express"; ORGANIZATIONNAME = "Copter Express";
TargetAttributes = { TargetAttributes = {
7C51653C20139237004D1F4D = { 7C51653C20139237004D1F4D = {
@@ -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;
@@ -294,6 +288,7 @@
CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES; CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
@@ -301,6 +296,7 @@
CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -351,6 +347,7 @@
CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES; CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
@@ -358,6 +355,7 @@
CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -393,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;
@@ -409,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

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

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

@@ -1,94 +1,169 @@
{ {
"images" : [ "images" : [
{ {
"idiom" : "iphone",
"size" : "20x20", "size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "iphone",
"size" : "20x20", "size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"idiom" : "iphone",
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "iphone",
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"idiom" : "iphone",
"size" : "40x40", "size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "iphone",
"size" : "40x40", "size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "60x60", "size" : "60x60",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "cleverios180.png", "filename" : "Icon-App-60x60@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "60x60", "size" : "60x60",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "cleverios180-1.png", "filename" : "Icon-App-60x60@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"idiom" : "ipad",
"size" : "20x20", "size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"idiom" : "ipad",
"size" : "20x20", "size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x-1.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "ipad",
"size" : "29x29", "size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"idiom" : "ipad",
"size" : "29x29", "size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x-1.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "ipad",
"size" : "40x40", "size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"idiom" : "ipad",
"size" : "40x40", "size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x-1.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "ipad",
"size" : "76x76", "size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"idiom" : "ipad",
"size" : "76x76", "size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "ipad",
"size" : "83.5x83.5", "size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "1024x1024",
"idiom" : "ios-marketing", "idiom" : "ios-marketing",
"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", "size" : "1024x1024",
"scale" : "1x" "scale" : "1x"
} }
@@ -96,5 +171,8 @@
"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: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

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

@@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Clever RC</string> <string>CLEVER RC</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -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>1</string> <string>6</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>

View File

@@ -3,19 +3,19 @@
// 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
class ViewController: UIViewController, WKScriptMessageHandler { class ViewController: UIViewController, WKScriptMessageHandler {
@IBOutlet weak var webView: WKWebView! @IBOutlet weak var webView: WKWebView!
let impactGenerator = UIImpactFeedbackGenerator(style: .medium) let impactGenerator = UIImpactFeedbackGenerator(style: .medium)
let notificationGenerator = UINotificationFeedbackGenerator() let notificationGenerator = UINotificationFeedbackGenerator()
let udpSocket = UDPClient(address:"255.255.255.255", port: 35602) let udpSocket = UDPClient(address: "255.255.255.255", port: 35602)
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@@ -24,6 +24,7 @@ class ViewController: UIViewController, WKScriptMessageHandler {
UIApplication.shared.isIdleTimerDisabled = true UIApplication.shared.isIdleTimerDisabled = true
// Setup webview event handlers // Setup webview event handlers
webView.scrollView.bounces = false;
webView.configuration.userContentController.add(self, name: "control") webView.configuration.userContentController.add(self, name: "control")
webView.configuration.userContentController.add(self, name: "controlStart") webView.configuration.userContentController.add(self, name: "controlStart")
webView.configuration.userContentController.add(self, name: "lowBattery") webView.configuration.userContentController.add(self, name: "lowBattery")
@@ -56,18 +57,28 @@ class ViewController: UIViewController, WKScriptMessageHandler {
} else if (message.name == "lowBattery") { } else if (message.name == "lowBattery") {
// Got low battery notification // Got low battery notification
print("Low battery notification") print("Low battery notification")
notificationGenerator.notificationOccurred(.warning) tapticNotify()
} 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() func tapticNotify() {
} else { if let feedbackSupportLevel = UIDevice.current.value(forKey: "_feedbackSupportLevel") as? Int {
let banner = NotificationBanner(title: m["msg"] as! String, style: .danger) switch feedbackSupportLevel {
banner.show() case 2:
// 2nd Generation Taptic Engine w/ Haptic Feedback (iPhone 7/7+)
notificationGenerator.notificationOccurred(.warning)
case 1:
// 1st Generation Taptic Engine (iPhone 6S/6S+)
let peek = SystemSoundID(1519)
AudioServicesPlaySystemSound(peek)
case 0:
// No Taptic Engine
break
default: break
} }
} }
} }

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

@@ -7,6 +7,10 @@ html, body {
color: rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9);
} }
* {
user-select: none;
}
.stick { .stick {
border-radius: 50%; border-radius: 50%;
width: 5cm; width: 5cm;
@@ -72,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;
@@ -89,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']; 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

@@ -4,13 +4,19 @@
"author": "Copter Express", "author": "Copter Express",
"language": "ru", "language": "ru",
"root": "docs/", "root": "docs/",
"plugins": ["youtube", "richquotes", "disqus", "versions"], "plugins": ["youtube", "richquotes", "versions", "yametrika"],
"pluginsConfig": { "pluginsConfig": {
"disqus": { "disqus": {
"shortName": "coex-clever" "shortName": "coex-clever"
}, },
"versions": { "versions": {
"type": "tags" "type": "tags"
},
"yametrika": {
"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,55 +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="false"/> <arg name="respawn" default="true"/>
<node pkg="mavros" type="mavros_node" name="mavros" required="false" clear_params="true" respawn="$(arg respawn)" respawn_delay="3" 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://@192.168.11.14:14550" if="$(eval gcs_bridge == 'udp')"/> <!-- TODO: fix --> <param name="gcs_url" value="udp://0.0.0.0:14550@14550" if="$(eval gcs_bridge == 'udp')"/>
<param name="gcs_url" value="udp-b://192.168.11.1: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="" if="$(eval not gcs_bridge)"/> <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_quiet_mode" value="true"/>
<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)[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)[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)[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()
@@ -348,6 +361,7 @@ def get_telemetry(req):
'z': float('nan'), 'z': float('nan'),
'lat': float('nan'), 'lat': float('nan'),
'lon': float('nan'), 'lon': float('nan'),
'alt': float('nan'),
'vx': float('nan'), 'vx': float('nan'),
'vy': float('nan'), 'vy': float('nan'),
'vz': float('nan'), 'vz': float('nan'),
@@ -368,11 +382,9 @@ def get_telemetry(req):
res['x'] = p.pose.position.x res['x'] = p.pose.position.x
res['y'] = p.pose.position.y res['y'] = p.pose.position.y
res['z'] = p.pose.position.z res['z'] = p.pose.position.z
# Get yaw in the request's frame_in
_, _, res['yaw'] = euler_from_orientation(p.pose.orientation) # Calculate roll pitch and yaw as Tait-Bryan angles, order z-y-x
# Calculate pitch and roll as angles between the pose and fcu_horiz res['yaw'], res['pitch'], res['roll'] = euler_from_orientation(p.pose.orientation, axes='rzyx')
attitude_pose = tf_buffer.transform(pose, 'fcu_horiz', TRANSFORM_TIMEOUT)
res['roll'], res['pitch'], _ = euler_from_orientation(attitude_pose.pose.orientation)
if velocity: if velocity:
v = Vector3Stamped() v = Vector3Stamped()
@@ -383,11 +395,15 @@ def get_telemetry(req):
res['vx'] = linear.vector.x res['vx'] = linear.vector.x
res['vy'] = linear.vector.y res['vy'] = linear.vector.y
res['vz'] = linear.vector.z res['vz'] = linear.vector.z
# TODO pitch_rate, roll_rate, yaw_rate
res['yaw_rate'] = velocity.twist.angular.z
res['pitch_rate'] = velocity.twist.angular.y
res['roll_rate'] = velocity.twist.angular.x
if global_position and stamp - global_position.header.stamp < rospy.Duration(5): if global_position and stamp - global_position.header.stamp < rospy.Duration(5):
res['lat'] = global_position.latitude res['lat'] = global_position.latitude
res['lon'] = global_position.longitude res['lon'] = global_position.longitude
res['alt'] = global_position.altitude
if state: if state:
res['connected'] = state.connected res['connected'] = state.connected

View File

@@ -6,8 +6,8 @@ def orientation_from_quaternion(q):
return Quaternion(*q) return Quaternion(*q)
def orientation_from_euler(roll, pitch, yaw): def orientation_from_euler(roll, pitch, yaw, axes='rzyx'):
q = t.quaternion_from_euler(roll, pitch, yaw) q = t.quaternion_from_euler(roll, pitch, yaw, axes)
return orientation_from_quaternion(q) return orientation_from_quaternion(q)
@@ -15,9 +15,9 @@ def quaternion_from_orientation(o):
return o.x, o.y, o.z, o.w return o.x, o.y, o.z, o.w
def euler_from_orientation(o): def euler_from_orientation(o, axes='rzyx'):
q = quaternion_from_orientation(o) q = quaternion_from_orientation(o)
return t.euler_from_quaternion(q) return t.euler_from_quaternion(q, axes)
def vector3_from_point(p): def vector3_from_point(p):

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)

View File

@@ -7,8 +7,9 @@ string mode
float32 x float32 x
float32 y float32 y
float32 z float32 z
float32 lat float64 lat
float32 lon float64 lon
float32 alt
float32 vx float32 vx
float32 vy float32 vy
float32 vz float32 vz

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,12 +5,16 @@
«Клевер» — это учебный конструктор программируемого квадрокоптера, состоящего из популярных открытых компонентов, а также набор необходимой документации и библиотек для работы с ним. «Клевер» — это учебный конструктор программируемого квадрокоптера, состоящего из популярных открытых компонентов, а также набор необходимой документации и библиотек для работы с ним.
Набор включает в себя полетный контроллер 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.
Также у нас есть чат для программистов, которые разрабатывают под PX4, автономную навигацию в помещениях и рои дронов https://t.me/DroneCode.
Образ для Raspberry Pi Образ для Raspberry Pi
---------------------- ----------------------
@@ -20,7 +24,7 @@
* Raspbian Stretch * Raspbian Stretch
* ROS Kinetic * ROS Kinetic
* Настроенную работу с сетью * Настроенную [работу с сетью](network.md)
* OpenCV * OpenCV
* mavros * mavros
* Набор ПО для работы с Клевером * Набор ПО для работы с Клевером

View File

@@ -1,15 +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)
* [Пилотирование со смартфона](rc.md)
* [SSH-доступ](ssh.md) * [SSH-доступ](ssh.md)
* [Устройство UART](uart.md)
* [Неисправности радиоаппаратуры](radioerrors.md) * [Неисправности радиоаппаратуры](radioerrors.md)
* [Безопасность](safety.md) * [Безопасность](safety.md)
* [Техника безопасности по пайке](tb.md) * [Техника безопасности по пайке](tb.md)
@@ -26,13 +30,21 @@
* [Визуализация с помощью rviz](rviz.md) * [Визуализация с помощью rviz](rviz.md)
* [Работа с SITL](sitl.md) * [Работа с SITL](sitl.md)
* [Подключение GPS](gps.md) * [Подключение GPS](gps.md)
* [Автозапуск ПО](autolaunch.md)
* [Использование 3G-модема](3g.md) * [Использование 3G-модема](3g.md)
* [Устройство сети RPi](network.md)
* [Работа с логами PX4](flight_logs.md)
* [Протокол MAVLink](mavlink.md)
* [Типы силовых разъемов](connectortypes.md)
* [Ошибки радиоаппаратуры](radioerrors1.md)
* [Настройка PID](calibratePID.md)
* Учебник * Учебник
* [Уроки](lessons.md) * [Теория и видеоуроки](lessons.md)
* [Учебно-методическое пособие](metod.md) * [Учебно-методическое пособие](metod.md)
* [Контрольные и проверочные материалы](tests.md) * [Контрольные и проверочные материалы](tests.md)
* [Другое](drugoe.md) * [Другое](drugoe.md)
* [CopterHack-2017](copterhack2017.md) * [CopterHack-2017](copterhack2017.md)
* [Прошивка ESC контроллеров с помощью Arduino](esc_firmware.md) * [Прошивка ESC контроллеров с помощью Arduino](esc_firmware.md)
* [Работа со светодиодной лентой](leds.md) * [Работа со светодиодной лентой](leds.md)
* [Проекты на базе коптера "Клевер"](projects.md)
* [Полезные ссылки](links.md) * [Полезные ссылки](links.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\). Для 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)

BIN
docs/assets/3dmodel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

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

BIN
docs/assets/ball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
docs/assets/bridge_udp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

BIN
docs/assets/calculation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
docs/assets/detal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 KiB

BIN
docs/assets/detal1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

BIN
docs/assets/detal2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 KiB

BIN
docs/assets/elements.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

BIN
docs/assets/elements1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

BIN
docs/assets/finalball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 KiB

BIN
docs/assets/flightplot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
docs/assets/listener.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB

BIN
docs/assets/safetyball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/assets/stmrev.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
docs/assets/table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

59
docs/autolaunch.md Normal file
View File

@@ -0,0 +1,59 @@
Автозапускаемое ПО
===
systemd
---
Основная документация: [https://wiki.archlinux.org/index.php/Systemd_(Русский)](https://wiki.archlinux.org/index.php/Systemd_(Русский)).
Все автоматически стартуемое ПО Клевера запускается в виде systemd-сервиса `clever.service`.
Сервис может быть перезапущен командой `systemctl`:
```bash
sudo systemctl restart clever
```
Текстовый вывод ПО можно просмотреть с помощью команды `journalctl`:
```bash
journalctl -u clever
```
Для того, запустить ПО Клевера непосредственно в текущей консольной сессии, вы можете использовать `roslaunch`:
```bash
sudo systemctl stop clever
roslaunch clever clever.launch
```
Вы можете выключить автозапуск ПО Клевера с помощью команды `disable`:
```bash
sudo systemctl disable clever
```
roslaunch
---
Основная документация: http://wiki.ros.org/roslaunch.
Список объявленных для запуска нод / программ указывается в файле `/home/pi/catkin_ws/src/clever/clever/launch/clever.launch`.
Вы можете добавить собственную ноду в список автозапускаемых. Для этого разместите ваш запускаемый файл (например, `my_program.py`) в каталог `/home/pi/catkin_ws/src/clever/clever/src`. Затем добавьте запуск вашей ноды в `clever.launch`, например:
```xml
<node name="my_program" pkg="clever" type="my_program.py" output="screen"/>
```
Запускаемый файл должен иметь *permission* на запуск:
```bash
chmod +x my_program.py
```
При использовании скриптовых языков вначале файла должен стоять [shebang](https://ru.wikipedia.org/wiki/Шебанг_(Unix)), например:
```bash
#!/usr/bin/env python
```

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,17 +2,17 @@
Хорошая статья, которая объясняет принцип работы 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 есть инструмент для создания интерфейсов программаторов.
@@ -35,7 +35,7 @@
![](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,7 +64,7 @@
Для отображения настроек со всех регуляторов одновременно можно воспользоваться вкладкой 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).
@@ -72,7 +72,7 @@
Для перепрошивки отдельного регулятора нужно сделать все остальные неактивными. Для перепрошивки отдельного регулятора нужно сделать все остальные неактивными.
#### Видеоинструкция по перепрошивке 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

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

55
docs/flight_logs.md Normal file
View File

@@ -0,0 +1,55 @@
Логи и топики PX4
===
Для детального анализа поведения прошивки PX4 можно просмотреть полетные логи. Полетные логи представляют собой сообщения в [uORB-топиках](https://dev.px4.io/en/middleware/uorb.html), записанные в файл с раширением `.ulg`. Лог-файл можно скачать с помощью QGroundControl по Wi-Fi или USB во вкладке *Log Download*:
![](assets/download-log.png)
Также необходимые `.ulg`-файлы можно скопировать непосредственно с MicroSD-карты, находившейся в полетном контроллере.
Анализ
---
Лог-файл можно анализировать с помомщью программы FlightPlot. Актуальную версию программы можно [скачать](https://github.com/PX4/FlightPlot/releases) на GitHub.
В программе можно просмотреть полный список записанных топиков (*Fields List*). В нем нужно выбрать необходимые топики, после чего они появятся на графике:
![](assets/flightplot.png)
Основные топики в PX4
---
[uORB](https://dev.px4.io/en/middleware/uorb.html) представляет собой pubsub механизм, аналогичный ROS-топикам, однако сильно упрощенный и подходящий для embedded-среды.
Полный список топиков можно узнать в исходном коде проекта [в каталоге `msg`](https://github.com/PX4/Firmware/tree/master/msg).
Список некоторых топиков:
* **vehicle_status** состояние коптера (режим и т. д.);
* **vehicle_local_position** локальная позиция коптера;
* **vehicle_attitude** – ориентация коптера;
* **vehicle_local_position_setpoint**  целевая точка (setpoint) коптера по позиции;
* **vehicle_global_position** – глобальная позиция коптера;
* **vehicle_vision_position** – полученная визуальная позиция коптера, аналог MAVLink пакета `VISION_POSITION_ESTIMATE` или MAVROS-топика `/mavros/vision_position_estimate/pose`;
* **att_pos_mocap** – полученная MOCAP-позиция коптера, аналог MAVLink пакета `ATT_POS_MOCAP` или MAVROS-топика `/mavros/mocap/pose`;
* **actuator_controls** сигналы на моторы;
* **vehicle_land_detected** – статус Land-detector'а;
Мониторинг топиков в режиме реального времени
---
Для более новых версий платы Pixhawk (`px4fmu-v3`), а также для плат Pixracer, в прошивку включен модуль `topic_listener`, который позволяет просматривать значения топиков в режиме реального времени (в том числе в полете).
Для ее использования нужно выбрать вкладку Mavlink Console в QGroundControl:
![](assets/listener.png)
Команда `list_topics` выводит список топиков, доступных для просмотра (включена только в [SITL](sitl.md)).
Команда `listener <название топика>` выводит текущее значение в топике. Существует третий опциональный параметр, который определяет количество сообщений, которые необходимо вывести.
Примеры команд:
`listener vehicle_local_position`
`listener vehicle_attitude 5`

View File

@@ -1,51 +1,72 @@
Использование QGroundControl через Wi-Fi Использование QGroundControl через Wi-Fi
=== ===
Возможен контроль, управление и настройка полетного контроллера квадрокоптера с помощью программы QGroundControl по Wi-Fi. Для этого необходимо подключиться к Wi-Fi сети `CLEVER-xxxx`. ![](assets/qground.png)
Возможны контроль, управление, калибровка и настройка полетного контроллера квадрокоптера с помощью программы QGroundControl по Wi-Fi.
Для этого необходимо подключиться к Wi-Fi сети `CLEVER-xxxx`.
После чего в launch-файле Клевера `/home/pi/catkin_ws/src/clever/clever/launch/clever.launch` выбрать один из преднастроенных режимов бриджа.
После изменения launch-файла необходимо перезагрузить сервис clever:
```(bash)
sudo systemctl restart clever
```
TCP-бридж TCP-бридж
--- ---
Необходимо убедиться с в launch-файле Клевера (`~/catkin_ws/src/clever/clever/launch/clever.launch`) включен TCP GCS Bridge: Изменить параметр `gcs_bridge` в launch-файле:
```xml ```xml
<arg name="gcs_bridge" default="tcp"/> <arg name="gcs_bridge" default="tcp"/>
``` ```
При изменени launch-файла необходимо перезагрузить сервис `clever`: Затем в программе QGroundControl нужно выбрать Application Settings > Comm Links > Add. Создать подключение со следующими настройками:
```bash
sudo systemctl restart clever
```
Затем в программе QGroundControl нужно выбрать Application Settings -> Comm Links -> Add. Создать подключение со следующими настройками:
![](assets/bridge_tcp.png) ![](assets/bridge_tcp.png)
Затем необходимо выбрать в списке подключений "Clever" и нажать "Connect". После этого можно будет настраивать, калибровать и просматривать состояние квадкоптера без проводов: Затем необходимо выбрать в списке подключений "Clever" и нажать "Connect".
![](assets/qground.png) UDP бридж (с автоматическим подключением)
UDP broadcast-бридж
--- ---
Для использования UDP broadcast-бриджа необходимо установить параметр `gcs_bridge` в значение `udp-b`: Изменить параметр gcs_bridge в launch-файле:
```xml ```xml
<arg name="gcs_bridge" default="udp-b"/> <arg name="gcs_bridge" default="udp-b"/>
``` ```
При изменени launch-файла необходимо перезагрузить сервис `clever`: При открытии программы QGroundControl соединение должно установиться автоматически.
```bash
sudo systemctl restart clever
```
При использовании UDB broadcast-бриджа достаточно подключиться к Wi-Fi сети Клевера. QGroundControl должен подключиться к коптеру автоматически. UDP-бридж (без автоматического подключения)
> **Note** UDP broadcast-бридж работает быстрее, чем TCP-бридж, но связь в нем менее стабильная: иногда могут возникать проблемы при загрузке миссии на коптер, а также при калибровке сенсоров.
UDP-бридж
--- ---
TODO Изменить параметр `gcs_bridge` в launch-файле:
```xml
<arg name="gcs_bridge" default="udp"/>
```
Затем в программе QGroundControl нужно выбрать Application Settings > Comm Links > Add. Создать подключение со следующими настройками:
![](assets/bridge_udp.png)
Затем необходимо выбрать в списке подключений "CLEVER" и нажать "Connect".
UDP broadcast-бридж
---
> **Hint** Особенностью UDP broadcast-бриджа является возможность просмотра телеметрии дрона одновременно с нескольких устройств (например с телефона и компьютера). Также он хорошо подходит для организации сети из устройств при помощи роутера.
Изменить параметр `gcs_bridge` в launch-файле:
```xml
<arg name="gcs_bridge" default="udp-pb"/>
```
При открытии программы QGroundControl соединение должно установиться автоматически.

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

@@ -2,8 +2,21 @@
=== ===
При подключении GPS появляются следующие возможности: При подключении GPS появляются следующие возможности:
* Удерживание коптером позиции при полете на улице * Удерживание коптером позиции при полете на улице
* Программирование автономных миссий в программе QGroundControl * Программирование автономных миссий в программе QGroundControl
* Полеты на глобальные точки в автономном режиме при помощи модуля [simple offboard](simple_offboard.md). * Полеты на глобальные точки в автономном режиме при помощи модуля [simple offboard](simple_offboard.md).
TODO Полезные ссылки:
* https://docs.px4.io/en/assembly/quick_start_pixhawk.html
* http://ardupilot.org/copter/docs/common-pixhawk-wiring-and-quick-start.html
* http://ardupilot.org/copter/docs/common-installing-3dr-ublox-gps-compass-module.html
Подключение
---
GPS-модуль подключается к разъемам "GPS" и "I2C" (компас) полетного контроллера.
При подключении GPS, необходимо заново откалибровать магнитометры в программе QGroundControl, подключившись по [Wi-Fi](wifi.md) или USB.
Далее, необходимо включить GPS в параметре `EKF2_AID_MASK` (при использовании EKF2) или `LPE_FUSION` (при использовании LPE).

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 для прерываний и формирования управляющего сигнала.
@@ -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.

View File

@@ -1,26 +1,51 @@
Оглавление # Теория
=======
[**Урок №1** «Знакомство. Принципы проектирования и строение мультикоптеров»](lesson1.md) [**Урок №1** «Знакомство. Принципы проектирования и строение мультикоптеров»](https://github.com/CopterExpress/clever/blob/master/docs/lesson1.md)
[**Урок №2** «Основы электричества»](lesson2.md) [**Урок №2** «Основы электричества»](https://github.com/CopterExpress/clever/blob/master/docs/lesson2.md)
[**Урок №3** «Теория пайки»](lesson3.md) [**Урок №3** «Теория пайки»](https://github.com/CopterExpress/clever/blob/master/docs/lesson3.md)
[**Урок №4** «Аэродинамика полета. Пропеллер»](lesson4.md) [**Урок №4** «Аэродинамика полета. Пропеллер»](https://github.com/CopterExpress/clever/blob/master/docs/lesson4.md)
[**Урок №5** «Бесколлекторные двигатели и регуляторы их хода»](lesson5.md) [**Урок №5** «Бесколлекторные двигатели и регуляторы их хода»](https://github.com/CopterExpress/clever/blob/master/docs/lesson5.md)
[**Урок №6** «Основы электромагнетизма. Типы двигателей»](lesson6.md) [**Урок №6** «Основы электромагнетизма. Типы двигателей»](https://github.com/CopterExpress/clever/blob/master/docs/lesson6.md)
[**Урок №7** «Принцип работы, типы и устройство аккумуляторов»](lesson7.md) [**Урок №7** «Принцип работы, типы и устройство аккумуляторов»](https://github.com/CopterExpress/clever/blob/master/docs/lesson7.md)
[**Урок №8** «Управление полётом мультикоптера. Принцип функционирования полётного контроллера. ПИД регуляторы»](lesson8.md) [**Урок №8** «Управление полётом мультикоптера. Принцип функционирования полётного контроллера. ПИД регуляторы»](https://github.com/CopterExpress/clever/blob/master/docs/lesson8.md)
[**Урок №9** «Основы радиосвязи. Принцип работы радиоаппаратуры управления»](lesson9.md) [**Урок №9** «Основы радиосвязи. Принцип работы радиоаппаратуры управления»](https://github.com/CopterExpress/clever/blob/master/docs/lesson9.md)
[**Урок №10** «Аналоговая и цифровая видеотрансляция. Применяемые камеры, радиопередатчики иприёмники»](lesson10.md) [**Урок №10** «Аналоговая и цифровая видеотрансляция. Применяемые камеры, радиопередатчики иприёмники»](https://github.com/CopterExpress/clever/blob/master/docs/lesson10.md)
Видеоуроки ## Видеоуроки
----------
Немного о видах коптеров
<iframe width="560" height="315" src="https://www.youtube.com/embed/LFOmZZwg-PE" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
Часть 1
<iframe width="560" height="315" src="https://www.youtube.com/embed/e9Z1pjW0vQU" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
Часть 2
<iframe width="560" height="315" src="https://www.youtube.com/embed/jWMGSgiLD_E" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
Часть 3
<iframe width="560" height="315" src="https://www.youtube.com/embed/WhxxXD4b1MY" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
Часть 4
<iframe width="560" height="315" src="https://www.youtube.com/embed/jkA9F9lSWDM" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
Часть 5
<iframe width="560" height="315" src="https://www.youtube.com/embed/Cz7EbJ1-xMw" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
Часть 6
<iframe width="560" height="315" src="https://www.youtube.com/embed/v00oNVzwICg" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>

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

View File

@@ -12,8 +12,7 @@
* об истории и тенденциях развития беспилотных летательных аппаратов; о том как можно улучшить их характеристики; * об истории и тенденциях развития беспилотных летательных аппаратов; о том как можно улучшить их характеристики;
* правила техники безопасности при эксплуатации БПЛА; * правила техники безопасности при эксплуатации БПЛА;
* основные компоненты коптеров; * основные компоненты коптеров;
* конструктивные особенности различных моделей, сооружений и * конструктивные особенности различных моделей, сооружений и механизмов;
механизмов;
* компьютерные среды для настройки полетных контроллеров; * компьютерные среды для настройки полетных контроллеров;
* основы аэродинамики полета; * основы аэродинамики полета;
* основы электричества, радиоэлектроники; * основы электричества, радиоэлектроники;
@@ -51,7 +50,9 @@
**Подведение итогов** **Подведение итогов**
Подведение итогов по курсу проводится в 3 этапа: Ниже предложен один из вариантов подведения итогов курса.
Финальное мероприятие включает 3 раздела:
1. Итоговый тест (см. [проверочные задания](tests.md)). 1. Итоговый тест (см. [проверочные задания](tests.md)).
2. Финальная гонка. 2. Финальная гонка.
@@ -380,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

@@ -1,21 +1,23 @@
# Образ для Raspberry Pi # Образ для Raspberry Pi
## Установка образа операционной системы на MicroSD карту
Для установки образа воспользуйтесь утилитой [Etcher](https://etcher.io):
[![Etcher](https://etcher.io/static/screenshot.gif)
](https://etcher.io)
## Образы
На образе установлены: На образе установлены:
* Raspbian Stretch * Raspbian Stretch
* ROS Kinetic * ROS Kinetic
* [Пакет ПО для Клевера](https://github.com/CopterExpress/clever_bundle) * [Пакет ПО для Клевера](https://github.com/CopterExpress/clever)
|Версия|Дата|Ссылка|Примечания| **Свежую версию образа можно [скачать на GitHub в разделе Releases](https://github.com/CopterExpress/clever/releases).**
|-|-|-|-|
|0.2|24.01.18|[Скачать](https://yadi.sk/d/n_Krnor03RkntU)|| ## Установка образа ОС на MicroSD карту
|0.1|15.12.17|[Скачать](https://drive.google.com/open?id=1Gtj_0iB7dFuorfUKAUUV8ImjmkZCkvc7)||
Для установки образа воспользуйтесь утилитой [Etcher](https://etcher.io).
[![Etcher](https://etcher.io/static/screenshot.gif)](https://etcher.io)
## Версия образа
Версию установленного образа можно узнать в файле `/etc/clever_version`:
```bash
cat /etc/clever_version
```

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