середу, 30 листопада 2016 р.

Учусь программировать робота для хакатона

Некоторое время назад я записалась быть учителем на детских курсах по программированию. Поигрались мы со Скретчем , и учителя решили, что детки могут больше. Стали им давать HTML. Вот, кстати, презентация о табличках с заданием сделать открытку на праздники маме-папе. Детям всегда лучше давать то, что позволяет быстро увидеть результат. Когда ребенку можно показать, что методом малых усилий что-то меняется и это что-то ему нравится, то, значит, основное задание учителя выполнено. Когда ребенок придумал идею, хочет ее реализовать доступными методами, и попал при этом в тупик, тогда надо подсказывать. Идея будет расти, и сам ребенок будет двигаться к звездам. :)

Организаторы курсов предложили учителям провести детский хакатон, основная задача которого - собрать и запрограммировать робота. За основу взяли конструктор Lego Mindstorm EV3 45544 и бесплатную программу LEGO® MINDSTORMS® Education EV3 Teacher Edition для программирования на нем.


До того, как я сама попробовала что-то запрограммировать для робота, задача мне казалась нетривиальной. Когда же я увидела, что программирование осуществляется визуальными блоками, которые должны взаимодействовать между собой, мне подумалось, что дети справятся. Но стоило мне поставить перед собой цель запрограммировать прохождение роботом лабиринта, после того, как научила его идти прямо и в случае преграды поворачивать направо, я впала в ступор. Дело в том, что я привыкла к объектно-ориентированному языку программирования, а тут пишешь все в кучу и не знаешь, как поставить метку, чтобы перейти на тот или иной кусок программы в некий момент. Спустя несколько дней, за которые я робота даже не трогала, пришло вдохновение, и я поняла, что без методов и функций тоже можно сделать что-то толковое, и притом даже изящно.

Даже если у вас нет под рукой робота, могу предложить вам придумать собственный алгоритм для прохождения лабиринта, используя только:
  • датчик расстояния от робота до преграды, дающий на выходе количество сантиметров;
  • двигатель, которому можно задать направление движения, его мощность и продолжительность (измеряется либо в количестве секунд, либо в оборотах колеса, либо длится вечно, пока не выполнится некоторое условие по таймеру);
  • циклы;
  • операторы выбора (switches);
  • переменные;
  • математические операции.

Чтобы лучше понимать, чем вы располагаете и как этим пользоваться, скачайте себе программу и набросайте алгоритм. Не пробовала, но судя по всему вы даже можете посмотреть, как он будет работать, имея не дорогого лего робота, а виртуального.

Описание моей версии алгоритма прохождения лабиринта с использованием ультразвукового датчика, дающего расстояние до преграды, расположенной впереди


Робот может находиться в четырех основных состояниях:
0: Движение прямо;
1: Поворот направо;
2: Поворот налево;
3: Разворот назад.

После пунктов 1-3 подразумевается движение прямо в случае отсутствия близкой преграды. Движение прямо выполняется, пока преграда не окажется на расстоянии менее 20 см. После каждого поворота в коде стоит switch, основанный на расстоянии до преграды. В нем переменная заполняется значением цифры, которая станет управляющей на следующей итерации.

Вы спросите, зачем же делать проверку при развороте назад? Программирование для робота сильно отличается от написания обычной программы, которая не будет обитать в случайно меняющейся среде и у которой есть физический облик. Случается, что перед роботом неожиданно вырастает преграда в виде маминой ноги или папиной руки, и роботу недостаточно места для разворота. В таких случаях ему лучше отъехать назад на расстояние, которого ему хватит для маневра. У меня это - один оборот колеса. Данное действие в случае необходимости выполняется перед входом в switch выбора направления движения и его реализации. Другая причина - робот разворачивается не одинаково точно в зависимости от поверхности, на которой он ездит: ковер и паркет дают разные результаты. Также на градусы поворота влияет мощность поворота и калибровка робота. Мне одолжили такой экземпляр, которому для поворота на 90° на мощности 50 из 100  пришлось прописать 400°.



