Дневничок

В формате таймшитов. Чтобы у меня не создавалось ощущения, что ни хера не делаю.

Sun, Jan 23, 2022

Начал делать telegram-bot-cpp-boost. Сразу возник вопрос, как завершить приложение по сигналу. Можно использовать встроенный в asio обработчик сигналов. В этом случае asio принимает сигнал на себя, а потом уже в пуле потоков вызвает пользовательский обработчик сигналов, и в нем можно вызвать io_service::stop. Но что делать, если я хочу дать пользователям возможность использовать бота как встраиваемую библиотеку? Я не хочу перехватывать их сигналы, а хочу дать им возможность остановить работу бота через вызов Bot::Stop. Интересный нюанс при этом, как избежать искуственной задержки между получением сигнала и выходом. Задержка возникает, если, например, есть busy loop, в котором проверяется, выставил ли обработчик сигнала флаг, и если да, то вызывается Stop. Чтобы цикл не ел 100% cpu, ставится искусственная задержка, скажем this_thread::sleep(200ms). Один из способов есть в примере к бусту, boost_asio/example/http/server/posix_main.cpp. Но тут целый поток тратится на что, чтобы сделать sigwait. Смотрю исходники буста, хочу понять, как сделать ф-ю Stop async-signal-safe согласно posix.

Код обработчика сигналов в asio в случае posix:

void boost_asio_signal_handler(int signal_number)
{
  int saved_errno = errno;
  signal_state* state = get_signal_state();
  signed_size_type result = ::write(state->write_descriptor_,
      &signal_number, sizeof(signal_number));
  (void)result;
  errno = saved_errno;
}

Mon, Jan 17, 2022

Начал читать `Anthony Williams, C++ Concurrency in Action`. Хочется уложиться в две недели.

Сайты libgen.*** это не зеркала одной и той же базы. На форумах можно найти историю того, как создавался проект и как распадался, какие базы поглощались. Сейчас это независимые базы данных с независимыми движками, имеющими общее прошлое. Если книги нет на одном из сайтов, поищите в гугле другие активные домены, на них книга, вероятно, будет.

Sun, Jan 16, 2022

Ближе к концу `Torjo, Boost.Asio` есть пример того, как выносить свои кастомные задачи в отдельный поток так, чтобы коллбеки приходили в общий пул потоков io_service. Так можно реализовать вычислительное ядро с асинхронной доставкой результата (при этом эти задачи могут быть не связаны с вводом-выводом). Еще есть параграф про корутины, но тут это скорее просто для красоты, я не буду использовать.

В мемексе теперь нормально открываются разделы в левой панели. Похожая навигация есть в readthedocs и на docs.oracle.com.

Sat, Jan 15, 2022

Сходили на скалодром. Все бывшие коллеги по лидарной команде, программисты и схемотехники. Надо бы потом конструкторов тоже подключить. Подсказали мне по поводу датчиков ближнего действия, я про них знал и даже в руках держал, но сейчас сам бы не догадался их использовать. Дочитал книжку про boost::asio.

Wed, Jan 12 - Fri, Jan 14, 2022

Езжу на м.Нагатинская, собираем роботов на гусеничном шасси. Добираться значительно удобнее, чем в гараж беспилотников. NDA не подписывал, но подробности рассказывать не буду. Пока все знакомо, вычислитель, 16-ти лучевой лидар, софт. Где-то надо будет сделать приватный раздел вики и в нем описывать подводные камни используемых готовых компонентов (дублировать то, что я пишу в корпоративной вики).

Tue, Jan 11, 2022

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

Я рассчитывал, что будут спрашивать по ROS (который Robot, а не Router), поэтому заранее немного прикинул, какие есть интересные вопросы именно про ros (ros1, про ros2 я не знаю). Вот они.

1/ В ros есть механизм получения и отправки сообощений. Сообщения приходят в виде асинхронных вызовов коллбек-функций. Но таким способом приходят только сообщения от других рос-нод. Если же надо получить сетевой пакет, например от лидара, или других датчиков, которые не имеют отношения к ros инфраструктуре, то нужно использовать либо POSIX вызовы, либо какие-то библиотеки вроде boost::asio. Вопрос, как правильно совместить эти системы. Например, как лучше встроить асинхронные вызовы ros функций в очередь коллбеков asio::io_context.

