tag:blogger.com,1999:blog-42793571666285937192024-03-13T09:53:45.042-07:00Строим вместе с Карандашом и СамоделкинымБлог команды робототехников "Карандаш и Самоделкин"darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.comBlogger198125tag:blogger.com,1999:blog-4279357166628593719.post-78404707601999642092021-07-04T03:21:00.003-07:002021-07-04T03:30:04.583-07:00KeyKeeper - хранитель паролей для истинного параноика!<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoFQ2bZvURcRcegusPF5oM5bEPPnr92wVvOsEQEPQy30Imbzf9qDz7TX0oUuoPPROornsLmSYsWewLW6E5kxQEl66_FOdzPTZVMXKoRY9U_Uhx9eA7OuVD5Fau8zh0ZIHUvnVKb76R4AeQ/s1286/logo_youtube.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="724" data-original-width="1286" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoFQ2bZvURcRcegusPF5oM5bEPPnr92wVvOsEQEPQy30Imbzf9qDz7TX0oUuoPPROornsLmSYsWewLW6E5kxQEl66_FOdzPTZVMXKoRY9U_Uhx9eA7OuVD5Fau8zh0ZIHUvnVKb76R4AeQ/w400-h225/logo_youtube.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both;">Почему именно наше устройство обеспечит сохранность Ваших паролей?</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>01 / Пароль от ваших данных не знает даже хранител</b>ь</div><div class="separator" style="clear: both;">Логины и пароли хранятся в устройстве в защищённом виде, при этом даже хранитель не знает правильный мастер-пароль от Ваших данных. Можно ввести любой мастер-пароль и хранитель выведет вам хранящиеся пароли, но расшифрованные неправильно, фактически они представляют случайный набор символов. При внешней угрозе вводите любой мастер-пароль, никто сможет понять, что он неправильный. Злоумышленник также не сможет получить его, взломав флеш-память устройства</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>02 / Максимальная надёжность от всех видов атак</b></div><div class="separator" style="clear: both;">Мы позаботились о сохранности Ваших паролей, защитив их многоуровневым шифрованием, с использованием нескольких алгоритмов, включая AES. Все данные не только хранятся, но и передаются, обрабатываются в защищённом виде. При необходимости Вы сможете экспортировать пароли в открытом виде в обычный текстовый файл для резервирования в стороннем криптоконтейнере</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>03 / Универсальность</b></div><div class="separator" style="clear: both;">KeyKeeper работает с популярными операционными системами Windows и Linux. Поддерживаются специальные режимы для ssh-сессий, linux-терминала, учитываются особенности популярных браузеров, таких как Chrome, Opera, Firefох. C точки зрения компьютера KeyKeeper - обычная USB-клавиатура, поэтому можно входить даже в BIOS/UEFI</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>04 / Хранитель похож на флешку, но вовсе ей не является</b></div><div class="separator" style="clear: both;">С виду хранитель похож на обычную USB-флешку, поэтому злоумышленник вряд ли распознает, что это защищённый хранитель паролей. KeyKeeper не определяется операционной системой как носитель информации, поэтому вирусы направленные на поражение носителей информации не способны поразить хранителя. Они не понимают что в "клавиатуре" могут храниться данные</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>05 / Практически вечный храниетель информации</b></div><div class="separator" style="clear: both;">Память KeyKeeper рассчитана на 3 млн циклов записи. Это значительно больше чем на любых USB-флешках, в них предусмотрено обычно от 10 до 100 тысяч циклов записи. Хранитель крайне устойчив к перебоям в питании, поэтому можно смело выдергивать его из порта в любой момент и не беспокоиться что пароли могут быть повреждены</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>06 / Встроенная защита от кейлоггеров</b></div><div class="separator" style="clear: both;">При вводе паролей на формы ввода используются специальные режимы перемешивания (быстрые хаотичные перемещения курсора, удаление и повторный ввод других символов). В итоге Ваш пароль будет введен верно, но кейлоггер не сообразит, что было введено</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b>07 / Удобный менеджер паролей</b></div><div class="separator" style="clear: both;">Специальная утилита обеспечивает возможность добавления, редактирования базы паролей на устройстве, резервного копирования в открытом и защищенном форматах, изменения настроек ввода под разные типы аккаунтов. Есть специальные настройки для пользователей ноутбуков, на клавиатуре которых могут быть не все клавиши</div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/ryV7mgoPEDc" width="320" youtube-src-id="ryV7mgoPEDc"></iframe></div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><b><a href="https://stepanovplaton.wixsite.com/keykeeper" target="_blank">Заказать KeyKeeper</a></b></div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnAN3JoJ-HiXkuKAS96z_3el5B9HCzl7M2CV62QNJScdzwx19-BCSYT6IL8yhQqHLDPugW4b4X5HE5sDykYEBZ3OxBXnUYphd60FnbnX1IRlNYn2lUKP6CfP5d8ShqBf_0TY9Xn9l3NeWm/s1747/%25D1%2584%25D0%25BE%25D1%2582%25D0%25BE2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="892" data-original-width="1747" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnAN3JoJ-HiXkuKAS96z_3el5B9HCzl7M2CV62QNJScdzwx19-BCSYT6IL8yhQqHLDPugW4b4X5HE5sDykYEBZ3OxBXnUYphd60FnbnX1IRlNYn2lUKP6CfP5d8ShqBf_0TY9Xn9l3NeWm/w400-h204/%25D1%2584%25D0%25BE%25D1%2582%25D0%25BE2.jpg" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div></div><br />darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-40348113708784607002020-07-06T03:22:00.004-07:002020-07-06T03:27:56.792-07:00NeyroGamer 2<div dir="ltr" style="text-align: left;" trbidi="on">
Всем привет, с вами Платон из команды "Карандаш и Самоделкин". Лето идёт полным ходом и наша команда не сидит без дела. Сегодня я готов представить вам продолжение проекта NeyroGamer, в котором я создам нейронную сеть, которая будет учиться играть в видео игры.<br />
<br />
Я всё глубже изучаю нейронные сети, и зачастую пишу код без использования библиотек с готовыми методами и инструментами для создания алгоритмов машинного обучения. Это связанно с желанием узнать, что находится «под капотом» у таких библиотек как Keras и TensorFlow. Однако алгоритм обратного распространения ошибки кажется мне несколько сложным, поэтому в NeyroGamer нейросети выступают в качестве особей генетического алгоритма. В сегодняшнем проекте я написал нейронную сеть с краткосрочной памятью с нуля, используя лишь стандартные библиотеки и NumPy.<br />
<span style="white-space: pre;"> </span><br />
В качестве игры, в которую будет учится играть мой алгоритм, снова выступит Nigel Mansell's World Championship Racing с платформы Sega Genesis. Так как я использую генетический алгоритм, использование эмулятора консоли и ретро игра дает мне следующие преимущества:<br />
<br />
<ul style="text-align: left;">
<li> Загрузка состояния с контрольной точки. Каждая особь начинает гонку со старта. </li>
<li> Простая графика для разбора OpenCV</li>
</ul>
<br />
В первой части проекта, я опирался на несколько моментов дороги, взятых OpenCV на разной высоте кадра. Такой подход казался мне более верным, в нем нейронной сети подавались предобработанные моментами данные. После многих поколений эволюции такой подход позволял обучать нейронную сеть, но процесс был очень долгий и после достижения N-ого уровня мастерства алгоритм переставал учится, «упираясь в потолок», так как не учитывал многие нюансы трассы - столбы, мосты, положение соперников друг относительно друга.<br />
<br />
Во второй части проекта я пошел другим путем. На вход нейронным сетям особей теперь подается изображение нижний части экрана (машина и дорога без показаний приборов, спидометра, коробки передач и миникарты) в виде уменьшенного полноцветного битмапа. После нескольких экспериментов было выбрано разрешение 64х16. При увеличении количества точек сильно растёт количество нейронов, что приводит к медленной работе алгоритма. На картинке с меньшим количеством точек не хватает данных.<br />
<div>
<br /></div>
<div style="text-align: center;">
<img alt="" height="50" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAQCAYAAACm53kpAAADOUlEQVRYCcVXQUsbQRSeq0gxIUSEnKzUkkB7UqSs0NK0kCYS00ZFPRQFBYmhECQYPHho2RL0UqQa7KGtECg9SEq9NBYpCK3Uk+jBk5CL/QHtweNXvomzrHGXZIPbLnx8M29mdt/73nubjSgX1kEcf/+Bs/zaJRyPzsh17jn7/cdAKBiSYwCSFwpjF+6hzl1rbcXwcFbe4+DLV7S0tMDj9cCT9GDxRo+E3+dDLDIjce/uUwT87YjNVOex3B28KSyAHBhtl+BY2c/8PTCDfmr9muEzz9A3QsWqOJ0bg1ATp5wQAonBjAG78+J8HzkzlzEwEJ/AxGRGguNVXb/koN0969nNAtTbKw43N+EUT5I5UIDFoIZ3D6LIejuQ8odAeyQSwfLScl1QkNud9yU45pmN9xuOfbHynQJY2a1sTVUAHfb5QwgFNWTnVhESQoJ2ZtOc6WbG9bJWb91RBdS7mXmdZcqAGKgZFEPNmwnY7oz52U7GjgSobJdhhaOtLVT29lDaLGG9sO4KcCLw+UPC9t77e/uQftj4aOU3bRTAbq3WfqEF7DJxVXZtrswfDdtL9FcrzOp5TirAyV5h9TC3bNqzMoaSQ7YQffYC0CcngTW613UBum52IRaNybLUkmWk0ilMTU8hFhUofxTYLQmk0lPSJgI6zPutEvFp5fWVCiHc6m/el72YGExIdAe7ocXL8iVKZv9TALKyC78On99nnOHZWv8qJxVpq+3lZueuC0ARCF3Xoa9V2z8Q/gkxDdx6WERH/BC9OeD01ykoAC9+S/T29UquFYBz+XI8OMJ+qWS87HiOz6jlsWhU7nn74jnUWDFFc1UAczalEMw8cOmnlGu8KADLnnNmn2wlgLKZq4HnrQRQdpkAJuFcJFUxrgqgvg0Uq55mYBSH/ycIzgfiA7IV1F7FKlg7pgg72ztSQBVcLWcnJ6oV+D8FYKCz6VmZ4TZvG7xer3SagXZe75QCcH18fNz4qOKaXeBmO0WYz80jHA5Lfhx9ZHCxWAQFGBkZka1Apu2fV4BqB74MrWAue5X9RgWgGBTB3BIqwHrsagvQsfzLPJbySw1lUmV15dWKPEdWtkZ499uuYxH+Amyvi0Wfpga+AAAAAElFTkSuQmCC" width="200" /> </div>
<div style="text-align: center;">
32х8</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<img alt="" height="80" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAAAgCAYAAADaInAlAAAJEUlEQVR4Ad1bYUyV1xk+Cf4Q4w8rQjDKQBph3Mx2qXUGLqWd4IgZXm50LtVaC6kMiYSO3KGE6BjSL8MFTGuGiBik0YWSYujapHJp0dQYNx3ZhnXDxdnwZ8n+NeGPZn+e5Xnpe/txuZd7ge9euNzkzXvO+c4573ve5znvd76DGn9XNyinm6vxQVcLsg5tAn5eC3x6M2pd3/yGzMF5rnedkzIW8Pv3X8bAuXS+UH648lwBf2nPXVgxQ0rLd8g6Ksq9cPtcqGr24nddNbgx/AGuXWpD95nz2JfhgjEGJcX5MjbfGFBqMlyoLq4Q6dlfi23bts2YO2CrctqmyTNo8tXAXe6C1V6DA74S1LTsQ1nzDrFtyg1cxzLgbclHU/sReXa+/SSudrVKnMZPngSszlnCNVpH3kbnuTq83rxL1suYMLbESTGj5ny0yTXSLuV01xsSA3s/lkt9O2Q856JvbDOTI34kkjA40fjbUFkR6NeQ54a3vB7ULil70d3VPUO85V54jQn0Y38dQ3v2+ez2uy0r7DN7v/mUucZw9uYzTzR9TTBLlntdM0AkPy2fhYEBv+x0OwG48+t99SElJdWFBmMwaoyQheOkbAz4LJRNy9cAZptQzxbaxjU6PWc4X1YcASpSXbJzdQdTM3Vbhe6QoNvJQHIQaGYCTfcss02JEy6QTrbHlQDRpInl1OdW35VAaqdfdwYH8cqPfoLN6Zuxbn02Tj33HE5lZuGbb6YkA3xxxsKRzCwBlUBmZWbh+PFTM9K/vg5afmOB8m5r+wzRdvbr/0M/+i5dxuTEI7Edi9jE9RXwt48GkYjycc8ltLW14XLPZdmd3KE/Mwada1JwbuvLqCrYL5mgaevL6N68Db3GBPqVlpbKWI5fjNA2x9MXJ2NIAtQePOjonOH8S6hD4OPhG+jt6cXnw5/P2MEEn5JkDHzGwJO7E+WeCnj2HkHe9wuk7Qc2AvDAp7veKU2f6Bt9XGxWiGsGWKyz8Rg/OjCA0ZFRkVCAKQGY4vnuzsnzzhK2a79YEED9Uj/p80JjE1cCOHl4cXIu++FsJZSdjI2Tc5knwzewXGT0ww8xcsOP4c+GcaHzwooSrolr4xqXS7zpx5KfAYb7+zF+98+S3hkkTaWx0mMjXuCJCcjtj7fG3KZ9LVwjXxNcM9e+0NeEU+OW5B5g8L33I36Txy7t78Z/7hlMPZwmweCV8BdDsfNh9kUUY+Jkao92rrgSoNOy4g682+eHO4pLoHBgm8L4+swYRQueE/1iSoClADwYSBLAsqwF/Glqeki8CRDsf6wJERMCLAfgNZBujx/8rNL6fHRFZQVManwzwFz+xYIM5uHQEJySq13duDl6U6SjvQOxlqrqKuTk5oi8tP2lkPb2VN9FUVERWltaRS6e24S95bm498dNIqw3/MobeK79qPfs2QOzxZpz/liv0T6/xpZxdgqzRX0F3B8awj9GRjB0fUhOtvf/dD9uJ+q237Yha0sWqn9RL7J3734UFxfPsu+tHINe/Hx2LR8bNhj4B777Crh60aDtXTNrnM7PDEAb4ea3n/DjVWac+SXBuDP+xGGhXwULIgBvubjYySeTIvFauN0OQeXhrqKyAfW+bgE5JTVlBpDsQwB5A2j5eNqfFvtnIMlAcRfy3wJ8d0Ws80+/AkLPb/dnqcp2DBZy+zgvAnCRZB6NUi/VommXAOXk5YCgs2wXtlHk6pcESLUEZAU7FAGmSeCWNemVMefnWBJNbbFst6X1pYxFKFyizQhzEmA57PRwgVUCEADLGpghbOu80CnHeB4CeZJ3e6ZJEAw+68wMJICrcEAOi/rJwHlIAAWfmhmH9rq7+HUxIHW2h/Nzvu1clxKQYyPVw80fbWaYQQD+bb2/9wr+9fCf+OrvX+HOl3em//7d2+fYAsM5PN92Bmbd+nWyO0MR4OzZs4KjdQEC4uYmYPD6Rew+UIfm0wYdbUa0vhbWev6LH3rugid/+48EWLVqlYDCrHL0aKMA//57n4pmPW1jmmPxaWxsFPNTU1MCfqT6XHHr6+0T/Igj8SSuxJc4a4Yw4598gtsfDcr9+9i9MYz/dRy3b912bEFzObiYZyQAAdm+fbsAYSdBSUlJ4NufBDh8+DA2eSaR/fYEWnv8qO2ZgNkPJOeNIzmrB8mvjkudGaDtbJsdfyEPx3NX0l7t8V+LvdbWftGsZ3wvw7F48c5C7y24xkj1F194Ub5ymhqboGXqEydOSPvB1w/C/oz4EmdeSRN3c2v0Fr5+/DUeP3rs2CIWA2y0YzU1FrgLcObMNbxV4QtIfgH/ta8bT58+Rcv5/0kQR2+OoviAH8kvPEVS3hSez30e6zesD6Rb1st+WoZh/3CAAByvZwASgP3LPeVi553634uu/2WLtEfrd6R+kQAP9ZwOr1mzBh0dHbJW6mfPnsk6WLYTSe0Tb+Julvowpw7NVysBuCv5DibgFJYJFsu8VOEZQMscMx/heDsBNAuoHWraZ/t8/Q/XPxhg2uDPP+IX34Pr7G//aZ0+6Y9lnTfYrgluSKS6AkIQ7MJ2CgEUQnz7KcgbQX2mWgmkddUMNMtyiLT9ayK26Rhq7e9U3BQogmffuZHq9MM+lv2VDEoE1oP9NHNdPS73ZwqGghCs1X/uYpYLiwqR68rF6tXJcrB7pagIqWmpSEpKwquvvSbA8llaehrKPGXTWcXjR907dQGgg21oXW0tVttBJAmjrdOuvW9KSgp25u8U7Kn1WbB/K5YADJ4ulruY5d2luwVIeyZgYPhTIDdu3AgGTwjw7bhjNceEDNonlFZbi9U8cPI38WhCbEaq24HVMsdz/RQt67Ng/xKaAGvXrg0AFwwKQT5adRRvvvWm6OqaatkRmVsy5fNx1493YXXyatTV1eHBgweSEXJycpCdnQ328e7z4tChQ/B6vfJfxOayRdvBgV1onSRNT08X4RyR6va+WqbmOB2rmu3BfiU0AcjwYODtdZKA71H204NitIdA9qewvz1j2OfXMs8CwYFNlHpCE4BpWkGIpJUAkfrxOQEnafSQR60Sajz7JgrgwX4mNAG4GJJAgSI4LAcv0sk6iWQnAe07OX+850p4AsQ7YCvN3v8BcqDF5p1TnSIAAAAASUVORK5CYII=" width="320" /></div>
<div style="text-align: center;">
64х16</div>
<div>
<br /></div>
<div>
<div>
Такой метод оказался намного лучше и обучение пошло значительно быстрее. Правда из-за того, что нейронная сеть очень сильно выросла (3000+ входов), пришлось заняться оптимизацией. Весь алгоритм обучения я переписал на NumPy. Самое «медленное» место в старом алгоритме оказалось в методе «предсказания»(использования) нейронной сети из-за «бега» циклом по 2м матрицам. После оптимизации этого места FPS вырос в 100 раз, с 6 до 600. Вместе с переработкой всего кода и его оптимизацией, была дополнена модель нейронной сети. Была добавлена краткосрочная память, то есть теперь я использую LSTM-сеть . </div>
<div>
<br /></div>
<div>
С помощью моментов на кадре выделяется данные о скорости (вырезается полоса с показаниями передачи и по ней берётся красный момент). Эти данные показывают текущую скорость — показатель по которому сортировались нейронные сети.</div>
</div>
<div>
<br /></div>
<div style="text-align: center;">
<img alt="" height="40" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAUCAYAAAB7wJiVAAACMUlEQVRoBe2Za07DMBCEcxXOV3E8uJ6Rqb+lGWeybpuI/DBSNHh3Zp81peqyfJcynwvNYC7jQsuolyNdyLKUZevhZm359mzowD3ulg8duMWptlF/xsviP6uH7zAKt4S5kN0XJHNzi1M7fId2IS3Q1/JR6lPaE8URsPFK8nP7vJX6nKUnPmWQhzN+7NF3qx8/fIeH65kjGIVhAOdCNnfy7wvhZoBdQbLA8JubE350YOOHf1Sf8HSqEV/yWp7WhQ5M8kc+4qBzmN0QFgFGAg1IQkHb6FH6ZCBp/kQf/dKXqdvmQQeqXs+HLYTAWYPwQMPXBvkbHwNK9PA0Dvbou+UnvvI543d6eA6tnj7AKAwDyKAe3tDrLekKgg+ik8qszvBF/vsPQW2qi2P08DQO9ui76RmY8jnjd3p4Dq2euYFRGAaQRkcXAl8q6hogvmLTB//ZeIYv5fQLpY5X85u89DGcP+rgF0USzYWsZsqg44XMnFas+on7/vlNzGEPfTd3NXAmYLYQeJKZgjokPtj0HS+Li15R4klZfiCio55Un9SZ6rv61cCZRHMhq5myqHiFM6cV68QbMvpJnTctqas7jjakQuJ3el5AijIoqxee5uWc6fHDV8Sf1h+bNg3NhdxHawfaFopfF8EZ/+sLYUEtYQTijB/EPorv6tA7zOpAl/HUj05Ree6sOj3bGwJxNLDjOXsWP9Ohd+j02NFxHkV0iu/qiZcuBOLEv+9YzpzFXMi1vjH8AeXgbwMNbSofAAAAAElFTkSuQmCC" width="200" /> <img alt="" height="40" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAUCAYAAAB7wJiVAAAAf0lEQVRoBe2XMQ4AIAjE+P+ncWe4CcmJNXFyEOlVY0REMq16YFUM4cAOu0DaFfS7JRpIloFRul8N/dEbFB6/p3fi/ABpSHUnKIAAhL+PMgpDMARDMMTMAoAAhGtJWaDWeNTN7AHIU0DMilWqb1nThgBkvD/jG25J8q1zAMTpFjieIlgZEpOwegAAAABJRU5ErkJggg==" width="200" /></div>
<div>
<br /></div>
<div>
<div>
Каждая из особей «загружается» с контрольной точки (на старте гонки) и тестируется в периоде N-ого времени. В каждый «тик» особи прибавляется количество очков в зависимости от её скорости. Таким образом переходить в следующее поколение будут самые быстрые особи. После тестирование всех особей происходит сортировка и скрещивание, после чего новое поколение особей заново тестируется. После каждых 5 поколений все особи сохраняются в файл, что бы обучение можно было продолжить позже.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/DpyXo5CuKYU/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/DpyXo5CuKYU?feature=player_embedded" width="320"></iframe></div>
<div>
<br /></div>
<div>
Вначале своего обучения, алгоритм ведёт себя крайне случайно. Однако после первых 2-3х поколений особи случайно нажавшие на газ начинают вести за собой остальных. Тут начинается 2й этап обучения - «Зажимай, авось получится!». Нейронные сети научившись давить на газ начинают зажимать случайные кнопки. Кто-то едет прямо, а кто-то постоянно улетает в правое ограждение. Получается довольно смешно. Далее алгоритм находит «середину» и обучается уже более сложным вещам - держатся по центру дороги, правильно входить в поворот, обгонять своих противников.</div>
</div>
<div>
<br /></div>
<div>
<div>
Язык Python. <a href="https://github.com/StepanovPlaton/NeyroGamer" target="_blank">Ссылка на репозиторий проекта</a></div>
<div>
Автор - Платон, 14 лет ("Карандаш и Самоделкин")</div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-20105930767396688422020-05-12T01:28:00.000-07:002020-05-12T04:38:58.911-07:00Нейронная сеть учится играть в Lunar Lander<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">Lunar Lander — аркадная игра, выпущенная Atari, Inc. в 1979 году. Цель игры — управлять посадочным лунным модулем, чтобы произвести мягкую посадку на поверхность Луны. На посадочный модуль действует гравитация и инерция</span><span style="color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">, кроме того количество топлива в нем ограничено.</span><span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;"> Управление производится 4 кнопками: наклоны посадочного модуля влево/вправо, управление тягой двигателя +/-. </span><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilnHWAnyXdZm_A37VRSp-g-o4Hwc7-1WiRA65T0Vd9PZnn2Olzf7eqF-CtENTgyfH48-sPuC2RbDcq1ucLjovFpwoHYBhauVt38GjtfZ1BRB1fX-l3jFxL-YgQ8VWzhWN_mWQXVNlQTukC/s1600/Untitled.mp4_snapshot_00.07.54_%255B2020.05.12_08.25.17%255D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilnHWAnyXdZm_A37VRSp-g-o4Hwc7-1WiRA65T0Vd9PZnn2Olzf7eqF-CtENTgyfH48-sPuC2RbDcq1ucLjovFpwoHYBhauVt38GjtfZ1BRB1fX-l3jFxL-YgQ8VWzhWN_mWQXVNlQTukC/s400/Untitled.mp4_snapshot_00.07.54_%255B2020.05.12_08.25.17%255D.jpg" width="400" /></a></div>
<br />
<span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">Задача, решаемая в рамках данного проекта - разработать самообучающуюся нейронную сеть, способную посадить на поверхность Луны посадочный модуль, выбрав при этом для этого пригодную для посадки площадку. Для управления посадочным модулем нейронная сеть должна "нажимать" кнопки на виртуальной клавиатуре, так как это делал бы реальный игрок.</span><br />
<span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg6h3OjzM9y07mey-j2bE9rQZXKQCcI89PQ3gkML4vzW4mzN2pgKEb9RQfn-vWzLSk1_-y6nZgxCP6ZVh-F5YmgNY_S10wQU6O61wOGmur78lKBXD60lOhvixL4YJDmXZf99YI8xM5hZuF/s1600/ezgif-4-39b81688822c.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg6h3OjzM9y07mey-j2bE9rQZXKQCcI89PQ3gkML4vzW4mzN2pgKEb9RQfn-vWzLSk1_-y6nZgxCP6ZVh-F5YmgNY_S10wQU6O61wOGmur78lKBXD60lOhvixL4YJDmXZf99YI8xM5hZuF/s400/ezgif-4-39b81688822c.gif" width="400" /></a></div>
<br />
<span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">Для ускорения обучения нейронной сети используется генетический алгоритм, в каждом поколении запускается 10 ее копий. Нейронная сеть имеет 2 скрытых слоя.
</span><span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">Проект разрабатывается на Python, никакие дополнительные нейросетевые фреймворки/модули не используются.</span><span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">
</span><span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;">Автор - Тихон, 13 лет ("Карандаш и Самоделкин")</span><br />
<a href="https://github.com/StepanovTihon/Lunar-hodec" style="font-family: roboto, noto, sans-serif; font-size: 15px; white-space: pre-wrap;" target="_blank">Исходный код</a><br />
<span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/wzvfET0hgxw/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/wzvfET0hgxw?feature=player_embedded" width="320"></iframe></div>
<span style="background-color: white; color: rgba(0 , 0 , 0 , 0.87); font-family: "roboto" , "noto" , sans-serif; font-size: 15px; white-space: pre-wrap;"><br /></span></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-48083059953843357472020-05-10T08:08:00.000-07:002020-05-10T08:08:38.075-07:00Звездолеты 3D<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="background-color: white; font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif; font-size: 17.6px;">Продолжение игры про звездолеты, теперь в 3D. Управление с помощью наэкранных кнопок. В демо 1 уровень, есть звуковые эффекты и музыка.</span><br />
<span style="background-color: white; font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif; font-size: 17.6px;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9SVcGywceNSTQJQIdO6LKVTXJAP2tBOnF783A__E_2ypuJG1GV5zYqPL9uncQ4Xk55Ir9rrCjvsMJu4Yq33pmALL5eTjDg37x-WehfN6q7UYhGZIkKl5fbhovVInxdX6kgge84z3VyVdB/s1600/ezgif-4-25057049db6a.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9SVcGywceNSTQJQIdO6LKVTXJAP2tBOnF783A__E_2ypuJG1GV5zYqPL9uncQ4Xk55Ir9rrCjvsMJu4Yq33pmALL5eTjDg37x-WehfN6q7UYhGZIkKl5fbhovVInxdX6kgge84z3VyVdB/s320/ezgif-4-25057049db6a.gif" width="320" /></a></div>
<br />
<span style="font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif;"><span style="font-size: 17.6px;">Язык C#, среда разработки - Unity.</span></span><br />
<span style="font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif;"><span style="font-size: 17.6px;">Автор - Тихон, 13 лет ("Карандаш и Самоделкин")</span></span><br />
<span style="font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif;"><span style="font-size: 17.6px;">Исходный код <a href="https://github.com/StepanovTihon/Star-Destroer-2.0" target="_blank">здесь</a></span></span></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-2235697248308704122020-05-09T08:53:00.003-07:002020-05-09T08:53:50.842-07:00Звездолеты<div dir="ltr" style="text-align: left;" trbidi="on">
Игра про звездолеты. Несколько уровней, разные типы врагов и оружия. Подбираемые боеприпасы и "аптечки". Управление движением - на гироскопе/акселерометре телефона, выстрелы разным типом оружия - тапы в разных зонах экрана. Есть звуковые эффекты и миникарта. Написана без использования готовых библиотек и конструкторов.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieDz9L4msAh9DvK5dGd2JBeRwnJl2qT5ueykw8CEWeOGl-Opb91FqPbl43xutMrO8R_DIRE-r6Glwv-K6F-oQnxyrnv9UBDro_sdhtIIQRTWnfcX-IQRSTDuyh5VADnrYDbr4MzHhdIyja/s1600/ezgif-4-55d4fe2206ad.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="600" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieDz9L4msAh9DvK5dGd2JBeRwnJl2qT5ueykw8CEWeOGl-Opb91FqPbl43xutMrO8R_DIRE-r6Glwv-K6F-oQnxyrnv9UBDro_sdhtIIQRTWnfcX-IQRSTDuyh5VADnrYDbr4MzHhdIyja/s400/ezgif-4-55d4fe2206ad.gif" width="200" /></a></div>
<br />
Язык Java, среда разработки - Android Studio.<br />
Автор - Тихон, 13 лет ("Карандаш и Самоделкин")<br />
Исходный код <a href="https://github.com/StepanovTihon/Zvezdolotu" target="_blank">здесь</a><br />
<br />
<br />
<br /></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com2tag:blogger.com,1999:blog-4279357166628593719.post-90492964831692106732020-05-09T04:24:00.001-07:002020-05-09T09:04:14.056-07:00Tetris 2x<div dir="ltr" style="text-align: left;" trbidi="on">
Классический тетрис представляет собой головоломку, построенную на использовании геометрических фигур «тетрамино» — разновидности полимино, состоящих из четырёх квадратов. В нашей версии стакан имеет глубину в 2 квадрата (слоя), заполнять необходимо оба горизонтальных ряда из 10 клеток, расположенных на одной высоте. Управление на стрелках клавиатуры, переворот игрового поля на другой слой - Ctrl.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuQlxVk9S5O8gDLsGV3zoeF3v8SzBFMYGargi_36Jw4jR2Gos8AO9e-fD_KWu1nJLsOL-PAaSgEgDLVdzDFuzMPTX03w_RvfHV_iLMkZaQFmrwjK7hRNUai5h_KY61-OK73MxqpR0vw134/s1600/ezgif-1-fc68a2e25dd8.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuQlxVk9S5O8gDLsGV3zoeF3v8SzBFMYGargi_36Jw4jR2Gos8AO9e-fD_KWu1nJLsOL-PAaSgEgDLVdzDFuzMPTX03w_RvfHV_iLMkZaQFmrwjK7hRNUai5h_KY61-OK73MxqpR0vw134/s400/ezgif-1-fc68a2e25dd8.gif" width="400" /></a></div>
<br />
Язык C#, среда разработки - Unity.<br />
Автор - Тихон, 13 лет ("Карандаш и Самоделкин")<br />
Скачать можно c <a href="https://yadi.sk/d/4cKQRXMPNa31sQ" target="_blank">Яндекс.Диск</a>, исходный код <a href="https://github.com/StepanovTihon/Tetris-20" target="_blank">здесь</a><br />
Прототип игры сначала написал на Python, исходники по <a href="https://github.com/StepanovTihon/PythonTetris" target="_blank">ссылке</a></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-56781098878810575582020-05-09T02:49:00.002-07:002020-05-09T04:29:15.334-07:00NeyroGamer 1<div dir="ltr" style="text-align: left;" trbidi="on">
На самоизоляции сейчас непросто всем, но сидеть и унывать скучнее, чем заниматься любимым делом. Мы не сидим сложа руки и придумали довольно фановую штуку, назвав ее NeyroGamer.<br />
<br />
NeyroGamer это своего рода бот, играющий в видео игры. Так как нам нравятся старые консоли, первая игра, в которую мы хотим научить играть нашего бота - гоночная аркада на Sega Genesis под названием Nigel Mansell's World Championship Racing. Игры запускаются на эмуляторе консоли (мы используем Fusion 3). Проект немного похож на один из наших прошлых проектов "Длинный хвост питона", так как использует машинное зрение с OpenCV.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKRstYehU3ayeSEJf3fVT9WWbGb0ZEparFTNEWghRaibc3G42Qdom-lX4uPvxUMh_Jizv44q5Dv5WM3qXe8jzcBNsZ-d06MCajynUZTYK8Qm3Pbd7XFv82R4MDt4xD6I1ZhBHPsaBZ_1Qp/s1600/ezgif-1-432ea316e5c0.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="410" data-original-width="600" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKRstYehU3ayeSEJf3fVT9WWbGb0ZEparFTNEWghRaibc3G42Qdom-lX4uPvxUMh_Jizv44q5Dv5WM3qXe8jzcBNsZ-d06MCajynUZTYK8Qm3Pbd7XFv82R4MDt4xD6I1ZhBHPsaBZ_1Qp/s400/ezgif-1-432ea316e5c0.gif" width="400" /></a></div>
<br />
<a href="https://github.com/darkavengersmr/NeyroGamer-1" target="_blank">Исходный код проекта</a><br />
<br />
В коде реализовано 2 класса, каждый из которых отвечает за свою область.<br />
Класс ScreenReader содержит функциональность, позволяющую получать информацию о данных с экрана. Для этого делается скриншот. Мы пробовали множество вариантов — но самым быстрым был метод ImageGrab из модуля PIL. Он показал FPS в 25 кадров в секунду. Этого вполне достаточно для реагирования на повороты. После взятия изображения оно обрабатывается с помощью библиотеки OpenCV. Я накладываю маску, что бы выделить дорогу из кадра. Маска берётся не на всём кадре, а на 2 полосах экрана, первая из которых находится в самом низу кадра, а вторая почти под линией горизонта. Таким образом можно понять в какую сторону изгибается дорога. С помощью двух моментов можно притормаживать на поворотах и газовать максимально на прямых участках.<br />
<span style="white-space: pre;"> </span>Второй класс, Сontrol — отвечает за управление машинкой путем передачи в игру нажатия кнопок на виртуальном геймпаде.<br />
<br />
<b>Настройка эмулятора и виртуального геймпада. </b><br />
Для управления игрой в эмуляторе была установлена программа Vjoy, с помощью которой к компьютеру был подключен виртуальный геймпад. На геймпаде 11 кнопок и 1 стик. Для управления этим геймпадом из программы я использую модуль PyVjoy. Для корректной работы модуля внутрь папки требуется положить специальный DLL-файл, который генерируется в папке, куда вы установили Vjoy. После этого вы сможете управлять виртуальным геймпадом из программы на Python. Необходимо установить в настройках эмулятора вход 1. На него следует поставить 3х кнопочный джойстик Genesis и выбрать в качестве него ваш виртуальный геймпад.<br />
После этого надо запустить программу AssignKeys.py. Она будет нажимать кнопки виртуального геймпада в том порядке, какого требует эмулятор Fusion 3. Во время назначения клавиш фокус должен быть всё время на программе-эмуляторе. Когда эмулятор будет ждать клавиши старт, нажмите любую удобную кнопку на клавиатуре. Это нужно для возможности войти в гонку и поставить паузу. Всё готово! Вы можете запускать гонку в полноэкранном режиме предварительно запустив run.py.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/MkkBPJjI-rs/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/MkkBPJjI-rs?feature=player_embedded" width="320"></iframe></div>
<br />
<span style="white-space: pre;"> </span>У вас наверно возник вопрос - почему проект носит порядковый номер 1? Всё просто. В репозитории пока открыт только демо-код, алгоритм которого не идеальный. Гонку мы пока проходим на 8-9 месте, поэтому будем дорабатывать NeyroGamer. Первая часть проекта - научиться взаимодействовать с игрой, получать игровые события, передавать команды управления. Сейчас мы работаем над нейронной сетью, которая улучшит игровые результаты.<br />
<br />
Язык Python.<br />
Автор - Платон, 14 лет ("Карандаш и Самоделкин")</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-53119042233758222352020-04-23T22:08:00.001-07:002020-05-09T04:28:27.562-07:00Lode Runner<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglh-qBTMesN_VOrrk-6vJSU_b9VLN6vcy8KCLj0nFBKMTUqLSNi7Wb-L88v1Iqo1BegrfSP4P7VHvMLXzb2ASEU0s6eGMBzUAUFuO7AbcKiVtkJbzDJ_9NAHh2jB3NNIeWsMdmzHwmBbgV/s1600/LodeRunner2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="889" data-original-width="1600" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglh-qBTMesN_VOrrk-6vJSU_b9VLN6vcy8KCLj0nFBKMTUqLSNi7Wb-L88v1Iqo1BegrfSP4P7VHvMLXzb2ASEU0s6eGMBzUAUFuO7AbcKiVtkJbzDJ_9NAHh2jB3NNIeWsMdmzHwmBbgV/s400/LodeRunner2.jpg" width="400" /></a></div>
<br />
Чем заняться на самоизоляции? Как вариант - написать игру, в которую можно играть всей семьей.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJsuJBh7VwIe47L95b-1apDj-y0WG5IZtTXdqC0Lfe29DtR8ftvj3B1p4jhk4hcGlDhekwleMGB30jzym8duLUrPMnEnNsHbUhmvGC2qXaju8NAxEUsEOTgU8Or3pMCDyzColI43TM9BvK/s1600/LodeRunner.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="902" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJsuJBh7VwIe47L95b-1apDj-y0WG5IZtTXdqC0Lfe29DtR8ftvj3B1p4jhk4hcGlDhekwleMGB30jzym8duLUrPMnEnNsHbUhmvGC2qXaju8NAxEUsEOTgU8Or3pMCDyzColI43TM9BvK/s400/LodeRunner.jpg" width="400" /></a></div>
<br />
Ремейк игры Lode Runner (Apple II) с оригинальным набором уровней. Главная фишка - режим hot seat до 4 человек, где остальные игроки играют за противников главного героя. Однако от уровня к уровню могут играть разное количество игроков, так как количество противников разное на разных уровнях.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjZaa6S6_NYRbiA22r3gZUU5K86T4CM04TE_UEAiTvjnKSkEp5GkhKBouajM8UttdQY_HEWzsDwQ_HZlWYjyY2aW95hrkuqPKHdGVE3V5VSN-1mhaHA3n7Xw_k3mgGswxDtihV7A6UHWHp/s1600/LodeRunner1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="539" data-original-width="543" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjZaa6S6_NYRbiA22r3gZUU5K86T4CM04TE_UEAiTvjnKSkEp5GkhKBouajM8UttdQY_HEWzsDwQ_HZlWYjyY2aW95hrkuqPKHdGVE3V5VSN-1mhaHA3n7Xw_k3mgGswxDtihV7A6UHWHp/s320/LodeRunner1.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Игрок управляет маленьким человечком и должен собрать всё золото, лежащее на данном уровне, избегая встречи с противниками. Весь уровень целиком виден на экране и состоит из кирпичных платформ, лестниц, а также натянутых верёвок, по которым можно двигаться, держась за них руками. Персонаж игры не может убивать роботов, но может создавать для них ямы в кирпичном полу — попавший в яму робот задерживается там на некоторое время. Герой может падать с любой высоты, не разбиваясь, но не может подпрыгивать. После того, как все ящики с золотом собраны, где-либо появляется лестница (или несколько), по которой нужно добраться до верха экрана — это приведёт к переходу на следующий уровень.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0XefjJYMnDuqLas6gDuo_9wVEWMJmJIrrBcfumw4PPnPuVGU5BsMm74hciJWocYbVVLvIzL9jEjoNrpND9HOaxXTQA9jblmMiqnzFRpHxF8y95SuBTRkCeF1lcne7dPc2JSUXGB39AM4O/s1600/LodeRunner3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="896" data-original-width="1600" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0XefjJYMnDuqLas6gDuo_9wVEWMJmJIrrBcfumw4PPnPuVGU5BsMm74hciJWocYbVVLvIzL9jEjoNrpND9HOaxXTQA9jblmMiqnzFRpHxF8y95SuBTRkCeF1lcne7dPc2JSUXGB39AM4O/s320/LodeRunner3.jpg" width="320" /></a></div>
<br />
Всего в игре 150 уровней. На каждом новом уровне требуется более сложная стратегия в отношении того, в каком порядке обходить уровень и где прорыть ямы с тем, чтобы собрать все ящики с золотом и не попасться. Стратегия также может включать способы создания одной большой ямы из множества обычных, прорытых друг за другом.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaufF-t_jZdlE7Zcs-ATQhwsxjcKtArXxzPFDBpWQPFffLrypWTyY55djnVAO1i52iTEVuFAQufp3xIFCxLFDLqHW_5WTj7LAmw17xnhTTWWbeT0MYWG9QUEEdvly77Mv74KZ6VCxH3yJO/s1600/ezgif-1-c5a1c32a54d9.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaufF-t_jZdlE7Zcs-ATQhwsxjcKtArXxzPFDBpWQPFffLrypWTyY55djnVAO1i52iTEVuFAQufp3xIFCxLFDLqHW_5WTj7LAmw17xnhTTWWbeT0MYWG9QUEEdvly77Mv74KZ6VCxH3yJO/s400/ezgif-1-c5a1c32a54d9.gif" width="400" /></a></div>
<br />
С переходом на более высокие уровни игра становится более «головоломной» чем игрой на скорость реакции, хотя и то и другое остаётся важным.<br />
<br />
Язык C#, среда разработки - Unity.<br />
Автор - Платон, 14 лет ("Карандаш и Самоделкин")<br />
Скачать можно c <a href="https://rutracker.org/forum/viewtopic.php?t=5885455" target="_blank">rutracker.org</a> или c <a href="https://yadi.sk/d/oOdavKi8i_L46Q" target="_blank">Яндекс.Диск</a></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-19588968691746875212019-07-07T11:03:00.001-07:002019-07-11T09:02:13.416-07:00Sudoku Hunter<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">В последнее
время наш блог молчит и может показаться,
что «Карандаш и Самоделкин» все, сдулись.
На самом деле работа кипела, а отсутствие
публикуемых материалов было связано с
тем, что проекты раз за разом становятся
все сложнее и требуют все больше времени
на реализацию. Последние наши разработки
были так или иначе связаны с нейросетями,
поэтому логично было за это время
подтянуть скиллы по этой теме, что и
было сделано – был пройден ряд онлайн
курсов по и даже пара оффлайновых, из
которых особенно понравилась «Зимняя
школа машинного обучения» (<span lang="en-US">Machine</span>
<span lang="en-US">Learning</span>
<span lang="en-US">Winter</span>
<span lang="en-US">School</span>).</span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcfMC2vVpDWKJVY8a648qx323RbkH3SElfjSsZGCKY9lvAZWKZcArQ6AF6j4hHnrvDZkrZcbGpMT3kb9vjotUZmfsuPfNzvBpHLXZm8FYd8NqBHh8KL-lc_4tD9pmyPlpg7qh1SKJy1lxl/s1600/Sudoku+Hunter.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcfMC2vVpDWKJVY8a648qx323RbkH3SElfjSsZGCKY9lvAZWKZcArQ6AF6j4hHnrvDZkrZcbGpMT3kb9vjotUZmfsuPfNzvBpHLXZm8FYd8NqBHh8KL-lc_4tD9pmyPlpg7qh1SKJy1lxl/s400/Sudoku+Hunter.jpg" width="400" /></span></a></div>
<div align="center" style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /><a href="https://www.blogger.com/null" name="_GoBack"></a></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Проект,
работа над которым шла больше 4 месяцев,
мы назвали Sudoku Hunter. Изначально была идея
собрать робота по мотивам <a href="https://www.youtube.com/watch?v=IOAOSSvRh9U" target="_blank">NXTSudokuSolver</a>,
однако постепенно она трансформировалось
в нечто иное, на наш взгляд не менее
интересное.</span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Итак,
<span lang="en-US">Sudoku</span> Hunter – это пистолет с <span lang="en-US">EV</span>3,
веб-камерой и <span lang="en-US">Raspberry</span>
<span lang="en-US">Pi</span>
на борту, из которого можно «стрелять»
по математическим головоломкам судоку,
получая на экране <span lang="en-US">EV</span>3-блока
их решение. В алгоритмической части
используются технологии машинного
зрения и машинного обучения, веб-технологии
для создания отладочной видеоконсоли.</span></div>
<div align="center" style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjNVDiqXF2ACup0wd7WuS1T8-kz63DJxzaTmJDQ-8xoBZTKHb2zOgS0dGOOIndmlg_GVrQUDGYMiR63RbKZti_5B2UasQoaJ9mWwNHLtcCTxV6TJ6JTS6fZNnlB7okZXHhL7_NaEeGE1DE/s1600/600px-Sudoku-by-L2G-20050714.svg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="600" data-original-width="600" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjNVDiqXF2ACup0wd7WuS1T8-kz63DJxzaTmJDQ-8xoBZTKHb2zOgS0dGOOIndmlg_GVrQUDGYMiR63RbKZti_5B2UasQoaJ9mWwNHLtcCTxV6TJ6JTS6fZNnlB7okZXHhL7_NaEeGE1DE/s200/600px-Sudoku-by-L2G-20050714.svg.png" width="200" /></span></a></div>
<div align="center" style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Если
кто не помнит, судоку - головоломка на
бумаге, игровое поле которой представляет
собой квадрат размером 9×9, разделённый
на меньшие квадраты со стороной в 3
клетки. Таким образом всё игровое поле
состоит из 81 клетки. В них уже в начале
игры стоят некоторые числа (от 1 до 9),
называемые подсказками. От игрока
требуется заполнить свободные клетки
цифрами от 1 до 9 так, чтобы в каждой
строке, в каждом столбце и в каждом малом
квадрате 3×3 каждая цифра встречалась
бы только один раз.</span></div>
<div align="center" style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpTo1UsllpUNUtwyUeIS0phHPGkkRPZ7kTdjtCxsNxk0TDrEglxcnzv_pQOLk3qwX_PvEXzGJCyiq_D8RX-nACQO0fsZQnv1zVE1Pt05sQPNKXH1BtlrwruM-WPu65G6ttVM3nBozSZiva/s1600/DSC07097.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpTo1UsllpUNUtwyUeIS0phHPGkkRPZ7kTdjtCxsNxk0TDrEglxcnzv_pQOLk3qwX_PvEXzGJCyiq_D8RX-nACQO0fsZQnv1zVE1Pt05sQPNKXH1BtlrwruM-WPu65G6ttVM3nBozSZiva/s400/DSC07097.JPG" width="400" /></span></a></div>
<div align="center" style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Конструкция
нашего робота не особенно замысловата,
поэтому инструкцию по сборке мы решили не
делать – вы легко соберете что-то
подобное просто глядя на фото. Мы
использовали следующие компоненты:</span></div>
<ul style="text-align: left;">
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Блок
<span lang="en-US">Lego</span>
<span lang="en-US">Mindstroms</span>
<span lang="en-US">EV</span>3
и строительные детали из этого набора</span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><span lang="en-US">Raspberry</span>
<span lang="en-US">Pi</span></span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Веб-камера
<span lang="en-US">Sony Playstation
Eye</span></span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><span lang="en-US">Wi</span>-<span lang="en-US">fi</span>
адаптер для связи <span lang="en-US">EV</span>3
с <span lang="en-US">RPi</span></span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><span lang="en-US">Powerbank
</span>для питания <span lang="en-US">RPi</span></span></div>
</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-lYNgqpziwOBLjNfvVSCrXcxlZnY56YbfFxY8J0yTkVZUjY4XSX05__vRHh4mklGd-_LeKO_nzwvwifn80Pob1QFjCFAfBe1LrN0Q5mSm8ScdhbHewFtQ4STs4mkUewv-SLHrbRTxug8I/s1600/DSC07099.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-lYNgqpziwOBLjNfvVSCrXcxlZnY56YbfFxY8J0yTkVZUjY4XSX05__vRHh4mklGd-_LeKO_nzwvwifn80Pob1QFjCFAfBe1LrN0Q5mSm8ScdhbHewFtQ4STs4mkUewv-SLHrbRTxug8I/s400/DSC07099.JPG" width="400" /></span></a></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: center;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программ,
которые необходимы для работы робота
- несколько, все они написаны на <span lang="en-US">Python</span>:</span></div>
<ul style="text-align: left;">
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа
для EV3 - отвечает за вывод информации
на экран блока, связь с Raspberry Pi, передачу
на <span lang="en-US">RPi</span>
состояния датчика-кнопки</span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа для
<span lang="en-US">Raspberry</span>
<span lang="en-US">Pi</span>
- отвечает за обработку кадров с камеры,
распознаванием цифр с использованием
обученной нейросети, последующим
решением распознанного судоку, связь
с <span lang="en-US">EV</span>3,<span lang="en-US"> </span>вывод
вспомогательной и отладочной информации
на веб-консоль,</span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа
для <span lang="en-US">Raspberry</span>
<span lang="en-US">Pi</span>,
предназначенная для создания дата сета
для обучения нейронной сети.</span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа
для ПК, используется для создания и
обучения нейросети на основе
подготовленного дата сета</span></div>
</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB43R5dMzQcRzI0iCJYA5S9F8hu8B6y82C8kfLu0gLWcG-McSHVwYXubwc9Y8ss9g7C49KddYsdK0Mcrn5RxmkloohsXwoI3RRqVlmpeMPeHJvBWnRA-HtWnXD_OhfjxiMwu-RSkwQdtXy/s1600/DSC07098.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB43R5dMzQcRzI0iCJYA5S9F8hu8B6y82C8kfLu0gLWcG-McSHVwYXubwc9Y8ss9g7C49KddYsdK0Mcrn5RxmkloohsXwoI3RRqVlmpeMPeHJvBWnRA-HtWnXD_OhfjxiMwu-RSkwQdtXy/s400/DSC07098.JPG" width="400" /></span></a></div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Основная
программа для <span lang="en-US">Raspberry</span>
<span lang="en-US">Pi</span>
работает по следующему алгоритму: </span></div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"></span></div>
<div style="text-align: left;">
</div>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Подключение
библиотеки машинного зрения <span lang="en-US">OpenCV</span></li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Подключение
библиотек машинного обучения keras(tensorflow), sklearn</li>
</span></ul>
<span style="font-family: Arial, Helvetica, sans-serif;">
Процесс
1<span lang="en-US">:</span></span><ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Взятие
кадра с камеры</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Преобразование
изображения из <span lang="en-US">BGR </span>в <span lang="en-US">HSV</span> </span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Наложение
маски для фокусировки
на значимых элементах изображения</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Запись
результирующего кадра в объект в памяти</span></li>
</ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Соединение
с <span lang="en-US">EV</span>3<span lang="en-US"> </span>с
помощью протокола <span lang="en-US">socket</span> </li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Основной
цикл:</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Чтение
кадра из объекта в памяти</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Поиск
в изображении с наложенной
маской объектов, напоминающих
квадрат </li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Передача
данных о предполагаемом расположении
квадрата на <span lang="en-US">EV</span>3,
для вывода на экран блока</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Приём
данных с <span lang="en-US">EV</span>3
о состоянии кнопки </li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Если
кнопка нажата:</li>
</span></ul>
<span style="font-family: Arial, Helvetica, sans-serif;">
Процесс
3<span lang="en-US">:</span></span><ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Запуск
веб-сервера (используется модуль <span lang="en-US">Flask</span>)</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Соединение
с <span lang="en-US">Raspberry</span>
<span lang="en-US">Pi </span>с
помощью протокола <span lang="en-US">socket</span></span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Получение данных
о предполагаемом расположении квадрата </span></li>
</ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Подключение
библиотеки машинного зрения <span lang="en-US">OpenCV</span></li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Подключение
библиотек машинного обучения keras(tensorflow), sklearn</li>
</span></ul>
<span style="font-family: Arial, Helvetica, sans-serif;">
Процесс
1<span lang="en-US">:</span></span><ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Взятие
кадра с камеры</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Преобразование
изображения из <span lang="en-US">BGR </span>в <span lang="en-US">HSV</span> </span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Наложение
маски для фокусировки
на значимых элементах изображения</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Запись
результирующего кадра в объект в памяти</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Соединение
с <span lang="en-US">EV</span>3<span lang="en-US"> </span>с
помощью протокола <span lang="en-US">socket</span></span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Чтение
кадра из объекта в памяти</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Поиск
в изображении с наложенной
маской объектов, напоминающих
квадрат </span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Передача
данных о предполагаемом расположении
квадрата на <span lang="en-US">EV</span>3,
для вывода на экран блока</span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Приём
данных с <span lang="en-US">EV</span>3
о состоянии кнопки </span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Если
кнопка нажата:</span></li>
</ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Запуск
веб-сервера (используется модуль <span lang="en-US">Flask</span>)</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Вывод
информации на веб-сервер - видеоконсоль
для удобства отладки</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Подключение
библиотек машинного обучения </li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Загрузка
дата сета изображений </li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Разбиение
дата сета на учебные
и тренировочные данные</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Создание
нейронной сети с заданными параметрами </li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Обучение
нейронной сети</li>
</span></ul>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<li>Сохранение
модели </li>
</span></ul>
<br />
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
</span></ul>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Процесс
2<span lang="en-US">:</span></span></div>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
<ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Изображение
обрабатывается и судоку «нарезается»
на 81 квадрат в каждом из которых одна
клетка головоломки </div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Каждый
из фрагментов проверяется на наличие
в нём цифры и если цифра обнаружена,
то клетка подаётся на распознавание
нейронной сети </div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Распознанная
цифра заноситься в массив. Когда массив
заполнен всеми цифрами, он подаётся в
алгоритм, решающий судоку </div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Массив содержащий
решённую головоломку передаётся на
<span lang="en-US">EV</span>3
для вывода на экран блока </div>
</li>
</ul>
</span></ul>
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Вывод
информации на веб-сервер - видеоконсоль
для удобства отладки</span></div>
</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfq1GXwzXJq8kNXRNXRhpjhQ3B3e7RbWDcsbv-fQp-SEirN4QE0a74akSKExWNQqbfKryKBnthsXSu-gqTcNZp4qDS0mYez5O5KonQY-EFWVAtJFAy7x2i8NzC4yQi_8RWz4S99zg6Z8tD/s1600/2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="450" data-original-width="600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfq1GXwzXJq8kNXRNXRhpjhQ3B3e7RbWDcsbv-fQp-SEirN4QE0a74akSKExWNQqbfKryKBnthsXSu-gqTcNZp4qDS0mYez5O5KonQY-EFWVAtJFAy7x2i8NzC4yQi_8RWz4S99zg6Z8tD/s400/2.gif" width="400" /></span></a></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа на
<span lang="en-US">EV</span>3
работает по следующему алгоритму:</span></div>
<ul style="text-align: left;">
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Вывод
контура квадрата на экран для
визуального контроля (размер квадрата,
угол разворота, степень его трапециевидности)</span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Передача
состояния датчика-кнопки
на <span lang="en-US">Rpi</span></span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Если
от <span lang="en-US">RPi</span>
получен массив данных с решенной
головоломкой - вывод решённого судоку
на экран блока</span></div>
</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBxb4QAFzwlawcu91qmtdOCyPFfDcXcrmZfsBIIlvzv5tDeSRqx0KNWW3Qbd9ZeYC-4BcJpZ1j0nM8gJk8VpgpXylBkUZi-wksZtJJbJk8isrymej5a9tNVeJiqn0gu38pGTUsXaRW1pgA/s1600/4.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="338" data-original-width="600" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBxb4QAFzwlawcu91qmtdOCyPFfDcXcrmZfsBIIlvzv5tDeSRqx0KNWW3Qbd9ZeYC-4BcJpZ1j0nM8gJk8VpgpXylBkUZi-wksZtJJbJk8isrymej5a9tNVeJiqn0gu38pGTUsXaRW1pgA/s320/4.gif" width="320" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа
создания дата сета для обучения нейронной
сети на <span lang="en-US">Raspberry</span>
<span lang="en-US">Pi</span>
имеет следующий алгоритм:</span></div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"></span></div>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
</span></ul>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Процесс
2<span lang="en-US">:</span> </span></div>
<ul style="text-align: left;">
<ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Изображение
обрабатывается и судоку «нарезается»
на 81 квадрат в каждом из которых одна
клетка головоломки </span></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Каждый
квадрат сохраняется в папку, формируя
дата сет</span></div>
</li>
</ul>
</ul>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Процесс 3:</span></div>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
</span></ul>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span><div style="text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzjW3AuH1CauN-IEkjKiU3qSWx4lSQjx31cuEO98AZ7JjKk1j2U6m_DAPDZV6UIqlnqIq9ScRcuxqhgKNYr0ZzJeF1scf6dbY7dIral5iDLboFrQREGWJlslHRO9d8eck9jZBjZGbSxDS/s1600/5.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="338" data-original-width="600" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzjW3AuH1CauN-IEkjKiU3qSWx4lSQjx31cuEO98AZ7JjKk1j2U6m_DAPDZV6UIqlnqIq9ScRcuxqhgKNYr0ZzJeF1scf6dbY7dIral5iDLboFrQREGWJlslHRO9d8eck9jZBjZGbSxDS/s320/5.gif" width="320" /></span></a></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Программа
на ПК, предназначенная для создания и
обучения нейросети на основе подготовленного
дата сета работает так: </span></div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"></span></div>
<ul style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">
</span></ul>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span><div style="text-align: left;">
</div>
<div style="margin-bottom: 0.35cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Стандартный
алгоритм обучения нейронной сети мы
усовершенствовали
путём запуска функции обучения не на
заданное количество
эпох, а по одной эпохе, с проверкой
результата на проверочной выборке после
каждой. Если результат ухудшается
несколько эпох подряд — прекращаем
обучения с ошибкой. Если результаты на
тестовой выборке выше 95% -
прекращаем
обучения, проверяем модель на отдельной
выборке (которую она ещё не видела ни
при обучении,
ни
при проверках после каждой эпохи).</span></div>
<div style="margin-bottom: 0.35cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Исходные коды всех программ проекта мы выложили здесь: <a href="https://github.com/darkavengersmr/Sudoku-Hunter" target="_blank">https://github.com/darkavengersmr/Sudoku-Hunter</a></span></div>
<div style="margin-bottom: 0.35cm; text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-family: Arial, Helvetica, sans-serif;">Д</span><span style="font-family: Arial, Helvetica, sans-serif;">емонстрация работы робота:</span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Arial, Helvetica, sans-serif;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/nHXPPqE8Ea0/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/nHXPPqE8Ea0?feature=player_embedded" width="320"></iframe></span></div>
<br /></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-3754348990924544942019-01-08T02:07:00.001-08:002019-01-27T03:57:16.998-08:00PiTanks Online<div dir="ltr" style="text-align: left;" trbidi="on">
Нам очень нравятся игры для программистов, такие как например <a href="https://ru.wikipedia.org/wiki/Colobot">Colobot</a> и <a href="https://ru.wikipedia.org/wiki/Ceebot">Ceebot</a>. Писать код, загружать его в своего бота и запускать его для выполнения миссий - что может быть интереснее? Поддержка сетевого режима, когда другие игроки запускают своих прокачанных кодом ботов против твоего? Несомненно. Однако еще более интересным нам показалось самим разработать игру для программистов и поиграть в нее с друзьями.<br />
Серверный игровой движок, многопоточность, асинхронный обмен данными, объекты и классы - все это мы приправим поддержкой дополненной реальности с использованием машинного зрения c OpenCV.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMxldJmObDmrad-N2uFs2M_6tyhUSwP9fMxxgYSTYnELPsvXpR1n5tiZklBOz6VzPBexDPrOwjxPpEgCATusLMVh_5742-tA_JhrtuFJmx-MKuxb9arkJYO4pTETjrE1sRqV2GTjHwI7pW/s1600/PiTanksOnline.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMxldJmObDmrad-N2uFs2M_6tyhUSwP9fMxxgYSTYnELPsvXpR1n5tiZklBOz6VzPBexDPrOwjxPpEgCATusLMVh_5742-tA_JhrtuFJmx-MKuxb9arkJYO4pTETjrE1sRqV2GTjHwI7pW/s400/PiTanksOnline.jpg" width="400" /></a></div>
<br />
Приставка Pi в названии проекта "PiTanks Online" однозначно намекает на то, что в качестве серверной платформы мы использовали Raspberry Pi. Игровое поле в нашем проекте нарисовано от руки на листе бумаги.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJjLnywmjLDlq9pWuJTTp6Hs4k-LemyZtmubkoJ1HrPx3SUOSr81_sCevq8ab9KsDMarx2oVmZWgjxVSQZrqkNUXkQDtPYo-zjreXsZTESQP2rpEamc4QjEFddFyX9drDGqASz_P8I0cU_/s1600/DSC06567_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="886" data-original-width="1600" height="221" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJjLnywmjLDlq9pWuJTTp6Hs4k-LemyZtmubkoJ1HrPx3SUOSr81_sCevq8ab9KsDMarx2oVmZWgjxVSQZrqkNUXkQDtPYo-zjreXsZTESQP2rpEamc4QjEFddFyX9drDGqASz_P8I0cU_/s400/DSC06567_2.jpg" width="400" /></a></div>
<br />
На него смотрит веб-камера, установленная на подставке, собранной из LEGO Technic. В качестве рисованного поля может использоваться также маркерная доска.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCBNDwCOxOe7-0SGPrDsSfFPkF4uupuhy7rch2xdAgwh42XO3-i84OovZ7_3u2ogD5L4dddLppHaQ_kXk00bGQncP2h7i5UhwDusqlO1Ab2Qkz2koma5yG45HG3cFAKc14gUyfdt36-Jmc/s1600/DSC06570.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1067" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCBNDwCOxOe7-0SGPrDsSfFPkF4uupuhy7rch2xdAgwh42XO3-i84OovZ7_3u2ogD5L4dddLppHaQ_kXk00bGQncP2h7i5UhwDusqlO1Ab2Qkz2koma5yG45HG3cFAKc14gUyfdt36-Jmc/s400/DSC06570.JPG" width="266" /></a></div>
<br />
Каждый кадр, полученный с камеры, обрабатывается в реальном времени. Все нарисованные или размещенные на поле объекты становятся непроезжаемыми для ботов препятствиями. Игра полна интерактива - положенная на игровое поле спичка или монетка становится новым испытанием - с момента их появления на поле ботам игроков приходится думать как их объезжать. Игровое поле опубликовано на веб-сервере, любой игрок может наблюдать за ходом битвы в браузере.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhFHpr6vT0u-WHwzntKd0GIGQdI2G4hu85WuViL0Y4iZQOap89bIWRsFrhlAFi52F8cNMtzQsALtQ_XL-_2MTXIzkgVwbZ9UyNYh-GRo-8W0a33_BNTVWlpxzhJT7e_6Ed1-rmqQWrPtGQ/s1600/PiTanks1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhFHpr6vT0u-WHwzntKd0GIGQdI2G4hu85WuViL0Y4iZQOap89bIWRsFrhlAFi52F8cNMtzQsALtQ_XL-_2MTXIzkgVwbZ9UyNYh-GRo-8W0a33_BNTVWlpxzhJT7e_6Ed1-rmqQWrPtGQ/s640/PiTanks1.jpg" width="640" /></a></div>
Для участия в битве игрок может скачать одну из заготовок кода бота и, модифицировав ее, подключить бота к игровому серверу. Взаимодействие клиент-сервер организовано посредством socket-соединения. Все примеры ботов написаны на Python, хотя ничего не мешает использовать на клиентской стороне любой другой язык программирования, умеющий работать с сетевыми сокетами.<br />
<br />
Наши примеры ботов имеют следующие наборы "команд":<br />
<ul style="text-align: left;">
<li><span style="font-family: "courier new" , "courier" , monospace;"><b>forward()</b> </span>- бот смещается на 1 единицу дистанции вперед (в сторону, в которую он в данный момент развернут)</li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">backward()</span></b> - бот смещается на 1 единицу дистанции назад</li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">right()</span></b> - бот поворачивается на месте на 1 градус вправо</li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">left()</span></b> - бот поворачивается на месте на 1 градус влево</li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">radar(a)</span></b> - запросить данные с радара по направлению a (угла в градусах 0..359 от текущего направления бота). Функция возвращает кортеж из символа, обозначающего объект, который обнаружил радар (t - живой бот противника, w - стена или мертвый бот противника, n - "ничего нет") и числа - расстояния до обнаруженного объекта (0 в случае объекта "ничего нет") </li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">fire()</span></b> - бот производит выстрел, снаряд летит по направлению разворота бота</li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">energy()</span></b> - возвращает количество доступных очков действий. Очки действий тратятся на движение, стрельбу и работу радара. Пополняются каждую секунду. Введены, чтобы никто из игроков не мог получить приоритета в обработке его бота сервером. </li>
<li><b><span style="font-family: "courier new" , "courier" , monospace;">exit()</span></b> - отключиться от сервера, выйти из боя</li>
</ul>
Каждая из функций <b><span style="font-family: "courier new" , "courier" , monospace;">forward, backward, left</span></b> и <b><span style="font-family: "courier new" , "courier" , monospace;">right</span></b> возвращает <span style="font-family: "courier new" , "courier" , monospace;"><b>True</b></span> или <span style="font-family: "courier new" , "courier" , monospace;"><b>False</b></span> давая понять боту, была ли отработана команда. Это может быть удобным, например для понимания не застрял ли бот при маневре, упершись в препятствие.<br />
<br />
При желании можно не использовать готовые функции из примеров, а написать свои. Например, доработать функции поворота возможностью принимать параметр "угол поворота", а функции движения - параметр "дистанция". Логику управления ботом в целом можно накрутить довольно сложную. Вполне адекватно работают, например, ПИД-регуляторы по дальномерам ботов, можно использовать элементы SLAM для локализации на карте.<br />
<br />
Написанный на Python бот может работать не только на ПК, подходит практически любое устройство с интерпретатором этого языка, например LEGO EV3, ESP8266 или смартфон:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEialaIPkLxge7sI4rfDPFmeE6qjiIBevQgJtKW4mweo5JaPW4SEXDkpKevZX_3GKBdwHml8QHnTzz5g_EV9keOegp1hhqEsOqecbTiv7kzndiOfcdfprRGtFSaxPjOWj5MM5FnYXrKDLtK-/s1600/Screenshot_20190103-111945.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1280" data-original-width="720" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEialaIPkLxge7sI4rfDPFmeE6qjiIBevQgJtKW4mweo5JaPW4SEXDkpKevZX_3GKBdwHml8QHnTzz5g_EV9keOegp1hhqEsOqecbTiv7kzndiOfcdfprRGtFSaxPjOWj5MM5FnYXrKDLtK-/s400/Screenshot_20190103-111945.png" width="225" /></a></div>
<br />
Исходный код сервера и примеры ботов доступны по <a href="https://github.com/darkavengersmr/PiTanksOnline" target="_blank">ссылке</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/_1R7BtP1ONM/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/_1R7BtP1ONM?feature=player_embedded" width="320"></iframe></div>
<br /></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-58783444947099018332018-11-30T21:46:00.000-08:002018-11-30T21:46:03.055-08:00Pong: Next<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="line-height: 115%;">Читатели нашего блога вероятно помнят наш проект 2016 года </span><a href="http://karandashsamodelkin.blogspot.com/2016/10/lego-laser-pong.html"><span lang="EN-US" style="line-height: 115%;">Laser</span><span lang="EN-US" style="line-height: 115%;"> </span><span lang="EN-US" style="line-height: 115%;">Pong</span></a><span style="line-height: 115%;">, в котором мы создали робота для игры в одну из первых
компьютерных игр – </span><span lang="EN-US" style="line-height: 115%;">Pong</span><span style="line-height: 115%;">. Этой осенью
мы снова решили вернуться к теме двух ракеток и мяча, взглянуть на эту простую, но увлекательную игру несколько под иным углом. Причем взглянуть - в прямом смысле этого слова: р</span>обот с машинным зрением будет смотреть камерой на экран и нажимать кнопки на компьютерной клавиатуре, играя на эмуляторе классического игрового автомата. Никаких регуляторов, только хардкор в виде расчетов траекторий полета мяча и отскоков. Но и это еще не все - в рамках проекта мы разработали свой Pong, с нейросетями и прочим машинным обучением. Интересно кто победит - машинное зрение и четкая математика или нейронные сети и вероятностная логика?</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVKTGC8kmrBp-jjHt6QYis0iA9BYRgM8IB9cqpYBOqYO1_y-bBPoNrCibZU-OdvfmQrpPzI4VYFMWsibrnjXKdYZ-QF6q82aWLG90c_ZtmdDCrDolpYRCSoeE2Q83lHGK9C86TNGm-MkJq/s1600/Pong+Next.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVKTGC8kmrBp-jjHt6QYis0iA9BYRgM8IB9cqpYBOqYO1_y-bBPoNrCibZU-OdvfmQrpPzI4VYFMWsibrnjXKdYZ-QF6q82aWLG90c_ZtmdDCrDolpYRCSoeE2Q83lHGK9C86TNGm-MkJq/s400/Pong+Next.jpg" width="400" /></a></div>
<br />
<div class="MsoNormal">
<span style="font-family: "arial" , "helvetica" , sans-serif;">Старший участник команды «Карандаш и Самоделкин» спроектировал, построил и запрограммировал:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Робота, использующего камеру и технологии машинного зрения для распознавания и анализа происходящего на экране, способного играть в Pong, нажимая кнопки на компьютерной клавиатуре</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Алгоритм игры в Pong, основанный на математической модели движения мяча, учитывающий траекторию его движения, множественные столкновения со стенками и передающий роботу информацию о том, где должен оказаться мяч после серии отскоков</span></li>
</ul>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Робот собран на базе LEGO Mindstorms EV3 и использует мотор для нажатия 2-х кнопок на клавиатуре. Для полноценной обработки видеопотока с камеры в реальном времени вычислительные мощности блока EV3 усилены микрокомпьютером Raspberry Pi 2, объединенным с ним беспроводной сетью. EV3 выступает в роли контроллера двигателя, управляемого по сокету TCP/IP.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXUDqlqsp3nKe5LBvbFkfCYheBF9DYXvennCz_9VPZ2UY_dfBuZpT6kwUtRvBVvUsrAH9Zms43hY8dlSzE51YXrhv7YkTuzVqc42_C6L3twwbbsy2fpCNUJ7zDIaN5UGfMUyC60rcwX841/s1600/DSC06530_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1297" data-original-width="1600" height="259" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXUDqlqsp3nKe5LBvbFkfCYheBF9DYXvennCz_9VPZ2UY_dfBuZpT6kwUtRvBVvUsrAH9Zms43hY8dlSzE51YXrhv7YkTuzVqc42_C6L3twwbbsy2fpCNUJ7zDIaN5UGfMUyC60rcwX841/s320/DSC06530_2.jpg" width="320" /></a></div>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Все программы в проекте Pong:Next написаны на языке Python, на ПК используется ОС семейства Windows, на Raspberry Pi и EV3 – Linux.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Для робота разработаны три программы:</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">1. <a href="https://github.com/darkavengersmr/PongNext/blob/master/rpi/control_camera.py">Программа для позиционирования камеры</a> относительно монитора. Использует веб-сервер для вывода на него видеопотока с камеры.<br />2. <a href="https://github.com/darkavengersmr/PongNext/blob/master/ev3/keybord.py">Программа для блока EV3</a> содержит в себе socket-сервер и пропорциональный регулятор управления двигателем. Для их независимого функционирования используется модуль threading. Кроме этого робот выводит на экран EV3 текущий счет в игре.<br />3. <a href="https://github.com/darkavengersmr/PongNext/blob/master/rpi/main.py">Основная программа, запускаемая для Raspberry Pi</a>, работает по следующему алгоритму:</span><br />
<ol style="text-align: left;">
</ol>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"> Однократно:</span></div>
<ul style="text-align: left;">
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Устанавливаем соединение socket-клиентом с сервером на EV3</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Берём пробный кадр с камеры и устанавливаем размеры игрового поля</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Запускаем параллельный процесс, отвечающий за веб-сервер и вещание картинки с отладочной информацией</span></li>
</ul>
<span style="font-family: "arial" , "helvetica" , sans-serif;"> Главный процесс:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Обновляем кадр с камеры</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Производим контурный анализ кадра, выделяя на нем мяч и ракетки с использованием модуля OpenCV</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">По данным данного и одного из предыдущих кадров определяем направление движения мяча и рассчитываем точку его касания о линию движения ракетки. Для этого рекурсивно находим пересечения линий, образованных точками текущего положения мяча и его положением в предыдущий момент времени с боковыми частями поля до тех пор, пока не будет вычислена точка касания с линией, вдоль которой двигается ракетка.</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Проверяем, был ли гол, основываясь на перескоке мяча в центр кадра после его пропадания около одной из ракеток</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">По данным разницы между фактическим положением ракетки в кадре и желаемым ее положением по расчетным данным, определяем, какие кнопки на клавиатуре нужно нажать</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Отправляем на EV3 данным о кнопках, которые требуется нажать и о счете в игре для отображения на экране блока EV3</span></li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJc6j5sf-fURbGl8XHKR5xfuzksZByChhz2ycWxVyQDA9leHu-ewerO0qneN7s7QjBhy-arKXgsId2g5YqsXcdeEIwhLbayMecXcujBtxnJh7nitLA9UxwXLQAOuvXuiz0_Ab5x5uSwSAa/s1600/gif1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="403" data-original-width="600" height="267" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJc6j5sf-fURbGl8XHKR5xfuzksZByChhz2ycWxVyQDA9leHu-ewerO0qneN7s7QjBhy-arKXgsId2g5YqsXcdeEIwhLbayMecXcujBtxnJh7nitLA9UxwXLQAOuvXuiz0_Ab5x5uSwSAa/s400/gif1.gif" width="400" /></a></div>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Младший участник команды «Карандаш и Самоделкин» в рамках проекта разработал:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Игру Pong для ПК на двух игроков с возможностью игры с клавиатуры</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://github.com/darkavengersmr/PongNext/blob/master/pc/pong_human_learning.py">Нейронную сеть и алгоритм ее обучения при игре с человеком</a>, позволяющий научить сеть базовым правилам игры в Pong</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://github.com/darkavengersmr/PongNext/blob/master/pc/pong_machine_learning.py">Алгоритм машинного обучения</a> для дальнейшего дообучения сети при игре двух ее копий друг против друга</span></li>
</ul>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Программа для игры в Pong для ПК воссоздает классический игровой автомат с квадратным пиксельным мячом. Реализованы «подкручивания» мяча в момент его отбивания ракеткой – для корректировки угла отскока. Алгоритм компьютерного игрока основывается на использовании простейшей однослойной нейронной сети. Мы разбиваем поле на прямоугольные зоны, в каждой из которых выделяем N направлений полета мяча. Кроме этого выделяем зоны, в которых можем находиться управляемая сетью ракетка. Такие сочетания образуют нейрон сети, выход нейрона – вероятность нажатия кнопок «вверх» и «вниз» (либо отсутствия нажатий кнопок вообще, если вероятность низка).</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Алгоритм обучения сети мы провели в два этапа:</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">1. «Обучения с учителем», сеть учится базовым правилам игры, играя с игроком.</span><br />
<ul style="text-align: left;">
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Поначалу вероятность нажатия кнопок «вверх», «вниз» и «не нажата» равны, управляемая сетью ракетка в каждый момент времени движется хаотично</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Параллельно сеть наблюдает в какой зоне, при каком угле полета мяча и при каком начальном положении ракетки человека какие кнопки на клавиатуре он нажимает. Эту информацию она обрабатывается, накапливаясь в коэффициентах (весах) нейронов</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Чем дольше человек обучает сеть, тем больше информации о игровых ситуациях и действиях в них будет аккумулировано в нейронной сети. Уже с первых секунд игры хаотичные движения ракетки начинают трансформироваться в более «разумные». Через час игры сеть почти полностью копирует стиль игры человека.</span></li>
</ul>
<span style="font-family: "arial" , "helvetica" , sans-serif;">2. «Машинное обучение». Две копии обученной человеком сети играют друг с другом, улучшая навыки игры, разыгрывая в том числе ранее не встречавшиеся игровые ситуации:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Ведем историю последних N комбинаций положения мяча, угла его полета и положения управляемой сетью ракетки в этот момент</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Если управляемая сетью ракетка отбила мяч, увеличиваем коэффициенты соответствующих нейронов, укрепляя желание сети сыграть таким же образом в схожей игровой ситуации</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Если управляемая сетью ракетка пропустила мяч, уменьшаем коэффициенты нейронов для последних N/5 комбинаций в истории</span></li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4APSiXDVhxHEpVQ4AE2vduWLPH4_uub-j6fv0tYsSkk08epBM3Ub47DmiDyFMYYhDkwiPcbxKHcFTiyPxxLt95G0MWrReJok9MOXPa4Kl2cWBcKshsUkr1MDFxVjNBzzUEJD-VK68njUu/s1600/gif2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4APSiXDVhxHEpVQ4AE2vduWLPH4_uub-j6fv0tYsSkk08epBM3Ub47DmiDyFMYYhDkwiPcbxKHcFTiyPxxLt95G0MWrReJok9MOXPa4Kl2cWBcKshsUkr1MDFxVjNBzzUEJD-VK68njUu/s400/gif2.gif" width="400" /></a></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: arial, helvetica, sans-serif;">Демонстрацию работы робота можно посмотреть на следующем видео:</span><br />
<span style="font-family: arial, helvetica, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/DrHty2nj1U4/0.jpg" src="https://www.youtube.com/embed/DrHty2nj1U4?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-44986471502502119702018-09-15T05:37:00.000-07:002018-09-15T12:07:32.897-07:00NXT for Speed<div dir="ltr" style="text-align: left;" trbidi="on">
Похоже LEGO Mindstorms NXT уже всеми забыт и в мире пластиковой робототехники безраздельно правит EV3. Однако мы не спешим списывать его со счетов и в нашем сегодняшнем проекте он еще даст жару!<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDntUlJ12C46nJF6je5kqiyo7yGoUia0iTop3O0JTDGpvDuUiKmOxnkVHCrwJ3uho8YTmRo5TVYDBmXyIv0xsUN1U2PJnPIbf2ogdq5tG-j1OyMDlxkOZqDbrTLAYR9Oa2WZxVbDkukeZ8/s1600/NXT+for+Speed.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDntUlJ12C46nJF6je5kqiyo7yGoUia0iTop3O0JTDGpvDuUiKmOxnkVHCrwJ3uho8YTmRo5TVYDBmXyIv0xsUN1U2PJnPIbf2ogdq5tG-j1OyMDlxkOZqDbrTLAYR9Oa2WZxVbDkukeZ8/s400/NXT+for+Speed.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
NXT for Speed - гоночный аркадный автомат с использованием руля и педалей. Основная цель проекта - изучение основных принципов работы с динамической векторной графикой, закрепление навыков программирования многопоточных приложений на С.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOp7_ZNMsk4ekPA1tw7nj37u81EX4Zzn-5Xtix0o1IXJzm5QF2NFkimFqiUTRKs4x3rfT1Ca5fQA4uCM-BCdxJcgBpSOT6whzmwx7psjT0IStvFThO4DLLI9IV33-9Cm3IJjGpsSDLf4NW/s1600/1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="256" data-original-width="400" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOp7_ZNMsk4ekPA1tw7nj37u81EX4Zzn-5Xtix0o1IXJzm5QF2NFkimFqiUTRKs4x3rfT1Ca5fQA4uCM-BCdxJcgBpSOT6whzmwx7psjT0IStvFThO4DLLI9IV33-9Cm3IJjGpsSDLf4NW/s320/1.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</div>
<div>
В нашем проекте мы реализовали:</div>
<div>
<ul style="text-align: left;">
<li>динамический расчет конфигурации трассы</li>
<li>физическую модель, учитывающую силу нажатия на педаль газа, сопротивление покрышек, сопротивление воздуха. Автомобиль способен двигаться накатом, тормозить с учетом силы нажатия на педаль тормоза.</li>
<li>вид от третьего лица с изменением угла зрения на автомобиль</li>
<li>"плавающий" горизонт с задним фоном (горы)</li>
<li>дорожные знаки на обочинах дороги </li>
<li>управление с использованием руля (контроль угла поворота) и педалей (газ-тормоз)</li>
<li>реализован автовозврат педалей - они жесткие и возвращаются в исходную позицию, если их отпустить</li>
<li>обратная связь от препятствий - при съезде на обочины руль трясет</li>
<li>обратная связь от скорости движения - чем выше скорость тем сложнее резко повернуть руль, на стоящей машине руль поворачивается легко</li>
<li>цифровой спидометр в углу экрана</li>
<li>подсчет очков</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWm49DpwLbYOLasmA_hjK1WOh1ig7Xem8vSafjs3IobndQ49k1yXIFLx3Ge8Y65WZE6_HQUBQlYQN5YuRdRWXSvz3jMXxVNORy-SqeWxuiCRPD9M6PlCcQ26SlOH6h6knVtN2yeG9gkx55/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="256" data-original-width="400" height="203" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWm49DpwLbYOLasmA_hjK1WOh1ig7Xem8vSafjs3IobndQ49k1yXIFLx3Ge8Y65WZE6_HQUBQlYQN5YuRdRWXSvz3jMXxVNORy-SqeWxuiCRPD9M6PlCcQ26SlOH6h6knVtN2yeG9gkx55/s320/2.png" width="320" /></a></div>
<div>
<br /></div>
<div>
Инструкцию по сборке в формате LEGO Digital Designer можно скачать по ссылке.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7a0mlh0qi3jAmJvtG7eHrKEAxBwaZ4xvT_7z3wR4P6j5BkcV9IsgBWiba4YwdOmo5g6LPt4FWjeyK-c7XUBx0sNVmfLO0gGp8YTAJ0vo8h2xalDSU_pIlZKJ43jMfu502ne9hdp8ziADm/s1600/NXT+for+Speed+-%25D0%25B8%25D0%25BD%25D1%2581%25D1%2582%25D1%2580%25D1%2583%25D0%25BA%25D1%2586%25D0%25B8%25D1%258F.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7a0mlh0qi3jAmJvtG7eHrKEAxBwaZ4xvT_7z3wR4P6j5BkcV9IsgBWiba4YwdOmo5g6LPt4FWjeyK-c7XUBx0sNVmfLO0gGp8YTAJ0vo8h2xalDSU_pIlZKJ43jMfu502ne9hdp8ziADm/s400/NXT+for+Speed+-%25D0%25B8%25D0%25BD%25D1%2581%25D1%2582%25D1%2580%25D1%2583%25D0%25BA%25D1%2586%25D0%25B8%25D1%258F.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Программа написана на языке NXC и выглядит следующим образом:</div>
<div>
<br /></div>
<div>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b>Код</b>: <input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Показать'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Показать'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 60px;" type="button" value="Показать" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int ohki=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int trig=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int r=23;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int ry=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int rx=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int mx=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int my;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">float rz=2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int l=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int c=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">long t;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">float m=500;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int f=4;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">float x1=25,x2=75,y1=0,y2=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int rt=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int o=-10000000000,p=100000000;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int u=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">float k=0.90;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int tmp =0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">float turn[48];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int ch=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">float a=50;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int b=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int e=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int Sign(int x, int y,int v,int c)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(c==0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x,y,x,y+v/2,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x-v/4,y+v/2,v/2,v/2,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x,y,x,y+v/2,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x-v/4,y+v/2,v/2,v/2,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int lines(int x, int y,int color)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> mx=x;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(color==0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x-6,y+4,11,3,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x-5,y+2,2,2,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x+2,y+2,2,2,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+5,y+7,x+3,y+10,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-6,y+7,x-4,y+10,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x+3,y+10,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(CurrentTick()-t>500){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> TextOut(0,0," ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> e=(500-m)/5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> NumOut(0,0,e);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> t=CurrentTick();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(MotorRotationCount(OUT_A) > 15){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+5,y+6,x+9,y+9,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+3,y+10,x+7,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x-2,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x,y+12,x+7,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+7,y+12,x+10,y+5,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+6,y+3,x+10,y+5,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+10,y+4,x+10,y+3,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+9,y+3,x+10,y+3,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(x+10>=p+10){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> TextOut(35,20,"Over");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rt=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(MotorRotationCount(OUT_A) <-15){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+3,y+10,x+1,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x-7,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+1,y+12,x-8,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-6,y+7,x-9,y+10,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-8,y+11,x-11,y+7,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-11,y+7,x-7,y+4,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-11,y+7,x-11,y+4,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-11,y+4,x-9,y+4,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(x-11<=o-10){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> TextOut(35,20,"Over");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rt=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+3,y+10,x+1,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x-2,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-2,y+12,x+1,y+12,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-5,y+11,x-5,y+11,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+4,y+11,x+4,y+11,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> //if(x+10<=p || x-6>=o){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // TextOut(0,0,"Over");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // rt=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> //}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(10);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x-6,y+4,11,3,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x-5,y+2,2,2,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> RectOut(x+2,y+2,2,2,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+5,y+7,x+3,y+10,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-6,y+7,x-4,y+10,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x+3,y+10,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+5,y+6,x+9,y+9,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+3,y+10,x+7,y+12,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x,y+12,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x,y+12,x+7,y+12,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+7,y+12,x+10,y+5,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+6,y+3,x+10,y+5,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+10,y+4,x+10,y+3,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+9,y+3,x+10,y+3,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+3,y+10,x+1,y+12,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-4,y+10,x-7,y+12,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x+1,y+12,x-8,y+12,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-6,y+7,x-9,y+10,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-8,y+11,x-11,y+7,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-11,y+7,x-7,y+4,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-11,y+7,x-11,y+4,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(x-11,y+4,x-9,y+4,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">task mot()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(3000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float P=0.7;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> //P=0.3*e;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float Kp=e/100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float P2=0.7;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float P3=0.7;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float ERR1=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float ERR2=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float ERR3=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float u1=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float u2=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float u3=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while(1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(rt==1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> break;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> float Kp=e/100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ERR1=0-MotorRotationCount(OUT_A);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u1=P*ERR1*Kp;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ERR2=0-MotorRotationCount(OUT_B);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u2=P2*ERR2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ERR3=0-MotorRotationCount(OUT_C);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u3=P3*ERR3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(mx-11<=o+3){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u1=Random(70)-35;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(mx+10>=p-3){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u1=Random(70)-35;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u1>100)u1=100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u1<-100)u1=-100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u1<0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> OnRev(OUT_A,-1*u1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> OnFwd(OUT_A,u1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u2>100)u2=100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u2<-100)u2=-100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u2<0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> OnRev(OUT_B,-1*u2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> OnFwd(OUT_B,u2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u3>100)u3=100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u3<-100)u3=-100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u3<0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> OnRev(OUT_C,-1*u3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> OnFwd(OUT_C,u2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(100);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">task road()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for(int i =0;i<47;i++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> turn[i]=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while(true){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ch++;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> f--;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(f==0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> f=4;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> l+=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for(int i =0;i<23;i+=1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(25+turn[i]+i*0.9,i*2,25+turn[i+1]+(i+1)*0.9,i*2+3,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(75+turn[i]-i*0.9,i*2,75+turn[i+1]-(i+1)*0.9,i*2+3,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(i==r){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(trig==1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rx=25+turn[i]+i*0.9-5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ry=i*2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rx=75+turn[i]-i*0.9+5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ry=i*2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(i%4==f && i>5){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(50+turn[i],i*2,50+turn[i+1],i*2+3,DRAW_OPT_NORMAL );</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Sign(rx,ry,rz,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m+=5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m+=m*0.2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m>500){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m=500;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m<0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(abs(MotorRotationCount(OUT_B))> 5){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m<=500){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m-=1.7*abs(0-abs(MotorRotationCount(OUT_B))*2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m>500){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m=500;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m<0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(abs(MotorRotationCount(OUT_C))> 5){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m>=0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m+=1.7*abs(0-abs(MotorRotationCount(OUT_C)));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m>500){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m=500;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(m<0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> m=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(m);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for(int i =0;i<23;i+=1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(25+turn[i]+i*0.9,i*2,25+turn[i+1]+(i+1)*0.9,i*2+3,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(75+turn[i]-i*0.9,i*2,75+turn[i+1]-(i+1)*0.9,i*2+3,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(i%4==f && i>5)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(50+turn[i],i*2,50+turn[i+1],i*2+3,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(i==3){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> o=25+turn[i];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> p=75+turn[i];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Sign(rx,ry,rz,1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rz+=0.5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> r--;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(rz>=13){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rz=2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> r=23;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> trig=trig*-1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for(int i =0;i<47;i++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> turn[i]=turn[i+1];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(ch==23){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ohki+=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ch=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u = Random(100);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> turn[47]=u-50;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for(int i =23;i<47;i++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> turn[i]=turn[i-1]*k+turn[47]*(1-k);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(rt==1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> break;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(l==1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,70,35,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,35,30,35,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,17,30,17,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,30,0,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,70,35,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,35,30,35,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,17,30,17,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,30,0,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(30,0,70,35,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(30,35,70,35,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,30,0,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(30,0,70,35,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(30,35,70,35,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,30,0,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(30,17,70,35,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,70,35,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(30,17,70,35,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(70,0,70,35,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">task main()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> t=CurrentTick();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> SetSensorTouch(IN_4);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> start road;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> start mot;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ClearScreen();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(0,48,100,48,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lines(a,b,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while(true){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> NumOut(80,0,ohki);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> c=30-((a-50)/2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c-50,49,c-30,53,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c-10,49,c-30,53,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c-10,49,c,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+10,49,c,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+5,51,c+15,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+25,51,c+15,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+20,51,c+35,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+40,49,c+35,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+40,51,c+55,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+60,49,c+55,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+60,51,c+85,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+100,49,c+85,55,DRAW_OPT_NORMAL);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lines(a,b,1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(abs(MotorRotationCount(OUT_A))>=15){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> a+=(MotorRotationCount(OUT_A))/100.0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c-10,49,c,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+10,49,c,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+5,51,c+15,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+25,51,c+15,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+20,51,c+35,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+40,49,c+35,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+40,51,c+55,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+60,49,c+55,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+60,51,c+85,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c+100,49,c+85,55,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c-50,49,c-30,53,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> LineOut(c-10,49,c-30,53,DRAW_OPT_CLEAR);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lines(a,b,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(rt==1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> break;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Wait(1500);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<br /></div>
</div>
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/LY-XZCEiynE/0.jpg" src="https://www.youtube.com/embed/LY-XZCEiynE?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br /></div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com4tag:blogger.com,1999:blog-4279357166628593719.post-59542002615424313812018-08-29T23:51:00.002-07:002018-08-29T23:53:49.217-07:00Муравей учится ходить<div dir="ltr" style="text-align: left;" trbidi="on">
Наш проект продолжает серию проектов, связанных с простейшими нейронными сетями и снова связан с самообучением. Робот-муравей ANTY, собранный по инструкции из книги Laurens Valk "The LEGO MINDSTORMS EV3 Discovery Book" будет обучаться ходить, не имея изначально ни малейшего представления о том, как это делать. Нейронная сеть робота будет оценивать попытки робота-муравья двигаться, оценивая их с точки зрения скорости движения и сохранения его направления и выстроит в итоге оптимальную взаимосвязь между движениями ног.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7DYujrziWlFn0pSrzGgZ5BpYCG6dwdHVU32NGI3RbsCyvtzwQWIlav9dV0bhHVx4JYcf0OLDE_qOX1gpLCZiauTP2d8MkXPfhSKobaISpv2PEqSfaUHjyhvuJz6JiKTO5t_1lLyr3EjK6/s1600/ant1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7DYujrziWlFn0pSrzGgZ5BpYCG6dwdHVU32NGI3RbsCyvtzwQWIlav9dV0bhHVx4JYcf0OLDE_qOX1gpLCZiauTP2d8MkXPfhSKobaISpv2PEqSfaUHjyhvuJz6JiKTO5t_1lLyr3EjK6/s400/ant1.jpg" width="400" /></a></div>
<br />
Когда мы идем, делаем шаг, другой, то не задумываемся над тем, как синхронизированы наши ноги, какое движение в каждый момент времени должна выполнять одна нога по отношению к другой. Дело в том, что нейронные связи, ответственные за ходьбу у нас давно сформировались и постоянно подкрепляются ежедневными тренировками. Маленький ребенок, который еще только учится ходить находится на этапе формирования таких нейронных связей, он делает шаг за шагом, падает, поднимается, учитывает свои ошибки и снова пробует идти. Несомненно огромную роль в формировании таких взаимосвязей играет его наблюдение за тем, как ходят те, кто уже это умеет, однако научиться ходить он может и без этой визуальной информации.<br />
Давайте попробуем поставить себя на его место. Встаньте на месте и попытайтесь на время забыть, как это - идти. Формально мы знаем, что когда одна наша нога делает шаг, вторая выполняет роль опоры, одновременно немного сгибаясь как пружина, готовая повторить движение другой ноги. Попробуйте сделать несинхронизированные друг с другом шаги, например когда одна нога делает шаг и сделала его на 50% (находится в воздухе), начните такое же движение другой ногой. Скорее всего за такой попыткой последует падение или движение, направленное на то, чтобы его избежать. Варьюируя степень синхронизации ног (0..100%) можно убедиться, что часть таких попыток будет приводить к "топтанию на месте", часть - к движению с поворотом в одну из сторон и только один, узкий диапазон синхронизации ног, приведет к прямолинейной ходьбе.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq8QR8hHFtwc6wGuBzDB1GVpDRrz4tGdaDMx0EWjrmF8zUfX_0I4wGi1Nd_ubjsXrhGmSlogvPvTnWLW4bWn3d9tE5iLnBBtor-PpHbZiIZRlSl323QfLRBfFgPG47J-G53Tq9r6KvEgyK/s1600/DSC05807.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq8QR8hHFtwc6wGuBzDB1GVpDRrz4tGdaDMx0EWjrmF8zUfX_0I4wGi1Nd_ubjsXrhGmSlogvPvTnWLW4bWn3d9tE5iLnBBtor-PpHbZiIZRlSl323QfLRBfFgPG47J-G53Tq9r6KvEgyK/s400/DSC05807.JPG" width="400" /></a></div>
<br />
Конструкцию робота-муравья из книги мы оставили практически без изменений, однако в хвосте вместо датчика цвета мы установили гироскоп. Он понадобится для оценки степени отклонения от прямолинейного курса в процессе обучения нейронной сети.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPFrz4Ttxo-FSWXGPOIh8LKcLUEOTVupuzmqquqfQ1nIBrtZ-Y7rxSNJNJxh4toHU6ssym6QbOsTLCYYLsOSFUsC7TaoOrfl5qjoLh3zI7_dd_gn5UfjRPLKI0Bs7RI7z2qwvj1SsJgPIL/s1600/DSC05805.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPFrz4Ttxo-FSWXGPOIh8LKcLUEOTVupuzmqquqfQ1nIBrtZ-Y7rxSNJNJxh4toHU6ssym6QbOsTLCYYLsOSFUsC7TaoOrfl5qjoLh3zI7_dd_gn5UfjRPLKI0Bs7RI7z2qwvj1SsJgPIL/s400/DSC05805.JPG" width="400" /></a></div>
<br />
Нейронная сеть робота-муравья, которую мы будем обучать в этом проекте, будет действовать по следующему алгоритму:<br />
<ul style="text-align: left;">
<li>Пара моторов, которые управляют движениями ног робота-муравья могут быть рассинхронизированы в диапазоне 0..360 градусов. Разобьем этот интервал на 36 отрезков. Это мы сделаем только из экономии времени на обучение сети. можно работать и с 360 различными углами.</li>
<li>Каждый из 36 возможных углов между ходовыми моторами свяжем с нейроном сети. Так как изначально нейронная сеть не обучена, каждый из вариантов синхронизации ног равноценен. Запишем в каждый нейрон начальный вес - 1.</li>
<li>Цикл обучения нейронной сети начинается со случайного выбора нейрона с учетом его веса.</li>
<li>Выбрав нейрон, синхронизируем ноги робота-муравья в соответствии с углом, связанным с выбранным нейроном</li>
<li>После синхронизации запоминаем расстояние до препятствия впереди и угол разворота на гироскопе</li>
<li>Делаем несколько шагов вперед</li>
<li>Оцениваем, изменился ли угол, если он изменился несущественно (робот не отклонился от курса), проверяем сократилось ли расстояние до препятствия и насколько</li>
<li>Если робот продвинулся вперед - увеличиваем вес нейрона </li>
<li>Если робот не продвинулся вперед, то есть топчется на месте или пошел назад - уменьшаем вес нейрона, однако не менее чем до 1</li>
<li>Повторяем цикл обучения до тех пор, пока робот не будет выполнять шаги правильно и двигаться прямолинейно</li>
</ul>
<ul style="text-align: left;">
</ul>
Программу для робота мы написали на языке Python, выглядит она следующим образом:<br />
<br />
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b>Исходный код</b>: <input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Скрыть'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Показать'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 60px;" type="button" value="Показать" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">#!/usr/bin/env python3</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">from PIL import Image, ImageDraw, ImageFont</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">from ev3dev.ev3 import *</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">from time import sleep</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">import random</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorC = LargeMotor('outC')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorB = LargeMotor('outB')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">btn = Button()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">summ=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">rand=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">stopc=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">stopb=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorB.reset()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorC.reset()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">maxn=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">def PID(B,C):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> trig=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> triger=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> es1 = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> es2 = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u1 = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u2 = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Pk = 10</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> PD = 20</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopB = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopC = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while(stopB!=1 or stopC!=1):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if motorB.position>=0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> e1 = motorB.position%360 - B </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> e1 = -1*(abs(motorB.position)%360) - B</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if motorC.position>=0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> e2 = motorC.position%360 - C</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> e2 = -1*(abs(motorC.position)%360) - C</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u1 = e1 * Pk + PD * (e1 - es1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> u2 = e2 * Pk + PD * (e2 - es2)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u1 > 900): u1 = 900</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u2 > 900): u2 = 900</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u1 < -900): u1 = -900</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(u2 < -900): u2 = -900</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if abs(e1) <= 5:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.stop(stop_action='brake')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopB=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.run_forever(speed_sp=u1*(-1))</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if abs(e2) <= 5:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.stop(stop_action='brake')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopC=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.run_forever(speed_sp=u2*(-1))</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> es1 = e1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> es2 = e2</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">gy = GyroSensor('in2') </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">ir = InfraredSensor('in3') </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">ir.mode = 'IR-PROX' </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorC = LargeMotor('outC') </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorB = LargeMotor('outB') </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">ts = TouchSensor('in1')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">brain = []</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">for i in range(36):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain.append(1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">while True:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> summ=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for i in range(36):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> summ += brain[i]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> rand = random.randint(0,summ*1000)/1000</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> summ = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for i in range(36):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if summ < rand < summ + brain[i]:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> neuron = i</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> break</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> summ+=brain[i]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> sleep(1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> PID(0,neuron*10) </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> inf=ir.value()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> gir=gy.value()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> sleep(1) </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> b=motorB.position</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> c=motorC.position</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(ir.value()>=10 and ir.value()<45):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.run_forever(speed_sp=200)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.run_forever(speed_sp=200)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopb=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopc=0 </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while stopc==0 or stopb==0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if motorB.position>=b+360:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopb=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if motorC.position>=c+360:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopc=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.stop(stop_action='brake') </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.stop(stop_action='brake') </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if abs(gy.value()-gir)<=10:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if ir.value()-int(inf/2)>2:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain[neuron]+=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain[neuron]-=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if brain[neuron]<1:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain[neuron]=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print(neuron, brain[neuron]) </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> maxn=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> max=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for i in range(len(brain)):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if brain[i]>max:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> max=brain[i]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> maxn=i</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lcd = Screen()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> f =ImageFont.truetype('/usr/share/fonts/truetype/msttcorefonts/Arial.ttf', 75)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lcd.draw.text((3,0), str(maxn), font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> elif ir.value() <10: </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.run_forever(speed_sp= -400)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.run_forever(speed_sp= -400)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopb=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopc=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while stopc==0 or stopb==0: </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if motorB.position<=b-360:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopb=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if motorC.position<=c-360:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> stopc=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print("stop")</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.stop(stop_action='brake')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.stop(stop_action='brake')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if abs(gy.value()-gir)<=5:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if ir.value()-int(inf/2):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain[neuron]+=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain[neuron]-=3</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if brain[neuron]<1:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> brain[neuron]=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print(neuron, brain[neuron])</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> maxn=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> max=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for i in range(len(brain)):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if brain[i]>max:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> max=brain[i]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> maxn=i</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lcd = Screen()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> f =ImageFont.truetype('/usr/share/fonts/truetype/msttcorefonts/Arial.ttf', 75)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lcd.draw.text((3,0), str(maxn), font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if ir.value()>45:</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.run_forever(speed_sp=300)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.run_forever(speed_sp=300)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(btn.backspace):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.stop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.stop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> exit()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(btn.enter):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorB.stop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motorC.stop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> break</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">sleep(5)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">PID(0,maxn*10)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">while (not (btn.enter)): pass</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">print('dimonstracia')</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">for i in range(len(brain)):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print(i,brain[i])</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorB.run_forever(speed_sp=200)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorC.run_forever(speed_sp=200)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">while (not (btn.enter)): pass</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorB.run_forever(speed_sp=-200)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorC.run_forever(speed_sp=-200)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">while (not (btn.backspace)):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> pass</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorB.stop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">motorC.stop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">exit()</span><br />
<br /></div>
<br /></div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-33684558843656096792018-06-11T03:22:00.004-07:002018-06-11T04:18:33.835-07:00 Длинный хвост питона - часть 2<div dir="ltr" style="text-align: left;" trbidi="on">
В первой части проекта "<a href="http://karandashsamodelkin.blogspot.com/2018/05/1.html">Длинный хвост питона</a>" мы создали модель автономно управляемого транспортного средства, использующую машинное зрение и оснащенную бортовым одноплатным компьютером и камерой, которая двигалась по черной линии (трассе) с кратковременной остановкой на заданном расстоянии перед знаком "стоп".<br />
Во второй части мы поработаем над распознаванием знаков, предписывающих направление движения - "Влево", "Вправо", "Прямо", научимся проходить развилки трассы и улучшим алгоритм распознавания черной линии.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibfskMENs3VfOkb6M_puyHLzx2jq2d-C2D2hSgcWzqcfjsh6kRMQELYQJMHPaGIN0i9_-JdhQA5NJVV3rBrFvNk0ohM0VlalgyGIrN0grq-gwmiiEJz5brLadgcr97Csxs2nPefYHBc_2x/s1600/dhp2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="914" data-original-width="1600" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibfskMENs3VfOkb6M_puyHLzx2jq2d-C2D2hSgcWzqcfjsh6kRMQELYQJMHPaGIN0i9_-JdhQA5NJVV3rBrFvNk0ohM0VlalgyGIrN0grq-gwmiiEJz5brLadgcr97Csxs2nPefYHBc_2x/s400/dhp2.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Полевые испытания модели в первой части проекта показали, что она оказалась слишком масштабной для удобной отладки алгоритмов в условиях квартиры, поэтому мы собрали более компактную модель, имеющую меньшие радиусы поворота. Ходовой мотор теперь один и отсутствует подвеска, которая не играла особой роли в решаемой нами задаче.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja7HwGLBHwZR84OBa-Q0LHzcpOROvtdvTH3BDiKk7WLQ6AyjqCpB_hYa2lswthAx9imUgh_5ANVtPW8GzVytY2VnZB9wsTclEuCLDCqDejoHnH4HX09o9RO9VUGk4nurmb0wbPbtpfPY2u/s1600/DSC05439.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja7HwGLBHwZR84OBa-Q0LHzcpOROvtdvTH3BDiKk7WLQ6AyjqCpB_hYa2lswthAx9imUgh_5ANVtPW8GzVytY2VnZB9wsTclEuCLDCqDejoHnH4HX09o9RO9VUGk4nurmb0wbPbtpfPY2u/s400/DSC05439.JPG" width="400" /></a></div>
<br />
Алгоритм распознавания знаков "Влево", "Вправо", "Прямо" заключается в следующем:<br />
<ul>
<li>отрезаем правую часть кадра (знак должен быть только справа от дороги)</li>
<li>накладываем цветовую маску, отбрасывая все не синие объекты</li>
<li>проверяем, что в кадре есть синие объекты</li>
<li>ищем среди объектов эллипсы встроенной функцией OpenCV</li>
<li>если найден эллипс с диаметром, лежащем в заданном диапазоне (знак на удобном для распознавания расстоянии) - выполняем сравнение с сохраненными образцами</li>
<li>результат сравнения с наиболее "похожим" знаком накапливается, пока модель движется на удобном для распознавания расстоянии от знака</li>
<li>на основе накопленной информации принимается решение о направлении движения на следующей развязке</li>
</ul>
<div>
Пример прохождения трассы (вид из бортовой камеры):</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiImjDF4SZNL_Na_72utddAlcGiBDpu9DQBZzVu4_9ydLfTfRKVUzpkERV37yDr4FOfASHbg-BWGae02A7bRT6JVYCpjnvBeUmxdW6-VXf0Nv01vFF6AKWiJwy2YPH-zaf7KNzk4ba7S1NV/s1600/ezgif-4-b6a157a212.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiImjDF4SZNL_Na_72utddAlcGiBDpu9DQBZzVu4_9ydLfTfRKVUzpkERV37yDr4FOfASHbg-BWGae02A7bRT6JVYCpjnvBeUmxdW6-VXf0Nv01vFF6AKWiJwy2YPH-zaf7KNzk4ba7S1NV/s320/ezgif-4-b6a157a212.gif" width="320" /></a></div>
<div>
<br /></div>
<div>
Обновленный алгоритм распознавания черной линии:</div>
<div>
<ul style="text-align: left;">
<li>берем очередной кадр из объекта в памяти</li>
<li>отрезаем от кадра полоску высотой 20 пикселей в нижней его части</li>
<li>переводим в цветовое пространство HSV</li>
<li>используя функцию cv2.findContours проводим контурный анализ полоски, выделяя объекты</li>
<li>отбрасываем объекты со слишком малой площадью, которые не могут быть линиями</li>
<li>используя функцию вычисления моментов cv2.moments, вычисляем горизонтальное смещение каждого из оставшихся объектов относительно центра</li>
<li>выбираем из найденных линии ту, по которой мы продолжим движение, опираясь на распознанные знаки </li>
<li>передаем данные о смещении относительно линии процессу ПИД-регулятора</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/lv7zsBiRFdI/0.jpg" src="https://www.youtube.com/embed/lv7zsBiRFdI?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br /></div>
</div>
<div>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b>Исходный код программы для робота</b>: <input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Close'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Open'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 60px;" type="button" value="Open/Close" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#!/usr/bin/env python3</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">from flask import Flask, render_template, Response</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import serial, time</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import cv2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import threading</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">import numpy as np</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">from imutils.video import WebcamVideoStream</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">port = "/dev/ttyACM0"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">ser = serial.Serial(port , 115200, timeout = 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">time.sleep(5)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">cx = []</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">speed_go = 255</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">porog = 1000</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">porog1 = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">porog2 = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">speed_blue = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">speed = 255</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">K = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">see_blue = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">x = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">out_old = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">i_main = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">i_mail2arduino = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">i_see_sign = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">i_camera2inet = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">time_main = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">time_mail2arduino = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">time_see_sign = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">time_camera2inet = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">fps_main = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">fps_mail2arduino = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">fps_see_sign = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">fps_camera2inet = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pixel_ellips = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pixel_ellips_blue = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">class sign:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def __init__(self, way_in):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.sign_img = cv2.imread(way_in)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.sign_img_hsv = cv2.cvtColor(self.sign_img, cv2.COLOR_BGR2HSV)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> self.sign_img_inRange = cv2.inRange(self.sign_img_hsv, (0, 0, 0), (254, 254, 254))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">sign_right = sign("/var/www/html/sign_right.png")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">sign_left = sign("/var/www/html/sign_left.png")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">sign_forward = sign("/var/www/html/sign_forward.png")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">sign_direct = sign_right</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">direct = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">cap = WebcamVideoStream(src=0).start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">for i in range(5): frame = cap.read()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">frame = cap.read()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">frame_gray = cv2.inRange(hsv[420:,:, :], (0, 0, 0), (255, 255, 100))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">frame_red = cv2.inRange(hsv[:, 320:, :], (0, 150, 30), (10, 255, 80))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">frame_blue = cv2.inRange(hsv[:, 320:, :], (100, 220, 60), (150, 255, 255))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">cv2.imwrite('/var/www/html/dgip_frame_all.png', frame)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">def mail2arduino_pr1():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Start arduino thread")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global K, x, out_old, speed_go, speed, i_mail2arduino, fps_mail2arduino, time_mail2arduino</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while 1:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> local_x = x</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(local_x >= 0): out = "L"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else: out = "R"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> local_x = abs(int(local_x*K))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(local_x > 90): local_x = 90</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(local_x < 10): out += "0" + str(local_x)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else: out += str(local_x)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed >= 100): out += "F" + str(speed)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> elif(speed >= 10): out += "F0" + str(speed)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else: out += "F00" + str(speed)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(out != out_old):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ser.write(out.encode())</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_out = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_out > 2):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ser.write("0000000".encode())</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_out = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> out_old = out</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_mail2arduino += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_mail2arduino > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_mail2arduino = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> fps_mail2arduino = i_mail2arduino</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_mail2arduino = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">def image2jpeg(image):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ret, jpeg = cv2.imencode('.jpg', image)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return jpeg.tobytes()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">def camera2inet_pr2():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Start inet thread")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global frame_gray, frame, frame_red, hsv, i_camera2inet, time_camera2inet, fps_camera2inet, direct, pixel_ellips_blue</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global fps_main, fps_see_sign, fps_mail2arduino, fps_camera2inet, pixel_ellips, see_red, sign_direct</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global porog1, porog2, see_blue</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> app = Flask(__name__)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> @app.route('/')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def index():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return render_template('index.html')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def gen_gray():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_inet = cv2.inRange(hsv[460:, :, :], (0, 0, 0), (150, 255, 80))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.putText(frame_inet,"fps: "+str(fps_main)+" "+str(fps_see_sign)+" "+str(fps_mail2arduino), (0,10), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frameinet = image2jpeg(frame_inet)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def gen_frame():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_inet = frame</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frameinet = image2jpeg(frame_inet)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def gen_red():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.putText(frame_red,"red_see: "+str(see_red), (0,10), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.putText(frame_red,"red_pixel: "+str(pixel_ellips), (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frameinet = image2jpeg(frame_red)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def gen_direct():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frameinet = image2jpeg(sign_direct)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def gen_blue():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.putText(frame_blue,"direct: "+str(direct), (0,10), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.putText(frame_blue,"pixel_ellips_blue: "+str(pixel_ellips_blue), (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frameinet = image2jpeg(frame_blue)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> @app.route('/video_frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def video_frame():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return Response(gen_frame(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> @app.route('/video_line')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def video_line():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return Response(gen_gray(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> @app.route('/video_red')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def video_red():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return Response(gen_red(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> @app.route('/video_direct')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def video_direct():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return Response(gen_direct(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> @app.route('/video_blue')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> def video_blue():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return Response(gen_blue(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time.sleep(0.3)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_camera2inet += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_camera2inet > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_camera2inet = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> fps_camera2inet = i_camera2inet</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_camera2inet = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> app.run(host='0.0.0.0', debug=False,threaded=True)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">def see_sign_pr3():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print("Start see red thread")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> global K, see_blue, pixel_ellips, speed_blue, pixel_ellips_blue, see_red, hsv, frame_red, i_see_sign, time_see_sign, fps_see_sign, direct, sign_direct, frame_blue</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> print(frame_red.dtype)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_last_see_red = time.time()-10</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> search_red = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_last_see_blue = time.time()-10</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> search_blue = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_see_sign_forward = time.time()-10</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pre_direct = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while 1:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_red = cv2.inRange(hsv[:, 320:, :], (10, 10, 30), (10, 255, 255))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_blue = cv2.inRange(hsv[:, 320:, :], (90, 200, 50), (150, 255, 255))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(search_red):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_copy = frame_red.copy()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _, con, hierarchy = cv2.findContours(frame_copy, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for i in con:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if len(i)>10:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ellipse = cv2.fitEllipse(i)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _, y1 = ellipse[0]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _, y2 = ellipse[1]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pixel_ellips = abs(y2-y1)*0.3 + 0.7 * pixel_ellips</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(pixel_ellips > 1000):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pixel_ellips = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> see_red = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> search = False</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_last_see_red = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.ellipse(frame_red, ellipse, (255,0,0), 2)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else: see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> break</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_last_see_red <= 10):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> see_red = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_last_see_red > 10):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> K = 0.1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_last_see_red >= 12):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> K = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_last_see_red >= 20):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> search_red = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(search_blue and np.sum(frame_blue)>1200000):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> see_blue = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_copy = frame_blue.copy()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _, con, hierarchy = cv2.findContours(frame_copy, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> max_con = []</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(len(con)):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if len(con[i])>len(max_con):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> max_con = con[i]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ellipse = cv2.fitEllipse(max_con)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x1, y1 = ellipse[0]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x2, y2 = ellipse[1]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> t1 = ((int(x1)-int(x2/2)), (int(y1)-int(y2/2)))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> t2 = ((int(x1)+int(x2/2)), (int(y1)+int(y2/2)))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pixel_ellips_blue = abs((int(y1)-int(y2/2))-(int(y1)+int(y2/2)))*0.15 + 0.85 * pixel_ellips_blue</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cv2.rectangle(frame_blue, t1, t2, (100, 100, 100), 3)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(pixel_ellips_blue < 90 and pixel_ellips_blue > 70):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_last_see_blue = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pre_sign_direct = frame_blue[int(y1)-int(y2/2):int(y1)+int(y2/2), int(x1)-int(x2/2):int(x1)+int(x2/2)]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(pre_sign_direct.shape[0]>0 and pre_sign_direct.shape[1]>0): sign_direct = cv2.resize(pre_sign_direct, (64, 64), interpolation=cv2.INTER_AREA)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> sum_matr = [np.sum(sign_direct*sign_left.sign_img_inRange),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> np.sum(sign_direct*sign_forward.sign_img_inRange),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> np.sum(sign_direct*sign_right.sign_img_inRange)]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(np.argmax(sum_matr) == 2):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> direct += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> elif(np.argmax(sum_matr) == 0):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> direct -= 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> elif(np.argmax(sum_matr) == 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> direct == 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> K = 0.1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_see_sign_forward = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> see_blue = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_last_see_blue > 15):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> direct = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_see_sign_forward > 15):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> K = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_see_sign += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_see_sign > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_see_sign = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> fps_see_sign = i_see_sign</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_see_sign = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr2 = threading.Thread(target=camera2inet_pr2)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr2.daemon = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr2.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">time.sleep(5)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr1 = threading.Thread(target=mail2arduino_pr1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr1.daemon = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr1.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr3 = threading.Thread(target=see_sign_pr3)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr3.daemon = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">pr3.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">while 1:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame = cap.read()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> frame_gray = cv2.inRange(hsv[460:, :, :], (0, 0, 0), (150, 255, 80))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(np.sum(frame_gray) > porog and see_red != 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(see_blue != 1): speed = 255</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else: speed = 120</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cx.clear()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> min = 1000</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> _, contours, hierarchy = cv2.findContours(frame_gray.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for i in contours:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(i is not None):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> area = cv2.contourArea(i)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(area>=250):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> M = cv2.moments(i)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pre_x = int(M['m10']/M['m00'])</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> cx.append(pre_x)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(direct == 0):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(abs(pre_x-320)<min):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> min = abs(pre_x-320)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x = 320 - pre_x</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> elif(direct > 0):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(abs(pre_x-640)<min):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> min = abs(pre_x-640)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x = 320 - pre_x</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> elif(direct < 0):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(pre_x<min):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> min = pre_x</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x = 320 - pre_x</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> speed = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_main += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(time.time() - time_main > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> time_main = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> fps_main = i_main</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> i_main = 0</span></div>
</div>
</div>
</div>
</div>
<div>
<br /></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com2tag:blogger.com,1999:blog-4279357166628593719.post-50526858068497502642018-06-03T00:30:00.002-07:002018-06-04T02:54:55.177-07:00Страшная снаружи, добрая внутри<div dir="ltr" style="text-align: left;" trbidi="on">
После установки натяжного потолка в одной из комнат нам пришлось распрощаться с 5-рожковой люстрой 5x100 Вт и <a href="https://xn--80ajjimbfa0b5a.xn--p1ai/vyklyuchateli-s-du-sapfir-nootekhnika.html">диммером "Сапфир"</a> c плавным управлением яркостью с любого пульта ДУ. Лампы накаливания сильно греются и потолку от них нехорошо, поэтому мы начали искать замещающее решение с использованием светодиодных ламп. Света в сумме хотелось не меньше, такого же лампово-теплого по спектру и по-прежнему подвластного пульту.<br />
Оставлю за кадром решения, которые мы рассматривали, но в итоге направления осталось два:<br />
<ul style="text-align: left;">
<li>диммер для светодиодных ламп и использование недешевых диммируемых ламп</li>
<li>некий китайский контроллер, монтируемый в люстру и позволяющий последовательно зажигать до 3 каналов, повторным нажатием выключателя. Главный его недостаток - он не помнит установленным последним уровень освешенности. Достоинство решения - использование любых светодиодных ламп.</li>
</ul>
<div>
Параллельно с этим руки зачесались спаять что-нибудь самодельно-кустарное, получив все желаемые функции быстро и уже начать пользоваться люстрой, продолжая поиск более красивого и функционального аналога.</div>
<div>
<br /></div>
<div>
Итак, для очередного проекта выходного дня нам понадобились:</div>
<div>
<ul style="text-align: left;">
<li>4 настенных светильника для ванной комнаты. Для самоделки удобны тем, что будучи соединенными попарно винтами образуют корпуса для электроники между подставками</li>
<li>4 светодиодные лампы с патроном e27 на 5, 10, 20 и 20 Вт</li>
<li>алюминиевая трубка, алюминиевая полоса, винты и гайки м4</li>
<li>клеммы винтовые 2,5мм, провода</li>
<li>зарядка от телефона USB, которую мы лишили корпуса</li>
<li>arduino nano</li>
<li>4 реле модуля, управляемых 5В логикой</li>
<li>ИК-приемник VS1838B</li>
<li>микродинамик</li>
</ul>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVHPlLCoTYPnEjA7rT0IjFfWz92Q3bRCDJGscC4dI-mYxy91djK_hfktxu27DEs17v6haJUKg9uMiZhk5r6i11kO_mKGUTVekGP6eIEBmoxtYuy61f3oBHZ1XQouGy1Z_P9Pg5EK6TJKVa/s1600/DSC05417_.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVHPlLCoTYPnEjA7rT0IjFfWz92Q3bRCDJGscC4dI-mYxy91djK_hfktxu27DEs17v6haJUKg9uMiZhk5r6i11kO_mKGUTVekGP6eIEBmoxtYuy61f3oBHZ1XQouGy1Z_P9Pg5EK6TJKVa/s400/DSC05417_.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Собранная люстра обладает следующими функциями:</div>
<div>
<ul style="text-align: left;">
<li>включение-выключение обычным клавишным выключателем - вся электроника "нормально-разомкнута"</li>
<li>управление с любого пульта ДУ (используется 2 кнопки - прибавить яркость, убавить яркость)</li>
<li>11 уровней яркости: 5Вт, 10Вт, 15Вт(5+10), 20Вт, 25Вт(20+5), 30 Вт(20+10), 35Вт(20+10+5), 40Вт(20+20), 45Вт(20+20+5), 50Вт(20+20+10), 55Вт(20+20+10+5)</li>
<li>"плавный старт" - если в люстре в последний раз были включены, например, 3 лампы, то при повторном включении они будут последовательно включены с интервалом в 2 секунды - по нарастанию их мощности - чтобы не ослепить входящего в комнату человека</li>
<li>обучение под любой пульт ДУ - троекратное нажатие последовательности любых трех кнопок на любом пульте вводит люстру в режим обучения - издается звуковой сигнал. В режиме обучения ожидается нажатие любых двух кнопок - они будут запомнены как новые кнопки управления яркостью</li>
<li>запоминание установленного уровня яркости в энергонезависимой памяти через 30 сек после последней регулировки</li>
<li>автовыключение света через 6 часов</li>
<li>звуковое подтверждение всех операций по регулировке, обучению, сохранении настроек</li>
</ul>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnx6PMBqv0ePpu1GnFXCE9Vmas0yHhqgPFmUYwLHULFjkAy1HNHyQamWWXg5oYHb6Swur5FkDxEv_pP8WCiLC0fiHFBAa1qAXDJY-z_B9FUK2uQ7cnbQNu_rkCn4klGZ45bZxMI-gQ-Ilw/s1600/ezgif-2-ff59fc7ceb.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnx6PMBqv0ePpu1GnFXCE9Vmas0yHhqgPFmUYwLHULFjkAy1HNHyQamWWXg5oYHb6Swur5FkDxEv_pP8WCiLC0fiHFBAa1qAXDJY-z_B9FUK2uQ7cnbQNu_rkCn4klGZ45bZxMI-gQ-Ilw/s400/ezgif-2-ff59fc7ceb.gif" width="400" /></a></div>
<div>
<br /></div>
<div>
Код программы выглядит так:</div>
<div>
<br /></div>
<br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#include <IRremote.h> </span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#include <EEPROM.h></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int relay1 = 5; // 5W</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int relay2 = 6; // 10W</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int relay3 = 7; // 20W</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int relay4 = 8; // 20W</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int buzzer = 9; // speaker or led</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">unsigned long history[9];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">unsigned long power_up = 0xFFA05F;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">unsigned long power_down = 0xFF20DF;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">unsigned long timer = millis();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">boolean not_rec = false;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int receiverPin = 11; </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">IRrecv irrecv(receiverPin);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">decode_results results;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">byte power;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int mem_addr = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">long EEPROMReadlong(long address) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> long four = EEPROM.read(address);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> long three = EEPROM.read(address + 1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> long two = EEPROM.read(address + 2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> long one = EEPROM.read(address + 3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">void EEPROMWritelong(int address, long value) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> byte four = (value & 0xFF);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> byte three = ((value >> 8) & 0xFF);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> byte two = ((value >> 16) & 0xFF);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> byte one = ((value >> 24) & 0xFF);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROM.write(address, four);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROM.write(address + 1, three);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROM.write(address + 2, two);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROM.write(address + 3, one);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">void set_power(int p) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> timer = millis();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> not_rec = true;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Power: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(p);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> boolean r1, r2, r3, r4;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 40) {r4 = LOW; p -= 20;} else r4 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 20) {r3 = LOW; p -= 20;} else r3 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 10) {r2 = LOW; p -= 10;} else r2 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 5) {r1 = LOW; p -= 5;} else r1 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay1, r1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay2, r2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay3, r3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay4, r4); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 5W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 10W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 20W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 20W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r4); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">void init_power(int p) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> int init_delay = 2000;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Init power: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(p);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> boolean r1, r2, r3, r4;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 40) {r4 = LOW; p -= 20;} else r4 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 20) {r3 = LOW; p -= 20;} else r3 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 10) {r2 = LOW; p -= 10;} else r2 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (p >= 5) {r1 = LOW; p -= 5;} else r1 = HIGH;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> boolean light = false;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay1, r1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (!r1) light = true;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 5W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (light && !r2) delay(init_delay);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay2, r2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (!r2) light = true;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 10W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (light && !r3) delay(init_delay);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay3, r3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (!r3) light = true;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 20W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (light && !r4) delay(init_delay);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay4, r4); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.print("Relay 20W: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(!r4); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">void learn (unsigned long code) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(100);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for (int i=0; i<8; i++) history[i] = history[i+1];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[8] = code;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (history[0] == history[3] && history[0] == history[6] &&</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[1] == history[4] && history[1] == history[7] &&</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[2] == history[5] && history[2] == history[8] &&</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[0] != history[1] && history[1] != history[2]) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("Learn mode enabled"); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 880, 200); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.resume();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while (!irrecv.decode(&results));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 523, 200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power_up = results.value;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(100); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.resume();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while (!irrecv.decode(&results));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 440, 200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power_down = results.value;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(100); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.resume();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROMWritelong(mem_addr+1,power_up);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROMWritelong(mem_addr+5,power_down); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">} </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">void setup() {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(relay1, OUTPUT);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(relay2, OUTPUT);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(relay3, OUTPUT);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(relay4, OUTPUT);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay1, HIGH);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay2, HIGH);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay3, HIGH);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(relay4, HIGH);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(buzzer, OUTPUT); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 659, 500);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.begin(9600);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power = EEPROM.read(mem_addr);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> init_power(int(power));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.enableIRIn();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for (int i=0; i<9; i++) history[i] = i;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power_up = EEPROMReadlong(mem_addr+1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power_down = EEPROMReadlong(mem_addr+5);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">void loop() {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (irrecv.decode(&results)) { </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(results.value == power_up){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (power < 55) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 523, 200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power += 5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> set_power(int(power));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 329, 200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(results.value == power_down){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (power > 5) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 440, 200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power -= 5;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> set_power(int(power));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 329, 200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> learn (results.value);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.resume();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (not_rec && millis()-timer > 30000) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 262, 100);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> EEPROM.write(mem_addr, power); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("Save to EEPROM: ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(power);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> timer = millis();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> not_rec = false; </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (millis()-timer > 6*60*60*1000) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> power = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> set_power(int(power));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 659, 1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> tone(buzzer, 440, 1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-6670894311716035212018-05-06T05:20:00.002-07:002018-05-06T06:23:24.878-07:00Длинный хвост питона - часть 1<div dir="ltr" style="text-align: left;" trbidi="on">
Последние полтора года наша команда изучает Python и почти все наши проекты, использующие LEGO Mindstorms EV3 в качестве платформы, были разработаны с использованием этого языка программирования. Изучение Python и, параллельно, ОС Linux, велось не случайно, а имело далеко идущие планы. Дело в том, что Питон должен стать "переходным мостиком", протянув свой длинный хвост между LEGO-роботами и более серьезной робототехникой, в которой компонентов от LEGO должно становиться все меньше и меньше.<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3KqGZUW_wPJaxPQCGvoNKPsI_x_A8d1BEXk4TpSX4qSzMSDM6CWZ7NzzceYHaGsqMg8etuGCq7yLFViN68JNbOgjU0IhBED4sLrlvenLs_nCPnqr1kyFY6XJGqdo8E3Zi4j8eUulUH3Dd/s1600/%25D0%2594%25D0%25BB%25D0%25B8%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9+%25D1%2585%25D0%25B2%25D0%25BE%25D1%2581%25D1%2582+%25D0%25BF%25D0%25B8%25D1%2582%25D0%25BE%25D0%25BD%25D0%25B0+-+%25D1%2587%25D0%25B0%25D1%2581%25D1%2582%25D1%258C+1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="908" data-original-width="1600" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3KqGZUW_wPJaxPQCGvoNKPsI_x_A8d1BEXk4TpSX4qSzMSDM6CWZ7NzzceYHaGsqMg8etuGCq7yLFViN68JNbOgjU0IhBED4sLrlvenLs_nCPnqr1kyFY6XJGqdo8E3Zi4j8eUulUH3Dd/s400/%25D0%2594%25D0%25BB%25D0%25B8%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9+%25D1%2585%25D0%25B2%25D0%25BE%25D1%2581%25D1%2582+%25D0%25BF%25D0%25B8%25D1%2582%25D0%25BE%25D0%25BD%25D0%25B0+-+%25D1%2587%25D0%25B0%25D1%2581%25D1%2582%25D1%258C+1.jpg" width="400" /></a></div>
<br /></div>
<div>
Задача, которую мы начнем решать в рамках этого проекта - создание модели автономно управляемого транспортного средства, использующего машинное зрение. В первой части проекта, модель автомобиля, оснащенная бортовым одноплатным компьютером и камерой, должна будет двигаться по черной линии (трассе) с кратковременной остановкой на заданном расстоянии перед знаком "стоп".<br />
Продвинутый читатель возможно обратит внимание, что решаемая задача в чем-то схожа с описанной в регламенте состязания ВРО "Автотранспортные интеллектуальные робототехнические системы" и будет несомненно прав. Однако следует заметить, что мы не готовимся к соревнованиям, мы решаем интересные задачи в рамках самообразования. Использовать или нет опубликованный нами код в соревновательной плоскости - дело вашей совести.<br />
<br />
Конструкция модели автомобиля, которую мы будем использовать, во многом повторяет модель LEGO Technic #9398, имеет полноприводное шасси и рулевой сервомотор.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyPFRbbdCNpW2zzWl-RCJIPAFBw1P-C6ANh-G0PPr3GbQ9-rusGKHtmaV69_IfSkHiJUbI48tw3yDaAsA8Zi4r2wgbWTYtJddZMdyXXELeqga4iVEX6f9S9zbgMbiFSNEy4JrMBSmg8BAf/s1600/Ane2DvtLBZE.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1068" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyPFRbbdCNpW2zzWl-RCJIPAFBw1P-C6ANh-G0PPr3GbQ9-rusGKHtmaV69_IfSkHiJUbI48tw3yDaAsA8Zi4r2wgbWTYtJddZMdyXXELeqga4iVEX6f9S9zbgMbiFSNEy4JrMBSmg8BAf/s400/Ane2DvtLBZE.jpg" width="400" /></a></div>
<br /></div>
<div>
В проекте мы снова будем использовать Raspberry Pi, а вот в качестве контроллера двигателей, роль которого в прошлом проекте "<a href="http://karandashsamodelkin.blogspot.ru/2018/03/blog-post_10.html">Следуй за белым кроликом</a>" выполнял LEGO Mindstroms EV3, применим Arduino с установленным Adafruit Motor Shield. C LEGO Technic двигателями постоянного тока все понятно, они штатно подключаюся к клеммам M1 и M2 шилда и управляются функциями изменения скорости и направления вращения.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoARe7kHYiiy7zm-kHOnbrFPJ3Pyrmd-4_nf3dwt0__GDQOKd3xTsUwF-SKFgWFctPVtsQzXKEuGV-JaT3L71h9ZxR1R6QKGk2PtGC1Cov2S97HDOhRcQGNRmrlt1LpOLyvcXbGw5fkFpc/s1600/DK_Motorshield_V1_Top_Angle_B-3-800-600-80.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoARe7kHYiiy7zm-kHOnbrFPJ3Pyrmd-4_nf3dwt0__GDQOKd3xTsUwF-SKFgWFctPVtsQzXKEuGV-JaT3L71h9ZxR1R6QKGk2PtGC1Cov2S97HDOhRcQGNRmrlt1LpOLyvcXbGw5fkFpc/s320/DK_Motorshield_V1_Top_Angle_B-3-800-600-80.jpg" width="320" /></a></div>
<br />
А вот с LEGO сервомотором пришлось поэкспериментировать. Как оказалось, управляется он посредством ШИМ по двум средним проводам, крайние же обеспечивают питание. Соответственно подключить его можно точно также как обычный DC-мотор к, например, клеммам M3, однако необходимо дополнительно обеспечить ему питание 9В, которое можно взять с клемм питания шилда PWR_EXT. Для управления углом поворота сервомотора используется обычная ШИМ-модуляция, соответственно встроенные в библиотеку Adafruit Motor Shield функции для управления скоростью и направлением вращения DC-мотора начинают управлять углом поворота сервомотора.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisz212Po0WIO-HSXMC9VIXCPpfS4DQIz6ojsaS_lvQaHsA940otzTTUZ5z6ZqWQ5CzBOWixN03friIhnrxN-mEq_WMA5yKiNoeXqPoWJRK6URLlHF_sNhCLYVcjVSHhCvgK1tliOulSWn5/s1600/88004_main.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="557" data-original-width="690" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisz212Po0WIO-HSXMC9VIXCPpfS4DQIz6ojsaS_lvQaHsA940otzTTUZ5z6ZqWQ5CzBOWixN03friIhnrxN-mEq_WMA5yKiNoeXqPoWJRK6URLlHF_sNhCLYVcjVSHhCvgK1tliOulSWn5/s320/88004_main.jpg" width="320" /></a></div>
<br />
Как вы уже наверное успели заметить на фото выше - мы используем новую камеру - это камера Sony Playstation Eye. Ее основные преимущества - высокая частота кадров (до 180 fps), достаточно широкий, изменяемый физическим регулятором угол зрения и отличная поддержка со стороны Linux.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRW85uIaVQvS70CJYJXCtLpJmjqEDEjqUon2oOGigAU4YaoYYkG9rILT6FTUma701wx4KSGHN5VJa7qf0SwDvRy1GJrJNe3Zd0C9gNoT-62UFYc9ASqbZDiofso36lcvNliI5jG0QMghTR/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="614" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRW85uIaVQvS70CJYJXCtLpJmjqEDEjqUon2oOGigAU4YaoYYkG9rILT6FTUma701wx4KSGHN5VJa7qf0SwDvRy1GJrJNe3Zd0C9gNoT-62UFYc9ASqbZDiofso36lcvNliI5jG0QMghTR/s320/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" width="320" /></a></div>
<br />
Основные моменты, которые мы проработаем в первой части проекта:<br />
<ul style="text-align: left;">
<li>Организуем передачу данных между Raspberry Pi и Arduino, используя помехозащищенный "протокол", основанный на передаче текстовых строк</li>
<li>Настроим многопоточную обработку данных для разумного распределения вычислительных ресурсов</li>
<li>Запустим веб-трансляцию обработанного видеопотока для визуального мониторинга прохождения трассы</li>
<li>Научимся распознавать один знак - "Стоп", расположенный справа от дороги и остановку на заданном расстоянии до него.</li>
</ul>
Для взаимодействия Raspberry Pi и Arduino мы используем стандартное serial-соединение поверх USB и соответствующие библиотеки с обоих сторон. Так как нам нужно передавать различные данные - скорость и направление вращения ходового мотора и угол поворота сервомотора, то просто передавать число через serial не выйдет - принимающая сторона должна понимать что она получает. Мы организовали передачу пакета данных в виде текстовой строки в формате "L90F255", где:<br />
<ul style="text-align: left;">
<li>первый символ L/R - указывает направление поворота рулевого сервомотора</li>
<li>следующие два символа - угол поворота рулевого сервомотора в данном направлении, в диапазоне 0..90</li>
<li>четвертый символ - F/B - направление вращение ходового мотора (вперед-назад)</li>
<li>следующие три символа - скорость вращения ходовых моторов в данном направлении, в диапазоне 0..255.</li>
</ul>
Последний переданный пакет (строка) запоминается, и новый пакет, чтобы не забивать канал передачи данных, передается только при изменении углов/скоростей, либо раз в секунду подтверждается повторением, если последние переданные угол и скорость все еще актуальны. Необходимость в подтверждении связана с реализацией на принимающей стороне автоматического отключения двигателей, если за последние 3 секунды не приходило никаких "правильных" пакетов. Это очень удобно - можно прерывать программу на Raspberry Pi не опасаясь что Arduino продолжит крутить двигателями в соответствии с последней переданной командой.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-ooliHiTuQoiW-BXjzVAwgnxc_AGDGkMGjO_Aldz7-S1eqEehqurlqgmzp54jBKB2KHK7WMw0xM9vPWGZ0oV8DnWTpZrEATFqHydv8GGGgCEW4DVWvhfAFEMmALIH51PebJnUgpGAP8o8/s1600/HDV_0429.MP4_snapshot_00.19_%255B2018.05.06_17.20.38%255D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-ooliHiTuQoiW-BXjzVAwgnxc_AGDGkMGjO_Aldz7-S1eqEehqurlqgmzp54jBKB2KHK7WMw0xM9vPWGZ0oV8DnWTpZrEATFqHydv8GGGgCEW4DVWvhfAFEMmALIH51PebJnUgpGAP8o8/s400/HDV_0429.MP4_snapshot_00.19_%255B2018.05.06_17.20.38%255D.jpg" width="400" /></a></div>
<br />
На стороне Raspberry Pi у нас выполняется целый ряд задач, каждая из которых должна работать "в своем темпе", не тормозя работу остальных:<br />
<ul style="text-align: left;">
<li>взаимодействие с Arduino</li>
<li>чтение данных с камеры в памяти</li>
<li>анализ нижней части кадра, поиск линии, формирование отклонения от линии</li>
<li>ПИД регулирование (ошибка - отклонение от линии, управляющее воздействие - угол поворота рулевого сервомотора)</li>
<li>анализ правой части кадра, поиск знака "стоп"</li>
<li>трансляция видеопотока, формирующегося из нижней части кадров при поиске линии</li>
</ul>
Для параллельного выполнения задач в программе на стороне Raspberry Pi используется модуль threading.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNeUYiqDA7W2zqS1FO5Frw1w_x9DBrg32X2ltJZW6EQoImLwyi6nZNTfZFZqf2xwU_UBpdKw3bLGFCq2i8Lx9zy5IVd-ScloVjhLCrsC78zZucQAqDsWQh-3UjzcZMr-ZgXQ0TwMZ7nuy/s1600/HDV_0442.MP4_snapshot_00.20_%255B2018.05.06_13.12.11%255D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNeUYiqDA7W2zqS1FO5Frw1w_x9DBrg32X2ltJZW6EQoImLwyi6nZNTfZFZqf2xwU_UBpdKw3bLGFCq2i8Lx9zy5IVd-ScloVjhLCrsC78zZucQAqDsWQh-3UjzcZMr-ZgXQ0TwMZ7nuy/s400/HDV_0442.MP4_snapshot_00.20_%255B2018.05.06_13.12.11%255D.jpg" width="400" /></a></div>
<br />
Веб-трансляция видеопотока, формирующегося в ходе анализа положения линии относительно модели автомобиля, происходит с использованием модуля flask. Конечно, использование wi-fi дает некоторую задержку при трансляции, но при невысокой скорости движения это не так важно. Гораздо важнее иметь возможность "видеть как робот", понимать на каком участке трассы какие есть проблемы с распознаванием линии (засветка, радиусы поворота и т.п.).<br />
<br />
Для поиска знака "стоп" и остановки перед ним на заданном расстоянии мы будем использовать более умный алгоритм, чем используемый ранее в проекте "<a href="http://karandashsamodelkin.blogspot.ru/2018/03/blog-post_31.html">Подражая белому кролику"</a>. он состоит в следующем:<br />
<ul style="text-align: left;">
<li>отрезаем правую часть кадра (знак должен быть только справа от дороги)</li>
<li>накладываем цветовую маску, отбрасывая все не красные объекты</li>
<li>ищем в оставшихся в кадре объектах эллипсы встроенной функцией OpenCV</li>
<li>если найден эллипс с диаметром, лежащем в заданном диапазоне (знак на заданном расстоянии) - остановка на 10 секунд, после чего следующие 10 секунд движения алгоритм поиска знака не выполняется</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/nNswYYVFMmc/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/nNswYYVFMmc?feature=player_embedded" width="320"></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Исходный код программы для Raspberry Pi:</div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">#!/usr/bin/env python3</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">from flask import Flask, render_template, Response</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">import serial, time</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">import cv2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">import threading</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">import numpy as np</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">from imutils.video import WebcamVideoStream</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">port = "/dev/ttyACM0"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">ser = serial.Serial(port , 115200, timeout = 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">time.sleep(5)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">speed_go = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">porog = 500</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">speed = 155</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">K = 2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">x = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">out_old = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">i_main = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">i_mail2arduino = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">i_see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">i_camera2inet = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">time_main = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">time_mail2arduino = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">time_see_red = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">time_camera2inet = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">fps_main = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">fps_mail2arduino = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">fps_see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">fps_camera2inet = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pixel_ellips = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cap = WebcamVideoStream(src=0).start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">for i in range(5): frame = cap.read()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">frame = cap.read()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">frame_gray = cv2.inRange(hsv[420:,:, :], (0, 0, 0), (255, 255, 100))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">frame_red = cv2.inRange(hsv[:, 320:, :], (0, 150, 30), (10, 255, 80))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cv2.imwrite('/var/www/html/dgip_gray360.png', frame_gray)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cv2.imwrite('/var/www/html/dgip_frame_all.png', frame)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">def mail2arduino_pr1():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print("Start arduino thread")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> global x, out_old, speed_go, speed, i_mail2arduino, fps_mail2arduino, time_mail2arduino</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while 1:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> local_x = x</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(local_x >= 0): out = "L"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else: out = "R"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> local_x = abs(int(local_x*K))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(local_x > 90): local_x = 90</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(local_x < 10): out += "0" + str(local_x)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else: out += str(local_x)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(speed >= 100): out += "F" + str(speed)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> elif(speed >= 10): out += "F0" + str(speed)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else: out += "F00" + str(speed)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(out != out_old):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ser.write(out.encode())</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_out = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_out > 2):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ser.write("0000000".encode())</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_out = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> out_old = out</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_mail2arduino += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_mail2arduino > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_mail2arduino = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> fps_mail2arduino = i_mail2arduino</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_mail2arduino = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">def image2jpeg(image):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ret, jpeg = cv2.imencode('.jpg', image)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return jpeg.tobytes()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">def camera2inet_pr2():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print("Start inet thread")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> global frame_gray, frame, frame_red, i_camera2inet, time_camera2inet, fps_camera2inet</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> global fps_main, fps_see_red, fps_mail2arduino, fps_camera2inet, pixel_ellips, see_red</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> app = Flask(__name__)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> @app.route('/')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> def index():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return render_template('index.html')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> def gen_gray():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.putText(frame_gray,"fps_main: "+str(fps_main), (0,10), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.putText(frame_gray,"fps_see_red: "+str(fps_see_red), (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.putText(frame_gray,"fps_mail2arduino: "+str(fps_mail2arduino), (0,30), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.putText(frame_gray,"fps_camera2inet: "+str(fps_camera2inet), (0,40), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> frameinet = image2jpeg(frame_gray)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> def gen_red():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while True:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.putText(frame_red,"red_see: "+str(see_red), (0,10), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.putText(frame_red,"red_pixel: "+str(pixel_ellips), (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255,255,255), 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> frameinet = image2jpeg(frame_red)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> yield (b'--frame\r\n'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> b'Content-Type: image/jpeg\r\n\r\n' + frameinet + b'\r\n\r\n')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> @app.route('/video_line')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> def video_line():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return Response(gen_gray(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> @app.route('/video_red')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> def video_red():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return Response(gen_red(),</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> mimetype='multipart/x-mixed-replace; boundary=frame')</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time.sleep(0.15)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_camera2inet += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_camera2inet > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_camera2inet = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> fps_camera2inet = i_camera2inet</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_camera2inet = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> app.run(host='0.0.0.0', debug=False,threaded=True)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">def see_red_pr3():</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print("Start see red thread")</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> global K, pixel_ellips, see_red, hsv, frame_red, i_see_red, time_see_red, fps_see_red</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> print(frame_red.dtype)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_last_see_red = time.time()-20</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> search = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while 1:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> frame_red = cv2.inRange(hsv[:, 320:, :], (0, 120, 30), (10, 255, 255))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(search):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> frame_copy = frame_red.copy()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> _, con, hierarchy = cv2.findContours(frame_copy, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for i in con:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if len(i)>10:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ellipse = cv2.fitEllipse(i)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> _, y1 = ellipse[0]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> _, y2 = ellipse[1]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> pixel_ellips = abs(y2-y1)*0.15 + 0.85 * pixel_ellips</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(pixel_ellips > 200):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> pixel_ellips = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> see_red = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> search = False</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_last_see_red = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else: see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> cv2.ellipse(frame_red, ellipse, (255,0,0), 2)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> break</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_last_see_red <= 10):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> see_red = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_last_see_red > 10):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> K = 0.1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_last_see_red >= 12):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> K = 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_last_see_red >= 20):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> search = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_see_red += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_see_red > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_see_red = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> fps_see_red = i_see_red</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_see_red = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr1 = threading.Thread(target=mail2arduino_pr1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr1.daemon = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr1.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr2 = threading.Thread(target=camera2inet_pr2)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr2.daemon = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr2.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr3 = threading.Thread(target=see_red_pr3)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr3.daemon = True</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">pr3.start()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">while 1:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> frame = cap.read()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> frame_gray = cv2.inRange(hsv[420:,:, :], (0, 0, 0), (255, 255, 80))</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(np.sum(frame_gray) > porog and see_red != 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> speed = 255</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> moments = cv2.moments(frame_gray, 1)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> dM01 = moments['m01']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> dM10 = moments['m10']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> dArea = moments['m00']</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> x = 320 - int(dM10 / dArea)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> y = 120 - int(dM01 / dArea)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> speed = 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_main += 1</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(time.time() - time_main > 1):</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> time_main = time.time()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> fps_main = i_main</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> i_main = 0</span></div>
</div>
<div>
<br /></div>
<div>
<div>
Исходный код программы для Arduino:</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">#include <AFMotor.h></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">char in_command_array[7]; </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int napr = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int ugol = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int error = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">int speed_ = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">AF_DCMotor motor1(1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">AF_DCMotor motor2(2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">AF_DCMotor motor3(3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">void setup() {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.begin(115200); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.setSpeed(200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.run(RELEASE);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.setSpeed(200);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.run(RELEASE);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor3.setSpeed(0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor3.run(FORWARD);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> delay(5000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">void loop() {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> String inString = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> String ServoNapr = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> String ServoUgol = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> String MotorNapr = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> String MotorSpeed = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> char in_command_array[7];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> while (Serial.available()) { </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> in_command_array[0] = Serial.read();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if (ServoNapr == 'L' || ServoNapr == 'R') { </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> inString = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for (int i=0;i<3;i++) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> delay(1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> char inChar = Serial.read(); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if (isDigit(inChar)) in_command_array[i+1] = (char)inChar; </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int ServoUgol = inString.toInt();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> in_command_array[3] = Serial.read(); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> inString = "";</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for (int i=0;i<3;i++) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> delay(1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> char inChar = Serial.read(); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if (isDigit(inChar)) in_command_array[i+4] = (char)inChar; </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int MotorSpeed = inString.toInt();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(in_command_array);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> } </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(in_command_array[0] == 76) { napr = -1; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(in_command_array[0] == 82) { napr = 1; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(in_command_array[0] == 48) { napr = 0; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else { error++; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("napr = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(napr); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("error = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(error); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int ugol_num1 = in_command_array[1] - 48;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int ugol_num2 = in_command_array[2] - 48;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("ugol_num1 = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(ugol_num1); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("ugol_num2 = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(ugol_num2); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(ugol_num1 == 0) { ugol = ugol_num2; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(ugol_num1 != 0) { ugol = ugol_num1*10 + ugol_num2; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else { error++; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("ugol = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(ugol);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("error = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(error);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int speed_num1 = in_command_array[4] - 48;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int speed_num2 = in_command_array[5] - 48;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> int speed_num3 = in_command_array[6] - 48;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("speed_num1 = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(speed_num1); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("speed_num2 = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(speed_num2); </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("speed_num3 = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(speed_num3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(speed_num1 == 0 && speed_num2 == 0) { speed_ = speed_num3; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(speed_num1 == 0) { speed_ = ugol_num2*10 + speed_num3; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(speed_num1 != 0) { speed_ = speed_num1*100 + speed_num2*10 + speed_num3; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else { error++; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("speed = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(speed_);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.print("error = ");</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> Serial.println(error);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(speed_ >= 255) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> speed_ = speed_ - 255;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.run(FORWARD);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.setSpeed(speed_);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.run(FORWARD);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.setSpeed(speed_);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.run(BACKWARD);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.setSpeed(speed_);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.run(BACKWARD);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.setSpeed(speed_);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(speed_ == 255) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor1.run(RELEASE);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor2.run(RELEASE);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if(napr == 1) { motor3.run(FORWARD); }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> else if(napr == -1) { motor3.run(BACKWARD); }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> motor3.setSpeed(ugol*2.83);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></div>
<div>
<br /></div>
</div>
</div>
</div>
<div>
<a href="https://github.com/darkavengersmr/long_python_tail1">Ссылка на github</a></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com6tag:blogger.com,1999:blog-4279357166628593719.post-90946233848173612532018-03-31T09:44:00.002-07:002018-03-31T09:44:41.475-07:00Подражая белому кролику<div dir="ltr" style="text-align: left;" trbidi="on">
Робот, который <a href="http://karandashsamodelkin.blogspot.ru/2018/03/blog-post_10.html">следовал за белым кроликом</a> в нашем предыдущем проекте, очень захотел научиться так же ловко, как робот-кролик, двигаться вдоль черной линии. Мы решили ему в этом помочь, написав для него программу на Python, использующую камеру и машинное зрение с использованием библиотеки OpenCV.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKfpnG2I5zUhDOsg37HNy8wari7J3vBtEKl_qQCyozKLcrcopsHY5kbhSSozTWQKAGrqcRd3OOCuGqN6E_CGruCSexVCOc0XMJohXLjp9i4kr1EdMX8RJYFmayo9cMdiUbgySliX2cxMaj/s1600/white_rabbit_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="971" data-original-width="1600" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKfpnG2I5zUhDOsg37HNy8wari7J3vBtEKl_qQCyozKLcrcopsHY5kbhSSozTWQKAGrqcRd3OOCuGqN6E_CGruCSexVCOc0XMJohXLjp9i4kr1EdMX8RJYFmayo9cMdiUbgySliX2cxMaj/s400/white_rabbit_2.jpg" width="400" /></a></div>
<br />
Чтобы несколько усложнить задачу, мы решили построить дорожный знак и положить на линию условного "лежачего полицейского".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjc4Hty-wOXluWhfTtnGVV-lhjDNnbSQ1A4rH4QsvZUWuy2FzFhEO6Us91mpZzyOyHg-AISpn-IbEjvvFAhMlukmYtKpzVn2ot_m3To47y5YJm87eHlHWiChG8dMpVoGdElS6uxlN4JdD1/s1600/DSC05190.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjc4Hty-wOXluWhfTtnGVV-lhjDNnbSQ1A4rH4QsvZUWuy2FzFhEO6Us91mpZzyOyHg-AISpn-IbEjvvFAhMlukmYtKpzVn2ot_m3To47y5YJm87eHlHWiChG8dMpVoGdElS6uxlN4JdD1/s400/DSC05190.JPG" width="400" /></a></div>
<br />
Дорожный знак было решено построить на основе платы Arduino и сервопривода, а управлять им - используя произвольный ИК-пульт дистанционного управления.<br />
<br />
Код программы для дорожного знака выглядит следующим образом:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#define ServoPin 5 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <Servo.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <IRremote.h> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">Servo servo;</span><span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int receiverPin = 11; </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">IRrecv irrecv(receiverPin);</span><span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">decode_results results;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void setup() {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.begin(9600);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.enableIRIn();</span><span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void loop() {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if (irrecv.decode(&results)) { </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(results.value, HEX); </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(results.value == 0xFF609F){ </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servo.attach(ServoPin);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servo.write(180);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servo.detach();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(results.value == 0xFFE01F){ </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servo.attach(ServoPin);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servo.write(0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servo.detach();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> irrecv.resume();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0SeZDkkprJwlqgmMT8xcwTaXxzrPl4RFj38rDYY72PwrdDjUe_0LqvWeD0-HnNzI-xatkuZ2nS2szltf2uBAEKdV_oqnJi-0qAdsjqBhNXbhbLDxNLYX1V4aI6YEU7QKhuB0473Rz5ynb/s1600/DSC05191.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0SeZDkkprJwlqgmMT8xcwTaXxzrPl4RFj38rDYY72PwrdDjUe_0LqvWeD0-HnNzI-xatkuZ2nS2szltf2uBAEKdV_oqnJi-0qAdsjqBhNXbhbLDxNLYX1V4aI6YEU7QKhuB0473Rz5ynb/s400/DSC05191.JPG" width="400" /></a></div>
<br />
Конструкция робота не претерпела изменений по сравнению с <a href="http://karandashsamodelkin.blogspot.ru/2018/03/blog-post_10.html">предыдущим проектом</a>, разве что камеру развернули под иным углом, чтобы она видела одновременно и линию перед роботом и пространство рядом с дорогой.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmTCrDszX9GCqBfgxhEvO-hnFMQ4pho3vyag2mqNSNf0e1UssuAbM314SxnfZfMa13sJ6aIr1KOntclmwKVLHQh3qBDdJ5b1riLeks9LsPOcvLC97ur0K7WO9huMloSkyWnxrhXR3LZusM/s1600/DSC05183.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmTCrDszX9GCqBfgxhEvO-hnFMQ4pho3vyag2mqNSNf0e1UssuAbM314SxnfZfMa13sJ6aIr1KOntclmwKVLHQh3qBDdJ5b1riLeks9LsPOcvLC97ur0K7WO9huMloSkyWnxrhXR3LZusM/s400/DSC05183.JPG" width="400" /></a></div>
<br />
Увидев красный знак, робот должен остановиться и ожидать пока ему будет разрешено двигаться дальше с помощью зеленого знака. "Лежачим полицейским" будет перпендикулярная черной линии синяя полоса. Перед ней робот должен будет снизить скорость.<br />
<br />
Алгоритм работы нашего робота таков:<br />
<br />
<ul style="text-align: left;">
<li>Запускаем независимый процесс по непрерывному чтению данных с камеры в объект в памяти</li>
<li>Запускаем независимый процесс по управлению двигателями c использованием ПИД-регулятора</li>
<li>Запускаем основной процесс, в котором:</li>
<li>Берем очередной кадр из объекта в памяти, и переводим в цветовое пространство HSV</li>
<li>Отрезаем от кадра нижнюю четверть кадра и, используя функцию вычисления моментов cv2.moments, вычисляем горизонтальное смещение линии относительно центра</li>
<li>Передаем данные о смещении относительно линии процессу ПИД-регулятора</li>
<li>Отрезаем нижнюю половину кадра и анализируем количество "синих" точек в нем. Если их количество превышает заданную границу - сообщаем процессу ПИД-регулятора о снижении скорости движения</li>
<li>Анализируем количество "красных" точек во всем кадре. Если их количество превышает заданную границу - сообщаем процессу ПИД-регулятора о нулевой скорости движения</li>
</ul>
Робот видит примерно такую картинку:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_N-dSqiItNx9W0jh6mr7RQtDWSmSn8LBIxJfnm9uLV4wYNg9rQqZBGpTZEkMhLBNA2aIEPbyAcy8DcyBsr0LXU9srbY1lpxYI7U2si-YMzUtH0OoD7jnCGkKe127922RtI0KltNwmI1Ld/s1600/bot_control_central.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_N-dSqiItNx9W0jh6mr7RQtDWSmSn8LBIxJfnm9uLV4wYNg9rQqZBGpTZEkMhLBNA2aIEPbyAcy8DcyBsr0LXU9srbY1lpxYI7U2si-YMzUtH0OoD7jnCGkKe127922RtI0KltNwmI1Ld/s400/bot_control_central.png" width="400" /></a></div>
<div>
<br /></div>
Линию в нижней четверти кадра робот видит так:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4mqJzCgYkxyZv_BI4sKHvgdiOnPwm4s0h0CDIRfGZ4Iueln55Jea61IJ9mAEkhlL6AXFy2iauzWWjJjow4ckoNbH4AVj8UTk7nLPb31Dxqdq6cc9KCP3NKzeDH06tGgzL_sDmP5KBS5sh/s1600/kube_gray.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="120" data-original-width="640" height="75" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4mqJzCgYkxyZv_BI4sKHvgdiOnPwm4s0h0CDIRfGZ4Iueln55Jea61IJ9mAEkhlL6AXFy2iauzWWjJjow4ckoNbH4AVj8UTk7nLPb31Dxqdq6cc9KCP3NKzeDH06tGgzL_sDmP5KBS5sh/s400/kube_gray.png" width="400" /></a></div>
<br />
А вот так он выделяет в кадре красный знак:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVHcwDQUKE3vP4GcJZkwwK_eREyhHbfuciV05tobMEuE7TObAyQ7qwdlIBl2w3S2V0qoPn9y-KibGl-CRKEFaqkr3X5kZ6-u8CEgo3VtztHV7MV0iZex6b_Gk0oCpkf9q_JAuUQhWO9650/s1600/bot_control_green.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVHcwDQUKE3vP4GcJZkwwK_eREyhHbfuciV05tobMEuE7TObAyQ7qwdlIBl2w3S2V0qoPn9y-KibGl-CRKEFaqkr3X5kZ6-u8CEgo3VtztHV7MV0iZex6b_Gk0oCpkf9q_JAuUQhWO9650/s400/bot_control_green.png" width="400" /></a></div>
<br />
Исходный код программы робота:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#!/usr/bin/env python3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">import threading</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import rpyc</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import numpy as np</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from imutils.video import WebcamVideoStream</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import cv2, time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">conn = rpyc.classic.connect('192.168.32.209')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ev3 = conn.modules['ev3dev.ev3']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">btn = ev3.Button()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">mA = ev3.LargeMotor('outA')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">mD = ev3.LargeMotor('outB')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">P = 0.4</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">D = 1.0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">K = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">speed = 300</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">speed_go = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">max = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">x = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">es = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">dArea = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">size = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">cap = WebcamVideoStream(src=0).start()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">for i in range(10): frame = cap.read()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">hsv = cv2.cvtColor(frame[:][360:], cv2.COLOR_BGR2HSV)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">frame_gray = cv2.inRange(hsv, (0, 0, 0), (255, 170, 80))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cv2.imwrite('/var/www/html/camera_bot_line.png', frame_gray)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def motor_control():</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> global x, D, P, frame_gray, speed, es, speed_go</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed_go < speed): speed_go += 50</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed_go > speed): speed_go -= 50</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed_go < 150):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> P = 0.15</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> D = 0.2</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> P = 0.4</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> D = 1.0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed_go < 5): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> P = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> D = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> P = 0.4</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> D = 1.0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> speedA = speed_go - ((x*P) + D*(x-es))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speedD = speed_go + ((x*P) + D*(x-es))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedA > 900): speedA = 900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedA < -900): speedA = -900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedD > 900): speedD = 900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedD < -900): speedD = -900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> mA.run_forever(speed_sp=speedA)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> mD.run_forever(speed_sp=speedD)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> es = x</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">t1 = threading.Thread(target=motor_control)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">t1.daemon = True</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">t1.start()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while True:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> frame = cap.read()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> frame_gray = cv2.inRange(hsv[:][360:], (0, 0, 0), (255, 170, 80))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> frame_blue = cv2.inRange(hsv[:][240:], (90, 120, 60), (135, 250, 250))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> frame_red = cv2.inRange(hsv, (150, 100, 60), (255, 250, 250))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(np.sum(frame_blue) > 30000):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speed = 100</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> elif(np.sum(frame_red) > 80000):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speed = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speed = 300</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> moments = cv2.moments(frame_gray, 1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dM01 = moments['m01']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dM10 = moments['m10']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dArea = moments['m00']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(dArea != 0):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> x = 320 - int(dM10 / dArea)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> y = 80 - int(dM01 / dArea)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.backspace):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speed = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speed_go = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> x = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">mA.stop(stop_action="brake")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">mD.stop(stop_action="brake")</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/anufw3w4LKA/0.jpg" src="https://www.youtube.com/embed/anufw3w4LKA?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br /></div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-74773450726458371372018-03-10T08:13:00.002-08:002018-03-18T06:16:05.974-07:00Следуй за белым кроликом<div dir="ltr" style="text-align: left;" trbidi="on">
Машинное зрение использует достаточно ресурсоемкие алгоритмы и, хотя ev3dev на платформе LEGO Mindstorms EV3 и позволяет использовать веб-камеру с библиотеками OpenCV, производительность этой связки оставляет желать лучшего. С целью получения большей вычислительной мощности на борту, но в тоже время не отказываясь от удобных элементов прототипирования, входящих в наборы LEGO, мы решили использовать Raspberry Pi, который будет осуществлять все расчеты, оставляя блоку EV3 задачу низкоуровнего управления двигателями.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXYSLwC7O9w9SbPorTFNua6UoWrgOCMXNqVVYEUCRdPU5pT_2AotdxXP3ZUXRbNSWuaH_3M57IUMmpUiPsTHC14oNFQU1JSVjJfl65M0nUioMqHJUmXdQnYlZ1_MwdiHJJ17SaRfdzTg2Y/s1600/white+rabbit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="931" data-original-width="1600" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXYSLwC7O9w9SbPorTFNua6UoWrgOCMXNqVVYEUCRdPU5pT_2AotdxXP3ZUXRbNSWuaH_3M57IUMmpUiPsTHC14oNFQU1JSVjJfl65M0nUioMqHJUmXdQnYlZ1_MwdiHJJ17SaRfdzTg2Y/s400/white+rabbit.jpg" width="400" /></a></div>
<br />
В проекте "Следуй за белым кроликом" мы создадим робота, который будет обнаруживать заданный объект и следовать за ним на определенной дистанции, подстраиваясь под скорость его движения. В качестве "кролика", мы будем использовать другого робота, следующего по линии и везущего на себе контрастный предмет, за которым и будет следовать разрабатываемый в рамках проекта робот.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJA6anlNSNA9f2E8icMTlTrtp_5s1oPJVJJO0ZT1Nr-tW4WcG8YqF9Znhhp8cvqgGnnqqHGH-Er2rxBytWb-ewAf4h8DORcCMqAUupMEf3P9Gz24JN3ouVu8jDLbaeM7g1OdBW_XvRSte8/s1600/DSC05186_.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1591" data-original-width="1600" height="397" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJA6anlNSNA9f2E8icMTlTrtp_5s1oPJVJJO0ZT1Nr-tW4WcG8YqF9Znhhp8cvqgGnnqqHGH-Er2rxBytWb-ewAf4h8DORcCMqAUupMEf3P9Gz24JN3ouVu8jDLbaeM7g1OdBW_XvRSte8/s400/DSC05186_.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
В проекте мы используем Raspberry Pi второй версии. 4 ядра на борту дают возможность распределить по ним задачи:<br />
1) получение потока данных с камеры<br />
2) постобработка изображения и выделение в кадрах искомого объекта, анализ его размера и положения<br />
3) управление двигателями посредством двух ПИД-регуляторов.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguMPcm1Nc2NYL-u7QXWYpdR8ipx7O_28XFTvC-17m6yc12HKM5QGMbR1vz9WP0yerAXE-50ku_sT32kwvdb4p8C4nO5BjNRYx69rB4oTuv6iXsZKNh4ecXR8SfsJHHs82_M7SbmintKq3q/s1600/DSC05182.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguMPcm1Nc2NYL-u7QXWYpdR8ipx7O_28XFTvC-17m6yc12HKM5QGMbR1vz9WP0yerAXE-50ku_sT32kwvdb4p8C4nO5BjNRYx69rB4oTuv6iXsZKNh4ecXR8SfsJHHs82_M7SbmintKq3q/s400/DSC05182.JPG" width="400" /></a></div>
<br />
Для связи между Raspberry Pi и EV3 можно использовать как проводное подключение через USB (настроив сетевой LAN-интерфейс), так и беспроводную связь через WiFi/Bluetooth. Мы используем пару WiFi-адаптеров, один в EV3, другой в Raspberry Pi. Питание Raspberry Pi получает от повербанка, который робот также везет на себе. Для "удаленного" управления двигателями мы используем библиотеку RPyC (Remote Python Call).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp_flRP5ZGBSxCvGg4NYVzfydIKzwgSZ1gfO-sKgI1272f5KbL7hZf2D48_v6tNcz6QTvoJdLW7Iz1nndVT3tMu4TDFb95IQ4gB8AxDnEPb2DdAow81woFeowTpTjvgUXIgdXbiHUcKQmb/s1600/DSC04650.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp_flRP5ZGBSxCvGg4NYVzfydIKzwgSZ1gfO-sKgI1272f5KbL7hZf2D48_v6tNcz6QTvoJdLW7Iz1nndVT3tMu4TDFb95IQ4gB8AxDnEPb2DdAow81woFeowTpTjvgUXIgdXbiHUcKQmb/s400/DSC04650.JPG" width="400" /></a></div>
<br />
Алгоритм работы робота следующий:<br />
1) Получаем единичный кадр с камеры<br />
2) Анализируем цвет объекта и размер объекта, расположенного по центру кадра, именно за ним мы и будем следовать в дальнейшем<br />
3) запускаем процесс чтения данных с камеры, получая объект в памяти, содержащий в каждый момент времени актуальную картинку<br />
4) циклично анализируем кадр и пытаемся найти на нем искомый объект. Если объект найден - определяем его горизонтальное смещение и изменение размера относительно эталонного<br />
5) передаем процессу с ПИД-регуляторами данные о горизонтальном смещении и отклонении в размере<br />
6) ПИД регуляторы вырабатывают управляющие воздействия, которое суммируются и результат передается подсистеме управления двигателями.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/1pXwUFw-XI4/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/1pXwUFw-XI4?feature=player_embedded" width="320"></iframe></div>
<br />
<a href="https://github.com/darkavengersmr/follow-the-white-rabbit">Исходный код робота</a>, следующего за белым кроликом выглядит так:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#!/usr/bin/env python3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">import threading</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import rpyc</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import numpy as np</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from imutils.video import WebcamVideoStream</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import cv2, time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">conn = rpyc.classic.connect('192.168.32.209')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ev3 = conn.modules['ev3dev.ev3']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">btn = ev3.Button()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">mA = ev3.LargeMotor('outA')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">mD = ev3.LargeMotor('outB')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">P = 0.2</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">speed = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">max = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">x = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">dArea = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">size = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">cap = WebcamVideoStream(src=0).start()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">for i in range(10): frame = cap.read()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">H = hsv[320,240, 0]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">S = hsv[320,240, 1]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">V = hsv[320,240, 2]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Lo = np.array([H-35, S-50, V-75])</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Hi = np.array([H+35, S+50, V+75])</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">frame_gray = cv2.inRange(hsv, Lo, Hi)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cv2.imwrite('/var/www/html/kube_search.png', frame_gray)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def motor_control():</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> global dArea, x, P, size, frame_gray</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while True:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(np.sum(frame_gray) > 10000):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speedA = size*3 - (x*P)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> speedD = size*3 + (x*P)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedA > 900): speedA = 900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedA < -900): speedA = -900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedD > 900): speedD = 900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speedD < -900): speedD = -900</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> mA.run_forever(speed_sp=speedA)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> mD.run_forever(speed_sp=speedD)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> mA.stop(stop_action="brake")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> mD.stop(stop_action="brake")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">t1 = threading.Thread(target=motor_control)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">t1.daemon = True</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">t1.start()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while True:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> frame = cap.read()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> frame_gray = cv2.inRange(hsv, Lo, Hi)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(np.sum(frame_gray) > 10000):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> moments = cv2.moments(frame_gray, 1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dM01 = moments['m01']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dM10 = moments['m10']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dArea = moments['m00']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(max==0): max = dArea</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> size = 45 - (dArea / max * 100)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(dArea != 0):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> x = 320 - int(dM10 / dArea)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> y = 240 - int(dM01 / dArea)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(x>-10 and x < 10): x = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(size>-5 and size < 5): size = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.backspace):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> size = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> x = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">mA.stop(stop_action="brake")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">mD.stop(stop_action="brake")</span><br />
<div>
<br /></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com1tag:blogger.com,1999:blog-4279357166628593719.post-50158594025263087922018-03-10T05:48:00.002-08:002018-03-10T05:48:59.375-08:00НейроТир<div dir="ltr" style="text-align: left;" trbidi="on">
Простая и эффективная нейросеть, которую мы использовали в проекте НейроБашня, нам так понравилась, что мы решили сделать еще один проект с похожей основой.<br />
<div>
В проекте НейроТир мы создадим мишень, которая будет самообучаться противостоять игроку, стреляющему по ней, подстраиваясь под его манеру и опыт стрельбы и предлагая все более сложные для него комбинации целей.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXguKPvTH4xp4mWS1bCPdUlaRib5VSV02Bco9eRKtrJy6_gqPfEVwR2cvq-HM_cO1yNViT3JR0kk-3PG8JA0nW8iAjoAy3e8VUmA-WCYEpCczjRv9cvL5bL5IIktwvkJcdu1VX5W4RbPBq/s1600/%25D0%259D%25D0%25B5%25D0%25B9%25D1%2580%25D0%25BE%25D0%25A2%25D0%25B8%25D1%2580.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="872" data-original-width="1600" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXguKPvTH4xp4mWS1bCPdUlaRib5VSV02Bco9eRKtrJy6_gqPfEVwR2cvq-HM_cO1yNViT3JR0kk-3PG8JA0nW8iAjoAy3e8VUmA-WCYEpCczjRv9cvL5bL5IIktwvkJcdu1VX5W4RbPBq/s400/%25D0%259D%25D0%25B5%25D0%25B9%25D1%2580%25D0%25BE%25D0%25A2%25D0%25B8%25D1%2580.jpg" width="400" /></a></div>
<br /></div>
<div>
"Пистолет", из которого будет вестись стрельба по мишени, спроектирован на основе LEGO Mindstorrms NXT. Для стрельбы мы будем использовать лазерную указку, включенную на постоянное свечение. Луч лазера будет перекрываться специальной заслонкой, управляемой малым EV3-мотором и ПИД-регулятором.В роли спускового курка выступает датчик кнопка.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kxiDM6DTvYTm-OQjJ8IL4MzumJzJ0pvEf0-UA6vzB2VslBSeV21MgvO0V2qUGNellm4UUaYZjei35i2sxDKpbAZ72ES2AmLrfZ_AgU6Wtt-WdTDb9VygsgCkAWF5tLNBPbqt_P0U7hnc/s1600/DSC04641.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="941" data-original-width="1600" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kxiDM6DTvYTm-OQjJ8IL4MzumJzJ0pvEf0-UA6vzB2VslBSeV21MgvO0V2qUGNellm4UUaYZjei35i2sxDKpbAZ72ES2AmLrfZ_AgU6Wtt-WdTDb9VygsgCkAWF5tLNBPbqt_P0U7hnc/s400/DSC04641.JPG" width="400" /></a></div>
<br />
Для обучения нейронной сети в мишени необходима обратная связь от пистолета, чтобы она могла сопоставить момент выстрела и факт поражения цели. Такую связь мы реализуем посредством bluetooth. В момент выстрела пистолет посылает мишени "1".<br />
<br />
<a href="https://github.com/darkavengersmr/NeuralTarget">Программа для пистолета</a> выглядит следующим образом:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#define BT_CONN 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#define OUTBOX 5</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">long time=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int tri =1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int triger=1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int yes=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int es=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int u=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int Pk=3.5;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int PD=7;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int e=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void Send2BT()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> SendRemoteNumber(BT_CONN,OUTBOX,1);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void BTConnect()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> CommBTConnectionType args;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> args.Name = "ks2";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> args.ConnectionSlot = BT_CONN;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> args.Action = true;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(BluetoothStatus(BT_CONN)!=NO_ERR) SysCommBTConnection(args);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">task pid()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> es=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(true){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> e = MotorRotationCount(OUT_A)-yes;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> u = e*Pk+PD*(e-es);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(u>100){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> u=100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(u<-100){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> u=-100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> OnRev(OUT_A,u);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> es = e;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">task main()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ResetRotationCount(OUT_A);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> start pid;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> time=CurrentTick();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorTouch(IN_1);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> BTConnect();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(true){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(Sensor(IN_1)==1){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> yes=60 * triger;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> triger=triger*-1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for(int i=1500;i>300;i=i-50)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> PlayTone(i,10);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(10);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Send2BT();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(CurrentTick()-time>=500){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> time=CurrentTick();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> yes=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(700);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<div>
<br />
Инструкции по сборке в формате LEGO Digital Designer выкладываем <a href="https://github.com/darkavengersmr/NeuralTarget">по ссылке</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMVEtddAD1qvvAZArHQW_T_6pQrOYLaEcVc1mEMR7Y_X0ZHXCkbvEQvAQUrR2WKCgKFMfJKG57Nc1vrtS8_Y6im72FiyaWTNbh3-z9iMhKruC5BHm6YzQS1yDpmcHcC8T3NAf1TgZDrZVF/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B91.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="842" data-original-width="1600" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMVEtddAD1qvvAZArHQW_T_6pQrOYLaEcVc1mEMR7Y_X0ZHXCkbvEQvAQUrR2WKCgKFMfJKG57Nc1vrtS8_Y6im72FiyaWTNbh3-z9iMhKruC5BHm6YzQS1yDpmcHcC8T3NAf1TgZDrZVF/s400/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B91.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9p57wqMeuKfpMOCaGsnkPgMji1gvbLxwcAWaNMX4MZocn2gaRKW0TL7J2Nv5MF38cisSBXeQzgnyvO0sFq4sW5iViCRILvidmliL-Tz64xiZC4Qic5JchiEF8xJoJxhfiLC6rzQpaJWq5/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B92.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="863" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9p57wqMeuKfpMOCaGsnkPgMji1gvbLxwcAWaNMX4MZocn2gaRKW0TL7J2Nv5MF38cisSBXeQzgnyvO0sFq4sW5iViCRILvidmliL-Tz64xiZC4Qic5JchiEF8xJoJxhfiLC6rzQpaJWq5/s400/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B92.jpg" width="400" /></a></div>
<br /></div>
В основе мишени лежит еще один блок NXT, который управляет тремя NXT-моторами. Каждый мотор управляет заслонкой соответствующей цели, в качестве которой используется датчик освещенности. Для того, чтобы увеличить "зону поражения" лазером, сберечь фотодиод датчика при прямых попаданиях, используется рассеивающие фильтры из бумаги, а для устранения фоновой засветки - бленды из покрышек, как в проекте "LEGO UART: бит за битом". Если цель поражена - соответствующая заслонка закрывается, если игрок промахнулся - не пораженная цель вспыхивает красным цветом (используестя подсветка датчиков освещенности).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3aef4vaZRul16i0omehHTa6iBhXp8YwWmIzXs3UjaZ2osW-L0fXpRZ38ejF3n9aPVn8J0HNY79PvigXA-7ltYquHPGPJUUENSXQwSEcBquF6ICob_0LW4_7qx2ht92vwrkFpNGVdkCzXV/s1600/DSC04654.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3aef4vaZRul16i0omehHTa6iBhXp8YwWmIzXs3UjaZ2osW-L0fXpRZ38ejF3n9aPVn8J0HNY79PvigXA-7ltYquHPGPJUUENSXQwSEcBquF6ICob_0LW4_7qx2ht92vwrkFpNGVdkCzXV/s400/DSC04654.JPG" width="400" /></a></div>
<br />
Нейронная сеть обучается на основе истории попаданий игрока в мишень, учитывается 3 последних выстрела.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPHZ1geSou1TJS43qsvXHwvApAd0JgmP7QyZQI3NuDP0kHLma-9HbovCji2PF3rtKS5UcU1C0BLedmGkoBudQ5pXZ5sZdFOKDvFs2I4kndwfhafmN7Y8aDkqFfYTkznCjJCcEOKyXfPhC5/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="227" data-original-width="763" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPHZ1geSou1TJS43qsvXHwvApAd0JgmP7QyZQI3NuDP0kHLma-9HbovCji2PF3rtKS5UcU1C0BLedmGkoBudQ5pXZ5sZdFOKDvFs2I4kndwfhafmN7Y8aDkqFfYTkznCjJCcEOKyXfPhC5/s400/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" width="400" /></a></div>
<br />
Если представить алгоритм обучения нейронной сети в упрощенной форме в терминологии "коробков и камушков", получится следующее:<br />
<ul style="text-align: left;">
<li>Возьмем 64 пустые коробки и расположим их в виде куба 4x4x4, в каждую такую коробку положим по 1 камешку трех разных цветов (каждый цвет соответствует одной из целей) - это "мозг" нашего самообучающегося робота</li>
<li>Возьмем лист бумаги и будем записывать на него историю выстрелов, в какую мишень в каком порядке стрелял игрок. Из этой истории нас будут интересовать три последние выстрела.</li>
<li>Предположим игрок уже сделал 3 выстрела и их история зафиксирована на бумаге, например 3,1,2. Первые три цели выбираются случайным образом, нейронная сеть в их выборе не участвует.</li>
<li>В "кубе" с коробками выбираем 3 коробку в 1 ряду во втором слое и наугад вытягиваем один из камней, смотрим его цвет и кладем обратно. В зависимости от цвета камня поднимаем соответствующую мишень, предлагая игроку попасть в нее.</li>
<li>Если игрок промахнулся мимо выставленной цели, добавляем в коробку камень того цвета, который достали.</li>
<li>Если игрок попал в выставленную цель, убираем из коробки вытащенный камень проверив предварительно что в ней есть еще камне такого цвета. Последний камень каждого цвета всегда оставляем в коробке, таким образом число камней в коробке не может быть меньше 3 (по 1 каждого цвета).</li>
<li>Фиксируем в истории выстрелов цель, в которую стрелял игрок, например 3, Получаем историю - 3,1,2,3. "Забываем" самый первый выстрел, помним всегда только последние 3 - итого в истории 1,2,3.</li>
<li>Переходим на шаг 4, оперируя новой историей выстрелов</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBhC7Liy-XTPHYdVHivtD68dgZeaHiJ8u5N_hUCtrQW4wZ8Rgt1zQjqVCq9v9w1SMvV-20XgbXrLE6gUYPr0Uy4ePz6aQt5VcYpWaFMsB30AznsjZzPrFN_6sPtk3sEskJudD61vd52Jw5/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="985" data-original-width="1300" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBhC7Liy-XTPHYdVHivtD68dgZeaHiJ8u5N_hUCtrQW4wZ8Rgt1zQjqVCq9v9w1SMvV-20XgbXrLE6gUYPr0Uy4ePz6aQt5VcYpWaFMsB30AznsjZzPrFN_6sPtk3sEskJudD61vd52Jw5/s200/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.png" width="200" /></a></div>
<div>
<br /></div>
<div>
<a href="https://github.com/darkavengersmr/NeuralTarget">Исходный код программы для мишени</a>:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#define BT_CONN 0</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">#define INBOX 5</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">float l1,l2,l3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int BTMailbox = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">long BTtime = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">float random;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">long time1, time2, time3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int x=0, y=0, z=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int triger = 1, triger2 = 0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int target=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int history[3]={0,0,0};</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int brain[4][4][4][4];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int position1=0, position2=0, position3=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int es1=0, es2=0, es3=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int u1=0, u2=0, u3=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">int e1,e2,e3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">float Pk=3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">float PD=6;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">bool BTCheck(int conn)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (BluetoothStatus(conn) == NO_ERR) return true;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else return false;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">task pid()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while(true){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> e1 = MotorRotationCount(OUT_A)-position1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> e2 = MotorRotationCount(OUT_B)-position2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> e3 = MotorRotationCount(OUT_C)-position3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> u1 = e1*Pk+PD*(e1-es1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> u2 = e2*Pk+PD*(e2-es2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> u3 = e3*Pk+PD*(e3-es3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(u1>100) u1=100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(u2>100) u2=100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(u3>100) u3=100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(u1<-100) u1=-100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(u2<-100) u2=-100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(u3<-100) u3=-100;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(abs(e1)>15) OnRev(OUT_A,u1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else Off(OUT_A);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> es1 = e1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(abs(e2)>15) OnRev(OUT_B,u2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else Off(OUT_B);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> es2 = e2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(abs(e3)>15) OnRev(OUT_C,u3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else Off(OUT_C);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> es3 = e3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">task main(){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> OnFwd(OUT_ABC,18);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(3000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for(int x=0;x<=3;x++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for(int y=0;y<=3;y++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for(int z=0;z<=3;z++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> for(int t=0;t<=3;t++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> brain[x][y][z][t]=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ResetRotationCount(OUT_A);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ResetRotationCount(OUT_B);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ResetRotationCount(OUT_C);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(3000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Off(OUT_ABC);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> start pid;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorColorNone(IN_3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorLight(IN_2,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorLight(IN_1,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position1=-80;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position2=-80;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position3=-80;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(500);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> l1=Sensor(IN_1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> l2=Sensor(IN_2);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> l3=Sensor(IN_3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position1=-30;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position2=-30;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position3=-30;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while(true){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(triger>0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> x=brain[history[0]][history[1]][history[2]][1];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> y=brain[history[0]][history[1]][history[2]][2];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> z=brain[history[0]][history[1]][history[2]][3];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> random = abs(Random((x+y+z)*1000)/1000.0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(random<=x ){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position1=-80;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> target=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(random<=x+y){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position2=-80;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> target=2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(random<=x+y+z){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position3=-80;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> target=3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> BTMailbox=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> while(BTMailbox==0){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if (BTCheck(BT_CONN)) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ReceiveRemoteNumber(INBOX, true, BTMailbox);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger=0;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(target == 1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(Sensor(IN_1)>=l1+0.01){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position1= -30;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger+=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger2=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorLight(IN_1,1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(500);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorLight(IN_1,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(target== 2){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(Sensor(IN_2)>=l2+0.01){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position2= -30;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger+=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorLight(IN_2,1);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(500);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorLight(IN_2,0);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger2=2;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(target==3){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(Sensor(IN_3)>=l3+0.01){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> position3= -30;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(1000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger+=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorColorRed(IN_3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait(500);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> SetSensorColorNone(IN_3);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> triger2=3;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(triger==0) brain[history[0]][history[1]][history[2]][target]+=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(brain[history[0]][history[1]][history[2]][target]>1){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> brain[history[0]][history[1]][history[2]][target]-=1;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[0]=history[1];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[1]=history[2];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> history[2]=target;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
</div>
<div>
<br /></div>
После нескольких циклов обучения вероятности того, что нейронная сеть станет выбирать сложные для поражения конкретным игроком цели будет становится выше, причем процесс обучения будет продолжаться в процессе игры, постоянно подстраиваясь к мастерству игрока, выискивая его слабые места и предлагая все более сложные комбинации целей.<br />
<br />
<div>
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/e6cFgv-YV6k/0.jpg" src="https://www.youtube.com/embed/e6cFgv-YV6k?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br /></div>
<br />
<br /></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-36494363025031407212018-01-28T04:33:00.003-08:002018-01-28T04:34:00.023-08:00Voic3 Command3R<div dir="ltr" style="text-align: left;" trbidi="on">
Юбилейный, сотый, проект от "Карандаша и Самоделкина" просто обязан быть чем-то особенным! В прошлых сериях мы успели поработать в области машинного зрения, и наш робот на базе LEGO Mindstorms EV3 смог различать простейшие образы и даже сыграть с нами в <a href="http://karandashsamodelkin.blogspot.ru/2017/11/ev3.html">"Камень, ножницы, бумага"</a>. На этот раз мы решили освоить работу со звуком и решить одну из задач, связанных с "машинным слухом".<br />
<br />
Сделать робота, управляемого голосом, не так уж и сложно - достаточно воспользоваться готовым API от того же Google. В этом случае распознаваемый фрагмент отсылается онлайн-сервису, который в ответ сообщает распознанную текстовую строку. Если роботу нужна подобная автономная функциональность, существуют и готовые оффлайновые решения, вроде <a href="https://cmusphinx.github.io/">PocketSphinx</a>, правда работают они в условиях ограниченных ресурсов на роботе крайне задумчиво. Главной же фишкой нашего проекта станет то, что <b>мы не будем использовать никакие вспомогательные инструменты для распознавания речи, а напишем свой собственный "движок" для голосового управления</b>, пусть и простенький.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinIcWbN3k3E5sblp3Lo0ocren5P8_cWZr6yr3NY-yrjCFNx6Ji-gPUVxajoN8ePsvKYoWMu9oXo4vJFdoeKdzYNQj0oL0WViZjGTYARG1g3BY13UwPAFttq496kmq2qXGzyQUgf6Ayyxuy/s1600/Voic3Command3R.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="901" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinIcWbN3k3E5sblp3Lo0ocren5P8_cWZr6yr3NY-yrjCFNx6Ji-gPUVxajoN8ePsvKYoWMu9oXo4vJFdoeKdzYNQj0oL0WViZjGTYARG1g3BY13UwPAFttq496kmq2qXGzyQUgf6Ayyxuy/s400/Voic3Command3R.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Перво-наперво нам понадобится устройство, способное дать возможность роботу физически ощущать звуковую волну для возможности преобразования ее в цифровую форму. В комплекте с наборами LEGO NXT первой версии поставлялся датчик звука (NXT Sound Sensor). C его помощью можно измерять звуковое давление в условных единицах. Такого датчика у нас нет, поэтому мы решили использовать USB-микрофон, подключенный в соответствующий порт блока EV3. Что касается датчика звука NXT, то по информации от его владельцев, скорость опроса этого датчика невелика, поэтому на него рассчитывать все равно не стоит.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS73qfM6IjLpyVpGkm6XBoDQBeH4k9UalnTJSWs8K5zVzydbQwBkznuO4xPhHqnTghFhGrJDbA4szhPmGPqRHnI8gzoJMlCXgzZmRUnje0wSq7WGAYKnDGNMs8VHqwZ9w3CPpNDj783V3e/s1600/9845.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="550" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS73qfM6IjLpyVpGkm6XBoDQBeH4k9UalnTJSWs8K5zVzydbQwBkznuO4xPhHqnTghFhGrJDbA4szhPmGPqRHnI8gzoJMlCXgzZmRUnje0wSq7WGAYKnDGNMs8VHqwZ9w3CPpNDj783V3e/s320/9845.jpg" width="320" /></a></div>
В качестве USB-микрофона может выступать почти любая USB-звуковая плата, с подключенным к ней аналоговым микрофоном или USB-веб-камера, как правило имеющая встроенный микрофон. EV3-блок тоже имеет в своем составе звуковую плату, к выходу которой подключен встроенный динамик, а вот встроенного микрофона, увы, нет..Максимальная частота дискретизации этого устройства - 22кГц, поэтому качественно воспроизводить звук EV3-блок не может физически.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg5_NV9E9DDf7tpVLgEsFeXWBOEWr9UOEH2sT3tGUrPJTIUIntcyPccZtTjkaie8Oa1uV76dGtI-mSjXyQ853cQ8G7bhLvcDSQx_pBRclOivUMdCdH6pBmMxpignR6J-11ZEt-YY6goe0J/s1600/690683_v01_m.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="173" data-original-width="350" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg5_NV9E9DDf7tpVLgEsFeXWBOEWr9UOEH2sT3tGUrPJTIUIntcyPccZtTjkaie8Oa1uV76dGtI-mSjXyQ853cQ8G7bhLvcDSQx_pBRclOivUMdCdH6pBmMxpignR6J-11ZEt-YY6goe0J/s320/690683_v01_m.jpg" width="320" /></a></div>
При подключении дополнительного USB звукового устройства появляется возможность работать с ними одновременно, например получая данные с микрофона внешней звуковой платы и воспроизводя звук по прежнему встроенным динамиком. Возможна и конфигурация, при которой звук будет воспроизводиться внешней USB звуковой платой, при этом появляется возможность подключить к роботу качественную или "громкую" акустику.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6oTLXHAEgT8hPvesecvf66Cfpw1n_J_kU4Fz0wGO4QZzWAebQ1mqLlA5vHu2MVsMTSyH8bbOkNInErAcy_ShRHEpqTnQC50Em-2EBajkcacAPQVuA5nbEg-P4J9eXuKpt9LsjXz0vt5PI/s1600/Mini-USB-2-0-Direct-Connect-USB-Microphone-Studio-Speech-MIC-Audio-Adapter-Driver-Free-for.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6oTLXHAEgT8hPvesecvf66Cfpw1n_J_kU4Fz0wGO4QZzWAebQ1mqLlA5vHu2MVsMTSyH8bbOkNInErAcy_ShRHEpqTnQC50Em-2EBajkcacAPQVuA5nbEg-P4J9eXuKpt9LsjXz0vt5PI/s320/Mini-USB-2-0-Direct-Connect-USB-Microphone-Studio-Speech-MIC-Audio-Adapter-Driver-Free-for.jpg" width="320" /></a></div>
В проекте мы снова используем операционную систему ev3dev и будем программировать робота на языке Python. Для работы с звуковыми устройствами существует целый ряд python-модулей, мы остановили свой выбор на pyalsaaudio, обладающим высоким быстродействием в условиях ограниченных ресурсов. Для ускорения обработки данных и воспользуемся модулем NumPy. Хотя можно хранить данные и в традиционных для Python структурах, вроде списков, однако работа с звуковыми потоками, имеющими зачастую немалый объем, при таком подходе происходит крайне неторопливо.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi56BqXlZMB7CxCZvKt_F5lSLy7jykqHRnovCIM7MqYBgEq9d-frIjNDEBSHGZteALX89L3Ktu9hdeCWacpdiMQL_Rim6TF6nSAMzvi4yHTvMiiPMSHOzFKIOll_hQU1jx0S_e8ZRJLW9D5/s1600/voice.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="128" data-original-width="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi56BqXlZMB7CxCZvKt_F5lSLy7jykqHRnovCIM7MqYBgEq9d-frIjNDEBSHGZteALX89L3Ktu9hdeCWacpdiMQL_Rim6TF6nSAMzvi4yHTvMiiPMSHOzFKIOll_hQU1jx0S_e8ZRJLW9D5/s1600/voice.bmp" /></a></div>
<br />
<u>Общий алгоритм работы нашего робота таков:</u><br />
1) Стартуем процесс записи и анализируем приходящие со звуковой платы данные небольшими порциями, оценивая громкость. Как только она превысит заданный порог - начинаем запись заданной (избыточной для фразы) длительности, например 2 секунлы<br />
2) Анализируем полученный звуковой отрезок (сэмпл) на предмет выделения на нем слова (фразы).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr1M536NVxOxyl9uItPydTGcjKVqN78143J8C1pJ23l0CgEFsQYUnj7lUooFape-rm2Lg8RtyYxqY4hNviDv82mMQFogmWhQBBxadq8FAwf6gZfbopBU5X2afpomt0tuYa6zaIZsDjA6_G/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="120" data-original-width="390" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr1M536NVxOxyl9uItPydTGcjKVqN78143J8C1pJ23l0CgEFsQYUnj7lUooFape-rm2Lg8RtyYxqY4hNviDv82mMQFogmWhQBBxadq8FAwf6gZfbopBU5X2afpomt0tuYa6zaIZsDjA6_G/s320/1.png" width="320" /></a></div>
<br />
Так как мы начинали запись активацией по пороговому значению, слово всегда будет в начале сэмпла, а вот конец нужно обрезать:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_kf1Yc8muzZL16971Cf96FTki1GE0ZOqQGmIoiZazoBp0_afisVtfpAJlV1gU0Tusyoq6H4FfMH1wFlkAQ5gsMxVOfcK4noEBhSQyOlnmTr740Eh_F3Z5rliMVjSDdlqTh46tG0nS-O1J/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="120" data-original-width="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_kf1Yc8muzZL16971Cf96FTki1GE0ZOqQGmIoiZazoBp0_afisVtfpAJlV1gU0Tusyoq6H4FfMH1wFlkAQ5gsMxVOfcK4noEBhSQyOlnmTr740Eh_F3Z5rliMVjSDdlqTh46tG0nS-O1J/s1600/2.png" /></a></div>
<br />
3) Воспроизводим сэмпл для мониторинга корректности его записи и выделения слова.<br />
4) Разбиваем звуковой фрагмент на небольшие интервалы, длительностью около 20 мс. Лучший результат получается если разбивать на интервалы, перекрывающиеся н 50%, в этом случае скорость произношения фразы не будет заметно влиять на результат распознавания.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrohiDVx6nnCpYE3nALQnIQnQ7wa6y0B_lW5vn0RV_aioo942KvDr__lwTAf-QJ5STFtMVrOTsHwIfoawVqCUq_zSGE_XXHckQNmhLxQLBrMKuDFQK93CX28ISKU6owhZwMu3ZelJ70Xq7/s1600/5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="117" data-original-width="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrohiDVx6nnCpYE3nALQnIQnQ7wa6y0B_lW5vn0RV_aioo942KvDr__lwTAf-QJ5STFtMVrOTsHwIfoawVqCUq_zSGE_XXHckQNmhLxQLBrMKuDFQK93CX28ISKU6owhZwMu3ZelJ70Xq7/s1600/5.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
5) Анализируем каждый отрезок, выделяя в нем частоты с максимальной "громкостью". Частотный анализ фрагмента можно выполнить используя встроенную в NumPy функция быстрого преобразования Фурье.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPfYZd4Jxcuo_lZZUgL4gp8qPRHnJH1uJf4Qpg_9awKmrV5Eter_7Llndhy_a45gHmKXybyoIfFbZMD8V17g03ynVLFZFXQhr_jgXimJGhi4dbcN24p24Sj-qr2PLQGHEACI9RA5xVUoU8/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="373" data-original-width="746" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPfYZd4Jxcuo_lZZUgL4gp8qPRHnJH1uJf4Qpg_9awKmrV5Eter_7Llndhy_a45gHmKXybyoIfFbZMD8V17g03ynVLFZFXQhr_jgXimJGhi4dbcN24p24Sj-qr2PLQGHEACI9RA5xVUoU8/s400/4.png" width="400" /></a></div>
<br />
На рисунке выделено 8 таких частот.<br />
6) Получаем двумерную матрицу, содержащую несколько наиболее выраженным частот в каждом отрезке:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivnMpP5fJfyE0XrNxr3lnud-mqRHwQxOFfbNttRVsk0je7PZxfHOjWjJ7bzbvcLr552cGrjewDHnDpFmswb8jvY_QKmVC2wFrJ6YYe0Ts7lbTWozGiNCHdaT302fRY8O_McUFVZ9NyAJ1d/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="321" data-original-width="661" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivnMpP5fJfyE0XrNxr3lnud-mqRHwQxOFfbNttRVsk0je7PZxfHOjWjJ7bzbvcLr552cGrjewDHnDpFmswb8jvY_QKmVC2wFrJ6YYe0Ts7lbTWozGiNCHdaT302fRY8O_McUFVZ9NyAJ1d/s400/7.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
7) Сохраняем матрицу в виде именованного образца. Для каждого слова (голосовой команды) нужно записать несколько таких образков, с разной интонацией, можно разными голосами, если это необходимо.</div>
<div class="separator" style="clear: both; text-align: left;">
8) Чтобы распознать слово-команду необходимо выполнить наги 1-5 и сравнить полученную матрицу с сохраненными образцами. Здесь есть несколько вариантов:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul style="text-align: left;">
<li>Найти самый похожий образец</li>
<li>Найти группу образцов, к которой анализируемый ближе всего</li>
<li>Скомбинировать поиск по близости к образцу и по близости к группе образцов. Если, например, анализируемый образец ближе всего к группе с образцами "Влево" и, одновременно, ближе в образцу "Вправо", у робота появляется возможность ответить "Не понял команды, повторите!".</li>
<li>Использовать нейронную сеть, обученную на записанных образцах.</li>
</ul>
В проекте мы используем третий вариант, а четвертый в данный момент изучаем.<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div style="text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/s3l4q-Ixk8o/0.jpg" src="https://www.youtube.com/embed/s3l4q-Ixk8o?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com3tag:blogger.com,1999:blog-4279357166628593719.post-25875016847497274632018-01-27T08:59:00.002-08:002018-01-27T09:00:01.646-08:00MindSnake3D<div dir="ltr" style="text-align: left;" trbidi="on">
Пару недель назад <a href="https://vk.com/club56906164">в нашей группе VK</a> был запущен опрос, для чего предназначен робот на фото?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1sp6kZD_eltHFt2kxam9Mh_8mCQStVU1Uj3lQ_bSFWcQoiOw1gbvYn2ajnnKCIfvoZ9rM08TgJvW8lmeE5OwN578mxhgInProtdfTvwUe5H4-Bk9G6EONoCrJK98droZBnE2unD2CV7x4/s1600/1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1sp6kZD_eltHFt2kxam9Mh_8mCQStVU1Uj3lQ_bSFWcQoiOw1gbvYn2ajnnKCIfvoZ9rM08TgJvW8lmeE5OwN578mxhgInProtdfTvwUe5H4-Bk9G6EONoCrJK98droZBnE2unD2CV7x4/s400/1.jpg" width="400" /></a></div>
<br />
Подсказки были таковы:<br />
1) проект носит развлекательный характер<br />
2) робот использует трехмерные массивы<br />
3) разработка проекта ведется на языке С, однако сам проект тесно связан с другим языком программирования, который нам очень нравится<br />
4) Шелдону Куперу он наверняка пришелся бы по душе.<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_DdGtT0bLmNb3YoYA2VXJ-1gUJAruYuwxjwUQlaCbDpd9LqqMi4AUrlqn2UDpIo8jigL9V8f6N1FZFCbbGdlFhJ1owqqoS9SovVCRP34vrkRAoUXaegXXkAEKl5PwIT2adzMA4Z8XeluA/s1600/MindSnake3D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="902" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_DdGtT0bLmNb3YoYA2VXJ-1gUJAruYuwxjwUQlaCbDpd9LqqMi4AUrlqn2UDpIo8jigL9V8f6N1FZFCbbGdlFhJ1owqqoS9SovVCRP34vrkRAoUXaegXXkAEKl5PwIT2adzMA4Z8XeluA/s400/MindSnake3D.jpg" width="400" /></a></div>
<br /></div>
<div>
Пришла пора приоткрыть завесу тайны. На каникулах мы тоже любим отдыхать, поэтому наш очередной проект, о котором сегодня пойдет речь, действительно носит развлекательный характер. Наверное многие из вас играли в знаменитую игру Snake ("Змейка"), она портирована на множество различных платформ, а наибольшую популярность получила будучи предустановленной на телефонах Nokia (подсказка №3: Питон - змея).</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzN9xAXFSV0WCghm9RQSg7ArdGwTc6Rh_DzwZaDbtPgGTXpXLIGbl2ugxGBqr_3G7eyIhAohHpr98g-PMzfOr4aPBFBgN0TFDSMUEP7Hf8Fc6HTDX0pSmm7_KiS7XLdKxmChi2EtpUPMv/s1600/2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="980" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzN9xAXFSV0WCghm9RQSg7ArdGwTc6Rh_DzwZaDbtPgGTXpXLIGbl2ugxGBqr_3G7eyIhAohHpr98g-PMzfOr4aPBFBgN0TFDSMUEP7Hf8Fc6HTDX0pSmm7_KiS7XLdKxmChi2EtpUPMv/s400/2.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Змейка ползает по полю, поедая пищу, удлинняясь от каждой съеденной порции. Если змейка врезается в ограждение поля или в свой хвост - она погибает и игра начинается сначала. Цель игры - вырастить как можно более длинную змейку.</div>
<div>
Мы давно хотели сделать эту игру на платформе LEGO Mindstorms, но интересная реализация никак не вырисовывалась. Создавать очередной клон на экране NXT или EV3 блока нам не хотелось, а реализовать змейку в механике похоже не по зубам даже гуру LEGO-роботостроения. </div>
<div>
Наконец, когда пришла пора изучить трехмерные массивы - все сложилось и идея обрела законченную форму. Далеким прототипом стал наш наш проект 2015 года - <a href="http://karandashsamodelkin.blogspot.ru/2015/10/ev3_28.html">EV3 Муха</a>. В этой игре в уме (или "мыслилке", как мы называем такого типа развлечения) мы должны были двигать воображаемую муху по плоскому полю. </div>
<div>
В проекте MinSnake мы добавим пищи для ума в виде еще одного измерения. Наша змейка будет ползать в 3D-кубе, который игрок должен представить в уме, управление головой змеи мы реализовали в конструкции. Все игровые события робот озвучивает голосом, экран блока в геймплее не используется. Змейка как и в классическом варианте не должна выползти за пределы игрового поля (куба) и не должна врезаться сама в себя (в свой хвост). Заморочено, правла? Шелдону Куперу точно бы понравилось!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK5nlly-yQvyDPfWVS0IP4t6aBWN9t_GzKAaUohyphenhyphen8rOYyQevIMrPp4r3mOETgPp6Jrfhm7hivwZoGhudgXyiIzQuNyJrkjTNVGbVzrTpkFvU1D6ZmFfA2yk5_GsAfciEfqboloRzeJCMen/s1600/3dcube.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="534" data-original-width="931" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK5nlly-yQvyDPfWVS0IP4t6aBWN9t_GzKAaUohyphenhyphen8rOYyQevIMrPp4r3mOETgPp6Jrfhm7hivwZoGhudgXyiIzQuNyJrkjTNVGbVzrTpkFvU1D6ZmFfA2yk5_GsAfciEfqboloRzeJCMen/s400/3dcube.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Исходные данные таковы:</div>
<div>
- куб имеет размер 3x3 пиксела</div>
<div>
- змейка на старте имеет длину = 1, стартует из центра (ячейка 2,2,2)</div>
<div>
- стартовое направление в начале игры - направо</div>
<div>
- в зависимости от выбранного уровня сложности на ход дается в среднем 5 секунд, за это время игрок должен выбрать одно из 6 направлений движения (вверх-вниз-влево-вправо-к себе-от себя), в соответствии с которым змейка передвинется по истечении времени хода. На каждый следующий ход дается на несколько миллисекунд меньше чем на предыдущий</div>
<div>
- еда появляется в кубе случайным образом, на свободном от змейки месте. Робот называет ячейку где именно. Чтобы не путаться в координатах озвучивается слой сверху вниз (1-2-3) и номер ячейки 1..9 по телефонному принципу (см. рис)</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxbWBIUx6VnPCjCK8WKzkP8g6CKCe2yPRnL7wMe6I95nSze20KY3AdPVQgWZveuWLikyTlk9ODwaAZO1C_IY05UFQC8hIa9e1tB4jV97MWxZzqwRA8_MH_Mzk7z7K9nKZ1SwuqaZ97x_YR/s1600/3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="127" data-original-width="294" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxbWBIUx6VnPCjCK8WKzkP8g6CKCe2yPRnL7wMe6I95nSze20KY3AdPVQgWZveuWLikyTlk9ODwaAZO1C_IY05UFQC8hIa9e1tB4jV97MWxZzqwRA8_MH_Mzk7z7K9nKZ1SwuqaZ97x_YR/s320/3.jpg" width="320" /></a></div>
<div>
<br /></div>
<div>
- при совпадении головы змеи с ячейкой, в которой лежит еда, змейка удлинняется - при движении в такую ячейку хвост не подтягивается, за счет чего обеспечивается рост<br />
- если змейка не успела за отведенное время доползти до ячейки с едой, пища исчезает и появляется в новом месте. Время зависит от текущего уровня сложности<br />
- по достижению заданной на данном увроне длины змейки игра переходит на следующий уровень сложности (3 уровня).</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/xScVbf7EWtc/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/xScVbf7EWtc?feature=player_embedded" width="320"></iframe></div>
<br /></div>
<div>
Инструкцию по сборке нашего проекта в формате LEGO Digital Designer и программу к роботу вы можете <a href="https://github.com/darkavengersmr/MindSnake3D">скачать по ссылке.</a></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOat7KKW-KqEejCIn0CLbNMBqS2UDoR-tEKgduvsybMIEZMN9j1vJU2q3xqw2IgAQW1APFxKN4L-OUn5H07T2ze8TEUkzJcerfeXaSnXsmgfgHsnUMv64Nz9z12IAJUxPtYG80d6yMCr2Z/s1600/234.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="747" data-original-width="1327" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOat7KKW-KqEejCIn0CLbNMBqS2UDoR-tEKgduvsybMIEZMN9j1vJU2q3xqw2IgAQW1APFxKN4L-OUn5H07T2ze8TEUkzJcerfeXaSnXsmgfgHsnUMv64Nz9z12IAJUxPtYG80d6yMCr2Z/s400/234.png" width="400" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b>Исходный код программы на языке NXC</b>: <input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Close'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Open'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 60px;" type="button" value="Open/Close" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
struct coord{<br />
int x;<br />
int y;<br />
int z;<br />
};<br />
<br />
coord head;<br />
coord eda;<br />
coord max;<br />
<br />
int snake[3][3][3];<br />
<br />
void food(){<br />
while(true){<br />
eda.x=Random(2999)/1000.0;<br />
eda.y=Random(2999)/1000.0;<br />
eda.z=Random(2999)/1000.0;<br />
if(snake[eda.x][eda.y][eda.z]==0){<br />
break;<br />
}<br />
}<br />
}<br />
<br />
int otkl(int a, int b)<br />
{<br />
return ((a+36000)%360 + 540 - b)%360 - 180;<br />
}<br />
<br />
int direct(){<br />
if(abs(otkl(MotorRotationCount(OUT_B),0))<=45){<br />
return 4;<br />
}<br />
if(abs(otkl(MotorRotationCount(OUT_B),180))<=45){<br />
return 5;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),0))<=45 && abs(otkl(MotorRotationCount(OUT_B),90))<=45){<br />
return 3;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),0))<=45 && abs(otkl(MotorRotationCount(OUT_B),270))<=45){<br />
return 2;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),90))<=45 && abs(otkl(MotorRotationCount(OUT_B),90))<=45){<br />
return 1;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),90))<=45 && abs(otkl(MotorRotationCount(OUT_B),270))<=45){<br />
return 0;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),180))<=45 && abs(otkl(MotorRotationCount(OUT_B),90))<=45){<br />
return 3;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),180))<=45 && abs(otkl(MotorRotationCount(OUT_B),270))<=45){<br />
return 2;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),270))<=45 && abs(otkl(MotorRotationCount(OUT_B),90))<=45){<br />
return 1;<br />
}<br />
<br />
if(abs(otkl(MotorRotationCount(OUT_A),270))<=45 && abs(otkl(MotorRotationCount(OUT_B),270))<=45){<br />
return 0;<br />
}<br />
<br />
return -1;<br />
}<br />
int time_hod=5000;<br />
int direction=4;//0-туда1-обратно2-вверх3-вниз4-вправо5-влево<br />
int eda_farther=0;<br />
int maxa=0;<br />
int direction_old=4;<br />
long ti;<br />
int len=1;<br />
int level=0;<br />
int len_up;<br />
task main()<br />
{<br />
ClearScreen();<br />
//TextOut(0,16,"Easy");<br />
//TextOut(0,8,"Normal");<br />
//TextOut(0,0,"Hard");<br />
Wait(1000);<br />
while(ButtonPressed(BTNCENTER,0)<br />
&& ButtonPressed(BTNLEFT,0)<br />
&& ButtonPressed(BTNRIGHT,0)){<br />
<br />
}<br />
if(ButtonPressed(BTNCENTER,1)){<br />
level=2;<br />
len_up=9;<br />
time_hod=5000;<br />
ClearScreen();<br />
// TextOut(0,0,"Normal");<br />
}<br />
if(ButtonPressed(BTNLEFT,1)){<br />
level=1;<br />
len_up=3;<br />
time_hod=5000;<br />
ClearScreen();<br />
// TextOut(0,0,"Easy");<br />
}<br />
if(ButtonPressed(BTNRIGHT,1)){<br />
level=3;<br />
len_up=9;<br />
time_hod=3000;<br />
ClearScreen();<br />
// TextOut(0,0,"Hard");<br />
}<br />
Wait(3000);<br />
<br />
eda.x=10;<br />
eda.y=10;<br />
eda.z=10;<br />
head.x=1;<br />
head.y=1;<br />
head.z=1;<br />
PlayFile("start.rso");<br />
PlayFile("center.rso");<br />
ResetRotationCount(OUT_AB);<br />
direction=direct();<br />
for(int i=0;i<=2;i++){<br />
for(int z=0;z<=2;z++){<br />
for(int q=0;q<=2;q++){<br />
snake[i][z][q]=0;<br />
}<br />
}<br />
}<br />
snake[1][1][1]=1;<br />
long time=CurrentTick();<br />
long time_eda=CurrentTick();<br />
while(true){<br />
if(len==len_up && level==3){<br />
break;<br />
PlayFile("levelup.rso");<br />
}<br />
if(len==len_up && level==2){<br />
level=3;<br />
len_up=9;<br />
time_hod=3000;<br />
PlayFile("levelup.rso");<br />
Wait(1000);<br />
}<br />
if(len==len_up && level==1){<br />
level=2;<br />
len_up=6;<br />
PlayFile("levelup.rso");<br />
Wait(1000);<br />
}<br />
<br />
direction_old=direction;<br />
direction=direct();<br />
<br />
if(direction!=direction_old){<br />
switch(direction)<br />
{<br />
case 0:<br />
PlayFile("farther.rso");<br />
Wait(1000);<br />
break;<br />
case 1:<br />
PlayFile("closer.rso");<br />
Wait(1000);<br />
break;<br />
case 2:<br />
PlayFile("up.rso");<br />
Wait(1000);<br />
break;<br />
case 3:<br />
PlayFile("down.rso");<br />
Wait(1000);<br />
break;<br />
case 4:<br />
PlayFile("right.rso");<br />
Wait(1000);<br />
break;<br />
case 5:<br />
PlayFile("left.rso");<br />
Wait(1000);<br />
break;<br />
default:<br />
break;<br />
}<br />
}<br />
if(CurrentTick()-time_eda>=20000){<br />
time_eda=CurrentTick();<br />
food();<br />
PlayFile("food.rso");<br />
Wait(1000);<br />
if(eda.y==0){<br />
PlayFile("3.rso");<br />
Wait(1000);<br />
}<br />
if(eda.y==1){<br />
PlayFile("2.rso");<br />
Wait(1000);<br />
}<br />
if(eda.y==2){<br />
PlayFile("1.rso");<br />
Wait(1000);<br />
}<br />
if(eda.z==2){<br />
if(eda.x==0){<br />
PlayFile("1.rso");<br />
Wait(1000);<br />
}<br />
if(eda.x==1){<br />
PlayFile("2.rso");<br />
Wait(1000);<br />
}<br />
if(eda.x==2){<br />
PlayFile("3.rso");<br />
Wait(1000);<br />
}<br />
}<br />
if(eda.z==1){<br />
if(eda.x==0){<br />
PlayFile("4.rso");<br />
Wait(1000);<br />
}<br />
if(eda.x==1){<br />
PlayFile("5.rso");<br />
Wait(1000);<br />
}<br />
if(eda.x==2)<br />
{<br />
PlayFile("6.rso");<br />
Wait(1000);<br />
}<br />
}<br />
if(eda.z==0){<br />
if(eda.x==0){<br />
PlayFile("7.rso");<br />
Wait(1000);<br />
}<br />
if(eda.x==1){<br />
PlayFile("8.rso");<br />
Wait(1000);<br />
}<br />
if(eda.x==2){<br />
PlayFile("9.rso");<br />
Wait(1000);<br />
}<br />
}<br />
<br />
}<br />
if(CurrentTick() - ti>=1000){<br />
ti=CurrentTick();<br />
// ClearScreen();<br />
// NumOut(10,0,eda.z);<br />
// / NumOut(10,8,eda.y);<br />
// NumOut(10,16,eda.x);<br />
// NumOut(0,0,head.z);<br />
/// NumOut(0,8,head.y);<br />
// NumOut(0,16,head.x);<br />
// NumOut(0,24,direction);<br />
// NumOut(5,0,len);<br />
}<br />
if(CurrentTick()-time>=time_hod){<br />
PlayTone(440,100);<br />
time_hod=time_hod-10;<br />
<br />
time=CurrentTick()<br />
if(head.x==2 && direction==4<br />
|| head.x==0 && direction==5<br />
|| head.y==2 && direction==2<br />
|| head.y==0 && direction==3<br />
|| head.z==2 && direction==0<br />
|| head.z==0 && direction==1){<br />
break;<br />
}<br />
<br />
eda_farther=0;<br />
<br />
if(direction==0 && head.x==eda.x && head.y==eda.y && head.z+1==eda.z){<br />
eda_farther=1;<br />
}<br />
if(direction==1 && head.x==eda.x && head.y==eda.y && head.z-1==eda.z){<br />
eda_farther=1;<br />
}<br />
if(direction==2 && head.x==eda.x && head.y+1==eda.y && head.z==eda.z){<br />
eda_farther=1;<br />
}<br />
if(direction==3 && head.x==eda.x && head.y-1==eda.y && head.z==eda.z){<br />
eda_farther=1;<br />
}<br />
if(direction==4 && head.x+1==eda.x && head.y==eda.y && head.z==eda.z){<br />
eda_farther=1;<br />
}<br />
if(direction==5 && head.x-1==eda.x && head.y==eda.y && head.z==eda.z){<br />
eda_farther=1;<br />
}<br />
for(int i=0;i<=2;i++){<br />
for(int z=0;z<=2;z++){<br />
for(int q=0;q<=2;q++){<br />
if(snake[i][z][q]!=0){<br />
snake[i][z][q]+=1;<br />
}<br />
}<br />
}<br />
}<br />
max=0;<br />
for(int i=0;i<=2;i++){<br />
for(int z=0;z<=2;z++){<br />
for(int q=0;q<=2;q++){<br />
if(snake[i][z][q]>maxa){<br />
maxa=snake[i][z][q];<br />
max.x=i;<br />
max.y=z;<br />
max.z=q;<br />
}<br />
}<br />
}<br />
}<br />
<br />
if(eda_farther==0){<br />
snake[max.x][max.y][max.z]=0;<br />
}<br />
else{<br />
len++;<br />
time_eda=CurrentTick();<br />
eda.x=10;<br />
eda.y=10;<br />
eda.z=10;<br />
PlayFile("len.rso");<br />
Wait(1000);<br />
}<br />
maxa=0;<br />
max.x=0;<br />
max.y=0;<br />
max.z=0;<br />
if(direction==0){<br />
if(snake[head.x][head.y][head.z+1]==0){<br />
snake[head.x][head.y][head.z+1]=1;<br />
head.z++;<br />
}<br />
else{<br />
break;<br />
}<br />
}<br />
if(direction==1){<br />
if(snake[head.x][head.y][head.z-1]==0){<br />
snake[head.x][head.y][head.z-1]=1;<br />
head.z--;<br />
}<br />
else{<br />
break;<br />
}<br />
}<br />
if(direction==2){<br />
if(snake[head.x][head.y+1][head.z]==0){<br />
snake[head.x][head.y+1][head.z]=1;<br />
head.y++;<br />
}<br />
else{<br />
break;<br />
}<br />
}<br />
if(direction==3){<br />
if(snake[head.x][head.y-1][head.z]==0){<br />
snake[head.x][head.y-1][head.z]=1;<br />
head.y--;<br />
}<br />
else{<br />
break;<br />
}<br />
}<br />
if(direction==4){<br />
if(snake[head.x+1][head.y][head.z]==0){<br />
snake[head.x+1][head.y][head.z]=1;<br />
head.x++;<br />
}<br />
else{<br />
break;<br />
}<br />
}<br />
if(direction==5){<br />
if(snake[head.x-1][head.y][head.z]==0){<br />
snake[head.x-1][head.y][head.z]=1;<br />
head.x--;<br />
}<br />
else{<br />
break;<br />
}<br />
}<br />
direction=direct();<br />
}<br />
}<br />
PlayFile("end.rso");<br />
Wait(1000);<br />
}</div>
<div>
<br /></div>
</div>
<br /></div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-32053084723358816932017-12-17T06:19:00.002-08:002017-12-17T06:39:52.727-08:00SwarmLINEr<div dir="ltr" style="text-align: left;" trbidi="on">
В одном из предыдущих проектов, <a href="http://karandashsamodelkin.blogspot.ru/2017/11/geneliner.html">GeneLiNEr</a>, мы сделали очередной небольшой шажок в сторону искусственного интеллекта, опробовав в деле генетический алгоритм, создали на его основе робота, который самостоятельно учится двигаться по линии быстрее и точнее.<br />
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDhSFlIvJUEpxC38JoS2p8UnUay14TBjp8fyS3bSmhx9pElSBPb_6YIYMwBz_rb1SH28nm0crKlvwf6TfUWqNulFkg6udY7K82H3g6wTX2wfWUzieKySnDMcwK9sjJf7S0R64kKqBIaaDT/s1600/SwarmLINEr.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDhSFlIvJUEpxC38JoS2p8UnUay14TBjp8fyS3bSmhx9pElSBPb_6YIYMwBz_rb1SH28nm0crKlvwf6TfUWqNulFkg6udY7K82H3g6wTX2wfWUzieKySnDMcwK9sjJf7S0R64kKqBIaaDT/s400/SwarmLINEr.jpg" width="400" /></a></div>
<br /></div>
<div>
<div>
Мы не стали разбирать построенного робота и задумали "решить задачу другим способом", применив в этот раз иной метод, входящий в общую теорию искусственного интеллекта. Это подвид роевого интеллекта под названием <b>алгоритм роя частиц</b>.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt-xOpsGZizPhIgsnq3G00sfBeaj6Wwp85ClW_Erx4SjXnQ8b9QVvn9Ek50bsdHK0SK9rES1UahZP1jgPeqqizejB-HF0MBQ-0tWWSpIAMFCWU5u8CH8N2AmTT2nhk1Lu-G6AjkFib1L1F/s1600/123.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="321" data-original-width="595" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt-xOpsGZizPhIgsnq3G00sfBeaj6Wwp85ClW_Erx4SjXnQ8b9QVvn9Ek50bsdHK0SK9rES1UahZP1jgPeqqizejB-HF0MBQ-0tWWSpIAMFCWU5u8CH8N2AmTT2nhk1Lu-G6AjkFib1L1F/s400/123.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Системы роевого интеллекта, как правило, состоят из множества особей (агентов) взаимодействующих между собой и с окружающей средой. Идеи поведения, как правило, исходят от живой природы, а в особенности, от биологических систем. Каждый агент следует очень простым правилам и, несмотря на то, что нет какой-то централизованной системы управления поведением, которая бы указывала каждому из них на то, что ему следует делать, их взаимодействия приводят к возникновению разумного глобального поведения, не подконтрольного отдельным агентам.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Метод роя частиц в общем виде формулируется очень заумно, поэтому давайте попробуем описать его по простому, доступным языком. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiIWfPEo9_bB4mHExGCNAm7oUIg7x_X7X717l1W6-O6eCvO0wkSGI8E7-1IayZRRlrDPvJgg_jbg4HIstKomU5dnb1MrI_cEGSTAHr42slamZsoJGiDMhn5UibhTuU714xw8Kua6FJGQ-B/s1600/234.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="232" data-original-width="350" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiIWfPEo9_bB4mHExGCNAm7oUIg7x_X7X717l1W6-O6eCvO0wkSGI8E7-1IayZRRlrDPvJgg_jbg4HIstKomU5dnb1MrI_cEGSTAHr42slamZsoJGiDMhn5UibhTuU714xw8Kua6FJGQ-B/s320/234.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Итак, представьте себе стаю птиц. Каждая птица - это агент нашего алгоритма. Условимся, что наши птицы - из тех, которые не имеют в стае четко выраженного вожака. Несмотря на то, что каждая птица не обладает достаточным интеллектом чтобы управлять стаей, однако стая в целом проявляет вполне себе разумное поведение:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul style="text-align: left;">
<li>птицы в стае почти никогда не сталкиваются в воздухе</li>
<li>стая двигается плавно и скоординировано, словно ей кто-то управляет</li>
<li>кружа в небе, каждая из птиц следит за своими сородичами и корректирует свое движение согласно их положению</li>
<li>найдя источник пищи, она оповестит об этом остальных.</li>
</ul>
<div class="separator" style="clear: both; text-align: left;">
Именно оповещение других особей стаи о найденной пище и является основой рассматриваемого алгоритма. Такое странное поведение птиц было исследовано многими учеными, но они пока не сошлись во мнении, почему так происходит. Источники пищи располагаются обычно довольно случайным образом и отдельно взятая птица может летать довольно долго, но так и не найдя пищу, погибнет. С одной стороны, получив сигнал о расположении пищи, птица скорректирует свое направление и полетит к ней, что повышает ее шансы на выживание. С другой стороны, птицам приходится конкурировать с другими особями за найденную пищу, так как количество ее ограничено.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1OViOhPk8ibTQvi3PRLnhw9rmcwcHnwq6R-CbbRlMjdeWYB46XcrNANrIFmWURZMITz-wsWcxCPfXzHAt-0YDItfW_zDmZbS3rY8UNiwn3G6OkiW2fpMHDfKAqC55YGu2z8kgslGQPz9J/s1600/123.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="560" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1OViOhPk8ibTQvi3PRLnhw9rmcwcHnwq6R-CbbRlMjdeWYB46XcrNANrIFmWURZMITz-wsWcxCPfXzHAt-0YDItfW_zDmZbS3rY8UNiwn3G6OkiW2fpMHDfKAqC55YGu2z8kgslGQPz9J/s400/123.gif" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Алгоритм роя частиц моделирует такую стаю в памяти робота (компьютера), в нем птицы (агенты) совместно ищут источник пищи (оптимальное решение задачи), обмениваясь при этом информацией с соседями. С помощью алгоритма роя частиц мы снова будем искать лучшие коэффициенты для ПИД-регулятора, чтобы робот научился более быстрому и четкому движению по линии. Загружая текущие характеристики каждой птицы (агента) в физического робота, мы будем проводить автоматизированное испытание каждой особи, оценивая качество найденного ею решения задачи. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
В общем виде алгоритм выглядит так:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgfl4A3Zud0HWSRSGZnj8dqvwNmnxSSopcKQmia4d1tqTaAro9kgtFYC8IIawlrOFPbVOnp_OfbihoJPzSRjVhyEUs4-X6LAET4GSLN9xgfPcA5P_HoI8NQG23QAKCXbA2F58nyfSFiSgQ/s1600/345.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="401" data-original-width="481" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgfl4A3Zud0HWSRSGZnj8dqvwNmnxSSopcKQmia4d1tqTaAro9kgtFYC8IIawlrOFPbVOnp_OfbihoJPzSRjVhyEUs4-X6LAET4GSLN9xgfPcA5P_HoI8NQG23QAKCXbA2F58nyfSFiSgQ/s400/345.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Переведем алгоритм на "птичий язык". Создаем стаю птиц, причем в начальный момент времени они располагаются случайным образом равномерно в пределах определенной территории. Каждая из них начинает лететь в случайном направлении, осматривая окружающее пространство, каждый раз сигнализируя остальным сколько пищи она нашла и где она располагается. Остальные птицы, продолжая поиск, стараются, с одной стороны держаться поближе к месту, где эта птица нашла пищи больше всего, а с другой - старается направить свое движение к месту, где пищи больше всего по общему мнению стаи. Во время полета к этому "сытному месту" поиск продолжается, место, где пищи больше уточняется каждой птицей. Если птица вылетела за пределы территории то она пересоздается в случайном месте, ей задается случайное направление движения и она продолжает поиск по прежнему алгоритму.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Применительно к нашей задаче - долгота каждой птицы на карте - это значение П-коэффициента ПИД-регулятора, широта - значение Д-коэффициента, высота - значение И-коэффициента. Птицы должны найти такую точку в пространстве, в которой скорость движения робота по линии со значениями коэффициентов регулятора, соответствующих этой точке, будет наивысшей. Если робот слетает с линии, будем ограничивать результат, не давая птицам считать это хорошим решением задачи. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Попробуем реализовать алгоритм на практике. Конструкция робота полностью повторяет <a href="http://karandashsamodelkin.blogspot.ru/2017/11/geneliner.html">GeneLINErа</a>, инструкцию по сборке которого можно скачать по <a href="https://github.com/darkavengersmr/SwarmLINEr">ссылке</a>. Программировать LEGO Mindstorms NXT мы снова будем на полюбившемся нам <a href="http://bricxcc.sourceforge.net/">NXC</a>. Код нашей программы можно скачать <a href="https://github.com/darkavengersmr/SwarmLINEr">здесь</a>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Первым делом давайте опишем каждую птицу (агента)</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">struct agent</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">{</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // скорость агента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float speed;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // текущий П-коэффициент ПИД-регулятора у агента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float Kp;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // текущий И-коэффициент у агента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float Ki;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // текущий Д-коэффициент </span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float Kd;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // динамика изменения скорости у агента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float change_speed;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // динамика изменения П-коэффициента у агента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float change_Kp;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // динамика изменения И-коэффициента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float change_Ki;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // динамика изменения Д-коэффициента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float change_Kd;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">// лучшее значение П-коэффициента, найденное агентом</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float best_Kp;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // лучшее значение И-коэффициента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float best_Ki;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // лучшее значение Д-коэффициента</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float best_Kd;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // скорость, соответствующая лучшим значением </span><span style="font-family: "courier new" , "courier" , monospace;">коэффициентов</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> float best_speed;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // максимальная длина пути с лучшими из найденных параметров</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> long best_path;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> // текущий путь, пройденный за время последнего испытания</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> long path;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">};</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both;">
При создании каждого агента случайно сгенерируем его начальные параметры в некотором диапазоне с помощью функции born(). </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
В нашем случае мы полагаем что оптимальные параметры лежат в диапазоне</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<i>0 < Kp < 2</i></div>
<div class="separator" style="clear: both;">
<i>0 < Ki < 0.1</i></div>
<div class="separator" style="clear: both;">
<i>0 < Kd < 4</i></div>
<div class="separator" style="clear: both;">
<i>0 < speed < 100</i></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
а динамику их изменения установим в +/- 2..5%</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<i>-0.1 < change_Kp < 0.1</i></div>
<div class="separator" style="clear: both;">
<i>-0.005 < change_Ki < 0.005</i></div>
<div class="separator" style="clear: both;">
<i>-0.2 < change_Kd < 0.2</i></div>
<div class="separator" style="clear: both;">
<i>-2 < change_speed < 2</i></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">agent born(){</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> agent tmp;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.speed = Random(70)+30;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.Kp = Random(2000)/1000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.Ki= Random(10000)/100000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.Kd= Random(4000)/1000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.change_speed=(Random(4000)-2000)/1000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.change_Kp=(Random(2000)-1000)/10000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.change_Ki=(Random(1000)-500)/100000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.change_Kd=(Random(4000)-2000)/10000.0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.path = 0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> tmp.best_path=0;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> return tmp;</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
Создадим 10 птиц (агентов):</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">agents = 10</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">agent robot[agents];</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">for(int i=0;i<agents;i++){</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i]=born();</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
Еще одного агента создадим в качестве хранилища для лучшего найденного решения:</div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new" , "courier" , monospace;">agent best;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
Теперь испытаем каждую птицу, "узнаем сколько пищи он нашла" в тех координатах, в которых она сейчас находится. Функция pid() для испытания особей в целом не претерпела изменений по сравнению с <a href="http://karandashsamodelkin.blogspot.ru/2017/11/geneliner.html">GeneLINEr</a>, за исключением последнего параметра - это длительность испытания в миллисекундах.</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=0;i<agents;i++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].path = pid(robot[i].Kp,robot[i].Ki</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ,</span><span style="font-family: "courier new" , "courier" , monospace;">robot[i].Kd,robot[i].speed,2000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> // </span><span style="font-family: "courier new" , "courier" , monospace;">сохраняем</span><span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">лучшее общее решение, найденное стаей</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(robot[i].path>best.path){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> best.path=robot[i].path;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> best.speed=robot[i].speed;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> best.Kp=robot[i].Kp;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> best.Ki=robot[i].Ki;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> best.Kd=robot[i].Kd; </span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> // сохраняем лучшее решение, найденное каждой птицей</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(robot[i].path>robot[i].best_path){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].best_path=robot[i].path;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].best_speed=robot[i].speed;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].best_Kp=robot[i].Kp;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].best_Ki=robot[i].Ki;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].best_Kd=robot[i].Kd;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
Теперь самое сложное в алгоритме - коррекция скорости, направления полета и положения каждой птицы.</div>
<div>
<br /></div>
<div>
Сначала введем два параметра:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">float nostalgia =0.25;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">float confidence=0.75;</span></div>
</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Nostalgia</span> - это стремление птицы быть поближе к тому месту, где она нашла пищи больше всего. <span style="font-family: "courier new" , "courier" , monospace;">Confidence</span> - стремление птицы быть поближе месту, где пиши больше всего по общему мнению стаи.</div>
<div>
<br />
Формула для корректировки скорости изменения каждого параметра имеет вид:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b>СКОРОСТЬ_ИЗМЕНЕНИЯ_ПАРАМЕТРА = СКОРОСТЬ_ИЗМЕНЕНИЯ_ПАРАМЕТРА</b></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> + Nostalgia * СЛУЧАЙНОЕ_ЧИСЛО(0..1) </b></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> * (ЛУЧШЕЕ_ЗНАЧЕНИЕ_ПАРАМЕТРА_ОСОБИ - ТЕКУЩЕЕ_ЗНАЧЕНИЕ_ПАРАМЕТРА) </b></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> + Confidence * СЛУЧАЙНОЕ_ЧИСЛО(0..1) </b></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> * (ЛУЧШЕЕ_ЗНАЧЕНИЕ_ПАРАМЕТРА_СТАИ - ТЕКУЩЕЕ_ЗНАЧЕНИЕ_ПАРАМЕТРА)</b></span><br />
<br />
Давайте ее проанализируем на примере высоты полета птицы:<br />
<br />
<ul style="text-align: left;">
<li>скорость изменения высоты полета основывается на скорости изменения высоты полета в предыдущую единицу времени (то есть у птицы есть инерция)</li>
<li>чем больше параметр <span style="font-family: "courier new" , "courier" , monospace;">Nostalgia</span>, тем сильнее птица будет стремиться лететь на высоте, на которой она увидела больше всего пищи</li>
<li>чем выше птица поднимается от той точки, из которой она видела больше всего пищи, тем сильнее замедляется скорость набора высоты (тоже самое со снижением высоты полета)</li>
<li>чем больше параметр <span style="font-family: "courier new" , "courier" , monospace;">Confidence</span>, тем сильнее птица будет стремиться лететь на высоте, на которой по общему мнению стаи видно больше всего пищи</li>
<li>чем выше птица поднимается от той точки, из которой по общему мнению стаи больше всего пищи, тем сильнее замедляется скорость набора высоты (тоже самое со снижением высоты полета)</li>
<li>СЛУЧАЙНОЕ_ЧИСЛО(0..1) превносит в действия птицы элемент случайности, на каждом шаге птица может более или менее может хотеть действовать самостоятельно или подчиняться мнению стаи, это некие перепады ее настроения.</li>
</ul>
<br />
<div>
<div>
</div>
</div>
Формула для корректировки значения параметра выглядит так:<br />
<br />
<b style="font-family: "Courier New", Courier, monospace; font-size: small;">НОВОЕ_ЗНАЧЕНИЕ_ПАРАМЕТРА =</b><br />
<b style="font-family: "Courier New", Courier, monospace; font-size: small;"> СТАРОЕ_ИЗМЕНЕНИЯ_ПАРАМЕТРА + </b><b style="font-family: "Courier New", Courier, monospace; font-size: small;">СКОРОСТЬ_ИЗМЕНЕНИЯ_ПАРАМЕТРА</b><br />
<br />
В программе это выглядит следующим образом:<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=0;i<agents;i++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].change_Kp = robot[i].change_Kp+nostalgia </span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
</span>
<br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> * (Random(1000)/1000.0)</span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
</span>
<br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> * (robot[i].best_Kp-robot[i].Kp)</span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
</span>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> + confidence*(Random(1000)/1000.0)</span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
<div>
* (best.Kp-robot[i].Kp);</div>
<div>
robot[i].Kp=robot[i].Kp+robot[i].change_Kp;</div>
<div>
<br /></div>
<div>
robot[i].change_Ki = robot[i].change_Ki+nostalgia </div>
<div>
* (Random(1000)/1000.0)</div>
<div>
* (robot[i].best_Ki-robot[i].Ki)</div>
<div>
+ confidence*(Random(1000)/1000.0)</div>
<div>
* (best.Ki-robot[i].Ki);</div>
<div>
robot[i].Ki=robot[i].Ki+robot[i].change_Ki;</div>
<div>
<br /></div>
<div>
robot[i].change_Kd = robot[i].change_Kd+nostalgia </div>
<div>
* (Random(1000)/1000.0)</div>
<div>
* (robot[i].best_Kd-robot[i].Kd)</div>
<div>
+ confidence*(Random(1000)/1000.0)</div>
<div>
* (best.Kd-robot[i].Kd);</div>
<div>
robot[i].Kd=robot[i].Kd+robot[i].change_Kd;</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
robot[i].change_speed = robot[i].change_speed+nostalgia </div>
<div>
* (Random(1000)/1000.0)</div>
<div>
* (robot[i].best_speed-robot[i].speed)</div>
<div>
+ confidence*(Random(1000)/1000.0)</div>
<div>
* (best.speed-robot[i].speed);</div>
<div>
robot[i].speed=robot[i].speed+robot[i].change_speed;</div>
</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
Если птица вылетела за пределы территории поиска, она пересоздается:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=0;i<agents;i++){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"></span></div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if(robot[i].Kp<=0 || robot[i].Kp>=2 ||</span></div>
<div>
<div style="font-family: "Courier New", Courier, monospace;">
robot[i].speed<=0 || robot[i].speed>100 ||</div>
<div style="font-family: "Courier New", Courier, monospace;">
robot[i].Ki<=0 || robot[i].Ki>0.1 ||</div>
<div style="font-family: "Courier New", Courier, monospace;">
robot[i].Kd<=0 || robot[i].Kd>4){</div>
<div style="font-family: "Courier New", Courier, monospace;">
robot[i]=born();</div>
<div style="font-family: "Courier New", Courier, monospace;">
}</div>
</div>
<div style="font-family: "Courier New", Courier, monospace;">
<br /></div>
<div>
После того как прошло заданное количество итераций поиска или скорость перестала возрастать, запускаем робота на движение с лучшими найденными параметрами для оценки результата.</div>
<div style="font-family: "Courier New", Courier, monospace;">
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">final = pid(best.Kp,best.Ki,best.Kd,best.speed,100000);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
По мере улучшения найденного решения будем записывать лучшие найденные параметры в файл, для дальнейшего анализа:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">logstr =NumToStr(pok)+ ";"+NumToStr(best.Kp)+";"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> +NumToStr(best.Ki)+";" +NumToStr(best.Kd)+";"</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> +NumToStr(best.speed)+";"+NumToStr(best.path);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">msg_len = StrLen(logstr);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">WriteLnString(fh, logstr, msg_len);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/X_dsG5D-0io/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/X_dsG5D-0io?feature=player_embedded" width="320"></iframe></div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<br /></div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-50246717623873801542017-11-26T06:11:00.002-08:002017-11-26T11:45:18.134-08:00EV3 Робот, играющий в "Камень, ножницы, бумага"<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<b style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Камень, ножницы, бумага</b><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"> — популярная игра на руках, известная во многих странах мира. Часто используется как методика жеребьёвки для выбора персоны для какой-либо цели (наряду с бросанием монеты, вытягиванием соломинок и т. п.).</span><br />
<span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtogm1Ihsr0Zvb3C79wRvG9ch8VqqZXC4KwQChKI7O35bjzfsxyLlIwCuie2TH9KGKnXfKl2NaajhXaGSscObv0qCWgJSNNMxnoQl_ymmJ1FrGXsQbQafDlNczpR7qCfYxBoV3Zyhkdiws/s1600/KNB.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtogm1Ihsr0Zvb3C79wRvG9ch8VqqZXC4KwQChKI7O35bjzfsxyLlIwCuie2TH9KGKnXfKl2NaajhXaGSscObv0qCWgJSNNMxnoQl_ymmJ1FrGXsQbQafDlNczpR7qCfYxBoV3Zyhkdiws/s400/KNB.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; margin-bottom: 0.5em; margin-top: 0.5em;">
Игроки считают вместе вслух «Камень… Ножницы… Бумага… Раз… Два… Три», одновременно качая кулаками. На счёт «Три» они одновременно показывают при помощи руки один из трёх знаков: камень, ножницы или бумагу. <span style="line-height: 22.4px;">Знаки изображены на картинке.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibDL7f4EgNiIhKyXe68hzU9mskGRMB3ZmH59z4O_saAVqR1iift8LJ2CMR3a7TgQRv6utKQQ1W3d2PUePL53koRrxpweSznkbhQSStU3Yf8yTU1ku3i1q3r0yJfaRVMgH-zu1mlZr9Ah1b/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="216" data-original-width="600" height="143" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibDL7f4EgNiIhKyXe68hzU9mskGRMB3ZmH59z4O_saAVqR1iift8LJ2CMR3a7TgQRv6utKQQ1W3d2PUePL53koRrxpweSznkbhQSStU3Yf8yTU1ku3i1q3r0yJfaRVMgH-zu1mlZr9Ah1b/s400/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" width="400" /></a></div>
<div style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; margin-bottom: 0.5em; margin-top: 0.5em;">
<span style="line-height: 22.4px;">Победитель определяется по следующим правилам:</span></div>
<ul style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; list-style-image: url("data:image/svg+xml,%3C%3Fxml version=%221.0%22 encoding=%22UTF-8%22%3F%3E%0A%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%225%22 height=%2213%22%3E%0A%09%3Ccircle cx=%222.5%22 cy=%229.5%22 r=%222.5%22 fill=%22%2300528c%22/%3E%0A%3C/svg%3E%0A"); margin: 0.3em 0px 0px 1.6em; padding: 0px;">
<li style="margin-bottom: 0.1em;">Камень побеждает ножницы («камень слишком крепок для ножниц»)</li>
<li style="margin-bottom: 0.1em;">Бумага побеждает камень («бумага накрывает камень»)</li>
<li style="margin-bottom: 0.1em;">Ножницы побеждают бумагу («ножницы разрезают бумагу»)</li>
</ul>
<div style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; margin-bottom: 0.5em; margin-top: 0.5em;">
Если игроки показали одинаковый знак, то засчитывается ничья и игра переигрывается.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKdjukZXZDQFVWHHWCxiDjj_todEULjdlxvposrI_oFAMhJ3Dnj7PCdJ4IXfHldLrBsCldgENY2CWVZMlOeD025ID6De-UB35qsf2cJ-w8AdO-0rcPqtqgH879ATxZ-O2u1GnVRU9gNF87/s1600/600px-Rock-paper-scissors-ru.svg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="574" data-original-width="600" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKdjukZXZDQFVWHHWCxiDjj_todEULjdlxvposrI_oFAMhJ3Dnj7PCdJ4IXfHldLrBsCldgENY2CWVZMlOeD025ID6De-UB35qsf2cJ-w8AdO-0rcPqtqgH879ATxZ-O2u1GnVRU9gNF87/s320/600px-Rock-paper-scissors-ru.svg.png" width="320" /></a></div>
<br /></div>
<div style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; margin-bottom: 0.5em; margin-top: 0.5em;">
В предыдущем нашем проекте с использованием LEGO Mindstorms EV3, камеры и нейронной сети, <a href="http://karandashsamodelkin.blogspot.ru/2017/10/n3uralv1s10n.html">N3uralV1s10n</a>, мы уже научились распознавать простейшие образы. Использование машинного зрения открывает интересные возможности по решению давно задуманных задач. Одна из них - робот, способный играть с человеком в "Камень, ножницы, бумагу".</div>
<div style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; margin-bottom: 0.5em; margin-top: 0.5em;">
Начнем с конструкции робота. "Модуль распознавания образов" в виде подставки для камеры и рамка-держатель для фона перекочевали без особых изменений из "распознавателя цифр". Белый фон за рукой позволяет распознавать образы более стабильно, хотя возможна работа и без него. В конструкции предусмотрен датчик-кнопка, она может использоваться особо мнительными игроками в розыгрыше раунда. В "контактном" режиме игры до нажатия кнопки можно быть уверенным, что робот не подсмотрел, какую фигуру начал ставить или поставил человек. В основном режиме игры, "бесконтактном", никакие органы управления не используются, робот полностью опирается на данные с камеры.</div>
<div style="background-color: white; color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px; margin-bottom: 0.5em; margin-top: 0.5em;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0cnscCrEsPKamqUE9PbbC6Mr77DnTpemLNwTzYCV7bAIFjB0RMAJlXr23aaywBgyLm9kr8MpQGEhKCUG5vDUsylejfAzFC77Jdtsgh_w_6QzNzn-HhqGmZgdkpxXiZBWSZzfl08KoW3SA/s1600/KNB_LDD.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="881" data-original-width="1600" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0cnscCrEsPKamqUE9PbbC6Mr77DnTpemLNwTzYCV7bAIFjB0RMAJlXr23aaywBgyLm9kr8MpQGEhKCUG5vDUsylejfAzFC77Jdtsgh_w_6QzNzn-HhqGmZgdkpxXiZBWSZzfl08KoW3SA/s400/KNB_LDD.jpg" width="400" /></a></div>
<br /></div>
<div style="background-color: white; margin-bottom: 0.5em; margin-top: 0.5em;">
<span style="color: #222222; font-family: sans-serif;"><span style="font-size: 14px; line-height: 22.4px;">Руку робота мы сконструировали с использованием 4 моторов, три из которых управляют пальцами, а четвертый мотор позволяет "махать кулаком". </span></span></div>
<div style="background-color: white; margin-bottom: 0.5em; margin-top: 0.5em;">
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Инструкцию по сборке конструкции можно скачать <a href="https://github.com/darkavengersmr/EV3-Rock-paper-scissors">по ссылке.</a> </span><br />
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Программное обеспечение для робота написано на языке Python. В составе комплекта предусмотрено 2 программы:</span><br />
<ul style="text-align: left;">
<li><span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Программа обучения нейронной сети робота</span></li>
<li><span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Программа для игры в "Камень, ножницы, бумага", использующая данные обученной нейросети</span></li>
</ul>
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Первая программа предлагает человеку последовательно показывать предлагаемые роботом фигуры, чтобы робот запомнил как они выглядят и сформировал нейронные связи для их распознавания. После того как первая программа устойчиво начинает распознавать "камень", "ножницы" и "бумагу", нейронные связи сохраняются в файл для дальнейшего использования их второй, игровой программой.</span><br />
<br />
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b>Код программы для обучения нейронной сети:</b><input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Скрыть'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Показать'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 120px;" type="button" value="Показать/Скрыть" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">from ev3dev.ev3 import *</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import pygame</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import time</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import pygame.camera</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">from random import random</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">from PIL import Image, ImageDraw, ImageFont</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import datetime</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">lcd = Screen()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">btn = Button()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play('sound/load.wav').wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">form = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">game = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">ok = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">ok_all = True</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">v = 32</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">g = 24</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">S1 = TouchSensor("in2")</span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">buf = [ [0] * g for i in range(v)]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">class object:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> def __init__(self, n):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> self.name = n</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> self.sum = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> self.picture = [ [0] * g for i in range(v)]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">myObject = [object(1), object(2), object(3)]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def image2buf(surf):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> width, height = surf.get_size() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for y in range(height): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for x in range(width): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> red, green, blue, alpha = surf.get_at((x, y)) </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> L = 0.3 * red + 0.59 * green + 0.11 * blue</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if L > 70:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> buf[x][y] = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> buf[x][y] = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">pygame.init()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">pygame.camera.init()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">cameras = pygame.camera.list_cameras()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">cam = pygame.camera.Camera(cameras[0])</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play('sound/learnbegin.wav').wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">while(True):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.clear() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><span style="color: #222222; font-family: "courier new" , "courier" , monospace; font-size: 14px;"> </span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 1): Sound.play('sound/move2stone.wav').wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 2): Sound.play('sound/move2scissors.wav').wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 3): Sound.play('sound/move2paper.wav').wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> while(True): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(S1.value()): break </span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> time.sleep(2)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> cam.start()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image = cam.get_image()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> cam.stop() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.beep().wait() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image = pygame.transform.scale(image, (v, g))</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image2buf(image)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><span style="color: #222222; font-family: "courier new" , "courier" , monospace; font-size: 14px;"> </span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for j in range(g):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if buf[i][j] == 0:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.draw.rectangle((i*5+9, j*5+4, i*5+4+9, j*5+4+4),fill='white')</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.draw.rectangle((i*5+9, j*5+4, i*5+4+9, j*5+4+4),fill='black')</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.update()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><span style="color: #222222; font-family: "courier new" , "courier" , monospace; font-size: 14px;"> </span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> while(True):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for o in myObject:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> o.sum = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for o in myObject: </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for j in range(g):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> o.sum += buf[i][j] * o.picture[i][j]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> max_sum = -100000</span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for num in myObject:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if num.sum > max_sum:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> max_sum = num.sum</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmp_obj = num</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> a = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 1): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(tmp_obj.name == 1): a = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: a = -1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 2): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(tmp_obj.name == 2): a = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: a = -1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 3): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(tmp_obj.name == 3): a = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: a = -1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(a == 1): ok+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(a == -1): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> ok=0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> ok_all = False</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for j in range(g):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(buf[i][j] == 1):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmp_obj.picture[i][j] += a</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print(tmp_obj.name, ok)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(ok == 3): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> form+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(form == 4): form = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> ok = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> break</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(game > 9): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(ok_all): break</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: game-=3</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(game % 3 == 0): ok_all = True</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><span style="color: #222222; font-family: "courier new" , "courier" , monospace; font-size: 14px;"> </span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play('sound/saveneural.wav').wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace; font-size: 14px;"> </span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">f = open("kmn_file.txt", "w")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">for i in myObject:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f.write("\n" + str(i.name) + "\n\n")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for x in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for y in range(g):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f.write(str(i.picture[x][y]) + " ")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f.write("\n") </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">f.close()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play('sound/learncomplete.wav').wait()</span></span><br />
<span style="background-color: transparent; color: #222222; font-family: sans-serif; font-size: 14px;"></span>
<span style="background-color: transparent; color: #222222; font-family: sans-serif; font-size: 14px;"><br /></span>
</div>
</div>
</div>
<span style="background-color: transparent; color: #222222; font-family: sans-serif; font-size: 14px;">Вторая программа при запуске считывает файл с данными обученной с помощью первой программы нейронной сети, озвучивает правила игры и робот, начинает, тряся кулаком, отсчет первого раунда. Как только считалочка роботом произнесена, человек может установить задуманную им фигуру напротив белого экрана, нажав запястьем на кнопку,, тем самым дав понять роботу что игра началась.</span></div>
</div>
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">В момент нажатия кнопки робот, делает кадр с камеры для распознавания нейронной сетью и используя ряд заложенных в его программу стратегий поведения, устанавливает свою фигуру. Управления рукой робота производится с помощью четырех независимых ПИД-регуляторов. </span><br />
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Для независимого управления рукой робота используется параллельный процесс, организованный с применением модуля Threading.</span><br />
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">После того, как фигура роботом установлена, начинает работу нейронная сеть, ее цель - распознать фигуру, которую установил человек, по данным </span><span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">кадра, </span><span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">сохраненного в момент нажатия кнопки.</span><br />
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">Нейронная сеть в данном проекте однослойная, с прямым распространением ошибки. Такой сети вполне достаточно, чтобы отличить три фигуры друг от друга, она достаточно быстро работает на такой малопроизводительной по современным меркам платформе как EV3.</span><br />
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">В зависимости от исхода раунда робот озвучивает результат и переходит к розыгрышу следующего. В случае одинаковых фигур раунд переигрывается. </span><span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">В каждой игре всего 3 раунда.</span><span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"> по ее итогам робот сообщает результат.</span><br />
<br />
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b>Код основной игровой программы:</b><input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Скрыть'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Показать'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 120px;" type="button" value="Показать/Скрыть" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">from ev3dev.ev3 import *</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">from PIL import Image, ImageDraw, ImageFont</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import pygame.camera</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import threading</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import datetime</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import pygame</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import random</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">import time</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">lcd = Screen()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">btn = Button()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play("sound/load.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">lcd.clear()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">game = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">bot_win = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">man_win = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">game_itog = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">roboform = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">old_man_form = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">first_game = True</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">stop = False</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">v = 32</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">g = 24</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">PBC = 5</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">PA = 5</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">PD = 10</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">uA = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">uB = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">uC = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">uD = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">eA = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">eB = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">eC = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">eD = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">speedA = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">speedB = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">speedC = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">speedD = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">speed = 300</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">S1 = TouchSensor("in2")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">A = LargeMotor('outA')</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">B = LargeMotor('outB')</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">C = LargeMotor('outC')</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">D = MediumMotor('outD')</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">A.reset()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">B.reset()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">C.reset()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">D.reset()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">buf = [ [0] * g for i in range(v)]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">class object:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> def __init__(self, n):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> self.name = n</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> self.sum = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> self.picture = [ [0] * g for i in range(v)]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">myObject = [object(1), object(2), object(3)]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def write(n, m):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f = ImageFont.truetype('FreeMonoBold.ttf', 155)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.draw.text((40,-25), str(chr(58)), font=f)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f = ImageFont.truetype('FreeMonoBold.ttf', 155)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.draw.text((-10,-10), str(n), font=f)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f = ImageFont.truetype('FreeMonoBold.ttf', 155)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.draw.text((95,-10), str(m), font=f)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.update()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def image2buf(surf):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> width, height = surf.get_size() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for y in range(height): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for x in range(width): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> red, green, blue, alpha = surf.get_at((x, y)) </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> L = 0.3 * red + 0.59 * green + 0.11 * blue</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if L > 80:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> buf[x][y] = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> buf[x][y] = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def upload_file():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/loadneural.wav").wait() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f = open("kmn_file.txt", "r")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmp = []</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in f:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmp.append(i)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> j = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> x = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmpls = ""</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in range(len(myObject)):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> j+=3</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for x in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmpls = tmp[j].strip()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmpline = tmpls.split()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> j+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for y in range(len(tmpline)-1):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> myObject[i].picture[x][y] = int(tmpline[y])</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> f.close()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in myObject:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for x in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for y in range(g):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print(i.picture[x][y], end=" ")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print("\n\n")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def if_form(itog, man_form):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(man_form == 1 and itog == 1): return 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(man_form == 2 and itog == 1): return 2</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(man_form == 3 and itog == 1): return 3</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(man_form == 1 and itog == 0): return 3</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(man_form == 2 and itog == 0): return 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(man_form == 3 and itog == 0): return 2</span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def brake_motor():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> A.stop(stop_action="brake")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> B.stop(stop_action="brake")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> C.stop(stop_action="brake")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> D.stop(stop_action="brake")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def move_hand():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> pos = 30</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> while(True):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(pos == 0 and not stop): pos = 30</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> uA = (pos - A.position)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> speedA = uA*PA</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(stop):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> pos = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(abs(uA) < 5): speedA = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(abs(uA)<5):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> pos *= -1 </span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedA > 900): speedA = 900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedA < -900): speedA = -900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> A.run_forever(speed_sp=speedA)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> time.sleep(0.1)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> brake_motor()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def put_form(pB, pC, pD):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> time_start = time.time()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> while(True):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> uB = (pB - B.position)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> uC = (pC - C.position)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> uD = (pD - D.position)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(abs(uB)<10 and abs(uC)<10 and abs(uD)<15): break </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> speedB = uB*PBC</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> speedC = uC*PBC</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> speedD = uD*PD</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(time.time() - time_start > 3): break </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedB > 900): speedB = 900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedC > 900): speedC = 900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedD > 900): speedD = 900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedB < -900): speedB = -900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedC < -900): speedC = -900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(speedD < -900): speedD = -900</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> B.run_forever(speed_sp=speedB)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> C.run_forever(speed_sp=speedC)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> D.run_forever(speed_sp=speedD)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def put_stone():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_form(0, 0, 0)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> brake_motor()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def put_scissors():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_form(-160, 0, 0)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> brake_motor()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def put_paper():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_form(-160, 160, 0)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> brake_motor()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">def put_ok():</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_form(0, 0, -65)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> brake_motor()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">pygame.init()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">pygame.camera.init()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">cameras = pygame.camera.list_cameras()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">cam = pygame.camera.Camera(cameras[0])</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">upload_file()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">stop = True </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">move = threading.Thread(target=move_hand)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">move.daemon = True</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">move.start()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play("sound/rules.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">Sound.play("sound/begingame.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;">while(True):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> time1 = datetime.datetime.now()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> stop = False </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/knb123.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> while(True): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> cam.start()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image = cam.get_image()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> cam.stop()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> sum_image = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image = pygame.transform.scale(image, (v, g))</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> width, height = image.get_size()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for y in range(height):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for x in range(width):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> red, green, blue, alpha = image.get_at((x, y))</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> L = 0.3 * red + 0.59 * green + 0.11 * blue</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> sum_image += L</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print(sum_image/(width*height))</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(sum_image/(width*height) < 200): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> break</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.beep()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(btn.backspace): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> brake_motor()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> exit()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> stop = True </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(not first_game): old_man_form = tmp_obj.name</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(first_game): roboform = int(random.randint(100,399)/100)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: roboform = if_form(game_itog, old_man_form)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(roboform == 3):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_paper()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/paper.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(roboform == 1):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_stone()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/stone.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(roboform == 2):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_scissors()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/scissors.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> cam.start() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image = cam.get_image()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> cam.stop() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.beep().wait() </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image = pygame.transform.scale(image, (v, g))</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> image2buf(image)</span></span><span style="color: #222222; font-family: "courier new" , "courier" , monospace; font-size: 14px;"> </span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for o in myObject:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> o.sum = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for o in myObject: </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for i in range(v):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for j in range(g):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> o.sum += buf[i][j] * o.picture[i][j]</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> max_sum = -100000</span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> for num in myObject:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if num.sum > max_sum:</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> max_sum = num.sum</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> tmp_obj = num</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print(bot_win, man_win)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/" + str(tmp_obj.name) + "-" + str(roboform) + ".wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if((tmp_obj.name == 1 and roboform == 2) or (tmp_obj.name == 2 and roboform == 1)): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/rules12.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if((tmp_obj.name == 1 and roboform == 3) or (tmp_obj.name == 3 and roboform == 1)):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/rules13.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if((tmp_obj.name == 2 and roboform == 3) or (tmp_obj.name == 3 and roboform == 2)):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/rules23.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(tmp_obj.name == 1):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(roboform == 3): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/ok.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_ok()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> bot_win+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> elif(roboform == 2): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/robotlostround1.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/robotlostround2.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> man_win += 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: Sound.play("sound/paritet.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(tmp_obj.name == 2):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(roboform == 1):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/ok.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_ok()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> bot_win+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> elif(roboform == 3): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/robotlostround1.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/robotlostround2.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> man_win += 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: Sound.play("sound/paritet.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(tmp_obj.name == 3):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(roboform == 2):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/ok.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_ok()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> bot_win+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> elif(roboform == 1): </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/robotlostround1.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/robotlostround2.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> man_win += 1 </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game_itog = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game+=1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: Sound.play("sound/paritet.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.clear()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> write(bot_win, man_win)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(game >= 3):</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> game = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> if(bot_win > man_win): Sound.play("sound/robotwin.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: Sound.play("sound/robotlose.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> bot_win = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> man_win = 0</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> lcd.clear()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> write(bot_win, man_win)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> </span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print("\n\n\n NEW GAME \n\n\n")</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> Sound.play("sound/newgame.wav").wait()</span></span><br />
<br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> else: Sound.play("sound/newround.wav").wait()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> put_stone()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> time2 = datetime.datetime.now()</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> delta = time2-time1</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> print(delta.seconds)</span></span><br />
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"><br /></span></span>
<span style="color: #222222; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 14px;"> first_game = False</span></span><br />
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"></span>
<span style="color: #222222; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"><br /></span>
</div>
</div>
</div>
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="margin: 5px 20px 20px;">
<div class="separator" style="clear: both; color: #222222; font-family: sans-serif; font-size: 14px; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/7A7J4edtU1g/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/7A7J4edtU1g?feature=player_embedded" width="320"></iframe></div>
<div style="color: #222222; font-family: sans-serif; font-size: 14px;">
<br /></div>
</div>
</div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com0tag:blogger.com,1999:blog-4279357166628593719.post-75347749227599027452017-11-26T02:29:00.001-08:002017-11-26T02:29:09.346-08:00GeneLINEr<div dir="ltr" style="text-align: left;" trbidi="on">
Последнее время вокруг все больше разговоров об искусственном интеллекте, то там то тут звучат модные термины "нейросети" и "генетические алгоритмы". В прошлых проектах (<a href="http://karandashsamodelkin.blogspot.ru/2017/09/blog-post.html">НейроКачели</a>, <a href="http://karandashsamodelkin.blogspot.ru/2017/10/blog-post.html">НейроБашня</a> и <a href="http://karandashsamodelkin.blogspot.ru/2017/10/n3uralv1s10n.html">N3uralV1s10n</a>) мы уже создавали простейшие нейронные сети, разобрались с тем что это такое в первом приближении и как они работают. Похоже пришло время сделать тоже самое с генетическими алгоритмами.<br />
<br />
Генетический алгоритм - это прежде всего алгоритм эволюционный. Его основная фишка взята из живой природы. При поиске оптимального решения задачи мы порождаем варианты, отбираем из них лучшие, "скрещиваем" между собой, получая решения с общими для "родителей" удачными свойствами.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLYASAO79gFvuxCnQLg5ZE8TFkQTiWnIzj92myfxG3WTxxGLQj1_eHR3J-suO4K3G8xX_P3Rzg7M_eteAnzIuKPcT-ZK7Cy_hlyN3oQxbg6KmbbkDAsD-tQ17ozBW29GHDbCnhhaa_W6xs/s1600/GeneLINEr.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLYASAO79gFvuxCnQLg5ZE8TFkQTiWnIzj92myfxG3WTxxGLQj1_eHR3J-suO4K3G8xX_P3Rzg7M_eteAnzIuKPcT-ZK7Cy_hlyN3oQxbg6KmbbkDAsD-tQ17ozBW29GHDbCnhhaa_W6xs/s400/GeneLINEr.jpg" width="400" /></a></div>
<br />
<br />
Для того чтобы пощупать всю эту магию в действии мы применим ее к решению классической задачи робототехники - движению робота по черной линии, а точнее - к подбору параметров ПИД-регулятора для того, чтобы робот смог двигаться по линии быстрее и точнее.<br />
<br />
<i>Замечание: данный проект не несет в себе ни оттенка соревновательной составляющей. Наша основная цель не в том, чтобы "вывести" быстрого гонца по линии, мы хотим получить опыт использования алгоритмов генетического типа с целью дальнейшего их использования в близкой нам по духу хоббийной робототехнике.</i><br />
<br />
Начнем с конструкции робота. Это традиционная двухмоторная тележка на базе LEGO Mindstorms NXT, в передней части установлено 4 датчика освещенности, два из которых (внутренних, подключенных к портам 2 и 3) используются ПИД-регулятором робота для движения по линии, а два внешних(подключенных соответственно к портам 1 и 4) - для контроля срыва с линии в процессе обучения. Инструкцию в формате LEGO Digital Designer можно скачать <a href="https://github.com/darkavengersmr/GeneLINEr">по ссылке.</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8sshJw-Dwk5Ic30sTG4tNykOLFGfHKTLUyGabfpX84i8BgdXDKrmS_JgH8OleM7Prr86rWT__VJ5qVLdhE_V4q_TgNXJoRPwnfa4p8yrROKAb-6tnLibxZaqno1Xp2VcKocajCmh55sw1/s1600/GeleLINEr%2528LDD%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="905" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8sshJw-Dwk5Ic30sTG4tNykOLFGfHKTLUyGabfpX84i8BgdXDKrmS_JgH8OleM7Prr86rWT__VJ5qVLdhE_V4q_TgNXJoRPwnfa4p8yrROKAb-6tnLibxZaqno1Xp2VcKocajCmh55sw1/s400/GeleLINEr%2528LDD%2529.png" width="400" /></a></div>
<br />
<br />
Для реализации поиска лучших для данной трассы коэффициентов ПИД-регулятора с применением генетического алгоритма нам потребуется создавать в памяти экземпляры ПИД-регулятора и автоматизированно тестировать их на реальном роботе, оценивая результат на соответствие заданному условию - более длинный пройденный путь в единицу времени, соответственно выше скорость движения по линии, при этом срывы с трассы недопустимы.<br />
<br />
Алгоритм в общем виде выглядит следующим образом:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguPG-hgLn2r_kxSZj8aZ9K0EO6IVnrhVGXWLYcOWWwVRjRzW0eD7msJbPiLasQXd7f2lQezDws6ceZY4GdEdz5Y_lvReslcrC8JxqrCqWsuJATYnmjibEjMXk-MbuHsArHms_-S1hVQ4wU/s1600/%25D0%2593%25D0%25B5%25D0%25BD%25D0%25B5%25D1%2582%25D0%25B8%25D1%2587%25D0%25B5%25D1%2581%25D0%25BA%25D0%25B8%25D0%25B9_%25D0%25B0%25D0%25BB%25D0%25B3%25D0%25BE%25D1%2580%25D0%25B8%25D1%2582%25D0%25BC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1148" data-original-width="477" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguPG-hgLn2r_kxSZj8aZ9K0EO6IVnrhVGXWLYcOWWwVRjRzW0eD7msJbPiLasQXd7f2lQezDws6ceZY4GdEdz5Y_lvReslcrC8JxqrCqWsuJATYnmjibEjMXk-MbuHsArHms_-S1hVQ4wU/s400/%25D0%2593%25D0%25B5%25D0%25BD%25D0%25B5%25D1%2582%25D0%25B8%25D1%2587%25D0%25B5%25D1%2581%25D0%25BA%25D0%25B8%25D0%25B9_%25D0%25B0%25D0%25BB%25D0%25B3%25D0%25BE%25D1%2580%25D0%25B8%25D1%2582%25D0%25BC.png" width="165" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Для создания первой популяции виртуальных роботов давайте, для начала, опишем пользовательскую структуру данных, которая будет использоваться в качестве шаблона для создания особей в популяции.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">struct person</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // у каждой особи должно быть имя, хотя бы codename</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> string name;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // номер поколения, в котором родилась данная особь</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int generation;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // энергичность (быстрота) особи</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int speed;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // скорость реакции</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float reaction;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // мудрость (память) особи</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float memory;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // интуиция (проницательность)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float intuition;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // степень доминантности особи</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float dominance;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // пройденный особью путь за отведенный на тестирование промежуток времени</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int path;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">};</span><br />
<br />
Теперь создадим первую популяцию на основе этого шаблона, в ней у нас будет 6 особей:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">person robot[6];</span><br />
<br />
Генерируем случайным образом свойства особей первой популяции:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=0;i<6;i++){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].name = "GeneLINEr_"+NumToStr(Random(1000));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].generation=1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">// энергичность (быстрота) особи 0..100</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].speed = Random(70)+30;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // скорость реакции 0..3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].reaction = Random(3000)/1000;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // мудрость (память) особи 0..0,1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].memory = Random(100)/1000;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // интуиция (проницательность) 0..3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].intuition = Random(3000)/1000;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // степень доминантности особи не понятна до тестирования</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].dominance = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // </span><span style="font-family: "courier new" , "courier" , monospace;">пройденный особью жизненный путь = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].path = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
Далее начинается самое интересное. Начинаем условно бесконечный цикл смены поколений. В каждом поколении нам нужно испытать особей данного поколения и выявить из них самых быстрых и точных, не слетающих с трассы.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfOBxIdNL4ZXTLKi4sYP7sQAZaQ29063bg-riVZI9dHrBYRiHAJEOYWtFFZA2-ay6hPPXu7Q20C29DMt4qAcwkyv2jRa9OGqfBj3hsLIimCPQUFEDV9aA9-q1M2Gslu36WCg3wHZywkfhi/s1600/1-86-620x425.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="425" data-original-width="620" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfOBxIdNL4ZXTLKi4sYP7sQAZaQ29063bg-riVZI9dHrBYRiHAJEOYWtFFZA2-ay6hPPXu7Q20C29DMt4qAcwkyv2jRa9OGqfBj3hsLIimCPQUFEDV9aA9-q1M2Gslu36WCg3wHZywkfhi/s400/1-86-620x425.jpg" width="400" /></a></div>
<br />
В роботе реализована функция ПИД-регулятора движения по линии, принимающий на вход параметры Kp, Ki, Kd, скорость робота, выполняющая 5 секундное движение по линии и возвращающая длину пройденного пути, сглаженного до криволинейной траектории.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">long pid(float Pk,</span><span style="font-family: "courier new" , "courier" , monospace;">float Ik,</span><span style="font-family: "courier new" , "courier" , monospace;">float Dk,int speed){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long B=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long C=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long path=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long MC=MotorRotationCount(OUT_C);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long MB=MotorRotationCount(OUT_B);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long e = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int porog=28;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float ERRo=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float ERR=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float u=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float z1=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float z2=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> long tmp=CurrentTick();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int p;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int i;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int d;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(CurrentTick()-tmp<=5000){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> MC=MotorRotationCount(OUT_C);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> MB=MotorRotationCount(OUT_B);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ERR=Sensor(IN_3)-Sensor(IN_2);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> p=Pk*ERR;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> d=Dk*(ERR-ERRo);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> i=Ik*e;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(i>10)i=10;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(i<-10)i= -10;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> u=p+i+d;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> z1=speed-u;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> z2=speed+u;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed-u>100)z1=100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed-u<-100)z1=-100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed+u>100)z2=100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(speed+u<-100)z2=-100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> OnFwd(OUT_B,z1);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> OnFwd(OUT_C,z2);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(Sensor(IN_1)<=porog){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> PlayTone(TONE_C5, MS_500);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> RotateMotorEx(OUT_BC, 35, 100, 100, true, true);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> go_to_line();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(Sensor(IN_4)<=porog){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> PlayTone(TONE_C5, MS_500);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> RotateMotorEx(OUT_BC, 35, 100, -100, true, true);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> go_to_line();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ERRo=ERR;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> e+=ERR;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> B=MotorRotationCount(OUT_B)-MB;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> C=MotorRotationCount(OUT_C)-MC;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(B>0 && C>0){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(B<C){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> path+=B;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> path+=C;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Off(OUT_BC);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> return path;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void go_to_line(){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float P=1.0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float D=1.0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float ERRo=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float ERR=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float u=0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(abs(Sensor(IN_2)-Sensor(IN_3))>5){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int ERR=Sensor(IN_3)-Sensor(IN_2);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int u=P*ERR+D*(ERR-ERRo);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int z1=-u;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int z2=+u;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(z1>100) z1=100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(z1<-100) z1=-100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(z2>100) z2=100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(z2<-100) z2=-100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> OnFwd(OUT_B,z1);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> OnFwd(OUT_C,z2);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
В случае, если в процессе 5-секундного испытания особи один из внешних датчиков видит линию, считается что робот сошел с трассы. При этом функция возвращает его на линию и особь выбывает из тестирования с результатом, который успела набрать до срыва, как правило рейтинг данной особи будет низким.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=5;i>=0;i--){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].path = pid(robot[i].reaction,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].memory,</span><span style="font-family: "courier new" , "courier" , monospace;">robot[i].intuition,</span><span style="font-family: "courier new" , "courier" , monospace;">robot[i].speed);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> PlayTone(TONE_A4, MS_500);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxFio1kMMOk-FqMkEwYQJ8MTB8LAAzXAdMfAFyVzHfT3Oy-OGSt6XhRR9FpQg9wazOR-5onDGVq9RWTUWJfWklaRWn2qBb8r1098p0WFh-66eKj3mVw7VTwDTOKPzDdk65JS_DFGDtC8Gm/s1600/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="221" data-original-width="655" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxFio1kMMOk-FqMkEwYQJ8MTB8LAAzXAdMfAFyVzHfT3Oy-OGSt6XhRR9FpQg9wazOR-5onDGVq9RWTUWJfWklaRWn2qBb8r1098p0WFh-66eKj3mVw7VTwDTOKPzDdk65JS_DFGDtC8Gm/s400/%25D0%2591%25D0%25B5%25D0%25B7%25D1%258B%25D0%25BC%25D1%258F%25D0%25BD%25D0%25BD%25D1%258B%25D0%25B9.jpg" width="400" /></a></div>
<br />
После испытания всех особей текущего поколения ранжируем их в порядке убывания пройденного за время тестирования пути. Так как время на тест для каждой особи фиксировано - 5 секунд, соответственно у особей убывает и скорость. Будем использовать пузырьковую сортировку и "временную особь", для перестановки пар при ранжировании.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">person robot_tmp;</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=0;i<5;i++){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for (int j=0;j<(5-i);j++){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(robot[j].path < robot[j+1].path){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_tmp = robot[j];</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[j]=robot[j+1];</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[j+1]= robot_tmp;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
Чем выше у особи рейтинг, тем выше и доминантность данной особи, соответственно тем большую часть свойст данной особи унаследуют ее потомки (выше = ближе к 1):<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">for (int i=0;i<6;i++){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i].dominance=i+1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
Две особи, самые слабые в популяции (5 и 6 в ранжированном списке) умирают, остальные дают потомство, порождая 6 особей новой популяции, наследующих черты родительских особей. В скрещивании участвуют доминантные признаки особей, давая соотношение унаследованных признаков. Унаследованный признак новорожденного кроме этого подвергается колебанию в 20%, для ускорения эволюции.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">person newborn(person male, person female){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> person newburn;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> male.dominance = 1 - (male.dominance/(male.dominance+female.dominance));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> female.dominance = 1 - male.dominance;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.name = "</span><span style="font-family: "courier new" , "courier" , monospace;">GeneLINEr_</span><span style="font-family: "courier new" , "courier" , monospace;">"+NumToStr(Random(1000));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.generation=male.generation+1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(male.speed>female.speed){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.speed = male.speed;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.speed=female.speed;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.reaction = male.reaction * male.dominance + female.reaction * female.dominance;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.reaction =newburn.reaction *((Random(40)+80)/100.0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.memory = male.memory * male.dominance + female.memory * female.dominance;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.memory =newburn.memory *((Random(40)+80)/100.0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.intuition = male.intuition * male.dominance + female.intuition * female.dominance;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.intuition = newburn.intuition *((Random(40)+80)/100.0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newburn.path = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">newburn.</span><span style="font-family: "courier new" , "courier" , monospace;">dominance</span><span style="font-family: "courier new" , "courier" , monospace;"> = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(newburn.speed>max_speed){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> max_speed=newburn.speed;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> return newburn;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">// новая популяция из 6 особей</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">person robot_next_generation[6];</span><br />
<div>
<br /></div>
<span style="font-family: "courier new" , "courier" , monospace;">robot</span><span style="font-family: "courier new" , "courier" , monospace;">_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[0] = </span><span style="font-family: "courier new" , "courier" , monospace;">newborn(0,1);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">robot</span><span style="font-family: "courier new" , "courier" , monospace;">_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[1] = </span><span style="font-family: "courier new" , "courier" , monospace;">newborn(0,2);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">robot</span><span style="font-family: "courier new" , "courier" , monospace;">_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[2] = </span><span style="font-family: "courier new" , "courier" , monospace;">newborn(0,3);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">robot</span><span style="font-family: "courier new" , "courier" , monospace;">_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[3] = </span><span style="font-family: "courier new" , "courier" , monospace;">newborn(1,2);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">robot</span><span style="font-family: "courier new" , "courier" , monospace;">_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[4] = </span><span style="font-family: "courier new" , "courier" , monospace;">newborn(1,3);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">robot</span><span style="font-family: "courier new" , "courier" , monospace;">_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[5] = </span><span style="font-family: "courier new" , "courier" , monospace;">newborn(2,3);</span><br />
<br />
Теперь в дело вступает природа и у одной, случайной особи происходит мутация - ее один, случайный, признак изменяется. Мутация чаще всего приводит к появлению неконкурентоспособных или вообще нежизнеспособных особей, однако очень полезна в ситуации, когда вектор развития эволюции пошел изначально не в том направлении. В результате мутации может появиться особь со свойством, выигрышно выделяющим ее на фоне остальных. Такая особь сразу же окажется на вершине рейтинга и даст начало новой династии.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">// Мутация</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void mutants(){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int property=</span><span style="font-family: "courier new" , "courier" , monospace;">Random(3)</span><span style="font-family: "courier new" , "courier" , monospace;">;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int mutant=</span><span style="font-family: "courier new" , "courier" , monospace;">Random(5);</span><span style="font-family: "courier new" , "courier" , monospace;">;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(mutant<4){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> switch(property)</span><span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].speed = max_speed+5;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 1:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].reaction =robot_next_generation[mutant].reaction *((Random(40)+80)/100.0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 2:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].memory =</span><span style="font-family: "courier new" , "courier" , monospace;">robot_next_generation[mutant].memory *((Random(40)+80)/100.0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 3:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].intuition = robot_next_generation[mutant].intuition *((Random(40)+80)/100.0);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> default:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> switch(property) </span><span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].speed = max_speed+5;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 1:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].reaction = Random(3000)/1000;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 2:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].memory = Random(100)/1000;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> case 3:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot_next_generation[mutant].intuition = Random(3000)/1000;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> default:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> break;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
Теперь производим смену популяций. Дети сменяют родителей:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">for(int i=0;i<6;i++){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> robot[i]=robot_next</span><span style="font-family: "courier new" , "courier" , monospace;">_generation</span><span style="font-family: "courier new" , "courier" , monospace;">[i];</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
Теперь снова пришла пора испытать новое поколение, более приспособленное к решению поставленной задачи, оценить возросшую скорость,, выявить сильнейших и так до тех пор, пока результат не будет нас устраивать.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/_xFQ0cU9r1w/0.jpg" src="https://www.youtube.com/embed/_xFQ0cU9r1w?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
На этапе ранжирования можно сохранять информацию о свойствах особей в каждой популяции в файл.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">byte fh;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int msg_len;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">string logstr;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">for(int i=0;i<6;i++){</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> logstr = robot[i].name;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> logstr = logstr + ";" + NumToStr(robot[i].generation);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> logstr = logstr + ";" + NumToStr(robot[i].reaction) +";"+NumToStr(robot[i].memory)+";"+NumToStr(robot[i].intuition);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> logstr = logstr + ";" + NumToStr(robot[i].path)+";"+NumToStr(robot[i].speed);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> msg_len = StrLen(logstr);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> WriteLnString(fh, logstr, msg_len);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
По данным, накопленным в файле в процессе работы программы, можно представить ход эволюции в виде наглядного графика (ось X - номер поколения, ось Y - средняя скорость особи):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw3w-OuD3qbxwac1PaS5JyvPyDjWuCZ92hDCtNj8sfvpldP5nXKb4c8xphyphenhyphenGvNvzJf5rI2mJCyPdgVblsN9B8feExMtD10k_TZg95FNtHZ-J_38Yb_jtGU6FUoRAGWjbnWiSaBbHA2ngI7/s1600/1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="397" data-original-width="652" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw3w-OuD3qbxwac1PaS5JyvPyDjWuCZ92hDCtNj8sfvpldP5nXKb4c8xphyphenhyphenGvNvzJf5rI2mJCyPdgVblsN9B8feExMtD10k_TZg95FNtHZ-J_38Yb_jtGU6FUoRAGWjbnWiSaBbHA2ngI7/s400/1.jpg" width="400" /></a></div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com2tag:blogger.com,1999:blog-4279357166628593719.post-2243868443558423432017-10-15T05:06:00.000-07:002017-11-20T23:38:56.747-08:00N3uralV1s10n<div dir="ltr" style="text-align: left;" trbidi="on">
Камера, подключенная к LEGO Mindstorms EV3 уже давно не является чем-то необычным. Конечно, в комплекте с набором ее нет, да и стандартное ПО от LEGO лишено возможности ее использования, но с появлением "прошивок" от сторонних разработчиков, таких как ev3dev и leJOS, появилась возможность подключить практически любую современную веб-камеру с USB-интерфейсом.<br />
<div>
В нашем сегодняшнем проекте мы будем использовать камеру в качестве элемента системы машинного зрения, запрограммировав на Python простейшую нейронную сеть для распознавания образов.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirEGKsJ9oiK42ZoqatADszdhegdLztihvzeYbMhbSAo_yKEbF5IFMAfD-T75NhGPxwG88RORciyQiMPmb57tVX3lmOzt1gCqVBFdRoU3OZSU_LLu9-RkPmMmlqpEc_S9Yczbyx6RIVANbq/s1600/N3uralV1s10n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirEGKsJ9oiK42ZoqatADszdhegdLztihvzeYbMhbSAo_yKEbF5IFMAfD-T75NhGPxwG88RORciyQiMPmb57tVX3lmOzt1gCqVBFdRoU3OZSU_LLu9-RkPmMmlqpEc_S9Yczbyx6RIVANbq/s400/N3uralV1s10n.jpg" width="400" /></a></div>
<br /></div>
<div>
Python - современный, активно развивающийся язык программирования, для него существует множество готовых модулей для решения задач, связанных с машинным зрением, включая популярный <a href="https://ru.wikipedia.org/wiki/OpenCV">OpenCV</a>. Однако наша цель состоит именно в написании учебного алгоритма на основе нейронной сети, без использования готовых профессиональных библиотек, с тем чтобы разобраться "как это работает?".</div>
<div>
<br /></div>
<div>
Для получения информации с камеры мы будем использовать легковесный (по сравнению с OpenCV) модуль <a href="https://ru.wikipedia.org/wiki/Pygame">PyGame</a>. Он не установлен в ev3dev "из коробки", но его можно доустановить используя менеджер модулей pip.</div>
<div>
<br /></div>
<div>
Конструкция у робота незамысловатая, по сути это крепление для камеры и листа бумаги А4, но тем не менее мы традиционно выкладывает инструкцию по ее сборке в формате LEGO Digital Designer, скачать ее можно <a href="https://github.com/darkavengersmr/N3uralV1s10n">по ссылке</a>.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0TLSNOBcbMFKTdq1BR3QRk7HgkYLd-ien-Lw7X09cslv3QJjyRm82wdNwIUKahOakEP77l2hswKWquicinbhCFZekDzOKhh20wO85g99bozyIGw46coFrTRzk1N2cJ-JMZ31FFXyxIV9y/s1600/LDD.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="893" data-original-width="1600" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0TLSNOBcbMFKTdq1BR3QRk7HgkYLd-ien-Lw7X09cslv3QJjyRm82wdNwIUKahOakEP77l2hswKWquicinbhCFZekDzOKhh20wO85g99bozyIGw46coFrTRzk1N2cJ-JMZ31FFXyxIV9y/s400/LDD.jpg" width="400" /></a></div>
<br /></div>
<div>
Мы используем камеру Logitech C110, это простейшая веб-камера с разрешением 640x480, которая имеет поддержку со стороны Linux. В конструкции используется пара датчиков-кнопок подключенных к 1 и 4 портам - они используются для "поощрения" и "наказания" нейронной сети в процессе обучения, и означают, соответственно, "Да" и "Нет".</div>
<div>
<br /></div>
<div>
В качестве объектов для распознавания мы будем использовать листы бумаги и нарисованными на них цифрами, впрочем алгоритм без всяких изменений способен работать с произвольными образами.</div>
<div>
<br /></div>
<div>
<i>Иску́сственная нейро́нная се́ть - математическая модель, а также её программное или аппаратное воплощение, построенная по принципу организации и функционирования биологических нейронных сетей - сетей нервных клеток живого организма. Это понятие возникло при изучении процессов, протекающих в мозге, и при попытке смоделировать эти процессы. </i></div>
<div>
<i>Искусственный нейрон — это такая функция, которая преобразует несколько входных фактов в один выходной.</i></div>
<div>
<br /></div>
<div>
В нашей учебной сети в качестве фактов будут выступать пиксели в изображении, которое передает на робота веб-камера. Искусственные нейроны, воспринимая эту информацию, дадут на выходе ответ, какой же объект в данный момент видит робот. Если нейронная сеть угадала, мы будем поощрять ее, укрепляя соответствующие нейронные связи и ее уверенность в ответе, а если ошиблась - будем "ругать", ослабляя текущие связи с тем, чтобы сеть попыталась дать иной ответ.</div>
<div>
<br /></div>
<div>
В силу довольно скромной производительности блока EV3 мы не будем работать с полным разрешением камеры, мы снизим его в программе до 16x16 пикселов, что вполне достаточно для решения учебной задачи.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/4LeqWVXI1mk/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/4LeqWVXI1mk?feature=player_embedded" width="320"></iframe></div>
<br />
<br /></div>
<div>
В данном проекте у нас будет две программы, в которых реализована несколько отличающаяся логика в обучении нейронной сети.<br />
<br />
Первый алгоритм заключается в следующем:<br />
1) В памяти робота перечисляются сущности, которые он сможет отличать друг от друга. Для каждой сущности создается нейрон сети с 16x16=256 входами и 1 выходом. Веса на входах нейронов в начале одинаковы у всех входов и всех нейронов.<br />
2) Роботу показывается сущность из числа тех, которые перечислены в его памяти, он пытается угадать что это такое. Поначалу, конечно, он в большинстве случаев ошибается. Человек нажимает кнопку "Да", если робот угадал (в этом случае мы увеличиваем веса входов соответствующего нейрона, на которых были не белые пиксели), и кнопку "Нет", если не угадал (в этом случае уменьшаем веса входов соответствующего нейрона с закрашенными пикселами).<br />
3) Робот пытается угадать снова и пересчитывает веса на входах нейронов до тех пор, пока не научится стабильно распознавать все сущности из имеющегося у него списка.<br />
<br />
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b><a href="https://github.com/darkavengersmr/N3uralV1s10n">Код первой программы</a> на Python выглядит следующим образом:</b>: <input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Close'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Open'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 120px;" type="button" value="Показать/Скрыть" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<br />
<span style="font-family: "courier new" , "courier" , monospace;">from ev3dev.ev3 import *</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import pygame</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import pygame.camera</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from random import random</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from PIL import Image, ImageDraw, ImageFont</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">lcd = Screen()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">btn = Button()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">res = 16</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">S1 = TouchSensor("in1")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">S2 = TouchSensor("in4")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">buf = [ [0] * res for i in range(res)]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">class number:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> def __init__(self, n):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> self.name = n</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> self.sum = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> self.picture = [ [0] * res for i in range(res)]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">myNumbers = [number(1), number(2), number(3), number(4)]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def camera_update(x):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(x):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = cam.get_image()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = pygame.transform.scale(image,(res,res))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image2buf(image)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if buf[i][j] == 0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle((i*8+25, j*8, i*8+7+25, j*8+7),fill='white')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle((i*8+25, j*8, i*8+7+25, j*8+7),fill='black')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def write(n):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> f = ImageFont.truetype('FreeMonoBold.ttf', 175)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.text((30,-15), str(n), font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def image2buf(surf):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> width, height = surf.get_size() </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for y in range(height): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for x in range(width): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> red, green, blue, alpha = surf.get_at((x, y)) </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> L = 0.3 * red + 0.59 * green + 0.11 * blue</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if L > 100:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> buf[x][y] = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> buf[x][y] = 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">pygame.init()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">pygame.camera.init()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cameras = pygame.camera.list_cameras()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cam = pygame.camera.Camera(cameras[0])</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cam.start()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">f = ImageFont.truetype('FreeMonoBold.ttf', 25)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,50), "N3uralV1s10n", font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Sound.speak("nerual vision programm 1").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">time.sleep(2)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">str1 = "please put"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">str2 = "first object"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">str3 = "and press enter"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,30), str1, font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,55), str2, font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">f = ImageFont.truetype('FreeMonoBold.ttf', 20)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,80), str3, font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Sound.speak("please put first object and press enter").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.enter): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> camera_update(15)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = cam.get_image()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = pygame.transform.scale(image,(res,res))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image2buf(image)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if buf[i][j] == 0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle(((i+25)*8, j*8, (i+25)*8+7, j*8+7),fill='white')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle(((i+25)*8, j*8, (i+25)*8+7, j*8+7),fill='black')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for o in myNumbers:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> o.sum = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for o in myNumbers: </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> o.sum += buf[i][j] * o.picture[i][j]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> max_sum = -100000</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> for num in myNumbers:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if num.sum > max_sum:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> max_sum = num.sum</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> tmp_obj = num</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> write(tmp_obj.name)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("It is "+str(tmp_obj.name)).wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(S1.value()): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(S2.value()): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> if(S1.value()): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("ok yes").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> a = 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else: </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("no no").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> a = -1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(buf[i][j] == 1):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> tmp_obj.picture[i][j] += a</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("put a new object and press enter").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.enter): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.backspace):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("Exit programm").wait() </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> exit() </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">cam.stop() </span><br />
<br />
</div>
</div>
</div>
Второй алгоритм несколько отличается:<br />
1) Изначально память робота пуста.<br />
2) Показываем ему объект и нажимаем кнопку "Запомни эту сущность".<br />
3) Выбираем имя для объекта кнопками на блоке.<br />
4) В памяти робота формируется нейрон с 16x16=256 входами, при этом веса входов, которые видят закрашенные пиксели выше, чем входов с белыми пикселами.<br />
5) показываем роботу следующий объект, он пытается сопоставить его с теми, что уже знает.<br />
6) если робот угадал, поощряем его, нажимая "Да" (выполнится усиление связей с пересчетом весов на входах соответствующего нейрона). Если робот не угадал уже знакомый ему объект, нажимаем "Нет" (ослабляем связи), если объект новый для робота - нажимаем "Запомни эту сущность" и переходим к п. 2<br />
<br />
</div>
<div>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
<b><a href="https://github.com/darkavengersmr/N3uralV1s10n">Код второй программы</a> на Python выглядит так:</b>: <input onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = 'Close'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Open'; }" style="font-size: 10px; margin: 0px; padding: 0px; width: 120px;" type="button" value="Показать/Скрыть" /> </div>
<div class="alt2" style="border: 1px inset; margin: 0px; padding: 6px;">
<div style="display: none;">
<br />
<span style="font-family: "courier new" , "courier" , monospace;">from ev3dev.ev3 import *</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import pygame</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import pygame.camera</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from random import random</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">from PIL import Image, ImageDraw, ImageFont</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">lcd = Screen()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">btn = Button()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">res = 16</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">S1 = TouchSensor("in1")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">S2 = TouchSensor("in4")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">buf = [ [0] * res for i in range(res)]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">class number:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> def __init__(self, n):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> self.name = n</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> self.sum = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> self.picture = [ [0] * res for i in range(res)]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">myNumbers = []</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def camera_update(x):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(x):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = cam.get_image()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = pygame.transform.scale(image,(res,res))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image2buf(image)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if buf[i][j] == 0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle(((i*8+25), j*8, (i*8+25)+7, j*8+7),fill='white')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle(((i*8+25), j*8, (i*8+25)+7, j*8+7),fill='black')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def write(n):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> f = ImageFont.truetype('FreeMonoBold.ttf', 175)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.text((30,-15), str(n), font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">def image2buf(surf):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> width, height = surf.get_size() </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for y in range(height): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for x in range(width): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> red, green, blue, alpha = surf.get_at((x, y)) </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> L = 0.3 * red + 0.59 * green + 0.11 * blue</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if L > 100:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> buf[x][y] = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> buf[x][y] = 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">pygame.init()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">pygame.camera.init()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cameras = pygame.camera.list_cameras()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cam = pygame.camera.Camera(cameras[0])</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">cam.start()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">f = ImageFont.truetype('FreeMonoBold.ttf', 25)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,50), "N3uralV1s10n", font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Sound.speak("neural vision programm 2").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">time.sleep(2)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">str1 = "please put"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">str2 = "first object"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">str3 = "and press enter"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">f = ImageFont.truetype('FreeMonoBold.ttf', 25)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,30), str1, font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,55), str2, font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">f = ImageFont.truetype('FreeMonoBold.ttf', 20)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.draw.text((0,80), str3, font=f)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Sound.speak("please put first object and press enter").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.enter): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> camera_update(15)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = cam.get_image()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image = pygame.transform.scale(image,(res,res))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> image2buf(image)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if buf[i][j] == 0:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle(((i+25)*8, j*8, (i+25)*8+7, j*8+7),fill='white')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.draw.rectangle(((i+25)*8, j*8, (i+25)*8+7, j*8+7),fill='black')</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.update()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for o in myNumbers:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> o.sum = 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for o in myNumbers: </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> o.sum += buf[i][j] * o.picture[i][j]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> max_sum = -100000</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for num in myNumbers:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if num.sum > max_sum:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> max_sum = num.sum</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> tmp_obj = num</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(len(myNumbers)!=0): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> write(tmp_obj.name)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("It is "+str(tmp_obj.name)).wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else: Sound.speak("I do not know object").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(S1.value() and len(myNumbers)!=0): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(S2.value() and len(myNumbers)!=0): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.enter or len(myNumbers)==0): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> a=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(S1.value() and len(myNumbers)!=0): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("ok yes").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> a = 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> elif(S2.value() and len(myNumbers)!=0): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("no no").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> a = -1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else: </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("new object").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> time.sleep(1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> i = 48</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.enter): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.right): i+=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.left): i-=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(i>90): i=48</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(i<48): i=90</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(i>=58 and i<=64): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.right): i=65</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> else: i=57</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> time.sleep(0.15)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> write(chr(i))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> myNumbers.append(number(chr(i)))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("new object it is" + chr(i)).wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> myNumbers[len(myNumbers)-1].picture[i][j] = buf[i][j]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(a!=0):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for i in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for j in range(res):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(buf[i][j] == 1):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> tmp_obj.picture[i][j] += a</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("put a new object and press enter").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while(True):</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.enter): break</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if(btn.backspace): </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Sound.speak("Exit programm").wait()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> exit()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lcd.clear()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">cam.stop() </span><br />
<br /></div>
</div>
</div>
</div>
</div>
darkavengersmrhttp://www.blogger.com/profile/11787769820983115023noreply@blogger.com6