Вроде бы, все основное рассказала. Смотрите саму программу.



На этом видео можно увидеть робота в действии.


Если смотреть внимательно, то видно, что робот ни разу не входит в состояние “3”. Посмотрите внимательно на картинку программы, и вы поймете причину. Предпоследний блок ссылается на “3”, если расстояние слишком мало, и на “0”, если места достаточно. Последний блок называется “4”, а блока “3” не существует. :) А в таком случае он по умолчанию идет в “0” (на switch рядом с нулем отмечена соответствующая радио-кнопка). Тут корректная работа алгоритма

Алгоритм вышел действенный и простой, но у него есть недостаток. Что случится, если отверстие, в которое нужно попасть, находится в середине стены? Например, робот идет по шляпке буквы Т, а выход - в ноге. Этот алгоритм ждет преграды, и в отверстие в стене сбоку без случайности не попадет. Иными словами, алгоритм хорош для прогулок по квартире или офису. А что, если имеем настоящий лабиринт?

Модернизацию выполнить не так сложно. Для этого необходимо дописать диагностику правой стены с некой частотой во время движения прямо. Почему только правой, а не двух? Потому что если окажется, что справа прохода нет, а слева есть, то когда робот обойдет все слева и не найдет выхода, он, вернувшись в исходное место, уже не будет знать, куда ему поворачивать, чтобы пройти по коридору дальше. Повернет он в стандартном направлении, которое будет противоположно тому, куда бы он повернул, если бы был открыт правый проход. То же самое на примере: робот шел по шляпке буквы Т справа налево и зашел в ножку, обошел ее и вернулся на перекресток, где есть дорога как вправо, так и влево. Следует помнить, что тут он уже был, и чтоб идти дальше, нужно повернуть налево. А такой алгоритм уже будет в разы сложнее.

Выглядит модернизация алгоритма как дополнительный switch в цикле в блоке движения вперед, который переключается в на основе данных о расстоянии с датчика, снимающего их дискретно каждую секунду. В случае, если робот в течение секунды находит препятствие, он выходит из внутреннего и внешнего циклов с направлением “1” (вправо). Если же секунда истекла, а препятствий не обнаружено, он поворачивает направо и смотрит, есть ли там ход. В положительном случае он туда идет.


  
К сожалению, робота мне пришлось отдать, и настоящий лабиринт для тестирования времени построить не хватило. Но с помощью метода “внезапного препятствия” можно увидеть, как работает робот.

От детей, понятное дело, требовать такой сложности еще рано. Дети хоть и заинтересованы, но им порой не хватает усидчивости, чтоб перебрать несколько вариантов того, как можно заставить программу работать. На хакатоне у детей вышло запрограммировать последовательности конкретных движений робота. Отступать они не догадались, циклы тоже не применили. Поэтому робот мог падать в результате сталкновений, поворачивать под неправильным углом, когда пытался развернуть стенку вместе с собой, и т. п.  Больше всего детям понравилось собирать конструктор лего. :) Возраст детей - от 10 до 14.

Другие задания, которые были на хакатоне:

  1. Собрать роборуку и ею поднимать бумажный стаканчик.
  2. Собрать и написать логику для принтера (двигать машинку так, чтоб она ездила по особой осмысленной траектории и рисовала прикрепленным к ней фломастером).
  3. Борьба роботов: 2 команды собирают по роботу и встраивают в них датчик касания, так что при нажатии на него робот “умирает”. Один робот должен атаковать другого и попасть в то самое место :)

Скоро будет новый хакатон. Взрослые будут учиться давать детям посильные интересные задачи, а дети - их выполнять. :)

Если у кого-нибудь есть соответствующий опыт или полезные советы, буду рада прочитать.

понеділок, 17 жовтня 2016 р.

What to Do When Parallel Threads Modify the Same DB Row

During several days I was trying to solve an issue with rowlock on Oracle and MariaDB (MySQL). There were concurrent requests entering into @Transactional* method which changed data in the DB.





HOW TO DEBUG


