1. Почему вообще начал

На рынке есть готовые продукты: пара датчиков на ботинки, приложение считает технику катания, подсказывает, что тренировать. Работает неплохо. Но по подписке — и недёшево: например, у Carv безлимитный сезонный доступ стоит $249 / £199 в год. И вот тут возникает вопрос: насколько эта подписка вообще оправдана? Датчик — это акселерометр с гироскопом за пару долларов и Bluetooth‑модуль, приложение — по сути обработка сигнала и немного статистики. Разовая покупка железа плюс разработка — понятные, конечные затраты. А подписка — плата за то, что уже посчитано один раз и с тех пор просто работает. Есть ощущение, что здесь платишь не за вычисления, а за то, что вход на рынок для конкурентов высокий: откалибровать алгоритмы, написать мобильное приложение, а потом ещё поддерживать серверы, пользователей и производство железа — дорого и долго. Подписка отбивает эти инвестиции. Но большая часть этого барьера — стоимость разработки, а она за последние пару лет резко упала: с ИИ‑инструментами то, что раньше требовало команды, становится посильным для одного человека. Продукт для рынка так не сделать — там нужна калибровка на тысячах лыжников, поддержка и сертификация. А вот любительский инструмент — вполне.

Второй мотив — практический: проверить на реальном, не игрушечном проекте, что сейчас умеют ИИ‑инструменты в разработке. Не автодополнение строк, а весь путь: от идеи и архитектуры до калибровки алгоритмов на реальных данных с настоящего железа. Ниже, в разделе 9, — про то, как это было на практике, а не в презентациях.

2. Как писал алгоритмы

Начал не с чистого листа: на рынке уже есть продукты, которые решают ту же задачу, и по ним видно, что вообще нужно измерять у лыжника, чтобы оценить технику — какой список характеристик поворота в принципе имеет смысл считать. Это ценный ориентир на уровне постановки задачи. А вот сами формулы, веса и пороги в готовых продуктах — чёрный ящик, недоступный и не особо интересный: даже если бы получилось их скопировать, это были бы чужие калибровочные числа на чужих данных и чужом железе, без понимания, откуда они взялись.

Пошёл другим путём. Физика резаного поворота на лыжах достаточно хорошо описана в биомеханической литературе — есть модели геометрии карвинга (угол закантовки, радиус дуги, боковой вырез лыжи), есть работы про анализ техники горнолыжников по IMU‑данным (акселерометр + гироскоп на ботинке или лыже). Я отталкивался от этого класса моделей и от собственных записей, а не от подгонки под чей‑то вывод.

Итоговый список — около десятка метрик на поворот: угол закантовки, ускорение в повороте (g‑force, отсюда и название программы — G‑Force Skiing), форма дуги поворота, симметрия между левой и правой ногой, темп поворотов, насколько поворот «закрыт» к концу дуги, и ещё несколько. Из них считается один сводный показатель — GF Score: каждая метрика нормализуется в диапазон «типичный худший — типичный лучший результат» и суммируется с весом, который зависит от выбранной манеры катания (карвинг, короткие повороты, параллельные лыжи — для каждой свой набор весов, потому что важность одной и той же метрики для разных техник разная).

Дисциплины сознательно ограничены тремя. У Carv, например, есть ещё могул и фрирайд, но по этим техникам у меня нет нужной личной экспертизы, чтобы понимать, что в них вообще значит «технически правильно» — а калибровать метрики вслепую, не понимая физики движения, бессмысленно. Решил остановиться на том наборе, в котором могу сам оценить результат.

Детектор самого поворота — отдельная небольшая задача, на которую ушло на удивление много времени. По потоку ориентации ботинка (кватернион, 100 раз в секунду) нужно понять, где начался и закончился один поворот. Интуитивно казалось, что это должен быть переход угла закантовки через ноль — но решил, что это слишком просто, и попробовал более сложный алгоритм из статьи Martínez et al., Automatic Turn Detection Algorithm, Sensors 2019, 19(4):902. На практике он не прижился — давал нестабильные границы на реальных записях. В итоге вернулся к первоначальной интуиции и не прогадал: граница поворота — это переход сглаженного угла закантовки через ноль, а чтобы не ловить дребезг на почти прямом участке, поворот засчитывается только после того, как угол прошёл пик и откатился от него на пороговую величину (гистерезис). Порог подбирается автоматически по записи, обычно это несколько градусов. Для этого нужен один калибровочный спуск в каждой манере катания: приложение запоминает его данные, по ним находит порог и задним числом считает метрики этого же спуска, так что спуск не пропадает. Дальше порог берётся из сохранённой калибровки.

3. Тестирование на коньках

Лыжного сезона под рукой не было, а проверять алгоритмы на синтетических данных — значит проверять только код, а не физику. Решение — коньки: каток доступен круглый год, склон — только в сезон. Кантование конька на льду (езда на внешнем или внутреннем ребре) физически похоже на кантование горнолыжной лыжи на снегу: тот же наклон корпуса, та же перекантовка с ноги на ногу, та же дуга.

  • Перетяжки (серия связанных поворотов на одной ноге кант в кант, без отталкивания, пример на видео после 50 сек) — физический аналог карвинга: длинная стабильная дуга, постоянная закантовка.

  • Змейка — короткие частые повороты влево‑вправо — аналог коротких поворотов (short turns): высокий темп, быстрая перекантовка.