2.1/ В ros есть инструмент инструмент запуска процессов, roslaunch. Это кусок кода на питоне. Расскажите, как работает запуск и остановка процессов. Если завершить процессы через roslaunch, почему некоторые процессы могут остаться запущенными, и чем это грозит (если мы запускаем на одной машине или сразу на нескольких). Ответ такой, что там в питоне в цикле перебирается список процессов и последовательно им посылаются сигналы SIGINT, потом с задержкой SIGKILL. Если каке-то процессы перехватывают SIGINT в пользовательском коде и не выходят в ответ, то они зависнут до получения SIGKILL. Если roslaunch остановить раньше этого, то процессы останутся в памяти. Еще может потеряться связь с удаленным хостом и на нем процессы не завершатся. Еще были какие-то проблемы, но я уже не помню. Чтобы такие процессы не оставались в памяти нужно использовать механизмы, которые используются в докере и systemd, это cgroups и namespaces. (Надо про них кстати прочитать подробнее).

2.2/ Как в ros1 через roslaunch запустить ноды в определенном порядке и остановить их в обратном порядке? Возможно ли это для любых нод или только для определенной группы? Ответ такой, что только для нод из группы roscore есть гарантия, что они запустятся раньше обычных нод и остановятся позже них.

Mon, Jan 10, 2022

Читаю `John Torjo, Boost.Asio C++ Network Programming`. Не знал про существование в asio ф-й обработки POSIX сигналов. Не знал про рекомендацию использовать несколько io_service на общем endpoint при нагрузке от 1000 одновременных клиентов.

Sun, Jan 9, 2022

Почитал статьи и stackoverflow про возможные ошибки при декодировании h264 в chrome. Очень помогла статья про отладку программы srtplite (см раздел webrtc). Сохранил трафик с камер hikvision и xiaofang, перехватывал через tcpdump и wireshark на сервере (до попадания в janus gateway) и на компьютере. Смотрел в wireshark. Для распознавания RTP трафика в wireshark нужно включить подвиды этого протокола в меню analyze→enabled protocols. Пакеты от камер xiaofang отличались тем, что были больше 1520 байт и отображались как Fragmented. Еще увидел, что marked bit не устанавливается в конце последнего пакета keyframe, хотя метка времени меняется. Еще метка времени и метка последовательности не совпадают до janus и после него. Написал временный код в плагине janus, который проставляет marked bit. Нашел мои старые исходники rtsp_streamer для xiaofang(snx) и ограничил в live555 длину udp пакета до 1200 байт. Видео с камер стало отображаться, правда, с камеры agv оно довольно часто теряется или иногда все еще не отображается вовсе. По списку пакетов отличие в том, что я не могу визуально выделить большие наборы пакетов без marked bit. В потоке с другой камеры они есть, и это так выглядят пакеты keyframe. Но с этой камеры поток разбит на примерно одинаковые блоки пакетов между пакетами с marked bit. Попробовал поотключать переопределение меток времени и последовательности в janus, иногда становится лучше и видео не пропадает, иногда нет. Кажется, что дело именно в аккуратной последовательности этих меток. Нужно будет переписать rtsp_streamer, внимательно прочитав перед этим RFC про RTP. Ветка gozhev/f/support-snx-source.

Sat, Jan 8, 2022

Разобрался с fullscreen api, flex layout, css media query в браузере. Получилось сделать панельку управления видео, которая подстраивается под ориентацию окна браузера. Посморел janus api для плагина streaming, посмотрел пример переключения потоков, идущий в комплекте с janus. Сделал запрос списка и переключение потоков в интерфейсе панельки управления видео.

Камеры hikvision показывают нормально, камеры xiaomi показывают только первый keyframe и несколько секун после, потом изображение пропадает. chrome://webrtc-internals показывает, что кадры не декодируются.