When solving such issues, it might be hard to reproduce the situation because of the concurrency. One solution is to use logging or simple output. It’ll give understanding at least how many streams have passed a particular point in the code. Using static variables can also help. Iterating them might give an estimate of the number of times something happens.

It’s possible to send two concurrent threads using, for example, sleep() for a thread. Placing it before the problematic area will provide enough time to send as many threads as needed. However, you might need to use static counter in order to let every second thread without falling asleep.



HOW TO FIX

Lock


In the case of reading-writing the data, the safest fix is to put a trigger, which tells if the area contains consistent information or it’s better to wait till the previous thread finishes changing the resource. To find out more about this mechanism, read about Semaphores and, particularly, about one of its implementations, Mutex. What was especially strange with this approach in my case was that in MariaDB all worked fine but not in Oracle. The problem was that with the find request I used the following annotation: @Lock(PESSIMISTIC_WRITE). Its parameter is LockModeType enum value. Somehow it seems not to work proper with Oracle 12 or Hibernate 5.0.2.Final. What helped was to use entityManager.lock(Entity, LockModeType) method. You can also make a lock on the session: entityManager.unwrap(Session.class).lock(Entity, LockMode). Here you can get more general info about locking. For more information why the annotation didn't work and how to fix it check the following StackOverflow question of mine. One of the Hibernate authors was very kind to reply.


Exchange Uncommitted Info (Scarry)


There are different ways to fix the problem, but they heavily depend on the code. For example, you can enable information exchange between transactions-sessions. As soon as the data are changed in terms of one session, the other one will become aware of it and will read the already updated data. This feature can be enabled using READ_UNCOMMITED in the DB. Note that it’s a possible isolation level in MariaDB (MySql) which you can happily use when debugging but it’s not applicable in serious Oracle.
It’s also possible to use Hibernate’s second level cache.

Problems may occur, however. If the transaction that changed the data and gave it to the next parallel transaction rollbacks, the data, with which the second transaction operates, might become erroneous. Besides, it’s always better to have guarantees that 2 parallel transactions won’t read the data being changed, which they use to write new information. The first transaction still could want to continue updating the data, when the second one had already read it to change.


Try Until You Make it or Fast fix


Badly written locks can produce deadlocks. Two threads will constantly attempt to access the same resource. Each will wait until the other one releases the DB. If this happens very rarely, you might be interested in using Ostrich algorithm. The better solution might be to get rid of possible deadlocks and wait till the exception of writing to the DB happens. When it does, just try again and hope that this time, no other thread will want to disturb the same data. This solution might be applied when the problem happens really rarely, and when putting a lock will cause serious downshift in performance. For example, I knew that the erroneous insert to the DB was always followed by update, and I couldn’t have 2 bad consecutive inserts. So the just described fix worked for my problem.

I wish you good luck! Have fun with your problem. Hope the fix comes soon. :)

* This article is inspired by experienced problems in Java + Spring + Hibernate + SpringData + DB (Oracle and MariaDB)

неділю, 29 травня 2016 р.

Почему нам всем нужна герань или О старости

Сегодня вышла на улицу, а на ближайшем перекрестке на заборчике сидит бабушка, старая-старая, руки худые, что аж вены проступают. Разложила, что дома "запасного" нашла и продает. Пуговицы, грелка, перчатки резиновые, мелки, чтоб кройку помечать и др. Увидела, что я смотрю и сразу жадно сказала "Купіть". Я тогда только вышла, останавливаться не хотела, да и очень горько на все это смотреть было. Иду и думаю, что ей жить, наверно-то не на что, вот она и вынесла из дома, что могла. Она не идет просить милостыню от нужды, пытается заработать, как может. Не впервые я ее там вижу. Пол года назад она мне уже продала баночку меда, рассказывая, что ест по чайной ложке с мужем на ночь и уже прожила до почти 90 лет. Сказала, что мед лишний и им с мужем хватит. Сейчас, видно, "лишнего" уже нет. 
Когда назад шла, она все еще сидела. Дала я ей денег. Она очень обрадовалась и сначала даже не знала, что делать от счастья. Пошла потом вдогонку и стала давать мне мелок и перчатки. Настаивала, чтоб я взяла и что такое всем пригодится. Мне не хотелось брать вообще ничего от нее. Но все-таки взяла мелок, чтоб ей легче было, чтоб не выглядело, как милостыня для нее.
Очень стыдно, когда старые люди живут в нищете. Одно дело, когда перед тобой все двери могут открыться, ты только захоти, а другое - когда ты уже отдал все, что мог, и стал ненужным отбросом, оставленным на попечение только себе.