Два навыка так проверить не вышло: плуг и проскальзывание. Точнее, конёк технически тоже может скользить боком — но физика этого скольжения на льду не похожа на то, как скользит лыжа по снегу под острым углом закантовки, так что как полноценный аналог это не годится. Эти метрики и пороги для них пока откалиброваны только по физической модели и разумным предположениям, без живых данных — честно об этом ниже, в разделе про ограничения.

4. Основные сценарии использования

Лыжный инструктор (скриншот приложения)
Первый экран приложения
Первый экран приложения
  • Свободное катание — приложение само отличает спуск от подъёмника по GPS, пишет метрики в фоне, считает GF Score на каждом спуске. Ничего нажимать по ходу не нужно. Отдельно можно включить видео: если рядом едет и снимает на телефон другой человек, датчики передают в приложение все данные заезда, и на повторе видео можно увидеть GF Score по каждому повороту в виде графика поверх записи.

  • Тренировка навыка — выбираете конкретную деталь техники (например, раннюю закантовку), приложение следит только за её метриками и даёт обратную связь сразу, поворот за поворотом: короткий звуковой сигнал на каждом засчитанном повороте — один из двух разных звуков, в зависимости от того, насколько хорошо выполнен именно этот поворот. Уровень навыка растёт, когда нужное число поворотов подряд (обычно 8) прошли порог полностью — не «в среднем за день», а именно подряд, без провалов.

  • Без датчиков — просто GPS‑трек: маршрут, скорость, потраченные калории, набор высоты, чтобы поделиться треком с друзьями, если датчиков с собой нет.

5. Как строить обучение

Тренировки (скриншот окна приложения)
Экран тренировок
Экран тренировок

Навыки сгруппированы в три дисциплины по манере катания (параллельные лыжи, карвинг, короткий радиус), внутри каждой — навыки по возрастанию сложности, это и есть встроенная программа обучения. У каждого навыка уровень 0–30, порог «освоено» зависит от заявленного уровня лыжника (7 / 17 / 27 из 30 для новичка / среднего / эксперта) — чем опытнее лыжник, тем выше планка, после которой навык считается закрытым.

Уровень навыка не поднимается за один удачный спуск: система смотрит на стабильность — берёт подтверждённый результат по нескольким последним засчитанным спускам, а не лучший или последний. Один эффектный заезд не завышает прогресс; нужно показать результат несколько раз подряд, чтобы он засчитался.

6. Как работают рекомендации

Склон (скриншот приложения)
Рекомендации
Рекомендации

После каждого спуска на главном экране — две карточки: «Освоено» и «Поработать над этим». Логика простая и без ML: навыки внутри дисциплины уже идут по порядку сложности, и приложение находит первый навык, который ещё не набрал нужный порог. Он и следующий за ним — то, что предлагается тренировать. «Освоено» — самый сложный навык, который уже перевалил порог. Никакой отдельной оценки «важности» или ML‑модели, которая бы решала, что показать — вся рекомендация целиком выводится из уже посчитанных уровней навыков, по порядку программы обучения.

Это осознанный выбор в сторону от ML. У Carv, например, есть встроенная ИИ‑модель, которая оценивает, насколько ваш карвинг похож на экспертный, — по ощущениям, это больше маркетинговая фишка, чем действительно полезный инструмент: она может сказать что‑то вроде «похоже на эксперта на 73%», но не может сказать, что конкретно нужно исправить, чтобы стать лучше. Для пользователя это чёрный ящик — никто снаружи не знает, на основании чего модель приняла решение. Здесь вместо этого всё построено на прозрачной физике и явных порогах: можно всегда объяснить, почему именно этот навык предложен следующим и что конкретно в нём не так.

7. Железо

Готовые фирменные датчики стоят прилично: пара сенсоров Carv — €129. По сути это связка недорогого IMU‑модуля (акселерометр + гироскоп), BLE‑чипа, батарейки и корпуса с клипсой на ботинок. Своими руками пара таких датчиков собирается примерно за 5000 ₽ — дешевле фирменной пары, и без необходимости разбираться в закрытом протоколе: BLE‑протокол у датчика открытый и документированный. Прошивку самого датчика менять нельзя, но она и не нужна — вся обработка сигнала, калибровка и метрики живут в приложении, и там можно менять всё.

Комплект для изготовления одного датчика
Комплект для изготовления одного датчика

Само железо тоже не сразу устаканилось. Изначально использовался XIAO nRF52840 Sense Plus — компактный и удобный модуль, под который прошивку писал сам: чтение IMU, фильтр ориентации, свой BLE‑протокол. Но у его гироскопа оказался дикий дрейф показаний, который было не свести на нет программно. Перешёл на WT9011DCL — готовый датчик с фирменной прошивкой, который не только оказался стабильнее, но и дешевле. Своя прошивка ушла в прошлое, и, как выяснилось, без потерь.