В каждом городе есть бабушки и дедушки, которым стыдно просить.Поэтому они продают отвертку, книгу, старые часы или герань.По-моему, нам всем нужна герань!!?
Есть 2 хорошие поговорки:     На все воля Божья и     Бог не дает таких трудностей, с которыми мы не могли бы справиться.
Так что надо уметь жить сегодняшним днем, чтоб в случае непредсказуемой беды, было о чем вспомнить и вдохновиться. А так же надо стелить солому про запас, где упасть вдруг можем, чтоб мягче падать. Хорошему человеку люди не дадут пропасть.

вівторок, 10 травня 2016 р.

Visit to Riga Dev Day

Recently I had a chance to attend Riga Dev Day. This is an up-and-coming Java conference in the capital of Latvia, which is a high-key and at the same time poise place. Riga Dev Day has been held only since 2014 but its level of organization and interestingness was above my expectations. The talks took place in the first two days, and the last day was devoted to master classes.

There were many sponsor companies, and each advertised their products and wanted to hire more workers. Therefore, in case you want a nice job but are not sure which company to apply then just check out the sponsors. With high probability, you will find something neat for yourself.

What I personally liked the most is the IoT stuff (Arduino Company). As I envision this, it’s the part of houses of the future. The company cooperates with Bosh and tries to pave the way to reliable and cheap control systems for our belongings through Wi-Fi or Bluetooth. Currently they work on controlling the state of the washing machine by taking information from its electronic parts, which is a thin end of the wedge. As a result, they will have a program to give advice on which parts need updating, cleaning, or replacing, and when. After they’re done with the washing machine, they will put the chips in other devices produced by Bosh, and so make the communication between your belongings and yourself possible.

I have never seen a living IBM employee so for sure I staked to come to the stand. They proposed Bluemix—a server for web apps in different languages. Java, Python, JS, and many others are included, but no Kotlin for now.

Accenture is one of the biggest Latvian companies, which might be the reason why they gave the most generous presents to the participants. In order to participate in the lottery, one had to put the filled form in a little carton cube. The cube was then placed into a big box. The curious this is that the box was placed by a wooden robot-excavator on remote control. That was big fun. There were way too many buttons to navigate robot parts. You always get the feeling that the company cares a lot about its employees if it proposes something interesting you’ve got to handle to win the price.
The picture with the companies’ names is attached below so you may check on your own what others do/produce. I believe that none of them is are dubious.

Another thing I cared about was Ukrainians presenting some of the companies. Some of them work in Latvia, others are just Ukrainian partners that came to present the product. It was interesting to talk to them and hear out their opinions about working with the Latvians.

Obviously, sponsors are not the only thing you’d come to the conference for. Please check below some talks that might interest you.

  • Java 9 by Dalibor Topic—a general overview of the new features. The talk was about the changes brought to the language of the L size (impacts everyone), M size (you might come across like default garbage collector), and S size (you might stumble upon only in very limited cases).
  • Also, I have learnt the basics of Kotlin thanks to the talk by Svetlana Isakova, its developer. She really tried to make everyone follow what she was presenting, and, it seems, achieved the goal. 
  • The speaker who gets my other prize for an interesting talk is David Dalabassee with his news about the Web Front. He spoke a lot about parsing JSON, which is exactly what’s being used at my project.

To sum up, everyone at the conference was open-minded, easy-going, and just outstanding. I have got many positive impressions about the talks, the people, and the city, so be sure to come the next year and feel that for yourself.