8. Ограничения — честно

  • Ещё не было ни одного реального теста на склоне. Вся калибровка и вся проверка алгоритмов на сегодня — данные с коньков плюс физическое моделирование. Физика поведения (закантовка, g‑force, форма дуги) выглядит правдоподобно и на коньках воспроизводится похоже на лыжи, но это не то же самое, что настоящий снег, настоящие лыжи и реальный радиус бокового выреза. Первый тест на склоне — ближайший приоритет.

  • Плуг и проскальзывание не проверялись на живых данных вообще — см. раздел 3.

  • Оценка условий на склоне (жёсткий наст против рыхлого снега) в GF Score сейчас не участвует. А нужна она для поправки оценки: на льду показать хорошую технику заметно сложнее, чем на свежем «вельвете», и одинаковый GF Score на разном снеге на самом деле означает разный уровень. Выяснилось, что честная оценка требует полноценного ML‑классификатора по сотне с лишним признаков, это отдельная большая задача, которую пока сознательно отложил в пользу более простой эвристики по вибрации с датчика ботинка — тоже ещё не реализовано.

9. Как прошёл сам вайб‑кодинг на практике

Сразу оговорюсь: в классическом понимании вайб‑кодинг — это «принимаю код, не читая». У меня был вайб‑кодинг с ревью. Не «опиши функцию — получи готовое приложение». Ближе к разработке с очень быстрым и очень дотошным исполнителем, которому нужно чётко объяснять, что нужно, и проверять каждый результат. Практика, которая действительно помогла:

  • Ни одна калибровочная константа не бралась «на глаз» надолго. Например, пороги «сенсор лежит неподвижно» для авто‑калибровки нулевого положения датчика сначала были оценкой без данных — потом записал 70 секунд покоя/ходьбы/движения с датчиков, посчитал разброс шума и заменил оценку настоящими числами с запасом. Без такой проверки константа так и осталась бы условной.

  • Правило «на каждый найденный баг — тест». За время разработки нашлось несколько багов: например, формула одной из метрик ломалась на отрицательном диапазоне значений — без теста именно на таком диапазоне это осталось бы незамеченным до первого реального использования.

  • Спорные архитектурные решения — сначала обсуждение, потом код. Например, живой счётчик «сколько поворотов подряд прошли порог» сначала реализовал в реальном времени во время спуска — а потом решил, что это лишняя сложность: подъём уровня не обязан считаться именно во время катания, и переделал на пересчёт по уже сохранённым данным спуска, постфактум. Такие развороты — нормальная часть процесса, если задавать вопрос «а зачем именно так» на каждом значимом решении.

  • Обязательное ревью каждого куска кода. Не «сгенерировал — принял», а построчный разбор перед тем, как что‑то попадает в проект. Во многих случаях именно на этом шаге код в итоге заметно упрощался — первая рабочая версия почти никогда не была самой простой. ИИ порой действует прямолинейно там, где нужно чуть больше изящества, и, наоборот, усложняет то, что можно сделать проще. Правда, по специализации я backend‑разработчик, поэтому построчно ревьюил в основном бизнес‑логику, а UI‑код принимал почти как есть — просматривал, но без той же дотошности.

Главный вывод: результат сильно зависит не от инструмента самого по себе, а от того, насколько дотошно проверяется каждый шаг — тестами, реальными данными с датчиков, а не только тем, что код скомпилировался и не упал. Как говорится, доверяй, но проверяй.

На самом деле я немного переоценил свои возможности: изначально проект казался не особо сложным, но на втором месяце разработки превратился в чемодан без ручки — и бросить жалко, и тащить тяжело. Но в него уже было вложено немало времени и денег, так что я всё же довёл его до релиза.

10. Что дальше

  • Первый настоящий тест на склоне — калибровка по реальным данным вместо коньков и физической модели.

  • DSP‑эвристика по вибрации датчика ботинка для оценки жёсткости снега.

  • Постепенное расширение программы обучения по мере накопления реальных данных с разных лыжников.

  • Не хватает обучающих видео — коротких роликов с демонстрацией техники, как в готовых продуктах вроде Carv. Сейчас они есть только для двух навыков, а для упражнений нет вовсе. Если кто‑то готов снять или поделиться такими видео — буду рад помощи.

Где взять и как связаться с автором

  • Скачать: RuStore — приложение сразу приходит с демо‑данными (несколько спусков, прогресс по навыкам), чтобы можно было сразу оценить, как это выглядит, не катаясь; перед реальным использованием их можно удалить одной кнопкой в «Конфигурации». К сожалению админы не торопятся проводить модерацию, поэтому самая свежая версия лежит здесь Githib

  • Документация: прямо в приложении («Конфигурация» → «Документация») — полное описание всего заявленного функционала, то же самое руководство пользователя, что использовалось при подготовке этой статьи.

  • Обсуждение и вопросы: форум ski.ru

  • Написать напрямую: gf_skiing@mail.ru, либо через экран «Сообщить о проблеме» прямо в приложении (баг, идея, что угодно).