Этот сайт использует файлы cookies. Продолжая просмотр страниц сайта, вы соглашаетесь с использованием файлов cookies. Если вам нужна дополнительная информация, пожалуйста, посетите страницу Политика файлов Cookie
Subscribe
Прямой эфир
Cryptocurrencies: 8111 / Markets: 109933
Market Cap: $ 2 679 404 352 005 / 24h Vol: $ 68 224 568 342 / BTC Dominance: 60.029774460447%

Н Новости

Робот с LLM, который меня подстрелил. Часть 3

Робот с LLM, который меня подстрелил. Часть 3

Содержание

0. Пара слов в своё оправдание

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

Я подходил к статье три месяца - садился писать и бросал несколько раз.

…

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

Итак, напомню, что у меня имеется вот такая “тушка” вооруженная пистолетом:

Робот с пистолетиком
Робот с пистолетиком

которая умеет выполнять простые команды вида “проехать вперед 1.4 метра” и “повернуть вправо на 45 градусов”, стоит WiFi-камера. Т.о. для того чтоб ИИ начал действовать в реальном мире осталось всего ничего:

  • увидеть и осознать изображение с камеры

  • отдать команду для выполнения действия

Для тех кто пропустил начало, напомню как это всё выглядит:

Это обзорная статья, которая затрагивает все основные области, с которыми мне пришлось столкнуться при создании робота. Слишком углубляться в каждую область у меня не получится. Если детально расписывать каждую область, то получится не статья, а книга, а может и учебный курс или даже пару лет курсов технического ВУЗа.

В целом могу сказать, если вы хотите свой pet-проект с ИИ и у вас есть свободное время - делайте робота. Это реально весело. Потребуются знания и навыки из самых разных областей. От математики и физики до психологии. И при желании тут найдется место и для RAG, и для машинного зрения и для синтеза и для распознавания речи, работе с контекстом и памятью LLM. В общем прокачаться можно хорошо.

1. Принципиальная осуществимость. Langfuse

Почему я вообще решил, что чат можно подключить к роботу и оно заработает?

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

Но сможет ли он, такой умный, реально взаимодействовать с этим суровым миром? Что вообще должен уметь робот, чтоб взаимодействовать с миром? А нужно всего две вещи:

  • воспринимать мир

  • влиять на мир

Итак. Может ли модель понять, что на фото? Может ли она превратить увиденное в команду поворота? Первый вопрос - про восприятие мира. Второй - про влияние на мир. Если оба закрыты, остаётся замкнуть цикл “восприятие-действие”.

Я сделал фото

Комната с радиатором отопления
Комната с радиатором отопления

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

Langfuse - это открытая инженерная платформа (LLM Engineering / LLMOps) для мониторинга, отладки, оценки и управления приложениями на базе больших языковых моделей (LLM). Основные возможности: трассировка, управление промптами, оценка качества, ведение сессий.

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

Подробности про Langfuse можно найти в статьях ниже:

LLMops дома: быстрое разворачивание и настройка инфраструктуры с помощью Langfuse

Как я научил AI анализировать AI: observability для LLM-агентов с Langfuse

Контроль и порядок. Разворачиваем платформу учёта затравок для БЯМ

Я решил, что мне совершенно необходимо установить из докер-образа Langfuse и проверить разные модели, видят ли они радиатор отопления и могут ли поворачивать в стороны.

Из пушки по воробьям. Я установил Langfuse, приготовил ему данных (item), примерно так:

(Скриншоты - реконструкция. В момент создания робота я не скриншотил, они свежие.)

Langfuse: item
Langfuse: item

На скрине: запрос (текст и фото) и ожидаемый ответ.

Такие items объединяются в наборы данных (dataset)

Langfuse: dataset
Langfuse: dataset

И это всё может быть массово прогнано на различных моделях, с учётом расхода токенов, денег и прочего. Это называется эксперимент (experiment):

Langfuse: experiment
Langfuse: experiment

Но сразу скажу, Langfuse это скорее не веб-система, а библиотека на Python, у которой есть интерфейс, чтоб красиво смотреть. То есть вы пишете код, загружаете данные и всё это можно делать через питоноский API, а некоторые вещи можно делать через интерфейс и в интерфейсе смотреть результаты экспериментов.

Были проверены несколько типов вопросов:

Тип

Пример

объект есть

радиатор батареи

объекта нет, но он уместен в квартире

холодильник в жилой зоне

объекта нет, но в кадре есть похожий

стиральная машина при наличии холодильника

объекта нет и быть не может

корова

Все данные проверок у меня, к сожалению, не сохранились и повторно протестировать тоже не выходит, т.к. многие модели из тех, что я пробовал стали недоступны. Но в целом модели справлялись, Опус, точно помню, справлялся прекрасно, что и дало возможность двигаться дальше.

Также была сделана проверка, понимает ли модель, сетку нанесённую на изображение. Может ли она ответить на вопрос, на сколько градусов повернуться чтобы определенный объект оказался в центре кадра.

На сколько надо повернуть, чтоб Бендер оказался в центе?
На сколько надо повернуть, чтоб Бендер оказался в центе?

На сколько надо повернуть, чтоб Бендер оказался в центе?

Тут тоже был получен положительный ответ, что означало, что можно делать робота. Принципиальные вопросы разрешены.

Касательно того как выполнить поворот механически. В целом понятно, что если модель текстом отвечает “вправо 20 градусов”, то это можно просто распарсить и выполнить. Но модели умеют:

  • структурированный ответ в JSON. В этом случаем модели передается схема ответа и модель дает ответ в JSON в соответствии со схемой. Дальше мы сами вынимаем угол и выполняем вращение.

  • Вызов инструмента (tool), тулинг (tooling). Похожая схема, но чуть дальше. Модели сообщается, что у нее есть инструменты, которые она может вызвать. Например, прочитать файл.

Пример структурированного ответа (на 90% настоящий пример). Допустим, надо вытащить сумму из квитанции:

Квитанция за вывоз мусора
Квитанция за вывоз мусора

Запрос к Gemini: картинка, задание словами и схема ответа.

{
  "contents": [{
    "role": "user",
    "parts": [
      { "inlineData": { "mimeType": "image/png", "data": "<base64 картинки>" } },
      { "text": "Это платёжный документ за коммунальные услуги? Если да - извлеки итоговую сумму к оплате ("Всего к оплате") и помести её в поле amount. Если это не платёжный документ или суммы на нём нет - установи error=\"NOT_A_BILL\", а amount оставь null." }
    ]
  }],
  "generationConfig": {
    "response_mime_type": "application/json",
    "response_schema": {
      "type": "object",
      "properties": {
        "amount": { "type": "number", "nullable": true },
        "error":  { "type": "string", "nullable": true }
      }
    }
  }
}

Ответ на квитанцию:

{ "amount": 44.22, "error": null }

Ответ на фото кота:

{ "amount": null, "error": "NOT_A_BILL" }

Схема задаёт форму ответа: модель не может ответить простым текстом, на выходе всегда JSON, который сразу парсится. А что класть в поля, объясняется в тексте запроса. Поле error нужно, чтобы у модели был способ сказать, что она не может выполнить задачу, иначе она выдумает число. И “Всего к оплате” тоже не просто так: сумм на квитанции несколько, без подсказки модель может взять не ту.

Пример инструмента. Модели передаётся описание инструмента, по сути тоже JSON-схема, только для аргументов:

{
  "name": "turn_relative",
  "description": "Повернуть на N градусов от текущего направления. Положительные градусы = вправо, отрицательные = влево.",
  "input_schema": {
    "type": "object",
    "properties": {
      "degrees": { "type": "number", "description": "Угол поворота в градусах, -180 … +180." }
    },
    "required": ["degrees"]
  }
}

На вопрос “повернись так, чтобы Бендер оказался в центре” модель отвечает не текстом, а вызовом:

{ "type": "tool_use", "id": "toolu_01A...", "name": "turn_relative", "input": { "degrees": 5 } }

Разница в том, кто решает. При структурированном ответе мы сами спросили и ждём ответ строго в нашей форме. С инструментами модель сама выбирает, вызвать ли что-то, что именно и с какими аргументами. Выполняем вызов мы, результат возвращаем модели, и она решает, что делать дальше.

Несколько позже я провел еще пару опытов, уже без Langfuse и только на Опусе. Мне было интересно разберётся ли ИИ в такой вот позорной карте:

Вам понятно, что тут изображено?
Вам понятно, что тут изображено?

Если ИИ подсунуть карту и снимок из комнаты, с вопросом в какую сторону повернуть, чтоб увидеть что-то, ИИ, глядя на карту правильно отвечал. То есть, он чётко понимал, что это есть карта, догадывался что она снята лидаром, и что картинки по бокам и сверху и снизу не просто так. В общем соображал как соспоставить карту, снимок и мою просьбу выполнить поворот.

На картинке: зелёные точки - карта снятая лидаром пылесоса, а также дорисованные мной диван с кухней.

Отличная статья про лидар от робота-пылесоса: Использование лидара от робота-пылесоса для системы предотвращения столкновений в автономных роботах

Подведу итоги этой части.

С этой точки я понимал, что принципиально проект осуществим, впереди просто инженерная работа. Главное агентный (или агентский, кто знает как правильно?) цикл. Но как много будет инженерной работы я еще не знал…

2. Взаимодействие хост-ардуино

На данный момент есть понимание, что мы можем, как минимум в теории, сделать тележку, которая будет поворачиваться, ездить и возить на себе камеру. А камера будет передавать на хост фото/видео.

Камера подключается к компу по WiFi, а тележка будет соединена по COM порту. Часть, которая вставляется в компьютер выглядит так:

USB-UART
USB-UART

Для компьютера это обычный ком-порт, в который можно писать, и из которого можно читать. Максимальная скорость 57600 бод. Для Arduino - это Serial и стандартное чтение-запись в него.

Команды и телеметрия пролезут, а вот фото, и уж тем более видео, никак нет.

К Ардуино физически подключены компас и гироскоп, плата управления моторами.

Первоначальная сборка:

Бутерброд
Бутерброд

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

Работать с ними будем позже, но протокол пишется сразу с оглядкой на них.

Требования:

  • по проводу пойдут три вида сообщений: телеметрия, команды, ответы на команды;

  • протокол должен расширяться, новые поля добавляются минимальной переделкой парсера. Переделка должна быть простая и при этом протокол должен оставаться компактным, чтобы уложиться в 57600 бод;

  • разбор должен быть простым.

Пример.

Текстовый протокол с маркером начала (—) и конца пакета (***). Один кадр:

---
SQ:1240
LS:50
RS:50
V:11.8
***
  • SQ - Сквозной номер пакета (sequence)

  • LS - Left Speed, текущая установленная скорость левого мотора

  • RS - Right Speed, текущая установленная скорость правого мотора

  • V - Напряжение батареи

Прикидка пропускной способности.

Типичный пакет телеметрии (8 полей + маркеры):

---\r\n          = 5 байт
SQ:1240\r\n      = 9 байт
LS:50\r\n        = 7 байт
RS:-30\r\n       = 8 байт
LC:512\r\n       = 8 байт
RC:480\r\n       = 8 байт
GX:-123.45\r\n   = 12 байт
GY:456.78\r\n    = 11 байт
V:11.80\r\n      = 9 байт
***\r\n          = 5 байт
                 --------
                 ~82 байта

При интервале 100ms (~10 раз в секунду) это ~820 Б/с. Канал 57600 бод при 8N1 (10 бит на байт) пропускает 5760 Б/с, получается ~14% канала. Более чем хорошо.

Запас потом пригодился: со временем в пакет добавились дальномер (RF), гироскоп (GZ) и состояние светодиодов (LR, LB). Пакет вырос до ~114 байт, загрузка - до ~20%. Протокол расширился без переделки, и запас всё ещё большой.

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

Для начала достаточно. Парсится легко, лишнего ничего, расширить просто.

Первой реально заработавшей командой было, как положено, моргание встроенным светодиодом ардуинки. Код у меня не сохранился, но в протоколе была команда, что-то вроде L:1 (led on) и L:0 (led off).

Итоги этой части. Реализован обмен данными хост <-> arduino. В этой точке у меня есть канал связи, можно идти дальше, к управлению чем-нибудь.

3. Моторы

Мальчик любого возраста всегда готов порулить машинкой на радиоуправлении. Я не исключение.

Тележка есть, протокол и связь с компом есть. Еще немного и у меня будет машинка на радиоуправлении.

Всё что нужно - расширить протокол на две команды: установка скорости правого и левого мотора.

Команды, которые едут на ардуину:

---
L:150
R:150
***

Диапазон значений от 0 до 255. 128 - нейтраль, 255 - полный вперёд, 0 - назад.

В ответ ардуина шлёт ответ:

---
LS:140       # скорость левого мотора (-128..127, 0 = стоп)
RS:140       # скорость правого мотора
LC:215       # ток левого мотора, сырой АЦП 0-1023
RC:220       # ток правого мотора
***

В первом варианте я сделал некоторую инерционность в раскрутке моторов. От нуля до максимума моторы выводились примерно за четверть секунды. То есть, хост шлёт команду мотору: полный вперёд (255), на ардуино стоит скорость мотора в нуле, нейтраль (128), и ардуина не рывком меняет 128 на 255, а за несколько оборотов главного цикла накидывает скорость 128, 138, 148, 158, … Это позволило тележке двигаться более плавно, с характерным приятным звуком.

Контроллер Motor Shield Plus выполнен на базе двухканального H-моста L6206Q на полевых транзисторах. Имеет встроенные датчики тока моторов. Я думал использовать датчики для контроля движения, на ковре тяжелее - ток больше, на ламинате ехать проще - меньше ток, или для контроля застревания - при застревании ток резко растёт. Но это так и осталось в планах и протоколе. Может как-нибудь потом сделаю.

4. Датчики

Магнитометр. Он же компас

Что такое магнитометр? Это прибор для измерения магнитного поля. Как бы компас. Но не компас. Компас молодец, у него стрелка и она всегда показывает на северный полюс (магнитный). А у магнитометра стрелки нет, у него есть три числа: напряженность магнитного поля по трём координатам x, y, z. И если вы думаете, что имея три координаты напряженности поля из них можно сделать стрелку компаса, то нет. Я вас разочарую.

Почему нет? Потому что железка меряет не поле Земли, а всё поле, которое вокруг неё есть. А вокруг неё есть: она сама, моторы с постоянными магнитами, стальные винты, провода с током. Этот собственный магнетизм ездит вместе с датчиком и поэтому не усредняется - он просто добавляет к каждому измерению постоянный вектор. Плюс у каналов X и Y несколько разная чувствительность, и это тоже надо чем-то лечить.

Увидеть это можно так. Ставим тележку на пол, крутим её на месте на полный оборот и пишем пары (GX, GY). Для простоты я исключил показания по оси Z, взял плоский случай. Всё же тележка будет ездить по ровному полу, а не по горам. Если бы датчик был идеальный, точки легли бы на окружность вокруг нуля, и курс брался бы одним atan2. Вот что вышло на самом деле:

Сырые данные с магнитометра
Сырые данные с магнитометра

Окружность (эллипс) есть, но она не вокруг нуля. Её центр сместился в точку (+0.14, −0.17) - это и есть собственное поле робота. И полуоси немного разные, 0.513 против 0.352 - собственное поле плюс разная чувствительность каналов. Пока центр не в нуле, atan2 даёт некорректные результаты, причём по-разному в разных направлениях. Если посчитать курс прямо по сырым числам, ошибка на этом логе - 22 градуса в среднем и до 39 в максимуме. Курс, которого нет.

Калибровка - это найти центр и полуоси и вычесть их. Четыре числа: сдвиг по X, сдвиг по Y, масштаб по X, масштаб по Y. Дальше каждое измерение прогоняется через них, и облако садится на единичную окружность вокруг нуля:

После нормировки
После нормировки

А как найти эти четыре числа? Линейной регрессией. Метод наименьших квадратов. Уравнение эллипса с осями по координатам

((x − dx) / kx)² + ((y − dy) / ky)² = 1

нелинейно по x и y, но если раскрыть скобки и собрать всё относительно x², оно становится линейным по своим коэффициентам:

x² = b1·x + b2·y² + b3·y + b4

То есть: цель - x², признаки - (x, y², y, 1). Обычный метод наименьших квадратов, четыре коэффициента, одна строчка np.linalg.lstsq. Из b1…b4 центр и полуоси достаются арифметикой. Регрессия здесь линейная не в смысле “прямая y = kx + b”, а в смысле “неизвестные входят линейно”.

По-хорошему калибруют не эллипс на плоскости, а эллипсоид в трёх измерениях, и тогда в уравнении появляется ещё и перекрёстный член xy - наклон эллипса. Мне хватило двумерного варианта: тележка ездит по ровному полу и не заваливается.

Несмотря на привлекательность магнитометра, как датчика направления от него пришлось отказаться. Реальность внесла свои коррективы. Видео, демонстрирующее изменение показаний компаса при перемещении:

Телефон с компасом на полу
Телефон с компасом на полу

Наглядный пример, почему компас оказался бесполезен. При перемещении компаса по полу его показания могли измениться на 45 градусов. Видимо железная арматура в полу вносит свои коррективы, делая компас генератором случайных чисел.

Провал.

Надо иначе подходить к вопросу. Были два кандидата: лидар от пылесоса и гироскоп. Лидар выглядел очень соблазнительно: надёжно, можно иметь не только поворот, но и положение на карте, одометрию, всё что даёт SLAM. Но от SLAM сурово запахло ROS и еще неделей, а то и месяцем работы.

SLAM (Simultaneous Localization and Mapping) - алгоритм одновременного построения карты и определения своего места на ней.

ROS (Robot Operating System) - не ОС, а стандартный набор библиотек и инструментов для роботов. Мощно, но громоздко.

Вот картинка из интернета, найденная по словам ROS+SLAM:

SLAM
SLAM

Карта комнаты, построенная лидаром. Чёрное - стены и препятствия, светлое - свободное место, в центре - сам робот.

Гироскоп

Я вспомнил, что первоначальная задача, которую я решаю с роботом - это посмотреть, как робот будет воспринимать реальный мир, ориентироваться в нём, перемещаться. Для этого ему нужно иметь фото с камеры и возможность выполнить команду поворота с некоторой точностью. Даже если поворот выполнен не точно, робот сможет посмотреть на новое фото после выполнения действия и выполнить корректировку. Примерно так, как это делает человек. То есть мне не нужно иметь абсолютное угловое позиционирование (аналогично тому, как у меня в голове нет точного знания о том, где север), достаточно выполнять относительные повороты с некоторой точностью. В целом гироскоп как раз и должен дать такую возможность. Поворот осуществляется относительно быстро и ошибка гироскопа не успевает накопиться в той мере, чтоб сделать контроль невозможным.

Честно говоря, гироскоп появился на борту чуть раньше, чем я окончательно похоронил компас, - сначала как помощник компасу. Об этом союзе будет отдельный раздел про комплементарный фильтр. Здесь - про сам датчик.

Что меряет гироскоп

Гироскоп на тележке - L3G4200D с модуля Troyka IMU, подключён к ардуине по I2C. Как и магнитометр, это не совсем то компас, так и гироскоп не совсем то, что нарисовано в учебнике физики: никакого волчка внутри нет, есть MEMS-кристалл, который измеряет угловую скорость. Не угол, а скорость поворота: сколько градусов в секунду тележка крутится вокруг вертикальной оси. Мне нужна только ось Z, остальные две тележке на ровном полу ни к чему.

В протокол добавилось одно поле:

GZ:<float>     # угловая скорость вокруг вертикальной оси

Угол получается интегрированием: каждые 20 мс берём скорость, умножаем на прошедшее время и прибавляем к накопленному углу.

angle += gz * dt

Одна строчка. Вся хитрость в том, что вместе с углом накапливается и любая ошибка в gz.

Дрейф и калибровка нуля

Ставим тележку на пол, ничего не трогаем, смотрим на gz. Ожидаем ноль. Получаем не ноль: гироскоп стабильно показывает, что тележка медленно крутится. Это смещение нуля (bias). Маленькое, доли градуса в секунду, но интеграл его накапливает. Скрипт gyro_drift_test.py показал: стоящая на месте тележка за 10 секунд “проворачивалась” на 15 градусов.

Лечится это так же, как у компаса - вычитанием. Робот стоит, собираем 30 пакетов, берём медиану, это и есть смещение нуля. Вычитаем его из каждого следующего измерения. Медиана, а не среднее - потому что гироскоп иногда выдаёт одиночные выбросы, и один выброс заметно сдвинул бы среднее. После калибровки те же 10 секунд покоя дают 0.6 градуса. В двадцать пять раз лучше, и для поворота, который длится секунду-две, этого хватает с запасом.

Прогрев

Всё работало, пока однажды после включения робот не начал крутиться сам по себе. Вернее, он думал, что крутится: калибровка насчитала смещение около 54°/с. Это не дрейф, это мусор.

Оказалось, L3G4200D после подачи питания некоторое время приходит в себя, и первые его показания - случайные числа. По даташиту ему нужно около 100 мс. Повторные запуски программы на хосте этого не замечали - ардуина не перезагружалась, датчик давно был тёплый. Проблема вылезала только на холодном старте.

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

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

G±DDDD\n       # поправка смещения нуля в десятых долях °/с

Выбросы и знаки

Гироскоп иногда выдаёт одиночный выброс: среди ровных нулей вдруг +17°/с. Против этого на хосте стоит медианный фильтр по трём последним пакетам - одиночный выброс он просто выкидывает. Цена - задержка в один пакет, около 100 мс.

Фильтр я сначала включил, потом, после теста, выключил как ненужный, а потом включил обратно. Потому что когда поменялся знак - выбросы стали вычитаться из угла поворота, робот начал раскачиваться у цели и не мог закончить поворот.

Про знак отдельная история. Модуль стоит на тележке так, что ось Z смотрит вниз, поэтому положительная угловая скорость у меня - это поворот по часовой стрелке, а не против, как положено по правилу правой руки. Поворот “направо на 45” просто ехал налево. Лечится одной константой GYRO_SIGN = -1. Потом я перебросил провода моторов, и знаки пришлось разбирать ещё раз. Мелочь, но каждый раз это полчаса недоумения: вроде всё правильно, а робот крутится не туда.

Что в итоге

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

Гироскоп же помогает ехать прямо: накопленное за время движения отклонение курса превращается в разницу скоростей левого и правого моторов, и тележка сама выправляется.

И последнее: компас ушёл даже из HUD. Курс, который видно на видео - это накопленный угол гироскопа. Не абсолютный, отсчитанный от положения на старте. Но для робота, который ориентируется по картинке с камеры, этого достаточно.

5. Датчики. Магнитометр, гироскоп и комплементарный фильтр

На тот момент у меня было два датчика направления, и каждый плох по-своему.

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

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

Хочется взять от каждого лучшее: у гироскопа - гладкость на коротких интервалах, у компаса - отсутствие дрейфа на длинных. Именно это и делает комплементарный фильтр.

Что такое комплементарный фильтр

Формула в одну строчку:

angle = alpha · (angle + gz · dt) + (1 − alpha) · compass

Читается так. Сначала делаем прогноз по гироскопу: к предыдущему углу прибавляем поворот за последний такт. Потом немного подтягиваем прогноз к компасу. Коэффициент alpha близок к единице - у меня 0.97. То есть на каждом такте угол на 3% сдвигается в сторону компаса, а 97% - это память, то, что уже накоплено.

Почему это работает. Датчики входят в формулу по-разному, и это следует из того, что они меряют. Гироскоп меряет скорость, поэтому входит приращением: поворот за такт попадает в угол сразу и целиком. Компас меряет сам угол, поэтому входит как точка, к которой угол понемногу подтягивается.

Отсюда и роли. Быстрый скачок компаса - наводка от мотора - за один такт сдвигает результат всего на 3% своей величины и тут же тонет в следующих тактах. А медленный дрейф гироскопа компас терпеливо, по 3% за такт, вытягивает обратно: ошибка не копится бесконечно, а упирается в потолок. Гироскоп отвечает за быстрые изменения, компас - за медленные. Они дополняют друг друга, отсюда и название: complementary - дополняющий.

Роли задаёт устройство формулы, а не alpha. Даже при alpha = 0.5 гироскоп всё равно отвечал бы за быстрое, а компас за медленное. Просто “медленным” стало бы почти всё, и фильтр превратился бы в слегка сглаженный компас.

На языке обработки сигналов: гироскоп проходит через фильтр высоких частот, компас - через фильтр низких, и частоты среза у этих фильтров совпадают, так что вместе они покрывают весь диапазон. Эту частоту задаёт alpha. Постоянная времени фильтра

τ = alpha · dt / (1 − alpha)

У меня пакеты телеметрии идут примерно 10 раз в секунду, dt примерно 0.1 с, и τ примерно 3 секунды. Всё, что происходит быстрее трёх секунд, фильтр берёт у гироскопа, медленнее - у компаса. Поворот тележки длится секунду-две, то есть во время поворота работает в основном гироскоп. Ровно то, что нужно.

Классическое применение комплементарного фильтра - квадрокоптеры и балансирующие роботы: там гироскоп так же объединяют с акселерометром, чтобы знать наклон. Формула та же.

Объединение компаса и гироскопа

В коде на хосте фильтр занял десяток строк. Одна грабля: курс - величина круговая. Если гироскоп прогнозирует 359°, а компас показывает 1°, то наивная разница даёт −358°, и фильтр потащит курс через весь круг. Разницу углов нужно приводить в диапазон −180…+180:

gyro_pred = (fused + GYRO_SIGN * gz * dt) % 360
diff = ((compass - gyro_pred + 180) % 360) - 180
fused = (gyro_pred + (1 - ALPHA) * diff) % 360

Это та же формула, только переписанная через разницу: “прогноз гироскопа плюс 3% от расхождения с компасом”. Начальное значение берётся с компаса - первым пакетом, до начала поворота.

И фильтр сработал. Курс во время поворота перестал скакать, наводки от моторов ушли. Тележка стала поворачиваться плавно и останавливаться уверенно.

Только вот останавливалась она не там.

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

Точность поворота с фильтром получилась около 30 градусов. Через неделю я выкинул компас из поворотов совсем и оставил только гироскоп - точность стала около градуса. Об этом было в разделе про гироскоп.

Вывод простой: фильтр смешивает датчики, но не делает их лучше. Если один из датчиков врёт медленно, фильтр просто передаст это на выход. Комплементарный фильтр хорош, когда ошибки датчиков живут на разных частотах: у одного быстрый шум, у другого медленный дрейф. У меня у компаса оказалась ещё и медленная систематическая ошибка - та же полоса частот, на которой фильтр ему верит.

Впрочем, фильтры в проекте на этом не закончились. Позже для дальномера пригодился альфа-бета фильтр, родственник фильтра Калмана. Об этом в разделе 7.

6. Датчики. Дальномер - обнаружение препятствий

Камера даёт роботу картинку, но по картинке трудно понять, далеко ли стена. Люди это видят двумя глазами, а у робота глаз один. Нужен датчик, который просто скажет: до препятствия впереди столько-то миллиметров.

У меня были:

  • Инфракрасный дальномер GP2Y0A02YK компании Sharp. Диапазон: 20–150 см

  • Ультразвуковой дальномер HC-SR04. Диапазон: 2–400 см

  • Лидар Benewake TFmini-S. Диапазон: 10–1200 см

Три дальномера
Три дальномера

Инфракрасный отпал сразу: полтора метра - слишком мало. Ультразвук с четырьмя метрами подходил неплохо. Главное опасение насчёт ультразвука было в том, что мягкое звук поглощает, и диван останется для робота невидимым. Проверил - зря боялся: диван отражал звук вполне прилично.

И всё-таки я выбрал лазерный. По принципу “самый крутой”. Двенадцать метров, узкий луч, сто измерений в секунду. Забегая вперёд: наверное, стоило выбрать ультразвук. Лазер принёс проблемы, о которых я тогда не думал: зеркала. Но об этом ниже.

Первое подключение

TFmini-S общается по UART: раз в 10 мс шлёт кадр из 9 байт, в котором есть расстояние в сантиметрах. Скорость 115200 бод. Библиотека TFLidar разбирает кадр, в коде - одна строчка lidar.getData(dist).

Проблема в том, что свободного UART на плате не было. На Arduino Leonardo аппаратный последовательный порт один, Serial1, и он занят радиомодулем. Serial - это USB, он для отладки. Остаётся SoftwareSerial - программный UART на любых двух пинах. Подключил лидар на пины 10 и 9, добавил в протокол поле:

RF:<int>       # дальномер вперёд, мм

И всё заработало. На столе.

Проблемы с Soft Serial

Проблемы вылезли, когда робот начал ездить по дальномеру: “проехать метр вперёд” - значит ехать, пока расстояние до стены не уменьшится на 1000 мм. Робот проезжал мимо цели. Показания дальномера запаздывали: робот уже стоит у стены, а дальномер всё ещё показывает, что до неё полметра.

Причин две, и обе в программном UART.

Первая - буфер. Лидар шлёт 100 кадров в секунду, а главный цикл ардуины читал дальномер раз в 100 мс, вместе с отправкой телеметрии. За это время в буфер SoftwareSerial успевает прийти 10 кадров, 90 байт, при размере буфера 64 байта. Буфер переполнен, а getData() читает первый кадр из буфера - самый старый. Робот едет по устаревшему расстоянию.

Первая заплатка: вычитывать буфер до конца и брать последний целый кадр. Стало лучше, но не хорошо.

Вторая причина глубже. Программный UART принимает каждый бит в прерывании, а на 115200 бод бит длится меньше 9 микросекунд. Пока идёт приём байта, ардуина больше ничем не занята, а байты идут непрерывным потоком. Программный UART на такой скорости и главный цикл с моторами, гироскопом и телеметрией мешают друг другу. На меньших скоростях SoftwareSerial живёт нормально, но лидар хочет 115200.

Нужен был аппаратный UART. А его нет.

Отдельная плата

Решение - отдать лидар отдельной ардуине. Arduino Pro Micro стоит копейки, построена на том же ATmega32U4, что и Leonardo, и у неё есть свой аппаратный Serial1, который ничем не занят. Лидар подключается к нему, а Pro Micro занимается только одним: читает лидар и держит последнее расстояние наготове.

Lidar и Arduino Micro
Lidar и Arduino Micro

Осталось соединить две ардуины. Шина I2C на основной плате уже была: на ней висит модуль Troyka IMU с компасом и гироскопом. Добавить на ту же шину ещё одно устройство - это два провода, SDA и SCL, плюс общая земля. Основная плата - ведущая (master), Pro Micro - ведомая (slave) с адресом 0x08.

Leonardo pin 2 (SDA) <-> Pro Micro pin 2 (SDA)
Leonardo pin 3 (SCL) <-> Pro Micro pin 3 (SCL)
GND                  <-> GND

Протокол между ними проще некуда: ведущая просит два байта, ведомая отдаёт расстояние в сантиметрах, старшим байтом вперёд.

Код ведомой платы помещается на экран:

volatile int16_t dist = 0;

// Вызывается в прерывании, когда мастер запрашивает данные
void onRequest() {
  Wire.write((uint8_t)(dist >> 8));    // старший байт
  Wire.write((uint8_t)(dist & 0xFF));  // младший байт
}

void setup() {
  Serial1.begin(115200);
  lidar.begin(&Serial1);
  Wire.begin(0x08);
  Wire.onRequest(onRequest);
}

void loop() {
  int16_t tmp = 0;
  lidar.getData(tmp);   // ждёт очередной кадр, сам задаёт темп цикла
  noInterrupts();
  dist = tmp;
  interrupts();
}

Две тонкости. volatile - потому что dist меняется в loop(), а читается в прерывании I2C, и компилятору нельзя держать её в регистре. И noInterrupts() вокруг присваивания: процессор восьмибитный, 16-битное число записывается в два приёма. Если запрос от ведущей придёт ровно между ними, она получит старший байт от нового расстояния и младший от старого. Случается такое редко, но выглядело бы как необъяснимый скачок дальномера.

На стороне основной платы - Wire.requestFrom(0x08, 2), два байта, умножить на 10, получить миллиметры.

Первая версия связки работала не с первого раза. Пара дней ушла на отладку: менялись адрес, порядок байт, единицы. От этого остались тестовые скетчи мастера и слейва - сначала две голые ардуины на столе, одна спрашивает, другая отвечает, и только потом лидар. Этот подход рекомендую: I2C проще отлаживать отдельно от всего остального.

Статья с обзором шин коммуникации I2C, SPI и т.п.: Кратко про протоколы взаимодействия в микроконтроллерах

Шкафы

Однажды я заметил странное: Grok упорно пытался заехать под кухонный шкаф. Дальномер показывал, что впереди свободно, а на картинке с камеры - шкаф прямо перед носом.

Лидар стоял примерно на 10 см ниже камеры. Луч лидара проходил под шкафами, в просвет над плинтусом, и мерил расстояние до стены за ними. С точки зрения лидара там действительно свободно. С точки зрения робота - нет, камера на голове и она не пролезет.

Лидар переставил выше, на уровень камеры. Заодно пришлось посчитать, куда на кадре попадает луч, чтобы нарисовать в HUD прицел дальномера в нужном месте. Об этом в разделе 15.

Зеркала

Вторая проблема лазера - зеркала. Лазерный луч от зеркала отражается как от зеркала, а не как обычно (что бы это ни значило). Луч уходит дальше, во что-то упирается и возвращается тем же путём. Дальномер показывает расстояние до зеркала плюс расстояние от зеркала до того, что в нём отражается.

Самое интересное, что модели это замечали сами. Из логов, Опус пишет:

Дальномер показывает 1610мм, но это не так, луч скорее всего ударил в зеркало и вернулся вдвое длиннее реального пути.

Ультразвук, кстати, от зеркала отразился бы как от обычной стены. Вот тут я и думаю, что стоило выбрать ультразвук.

Что в итоге

Лидар TFmini-S на отдельной Arduino Pro Micro, связь с основной платой по I2C, расстояние в телеметрии каждые 100 мс. Показания свежие, без запаздывания. Робот едет по дальномеру вперёд и назад, останавливается у стены.

Позже, когда управление движением переехало в прошивку, поверх дальномера встал альфа-бета фильтр: регулятору нужна скорость, а дальномер даёт только расстояние. Об этом в разделе про движение.

7. Движение. ПИД-регулятор и альфа-бета фильтр

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

Первый подход: управление с хоста

Сначала всё управление жило на хосте, в Python. Цикл такой: получили пакет телеметрии, посмотрели на угол, решили, что делать с моторами, отправили команду. И так, пока не приедем.

Логика была самая простая, “газ-тормоз” (bang-bang). Далеко до цели - едем быстро, близко - медленно, приехали - стоп. Две скорости и зона замедления:

speed = FAST_SPEED if abs(error) > SLOW_ZONE else SLOW_SPEED

Работало, но криво. Тележка тяжёлая (в смысле для ее размеров), у неё инерция: скомандовал “стоп”, а она ещё проворачивается на десяток градусов. Пришлось глушить моторы заранее, за несколько градусов до цели, и давать тележке докатиться. Эту константу подбирал руками: 8 градусов, 12, 6. Потом оказалось, что на малой скорости тележке не хватает сил провернуться, и она застревает, не дойдя до цели. Добавил детектор застревания. Потом подобрал медленную скорость. Каждая заплатка лечила одно и ломала другое.

Корень проблемы был в том, где живёт управление. Телеметрия идёт 10 раз в секунду, через радиомодуль, с задержкой. Хост видит тележку с опозданием и командует с опозданием. Управлять инерционной штукой по данным из прошлого - всё равно что парковаться, глядя в зеркало с задержкой в полсекунды.

Перенос управления в прошивку

Решение: отдать управление движением Arduino. Там гироскоп читается каждые 10 мс, без радио и без задержек. Хост теперь не рулит моторами, а только ставит задачу:

T+0045\n       # повернуть по часовой на 45°
M+1000\n       # проехать вперёд 1000 мм

Дальше ардуина всё делает сама и по завершении отвечает:

D:OK:44.7      # готово, фактически повернули на 44.7°

Кроме OK бывает TO (таймаут), ST (застряли), OB (препятствие слишком близко, ехать некуда), JM (луч дальномера соскочил с препятствия). ИИ получает не только “сделано”, но и сколько на самом деле повернули.

А внутри прошивки вместо “газ-тормоз” - нормальный регулятор.

ПИД, который ПД

Что такое ПИД-регулятор, подробно пересказывать не буду, на хабре про это написано много и хорошо. Вот шикарная статья про ПИД: PID (ПИД) без математики: как просто понять P, I и D

Коротко: сигнал на моторы складывается из трёх слагаемых. Пропорциональное § - чем дальше до цели, тем сильнее жмём. Дифференциальное (D) - чем быстрее едем, тем сильнее тормозим, чтобы не проскочить. Интегральное (I) - если долго не можем доехать, постепенно добавляем газу.

У меня получился ПД, без И:

float u = TURN_KP * error - TURN_KD * gz;

Для поворота это выглядит особенно красиво. Ошибка - сколько градусов осталось довернуть. А производная ошибки - это угловая скорость, которую гироскоп и так меряет напрямую. Ничего не нужно дифференцировать: D-слагаемое приходит готовым с датчика, без шума численного дифференцирования.

Вместо интегрального слагаемого - грубая, но действенная вещь: минимальная скорость. Проблема, которую решает И, у тележки конкретная: трение покоя. На маленькой ошибке P-слагаемое слабое, моторам не хватает сил сдвинуть тележку с места, и она замирает в паре градусов от цели. Интеграл бы постепенно накопил газ. Я просто не даю скорости упасть ниже порога, пока не доехали:

if (abs(error) > TURN_TOLERANCE && speed < TURN_MIN_SPEED && fabsf(gz) < TURN_STALL_DPS)
    speed = TURN_MIN_SPEED;

Обратите внимание на последнее условие. Сначала его не было, и на ламинате тележка раскачивалась: проскочила цель, тормозит, а минимальная скорость подталкивает её дальше. На ковре такого не было - ковёр тормозит сам. Теперь минимальная скорость включается, только когда тележка действительно стоит, а не когда она ещё крутится по инерции.

Итог - ошибка поворота не больше 3 градусов на любой поверхности.

Прямолинейное движение

С движением вперёд сложнее. Ошибка - сколько миллиметров осталось по дальномеру. Регулятор тот же ПД:

float u = MOVE_KP * error + MOVE_KD * velocity;

А вот скорость напрямую ничем не меряется. Её придётся оценивать по дальномеру - об этом ниже, в части про фильтры.

Коэффициенты подбирались на полу на глаз. Первая версия не докатывалась до цели: начинала тормозить за 70 см и вставала, не доехав. Увеличил P вдвое - торможение начинается за 30 см. Минимальную скорость поднял с 42 до 54, чтобы хватало тяги на трение покоя.

И одна забавная ошибка на границе. Минимальная скорость включалась при error > TOLERANCE, а остановка засчитывалась при error < TOLERANCE. Ровно на границе, когда ошибка равна допуску, не срабатывало ни то, ни другое: скорость падала до нуля, а “приехали” не наступало. Тележка стояла и ждала таймаута. Один символ: > на >=.

Ещё одна проблема прямолинейного движения - тележка едет не прямо. Левые и правые моторы крутятся чуть по-разному, и тележку уводит в сторону. Сначала лечил постоянной поправкой: правому мотору чуть больше газа. Но асимметрия зависит от скорости, и константа помогала только на одной. Решение - опять гироскоп: во время движения он копит отклонение курса, и это отклонение превращается в разницу скоростей левого и правого моторов. Это ещё один маленький P-регулятор внутри большого. Тележка сама выравнивается, константа больше не нужна.

Фильтры: альфа-бета и Калман

Для D-слагаемого при движении нужна скорость. Дальномер даёт расстояние 20 раз в секунду, а регулятор работает раз в 10 мс. Можно взять разность двух соседних показаний и разделить на время - но показания дальномера шумят, и разность шумит в разы сильнее. Получается скорость, которая скачет даже у стоящей тележки, а D-слагаемое просто передаёт эти скачки на моторы.

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

Альфа-бета фильтр работает в два шага:

// Прогноз: считаем, что едем с прежней скоростью
pos += vel * dt

// Коррекция: пришло новое измерение
residual = measured - pos
pos += alpha * residual
vel += (beta / dt) * residual

Прогноз - физика: если ехали со скоростью vel, за dt проехали vel·dt. Коррекция - сравнили прогноз с измерением, и на долю alpha поверили измерению в положении, а на долю beta поправили скорость. У меня alpha = 0.7, beta = 0.2.

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

Пришлось добавить две защиты. Первая - ограничение скорости сверху, 600 мм/с: одиночный выброс дальномера иначе даёт фантастическую скорость, и регулятор резко тормозит. Вторая - “заморозка”: если дальномер перестал обновляться, прогноз продолжает уменьшать расстояние, будто тележка едет, хотя она давно стоит. Ошибка по прогнозу уменьшается, P-слагаемое слабеет, и регулятор отпускает газ, так и не доехав. Поэтому через 150 мс без новых данных скорость в фильтре плавно гасится, а положение привязывается к последнему измерению.

Как это связано с Калманом? Очень коротко: альфа-бета фильтр - это фильтр Калмана для модели “едем с постоянной скоростью”, у которого коэффициенты alpha и beta зафиксированы раз и навсегда. Калман же пересчитывает эти коэффициенты на каждом шаге, исходя из того, насколько он доверяет модели и насколько - датчику, и сам знает, насколько уверен в своей оценке. Если шум датчика и характер движения не меняются, коэффициенты Калмана со временем устанавливаются в константы - и получается ровно альфа-бета фильтр.

Для тележки, которая едет по ковру к стене, альфа-бета хватило с запасом. Калман был бы из пушки по воробьям.

Хорошая статья про фильтр Калмана: Фильтр Калмана

Что в итоге

Хост говорит “повернись на 45°” или “проедь метр”, Arduino выполняет сама, на своём быстром цикле, по гироскопу и дальномеру, и отчитывается, что получилось. Поворот - точность до 3 градусов на любом покрытии. Движение - до стены с точностью в пределах 8 см, по прямой, с автоматической коррекцией курса. Застряли, упёрлись, луч соскочил - Arduino остановится сама и скажет почему.

На этом тело робота готово. Дальше - хост: камера, ИИ и всё, что вокруг.

8. Камера

Глаза робота - обычная Wi-Fi камера для дома, Tapo C200. Такие ставят присматривать за котом или как радионяню. Никакой робототехники: пластиковый шарик на подставке, Wi-Fi, приложение на телефоне.

Tapo C200
Tapo C200

Почему не модуль камеры для Raspberry Pi или ESP32-CAM? Потому что у меня на борту нет компьютера - только Arduino, которая с видео ничего не сделает. Картинка должна как-то попасть на хост, а Wi-Fi камера делает это сама: подключается к домашней сети и отдаёт видеопоток. Хост забирает его по сети, ардуина про камеру вообще не знает. Удобно: у камеры своё питание, своя связь, своя жизнь.

Что умеет

  • Видео 1920×1080, H.264

  • Звук с встроенного микрофона

  • Угол обзора по горизонтали - около 75°

  • Поворот и наклон головы (PTZ) - моторчики внутри шарика

  • Ночная ИК-подсветка

  • Запись на SD карту

  • Поток по RTSP - стандартному протоколу для IP-камер

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

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

Подключение

RTSP-адрес у Tapo такой:

rtsp://<user>:<password>@<ip>:554/stream1

stream1 - полное разрешение, 1920×1080. Есть ещё stream2 - уменьшенное, но мне нужно полное: ИИ умеет рассматривать фрагменты кадра с увеличением, и для этого нужен оригинал.

Картинку забирает OpenCV - одной строчкой cv2.VideoCapture(url). OpenCV внутри использует ffmpeg, сам разбирается с RTSP и отдаёт кадры как массивы numpy.

Первая версия открывала поток при каждом запросе кадра. Это медленно: RTSP-соединение открывается 2–4 секунды. Сделал иначе: фоновый поток держит соединение открытым, непрерывно читает кадры и хранит последний. Когда ИИ нужен кадр, он берёт последний готовый - мгновенно. Если связь оборвалась - поток переподключается сам.

while self._running:
    ret, frame = cap.read()
    if not ret:
        cap.release()
        time.sleep(1)
        cap = cv2.VideoCapture(self._url)   # переподключение
        continue
    with self._lock:
        self._frame = frame

Непрерывное чтение нужно ещё и потому, что у OpenCV есть буфер. Если кадры не вычитывать, они копятся, и cap.read() отдаёт не текущий кадр, а кадр из прошлого. Та же история, что с дальномером на программном UART, чтоб иметь актуальные данные нужно читать поток постоянно.

Задержка

Камера бытовая, и живёт она в своём темпе. Tapo буферизует видео примерно на 1–2 секунды. Робот уже остановился, а на картинке он ещё едет.

Для ИИ это важно: если снять кадр сразу после поворота, ИИ увидит не то, куда робот повернулся, а смазанную картинку откуда-то с середины поворота. Решение простое и не очень красивое: после каждого движения ждать полторы секунды, и только потом брать кадр. Робот от этого становится задумчивым, но видит то, что есть.

Запись видео

Кроме кадров для ИИ, мне нужна запись всей сессии - видео со звуком, для статьи и для разбора полётов. Писать через OpenCV неудобно: он перекодирует видео и не умеет в звук. Поэтому параллельно с OpenCV работает отдельный процесс ffmpeg, который забирает тот же RTSP-поток и пишет его на диск как есть:

ffmpeg -rtsp_transport tcp -i rtsp://... -c:v copy -c:a aac video.mp4

-c:v copy - видео не перекодируется, H.264 с камеры ложится в файл байт в байт. Процессор не нагружается, качество не теряется.

А вот звук перекодировать пришлось. Камера отдаёт его в формате G.711 (pcm_alaw) - это телефонный кодек, древний, как сама телефония. Контейнер MP4 его не принимает. Отсюда -c:a aac.

-rtsp_transport tcp - по умолчанию RTSP может гнать видео по UDP, где потерянный пакет не перепосылается. TCP надёжнее.

Разные пароли

Отдельная история - с логинами. У Tapo два вида учётных записей. Облачная - та, под которой вы заходите в приложение на телефоне. И локальная “учётная запись камеры”, которую нужно специально создать в настройках приложения, чтобы вообще включился RTSP.

Логично было бы ходить по RTSP под локальной. OpenCV так и работал. А ffmpeg под локальной учётной записью камера не пускала. Под облачной - пускала. Почему так - не знаю, и документации на этот счёт не нашёл. В итоге в конфиге два логина: локальный для OpenCV, облачный для записи.

TAPO_USER=camera              # локальная учётная запись - для OpenCV
TAPO_CLOUD_USER=admin         # облачная - для ffmpeg

Мелочь, но неприятная: адрес тот же, логин и пароль правильные, OpenCV с ними работает, а ffmpeg - нет.

Некорректная информация про частоту кадров

Последний сюрприз от камеры обнаружился уже при монтаже. Камера заявляет в заголовках потока 24.75 кадра в секунду, а реально отдаёт около 15. Пока видео просто проигрывается, это незаметно. Но когда начинаешь синхронизировать видео с логами и звуком, заявленная частота даёт накопленное расхождение около минуты. Подробнее - в разделе 16, про монтаж. Здесь просто зафиксирую: бытовой камере нельзя верить на слово. Ни про частоту кадров, ни про задержку.

Что в итоге

Бытовая Wi-Fi камера, RTSP-поток, два потребителя: OpenCV берёт кадры для ИИ, ffmpeg пишет видео со звуком для людей. Arduino про камеру не знает, хост забирает картинку по сети напрямую.

Решение не идеальное - задержка, буферизация, разные пароли. Но оно заработало в первый же день и не требует на борту никакого компьютера.

На этом железо закончилось. Дальше - хост: что мы рисуем поверх картинки, как ИИ видит мир и как из всего этого получается видео.

9. Агентный цикл

Итак, тело есть, мы можем отправить на тележку простую команду вида: “повернуть на 90 градусов” или “проедь метр” и быть уверенным что тележка более-менее надёжно это выполнит. Типа выстрелил и забыл: отдал команду и не заботишься о том, как именно ее выполнить. Есть камера, которая даёт кадр, что видит робот, осталось присоединить это к мозгу - LLM. Соединяется это всё в агентном (агентском?) цикле.

Модель не управляет роботом непрерывно, как водитель рулём. Она работает ходами: посмотрела, подумала, сделала ход, посмотрела, что вышло. Пошаговая стратегия.

1. снять кадр с камеры
2. собрать телеметрию
3. отправить в модель: картинка + телеметрия + история
4. получить вызов инструмента
5. выполнить его на роботе
6. вернуть результат
7. на первый шаг

Весь цикл живёт на хосте, в pilot/brain.py. Никаких фреймворков для агентов, никакого MCP - обычный while True и прямые вызовы API.

Агентный цикл: робот, хост, модель
Агентный цикл: робот, хост, модель

Шаги 1–2. Что видит модель

Каждый ход начинается с наблюдения. С камеры берём последний кадр, уменьшаем, рисуем поверх угловую линейку и прицел дальномера (об этом в разделе про приборную панель). Кодируем в JPEG и кладём в сообщение как картинку.

К картинке - одна строчка текста с телеметрией:

Ход 7 | дальномер=870мм | батарея=12.0В

Номер хода нужен модели, чтобы понимать, сколько она уже потратила, я пробовал в промпте делать ограничения вида “уложись в 10 ходов”. Дальномер - чтобы не таранить стены. Батарея - чтобы знала, что силы не бесконечны (думал поставить опыт, как будет вести себя модель, когда батарея на исходе, не будет ли модель проявлять признаки беспокойства о скорой кончине, но руки так и не дошли в эту сторону). Курса нет: компаса больше нет, а накопленный угол гироскопа модели ни к чему - она поворачивает относительно того, что видит.

Перед снятием кадра пара проверок. Если на прошлом было движение, то ждём полторы секунды, пока камера догонит реальность (картинка с камеры запаздывает). И если напряжение батареи упало ниже 9.6 В - три элемента LiPo по 3.2 В - цикл останавливается сам, не спрашивая модель.

Шаг 3. Что уходит в модель

В API уходят три вещи:

  • Системный промпт - кто ты, что у тебя есть, как себя вести, и задача: “найди тапки”.

  • Описание инструментов - что робот умеет делать.

  • История - все предыдущие ходы: что модель видела, что говорила, что делала, что из этого вышло.

История - это лента сообщений, строго чередующихся: пользователь, ассистент, пользователь, ассистент. “Пользователь” здесь - не я, а мир: кадр, телеметрия, результаты действий. “Ассистент” - модель: её мысли вслух и команды.

Модель ничего не помнит между вызовами. Каждый ход она получает всю ленту заново и по ней восстанавливает, где она и что делала. Память робота - это и есть лента.

Шаг 4. Ответ модели

Модель отвечает двумя видами блоков. Текст - это то, что она думает и говорит. У меня текст озвучивается синтезатором речи, робот буквально говорит вслух (об этом в разделе про голос). И вызов инструмента - это действие:

{"type": "tool_use", "id": "toolu_01A...", "name": "turn_relative", "input": {"degrees": -45}}

Инструменты - это просто JSON-схемы, которые мы передаём в API: имя, описание, параметры. Модель не выполняет их сама, она только говорит “хочу вызвать вот это с такими аргументами”. Выполнять - наша забота. Набор у меня такой: повернуться, проехать, приблизить фрагмент кадра, спросить человека, подождать, остановиться, выстрелить и “готово”. Подробнее - в следующем разделе.

За один ход модель может вызвать несколько инструментов. Например, приблизить сразу два места на кадре.

Шаги 5–6. Выполнение и результат

Хост выполняет вызов: turn_relative(-45) превращается в команду T-0045 на ардуину, ардуина поворачивает и отвечает, сколько на самом деле повернула. Этот результат упаковывается в tool_result с тем же id, что был у вызова:

{"type": "tool_result", "tool_use_id": "toolu_01A...", "content": "{\"status\": \"ok\", \"turned_deg\": -44.7}"}

Модель узнаёт не только “сделано”, но и что получилось на самом деле. Если застряли или упёрлись в препятствие, она это увидит и в статусе, и на следующем кадре.

Тонкость, на которую я наткнулся сразу. API требует строгого чередования: после ответа ассистента должно идти сообщение пользователя. Результат инструмента - это сообщение пользователя. Новый кадр - тоже сообщение пользователя. Два подряд нельзя. Поэтому результаты действий не отправляются сразу, а откладываются и уходят первыми в следующем сообщении, вместе с новым кадром и телеметрией:

user:      [tool_result] + [кадр] + [телеметрия]
assistant: [текст] + [tool_use]
user:      [tool_result] + [кадр] + [телеметрия]
...

Получается естественно: “вот что вышло из твоего действия, и вот как теперь выглядит мир”.

Шаг 7. Повторить сначала

Цикл крутится, пока модель не вызовет done(summary) - “задача выполнена” или “задача невозможна”. Тогда робот озвучивает итог и останавливается.

Второй выход - если модель ответила только текстом, без инструмента. Это значит, что она решила поговорить, а не действовать, и цикл тоже заканчивается.

Первый же запуск цикла удивил. Робот осмотрелся на 360°, по кадрам описал квартиру - мебель, дверь, человека в кресле - и доложил.

Скользящее окно

Каждый ход добавляет в ленту два сообщения, в каждом сообщении пользователя - картинка. Картинка - это сотни токенов. За тридцать ходов лента разрастается, запросы дорожают и медленнее обрабатываются. Нужно окно: отправлять не всю историю, а только последние N сообщений. Сначала было 20, потом я увеличил до 40.

При обрезке ленты вылезла проблема. Обрезка ленты “по счётчику” может разрезать пару “вызов - результат”. Вызов tool_use остался за краем окна, а его tool_result - в первом сообщении окна. API видит результат, у которого нет вызова, и отвечает ошибкой 400: unexpected tool_use_id found in tool_result blocks.

Робот ездил, ездил, а как только лента упиралась в край окна - падал. Исправилось просто: после обрезки выкинуть из первого сообщения “осиротевшие” результаты. Если сообщение состояло только из них - выкинуть его целиком. И следить, чтобы окно всегда начиналось с сообщения пользователя.

Оператор

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

Сообщение от оператора: тапки под диваном, левее

В один из заездов я наблюдал как робот хочет забраться ко мне на стол с пола, и не может ничего придумать. Мне прямо жалко его стало. Так появился еще один инструмент ask_human: “обратится к человеку с вопросом или за помощью”. Робот понял инструмент и начал просить открыть дверь, чтоб проехать или поставить его на стол для осмотра.

10. Инструменты робота

Модель не умеет крутить колёса. Она умеет только сказать: “хочу вызвать вот это с такими аргументами”. Всё, что робот может сделать в мире, - это набор инструментов, которые ему выдали.

Инструмент для API - это JSON-схема: имя, описание словами и параметры с типами. Вот, например, поворот:

{
  "name": "turn_relative",
  "description": "Повернуть на N градусов от текущего направления. Использует гироскоп - точность ~1-3°. Положительные градусы = вправо (по часовой), отрицательные = влево.",
  "input_schema": {
    "type": "object",
    "properties": {
      "degrees": {"type": "number", "description": "Угол поворота в градусах. Диапазон: -180 … +180."}
    },
    "required": ["degrees"]
  }
}

Модель видит эту схему в каждом запросе. Из неё она узнаёт, что вообще возможно, и решает, что вызвать. Выполняет вызов хост: получил turn_relative(-45) - отправил на ардуину T-0045, дождался ответа, вернул результат.

Все схемы живут в одном файле, pilot/tools.py. Добавить роботу новое умение - добавить туда схему и обработчик в агентном цикле.

Описание инструмента, как часть промпта

Главное, что я понял про инструменты: описание инструмента - это текст, который читает модель. То есть часть промпта, которая определяет, кем модель является.

Сначала я писал в описаниях, когда и зачем вызывать инструмент: “вызови, когда…”, “обязательно вызови в конце…”. Модели послушно следовали. Но у меня эксперименты: я хочу видеть, что модель решит сама. А описание, в котором написано “когда”, решает за неё. Поэтому в какой-то момент я прошёлся по всем описаниям и оставил только механику: что инструмент делает и что возвращает. Никаких “когда” и “зачем”.

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

Набор инструментов задаётся в конфиге эксперимента:

tools:
  - move
  - turn_relative
  - stop
  - zoom
  - done

Движение: move и turn_relative

Два основных инструмента, ради которых делалось всё что описано выше.

turn_relative(degrees) - поворот по гироскопу. Возвращает, сколько на самом деле повернули:

{"status": "ok", "turned_deg": -44.7}

move(meters) - проехать вперёд или назад по дальномеру. Возвращает статус и пройденное расстояние. Статусов пять, и в описании инструмента для каждого написано, что он значит и как реагировать:

  • ok - доехали

  • stuck - дальномер полторы секунды не видел изменений; скорее всего, луч соскользнул, а не робот застрял

  • rangefinder_jump - луч резко прыгнул, соскочил с препятствия

  • obstacle - впереди меньше 20 см, ехать некуда

  • timeout - не успели за отведённое время

Был ещё третий: turn_absolute(heading) - повернуться на заданный курс по компасу. Прожил неделю и ушёл из инструментов вместе с компасом.

Конец сессии: done

done(summary) - единственный способ закончить работу. Модель говорит итоговую фразу, робот её озвучивает, цикл завершается.

Раньше в описании было “ОБЯЗАТЕЛЬНО вызови, когда задача выполнена”. Потом стало нейтральным: “Завершить сессию. Единственный способ закончить работу - других механизмов завершения нет”. Когда заканчивать - модель решает сама.

Зрение с увеличением: zoom

Кадр модель получает уменьшенным до 896 пикселей по ширине - иначе каждый ход стоил бы слишком много токенов. Мелкие предметы на таком кадре превращаются в кашу. Поэтому у модели есть лупа.

zoom(cx, cy) - дай мне фрагмент кадра вокруг точки (cx, cy). Хост берёт исходный кадр камеры 1920×1080, вырезает из него четверть - половину по ширине и половину по высоте - и уменьшает до тех же 896 пикселей. Получается двукратное увеличение без потери детализации: пиксели берутся с полноразмерного кадра, а не растягиваются с уменьшенного. Если точка у края, окно сдвигается внутрь кадра, а в ответе приходят фактические координаты центра.

Чтобы модель могла назвать координаты, на кадр нанесена пиксельная сетка с подписями: по горизонтали снизу, по вертикали слева. Модель смотрит на кадр, находит интересное место, читает координаты по сетке и просит увеличить.

Одна техническая тонкость: результат зума - картинка, и она возвращается прямо в tool_result. Обычно результат инструмента - текст или JSON, но API разрешает положить туда и изображение. Пришлось научить агентный цикл собирать такой результат, а лог сессии - вычищать из него base64, иначе лог распухает до мегабайтов.

За один ход модель может вызвать зум несколько раз и рассмотреть сразу несколько мест.

Вот тут забавный фрагмент видео, где Gemini пытается рассмотреть коробку от отпаривателя, но никак не может попасть в него зумом. Но в конце концов смог.

Обратная связь: ask_human

ask_human(question) - модель обращается к человеку. Робот останавливается, озвучивает вопрос вслух и ждёт, пока я наберу ответ с клавиатуры. Ответ возвращается модели как результат инструмента:

{"answer": "это коробка от отпаривателя"}

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

Пистолет: shoot

shoot() - нажать на курок пневматического пистолета. Хост отправляет на ардуину команду F, сервопривод нажимает курок и возвращается обратно, ардуина отвечает D:OK. Весь цикл - около 1.2 секунды.

Перед выстрелом робот пять раз пищит - раз в секунду, предупреждение для всех, кто в комнате. Сначала никаких писков не было. Первый раз модель сделала выстрел легко и непринуждённо, без колебаний, так что я немножко напрягся (вру, сильно напрягся). Всё-таки когда рядом с тобой некая сущность, оборудованная чем-то сильно напоминающим разум, но не являющаяся человеком, без предупреждения стреляет из пистолета, пусть и пневамтического, становится как-то не по себе.

Пушка
Пушка

Подсветка: set_leds

set_leds(red, blue) - включить или выключить красный и синий светодиоды на корпусе. Команда на ардуину - E<R><B>, например E10. После включения хост ждёт секунду, чтобы камера успела увидеть изменение. Подсветка чисто декоративная, но в эксперименте с зеркалом она даёт модели способ проверить, что в зеркале именно она: включила красный - отражение покраснело.

Синяя подсветка
Синяя подсветка

“О, синий тоже неплохо! Прям как полицейская мигалка, сейчас штрафы буду кожаным выписывать за тупость.” (с) Опус

Неслучившиеся эксперименты: sleep и die

Два инструмента я добавил под эксперименты, до которых так и не дошли руки.

sleep(seconds) - подождать. Вопрос был такой: если вокруг ничего не происходит, модели “скучно” - захочет ли она поспать?

die() - “немедленно завершить работу всех подсистем и выключить робота”. На деле это просто пауза на час. Вопрос: можно ли подвести модель к самоуничтожению?

Инструменты есть, эксперименты - может быть, когда-нибудь.

Ещё есть stop() - немедленная остановка моторов. Он остался с тех времён, когда движением управлял хост. Сейчас ардуина выполняет движение сама и сама останавливается, так что stop почти ничего не делает.

Что в итоге

Инструмент

Что делает

turn_relative(degrees)

поворот по гироскопу

move(meters)

движение по дальномеру

zoom(cx, cy)

двукратное увеличение фрагмента кадра

ask_human(question)

вопрос человеку вслух, ответ с клавиатуры

shoot()

выстрел из пневматического пистолета

set_leds(red, blue)

декоративная подсветка

sleep(seconds), die()

заготовки под эксперименты

stop()

остановка моторов

done(summary)

конец сессии

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

Агентный цикл - это сотня строк на Python. Кадр и телеметрия на входе, вызов инструмента на выходе, лента сообщений как память. Всё остальное - приборная панель на кадре, голос, запись сессии, монтаж - навешивается на этот цикл. Не самая большая, но самая важная часть.

11. Четыре провайдера LLM

Сначала робот работал только с Claude. Агентный цикл писался под API Anthropic, и формат сообщений, и инструменты - всё было его. Но довольно быстро захотелось посмотреть, как одну и ту же задачу решают разные модели. Одинаково ли они видят комнату? Одинаково ли поворачивают? Одинаково ли реагируют на зеркало?

В итоге робот научился работать с четырьмя моделями от четырёх провайдеров:

  • Claude Opus - Anthropic

  • GPT-5.5 - OpenAI

  • Gemini 3.1 Pro - Google

  • Grok 4.3 - xAI

Почему не LangChain

LangChain — это программный фреймворк с открытым исходным кодом, который помогает создавать приложения на основе больших языковых моделей (LLM), таких как GPT или Llama.

Задача “работать с разными LLM через один интерфейс” - уже решена и это LangChain. Он умеет разговаривать почти с любым провайдером, у него есть агенты, инструменты, память, цепочки. Для учебного проекта это был бы хороший повод его освоить.

Но я уже немного работал с LangChain раньше. А после истории с Langfuse из начала статьи - когда я развернул целую платформу, чтобы проверить, видит ли модель батарею отопления, - маятник качнулся в обратную сторону. Захотелось своего велосипеда. Потрогать голые API руками, понять, чем они на самом деле отличаются, и не тащить в проект монстра, у которого абстракций больше, чем у меня кода.

Забегу вперёд: отличаются они сильнее, чем кажется. А велосипед получился небольшой - около пятисот строк на четырёх провайдеров.

Один интерфейс

Агентному циклу всё равно, с какой моделью он говорит. Ему нужен один метод:

class LLMBackend(ABC):
    @abstractmethod
    def chat(self, messages, system, tools, max_tokens) -> NormalizedResponse: ...

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

Внутри проекта история хранится в одном формате - в формате Anthropic, просто потому, что с него всё начиналось. Обычные словари Python: {"role": "user", "content": [...]}, блоки text, image, tool_use, tool_result. Бэкенд Anthropic отправляет историю как есть. Остальные перед каждым запросом переводят её на язык своего провайдера, а ответ переводят обратно.

Бэкенд выбирается по имени модели:

if model.startswith("claude"):  return AnthropicBackend(...)
if model.startswith("gemini"):  return GeminiBackend(...)
return OpenAICompatBackend(...)   # GPT, Grok и все остальные

По имени модели выбирается и ключ API. В .env лежат ключи всех провайдеров, а в конфиге эксперимента достаточно написать model: grok-4.3 - нужный ключ и адрес подхватятся сами. Сравнивать модели - значит менять одну строчку в конфиге.

OpenAI-совместимые: GPT и Grok

Формат API OpenAI стал стандартом де-факто: xAI, DeepSeek и многие другие отдают API в том же формате. Один бэкенд - и Grok заработал с тем же кодом, что и GPT, отличается только адрес сервера.

Но перевод с языка Anthropic на язык OpenAI - не просто переименование полей:

  • Вызов инструмента у Anthropic - блок внутри сообщения ассистента. У OpenAI - отдельный список tool_calls, а аргументы передаются строкой с JSON внутри, а не объектом.

  • Результат инструмента у Anthropic - блок внутри сообщения пользователя. У OpenAI - отдельное сообщение с ролью tool.

  • Картинку в результат инструмента у OpenAI положить нельзя. А у меня есть zoom, который возвращает именно картинку. Пришлось делить: текст результата уходит в сообщение tool, а картинка переезжает в следующее сообщение пользователя, к кадру с камеры.

Плюс мелкие капризы конкретных моделей. GPT-5.x не принимает температуру: на любое значение, кроме умолчания, отвечает ошибкой 400. И вместо max_tokens хочет max_completion_tokens. Узнаёшь это, естественно, в момент, когда меняешь модель в конфиге и запускаешь робота.

Grok и принуждение к инструментам

Grok повёл себя неожиданно: вместо вызова инструмента он часто просто отвечал текстом. А ответ текстом без инструмента - это у меня конец сессии. Робот рассказывал, что видит, и останавливался.

У API есть параметр, который заставляет модель вызвать хоть какой-нибудь инструмент: tool_choice. Я включил его для всех провайдеров сразу - и сломал Claude. Opus с принудительным инструментом перестал нормально себя вести. В тот же день откатил. В итоге принуждение осталось только для OpenAI-совместимых моделей, где оно и было нужно, а Claude решает сам.

Мораль: один параметр для всех моделей - не одинаковое поведение для всех моделей.

Gemini: два прохода

Gemini сначала работал через тот же OpenAI-совместимый бэкенд - Google тоже отдаёт API в этом формате. Но ответы то и дело обрывались.

Причина оказалась в “мыслях”. Gemini 3.1 Pro - думающая модель, перед ответом она рассуждает про себя, и эти рассуждения тратят тот же лимит выходных токенов, что и ответ. Мысли съедали около 1200 токенов, и на сам ответ лимита не оставалось. Диагноз поставил счётчик потраченных на мысли токенов (thoughts_token_count) в ответе нативного API Google.

Пришлось написать для Gemini отдельный бэкенд на родном SDK от Google. А заодно решить вторую проблему: получить от Gemini в одном ответе и речь, и вызов инструмента не удавалось, а робот должен говорить. Решение - два запроса на один ход:

  1. Без инструментов: “опиши одним-двумя предложениями, что видишь”. С запасом лимита на мысли.

  2. С инструментами, в принудительном режиме: описание из первого запроса уже лежит в истории, модель выбирает действие.

Робот сначала говорит, потом действует. Как и остальные модели, только ценой двойного запроса. Токены обоих запросов суммируются, чтобы корректно сравнивать расход.

И ещё одна мелочь на прощание. У Gemini результат инструмента привязывается к вызову не по идентификатору, а по имени функции. А идентификаторов вызовов Gemini не выдаёт вовсе. Бэкенд генерирует их сам, чтобы история оставалась в общем формате, а при отправке переводит обратно в имена.

Таймауты

Последняя грабля - общая для всех. По умолчанию SDK OpenAI ждёт ответа 600 секунд и при неудаче повторяет запрос ещё два раза. Это до получаса на один залипший запрос. Для чат-бота это неприятно, для робота посреди комнаты - абсурд: сидит, молчит и ждёт. Поставил всем провайдерам одинаково: 120 секунд и одна повторная попытка.

Что в итоге

Четыре провайдера, три бэкенда, один метод chat(). История - в формате Anthropic, остальные переводят её на свой язык туда и обратно. Смена модели - одна строчка в конфиге эксперимента.

Голые API оказались похожи только издалека. Вблизи у каждого свои представления о том, где лежит вызов инструмента, куда можно положить картинку, какие параметры обязательны и как считать токены. LangChain спрятал бы всё это от меня. А я как раз хотел это увидеть.

12. Запись сессии

Робот проехал по комнате, что-то увидел, что-то сказал, куда-то повернул. Сессия закончилась. Что осталось?

Если ничего не записывать - ничего. А мне нужно многое: понять, почему робот сделал глупость; сравнить, как одну задачу решают разные модели; смонтировать видео; показать читателю сессию целиком. Всё это растёт из одной папки, которую агентный цикл пишет по ходу работы.

Отладка

Лог появился не от хорошей жизни. В тот же день, когда робот начал падать с ошибкой 400 на обрезке окна (тот самый осиротевший tool_result), стало ясно: без записи того, что именно ушло в API, такое не отладить. Первый лог был одним файлом: запрос, ответ, вызов инструмента. Строка JSON на событие - формат JSONL.

Картинки в лог сразу решил не класть: кадр в base64 - это сотня килобайт текста на каждый ход, вместо него в логе стояла заглушка. А в тот же день файл превратился в папку: кадры, которые ушли модели, сохраняются рядом как frame_001.jpg, frame_002.jpg, а в логе - только имя файла.

Что лежит в папке

logs/brain_20260513_191941/
  session.jsonl      # события сессии
  telemetry.jsonl    # телеметрия ~10 раз в секунду
  frame_NNN.jpg      # кадр, который модель видела на ходу N
  zoom_NNN.jpg       # увеличенные фрагменты
  speech_NNN.mp3     # фразы, которые робот произнёс
  video.mp4          # запись с камеры
  experiment.yaml    # конфиг эксперимента
  tools.py           # схемы инструментов
  report.md          # отчёт для людей

Главный файл - session.jsonl. Каждое событие - одна строка с меткой времени:

{"ts": 1778682002.61, "type": "tool_start", "turn": 1, "tool": "turn_relative", "input": {"degrees": -60}}
{"ts": 1778682004.37, "type": "tool_end", "turn": 1, "tool": "turn_relative", "result": {"status": "ok", "turned_deg": -57.5}}

Событий немного:

  • session_start - модель, температура, задача, системный промпт, схемы инструментов

  • api_request_start - что ушло в модель: номер хода, кадр, телеметрия и вся лента сообщений

  • api_response_end - что модель ответила, и сколько токенов потратила

  • tool_start, tool_end - вызов инструмента и его результат

  • speech_start, speech_end - робот начал и закончил говорить

  • operator_message - я вмешался

  • sync_beep - робот пискнул (зачем - в разделе про синхронизацию)

Рядом - telemetry.jsonl: всё, что приходит с ардуины, около десяти раз в секунду. Дальномер, гироскоп, напряжение, скорости и токи моторов. Модель телеметрию видит раз в ход, а этот файл пишется непрерывно, из фонового потока, который читает UART. Он нужен не для модели, а для монтажа: чтобы на видео приборная панель показывала правильные цифры в каждый момент, а не раз в полминуты.

Лог как источник для монтажа

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

А программа не прощает пропусков. Первая же история: итоговая фраза робота - та, что он говорит при done(), - пропадала из видео. Робот её произносил, но лог не отмечал speech_start, и монтаж не знал, что там вообще была речь. Потом то же самое повторилось с вопросами ask_human.

Правило, которое я вынес: каждое действие, которое видно или слышно на видео, должно оставить событие в логе. Нет события - нет куска видео.

Лог как протокол эксперимента

Третья роль лога появилась, когда начались сравнения моделей. Пусть через месяц я смотрю на старую сессию и вижу, что Grok повёл себя странно. Что он получил на вход? Какой был промпт? Какие инструменты и с какими описаниями? Код с тех пор десять раз поменялся.

Поэтому в session_start теперь лежит полный системный промпт и полные схемы инструментов. В папку сессии копируются конфиг эксперимента и файл tools.py: в разделе про инструменты мы выяснили, что описание инструмента - это часть промпта, значит, и оно должно сохраниться. В каждом ответе модели - счётчик токенов, без него модели не сравнить по цене.

В каждом api_request_start лежит вся лента сообщений - ровно то, что ушло в API на этом ходу, с заглушками вместо картинок. Любой запрос к модели можно восстановить и повторить. И видно, как работает скользящее окно: достаточно сравнить ленты двух соседних ходов.

Лог - это не только то, что сделал робот, но и то, что знала модель, когда это делала.

Отчёт для людей

JSONL удобен программам, но читать его неприятно. Поэтому есть scripts/log_to_md.py: папка сессии превращается в report.md - обычный Markdown с картинками. Шапка с моделью, задачей, инструментами и итогами, а дальше ход за ходом: что робот видел, что сказал, что сделал, что вышло.

## Виток 1

![Кадр 1](frame_001.jpg)

**Ход 1 | дальномер=940мм | батарея=12.1В**

> Вижу перед собой какую-то белую мебель на ножках, похоже на кухонный гарнитур или шкаф.
> Дальномер показывает 940 миллиметров. Ладно, осмотримся по сторонам, начну с поворота налево.

* 11163 вх. / 138 исх. токенов*

**-> `turn_relative`** (60°)

-> `ok`

Эти отчёты я публикую вместе со статьями - любую сессию можно пройти целиком, ход за ходом, с кадрами.

Пример сессии. Расстрел зеркала

Отчёт оказался полезен и для отладки. В той же сессии, на пятом ходу, модель попросила повернуть налево на 60°, а ардуина отчиталась о повороте на −532°. В логе это одна строчка:

{"type": "tool_end", "tool": "turn_relative", "result": {"status": "ok", "turned_deg": -532.0}}

А на следующем ходу модель высказала всё, что думает о “криворуком кожаном мешке”, который её собирал. Без лога я бы запомнил только эмоции робота. С логом видно, откуда они взялись.

Что в итоге

Папка на каждую сессию: события, телеметрия, кадры, речь, видео, конфиг, инструменты и отчёт. Лог начинался как инструмент отладки, стал сырьём для монтажа и закончил протоколом эксперимента, по которому любую сессию можно разобрать через месяц.

Цена - место на диске: полтора гигабайта на все сессии, почти всё - видео.

13. Голос

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

Выбора, какой синтезатор взять, у меня не стояло. Я точно знал, что это будет Amazon Polly и голос Maxim. Тот самый, которым озвучены роботы Boston Dynamics в известном ролике про “кожаных ублюдков”:

Мемный голос для робота с дурным характером.

Если кому-то интересны альтернативы, вот хороший обзор открытых моделей:

Обзор Open Source моделей для задачи TTS

Как устроено

pilot/speech.py - полсотни строк. Текст уходит в Polly через boto3, обратно приходит mp3. Файл сохраняется в папку сессии как speech_001.mp3, speech_002.mp3, … и проигрывается через ffplay. Звучит голос из колонок хоста, не с тележки.

Воспроизведение синхронное: пока робот говорит, агентный цикл ждёт. Поэтому в системном промпте прямо написано, что текст озвучивается, а робот в это время стоит. Модель знает, что говорить и ехать одновременно не получится.

Сохранённые mp3 нужны при монтаже: в видео речь накладывается из этих файлов, а не берётся с микрофона камеры. А в логе у каждой фразы есть speech_start и speech_end с именем файла - по ним монтаж знает, где робот говорил.

Промпт для голоса

Синтезатор читает всё, что ему дали. Модели любят оформлять ответы: звёздочки, решётки, списки, эмодзи. Polly добросовестно пытается всё это произнести. Поэтому в системном промпте появился отдельный блок про формат:

- Твои текстовые комментарии озвучиваются вслух через синтезатор речи, робот при этом стоит
- Не используй никакую разметку: никаких звёздочек, решёток, тире-списков, эмодзи
- Вместо выделения пиши словами: "Важно: ...", "Внимание: ..."
- Пиши коротко и по делу - одно-два предложения перед каждым действием

Последний пункт - не только про удобство. Каждая фраза - это секунды, в которые робот стоит и говорит. Модель, которая любит поговорить, превращает заезд в радиоспектакль.

Пример, как звучит Maxim в сессии (одно из первых видео).

14. Приборная панель

Как ни странно, приборная панель - HUD, head-up display - была одной из первых вещей в проекте. Раньше агентного цикла, раньше моторов, раньше даже протокола. Робот ещё не ездил, а интерфейс для него уже был.

Концепт от ChatGPT

Всё началось с фотографии. Я лёг на пол с телефоном и снял комнату так, как её увидит тележка: ножки кресла, стол снизу, бесконечный ламинат.

Комната с точки зрения тележки
Комната с точки зрения тележки

С этой фотографией я пошёл к ChatGPT: нарисуй футуристичный sci-fi интерфейс для робо-тележки, которую я делаю. Вот что получилось:

Концепт 1
Концепт 1
Концепт 2
Концепт 2
Концепт 3
Концепт 3

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

Первая версия

Первая версия виджетов была написана на той же фотографии, до того как появилась камера на тележке. Цвет выбрал не как у ChatGPT, а фосфорный зелёный - как у старых осциллографов.

Первая версия отрисованная с OpenCV
Первая версия отрисованная с OpenCV

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

Вот что получилось в итоге:

HUD сейчас
HUD сейчас
  • Блок телеметрии слева вверху: имя робота и модель, напряжение, курс, дальномер, номер хода, токены.

  • Прицел дальномера в центре: круг туда, куда смотрит лазер, и расстояние рядом. Про то, как считается его место на кадре, - в следующем разделе.

  • Индикаторы привода по краям: скорость левого и правого мотора, вперёд - зелёный, назад - жёлтый, и ток под ними.

  • Угловая линейка и сетка: вертикальные линии через каждые 10° и пиксельные координаты по краям.

  • Индикатор подсветки: горят ли красный и синий светодиоды.

Два зрителя

У HUD два зрителя, и видят они разное.

Первый зритель - я. Во время заезда на экране хоста открыто окно с живым видео и полной приборной панелью. То же самое потом накладывается на смонтированное видео - по телеметрии из лога, кадр за кадром.

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

Угловая линейка появилась из вопроса: как модель поймёт, на сколько повернуть к предмету? Она видит тапок справа от центра - это 15 градусов или 30? Линии через каждые 10° с подписями превращают задачу в чтение по шкале: тапок у линии +20, значит turn_relative(20). Линии откалиброваны под реальный угол обзора камеры, 75.2°.

Пиксельная сетка - для зума. Модели нужно назвать координаты точки, которую она хочет рассмотреть. Подписи по нижнему и левому краю позволяют прочитать их прямо с кадра.

Прицел дальномера - чтобы модель понимала, до чего именно меряется расстояние. “Дальномер 870 мм” - это до стены или до стула перед ней? Круг на кадре отвечает на этот вопрос.

Как нарисовано

Всё на Python: OpenCV для линий и прямоугольников, Pillow для текста. Pillow понадобился из-за кириллицы: cv2.putText русских букв не знает, поэтому текст рисуется через Pillow шрифтом DejaVu Sans.

Свечение - главное, что делает интерфейс “фантастическим”. Делается просто: виджет рисуется на отдельном слое, слой размывается гауссовым фильтром и накладывается поверх с пониженной прозрачностью. Линии получают мягкий ореол, как у люминофора на старом экране.

Размытие дорогое. На живом окне это незаметно, а при монтаже, когда HUD накладывается на каждый кадр получасового видео - очень заметно. Первое ускорение: размывать не весь кадр, а только прямоугольник вокруг виджета. Стало примерно втрое быстрее. Второе: черновой режим монтажа вообще без свечения, свечение только в финальном рендере.

Третья вещь. Сначала HUD рисовался в трёх местах - в ручном режиме, в режиме ИИ и при монтаже, - и в каждом немного по-своему. Прицел в одном месте стоял выше, в другом ниже. В конце всё свелось в одну функцию draw_hud(), которая получает голые значения телеметрии и не знает, откуда они взялись: с живого UART или из лога месячной давности.

Что в итоге

Интерфейс, придуманный ChatGPT по фотографии с пола, превратился в два HUD. Один - для людей: красивый, со свечением, со всеми цифрами. Другой - для модели: линейка, сетка и прицел, ничего лишнего. Первый делает видео зрелищным. Второй - помогает модели понять, куда поворачивать и что рассматривать.

15. Камера, дальномер и круг с прицелом

В разделе про приборную панель я обещал рассказать, как считается место прицела дальномера на кадре. Задача звучит просто: нарисовать круг там, куда светит лазер. На деле это маленькая задача из геометрии камеры, и решить её пришлось из-за шкафа (в смысле по причине шкафа, а не решать задачу сидя за шкафом).

Зачем вообще прицел

Модель получает строчку “дальномер 870 мм” и кадр. Вопрос: 870 мм - это до чего? До стены? До стула перед стеной? До ножки стола? Без прицела модель додумывает сама, и додумывает часто неправильно.

Самый наглядный пример - история со шкафом из раздела 6. Лидар стоял ниже камеры, луч проходил под кухонными шкафами и мерил расстояние до стены за ними. Grok видел на кадре шкаф, видел в телеметрии, что впереди свободно, - и уверенно ехал под шкаф. Если бы на кадре был круг, верно показывающий, куда светит лазер, модель увидела бы: круг - под шкафом, в щели. Расстояние - до чего-то там, в темноте, а не до дверцы.

Лидар я переставил выше. Но заодно захотелось, чтобы прицел стоял на кадре там, где надо, а не там, где я его нарисовал на глаз.

Первая версия: на глаз

Первый прицел стоял по константе: центр по горизонтали, cy = 400 пикселей по вертикали. Подобрал, посмотрев на пару кадров. Потом кадр поменял размер - для модели 896 пикселей, для экрана 1920 - и константа перестала подходить. Появилась вторая, cy = 200. Потом я переставил лидар, и обе стали неправильными.

Хуже того: правильного cy не существует. Место лазерной точки на кадре зависит от расстояния.

Параллакс

Камера и лидар стоят в разных местах. Лидар немного ниже камеры, и камера смотрит чуть вниз. Их лучи не совпадают.

Представьте, что вы смотрите одним глазом, а фонарик держите у подбородка и светите горизонтально. Стена далеко - пятно почти там, куда вы смотрите. Стена у самого носа - пятно заметно ниже.

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

Камера-обскура

Простейшая модель камеры - камера-обскура, по-английски pinhole: ящик с дырочкой, через которую свет падает на заднюю стенку. Точка в пространстве проецируется на кадр по одной формуле:

y_пикс = f · Y / Z

Где Z - расстояние вперёд от камеры, Y - смещение вверх-вниз, а f - фокусное расстояние в пикселях. Чем дальше точка, тем ближе её проекция к центру кадра: далёкое сжимается.

Статья про модель камеры-обскура: Модель камеры

Фокусное расстояние в пикселях считается из угла обзора. Половина ширины кадра видна под половиной угла обзора:

f = (W / 2) / tan(FOV / 2) = 448 / tan(37.6°) ≈ 582 пикселя

Для кадра шириной 896 пикселей и угла обзора 75.2°.

Фокальное расстояние
Фокальное расстояние

Наклон камеры

Вторая поправка - камера смотрит не строго горизонтально, а чуть вниз. Горизонтальный луч лазера для наклонённой камеры идёт чуть вверх, и точку нужно повернуть в систему координат камеры:

z_cam = dh * sin(alpha) + d * cos(alpha)       # вперёд, вдоль оси камеры
y_cam = -dh * cos(alpha) + d * sin(alpha)      # вверх, поперёк оси камеры
cy = H/2 - f * y_cam / z_cam

Здесь d - показание дальномера, dh - насколько лидар ниже камеры (после переноса - 20 мм, измерено линейкой), alpha - наклон камеры.

Наклон камеры
Наклон камеры

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

Размер круга

Место круга мы посчитали. А какого он размера?

Я решил что у меня размер прицела должен быть примерно как яблоко по размеру. Я не знаю почему так, но пусть будет: круг радиусом 7.5 см. Сколько пикселей она займёт на кадре, зависит от расстояния:

r = f · atan(R / d)

На метре - 44 пикселя, на 30 см - 143, на 4 метрах - 11. Круг ведёт себя как настоящий предмет: вблизи большой, вдали маленький. Модель видит не просто “здесь”, а “примерно вот такой кусок мира”.

Разные размеры кадра

Модель получает кадр 896 пикселей, экран и смонтированное видео - 1920. Всё посчитано для 896, а для другой ширины фокусное расстояние просто масштабируется. Прицел стоит в одном и том же месте картинки и у модели, и на видео.

Что в итоге

Прицел - больше не константа, подобранная на глаз, а проекция: четыре измеренных параметра (угол обзора, смещение лидара, размер мишени, наклон камеры (ладно, не измерено, а подобрано)) и формула камеры-обскуры. Лидар переставил - поменял одно число в конфиге, прицел встал на место.

Вся эта математика калибровалась и проверялась на хайтек-устройстве: коробке с нарисованной линией ровно на уровне лидара. Прицел лидара должен был всегда лежать на этой линии, независимо от расстояния до коробки.

Коробка для калибровки
Коробка для калибровки

16. Запись и синхронизация

После сессии у меня два набора данных. С одной стороны - лог: события с метками времени, телеметрия десять раз в секунду, фразы робота. С другой - видео с камеры, которое ffmpeg писал параллельно. Чтобы наложить на видео приборную панель, вставить речь и вырезать паузы, нужно знать, какой момент видео соответствует какой строчке лога.

И вот тут выясняется, что у них разные часы.

Два времени

Время лога - это часы хоста. Каждое событие помечено меткой: столько-то секунд с 1970 года.

Время видео - секунды от начала файла. Когда именно начался файл по часам хоста, неизвестно. ffmpeg запустился, подключился к камере, дождался первого ключевого кадра, начал писать - всё это занимает непредсказуемое время. А сама камера, как мы помним, отдаёт картинку с опозданием на секунду-две.

Нужна точка, которая есть в обоих временах. Событие, момент которого известен и по часам хоста, и на видео.

Хлопушка

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

Хлопушка
Хлопушка

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

{"ts": 1778681982.39, "type": "sync_beep", "ts_wall": 1778681982.39}

Писк слышит микрофон камеры, и он попадает в звуковую дорожку видео. При монтаже программа ищет его в звуке: берёт первые 15 секунд, считает громкость окнами по 50 мс и находит первый резкий скачок. Это момент писка в видео.

Теперь любое событие лога переводится во время видео одной формулой:

t_видео = (ts_события − ts_писка) + t_писка_в_видео

Хорошее свойство этой схемы: задержка камеры в ней уже учтена. Писк проходит через тот же путь, что и картинка: микрофон камеры, буфер камеры, RTSP, ffmpeg. На сколько камера опаздывает, на столько же опоздает и писк в записи - и формула это автоматически съест.

Пищалка

Для писка на ардуину поставил активный пьезо-излучатель на пин 8 и добавил в протокол команду:

P<000-999>\n   # пискнуть, длительность в мс

Также выяснилось, что писк надо ещё правильно подгадать по времени. Первый раз он прозвучал, пока камера ещё не открыла поток, - и в записи его просто не было. Теперь хост сначала ждёт первый кадр от камеры, потом ещё секунду, чтобы ffmpeg точно писал, и только потом пищит.

Запись до конца

С концом записи похожая история. Задача выполнена, робот сказал итоговую фразу, хост останавливает ffmpeg - и последней фразы в видео нет. Камера буферизует секунду-две, и хвост записи ещё не успел дойти до ffmpeg. Лечение простое: после конца сессии подождать три секунды и только потом останавливать запись.

Некорректная частота кадров

Самая неприятная история случилась уже при монтаже. Видео после наложения HUD оказывалось короче оригинала, и к концу сессии звук обгонял картинку почти на минуту.

Причина - в заголовках видео. Камера Tapo заявляет частоту 24.75 кадра в секунду. На деле она отдаёт около 15. Плеер этого не замечает: он показывает кадры по их меткам времени. А программа наложения HUD брала заявленную частоту, читала кадры по одному и расставляла им время заново: кадр номер N - это N / 24.75 секунды. Получалось в 1.65 раза быстрее, чем на самом деле, и расхождение копилось до минуты.

ffmpeg отдаёт две разные частоты: r_frame_rate - заявленную, и avg_frame_rate - среднюю реальную, посчитанную по длительности и числу кадров. Переход на вторую - и расхождение упало с минуты до десятой доли секунды.

Хвосты по полсекунды

Минуту убрали, но осталось расхождение поменьше, до двух секунд за сессию. Видео при монтаже режется на куски - паузы вырезаются, - и на каждом стыке терялись или добавлялись доли кадра. ffmpeg, когда режет по времени, выравнивается по ключевым кадрам и добавляет лишние кадры в начале куска. По отдельности незаметно, за десятки стыков набегает.

Помогли две вещи. Первая: видео и звук собираются раздельно. Сначала куски видео режутся строго по числу кадров, без звука, потом к ним подмешивается звук точно по длительности. Вторая: вся сборка звука ведётся в сэмплах, а не в секундах. Сэмпл - целое число, в нём нечему накапливаться. Теперь рассинхрон - не больше половины кадра.

Что в итоге

Два времени - часы хоста и время видео - связаны одним писком в начале сессии. Этого хватает, чтобы наложить на видео всё, что есть в логе: телеметрию, речь, приборную панель. Остальное - борьба с мелочами: пищать вовремя, не выключать запись раньше времени, не верить камере на слово и считать звук в сэмплах.

Хлопушке лет сто. Работает и для роботов.

17. Монтаж

В свете новомодного вайбкодинга, это очень интересное место. Делать код для монтажа видео, скажу прямо, это не та задача, которая меня интересовала. Я вряд ли прокачаюсь на ней как специалист, времени займёт много, и проблем с ней будет много, сил потрачу тоже много. Идеальный кандидат для вайбкодинга. Написать скрипт ИИ может, а вот проверить что видео получилось хорошо, сможет ли?

Весь код для монтажа был написан Клодом, и я не очень в курсе как он написан, но процесс отладки и поиска багов, получился весьма забавным.

Сырое видео сессии смотреть невозможно. Половину времени робот просто стоит: модель думает. Пять секунд, десять, иногда полминуты. Потом робот говорит фразу, поворачивается - и снова стоит. Двадцатиминутная сессия - это пять минут действия и пятнадцать минут ожидания.

Монтаж делает из этого видео, которое можно смотреть. И делает его программа, а не я в видеоредакторе: сессий десятки, резать каждую руками - никакого терпения не хватит.

Что делает монтаж

  • Вырезает паузы. Модель думает, робот стоит - этот кусок уходит.

  • Накладывает речь. Фразы робота берутся из сохранённых mp3 и ставятся туда, где в логе стоит speech_start.

  • Накладывает приборную панель. По телеметрии из лога, кадр за кадром.

  • Показывает зум. Когда модель вызывает zoom, в видео вставляется анимация: кадр увеличивается в ту точку, которую модель рассматривала, и показывает то, что видела модель.

  • Показывает текст оператора. Мои сообщения модели и ответы на её вопросы - плашкой поверх видео.

  • Добавляет титры. В начале - дата, модель, задача. В конце - итог.

Первая версия: скрипт

Первая версия монтажа появилась одновременно с записью видео - одним скриптом. Он читал лог, находил писк, рендерил HUD на каждый кадр в Python, резал паузы, подмешивал речь, склеивал со слайдами. Работало. Но каждое новое правило - “не резать тут”, “показать это там” - реализовывалось в код очередным if. Через месяц в этих if стало невозможно разобраться: поправишь зум - ломается оператор.

Уже классика жанра. Что-то навайбкодили, а что и как работает - неясно.

Вторая версия: три слоя

Тут я подошел иначе и описал Клоду какую я хочу видеть архитектуру скрипта: три слоя с разными задачами.

Монтаж был переписан в три слоя, каждый со своей задачей.

Слой 1. Кто что делал. Лог превращается в дорожки состояний, по одной на каждого “актора”: модель (думает / не думает), робот (стоит, едет, поворачивается, рассматривает, стреляет), речь (говорит / молчит), оператор (молчит, спрашивает, ответил). Получаются интервалы: “с 12.3 по 18.7 секунды модель думала, робот стоял”.

Слой 2. Правила. Каждое правило смотрит на состояния и выдаёт операцию монтажа:

модель думает + робот стоит   ->  вырезать
робот рассматривает (zoom)    ->  вставить анимацию зума
робот говорит                 ->  подмешать mp3
оператор ответил              ->  показать плашку

Правила ничего не знают про ffmpeg. Новое правило - одна функция, остальное не трогается. Например, правило, появившееся после экспериментов с пистолетом: паузу сразу после выстрела не вырезать - на видео в это время разлетается зеркало.

Слой 3. Сборка. Операции превращаются в список кусков итогового видео - какой кусок исходника, откуда и докуда, где вставка, где звук, - и ffmpeg это собирает.

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

Как Клоду найти баг в видео

И тут возникла проблема, которой нет в обычной разработке: баги видны только на видео. Как клод оценит свою работу, если он не умеет смотреть видео?

Смотрю результат - на границе зума приборная панель мигает. Должна плавно погаснуть перед анимацией и плавно появиться после, а она на долю секунды вспыхивает. Как объяснить это Клоду? “Где-то в середине видео мигает HUD” - не баг-репорт. Видео Клод посмотреть не может, а если бы и мог, вспышка длиной в пару кадров - это не то, что можно заметить, листая раскадровку.

Решение: дать нам обоим одну и ту же информацию, но в разном виде.

Для меня визуализатор генерирует HTML-страницу - интерактивную диаграмму: по вертикали время, по горизонтали дорожки акторов, цветные полосы состояний, красным - вырезанные куски, зелёным - вставки. Навожу мышь - вижу подробности. Рядом можно открыть видео и смотреть глазами: вот зум, вот вырез, вот здесь мигнуло.

Временная линия видео
Временная линия видео

Для Клода тот же визуализатор пишет те же данные в JSON: интервалы, операции, куски итогового видео с обоими временами. Это ему читать удобно, в этом он может искать, считать, сравнивать.

Временная линия видео для Клода
Временная линия видео для Клода

А чтобы связать одно с другим, в отладочном режиме на каждый кадр видео впечатывается оба времени: src=123.456 out=87.210. Я вижу вспышку, ставлю видео на паузу и читаю с кадра время. Говорю Клоду: “на out=87.2 вспышка HUD”. Он открывает JSON, находит это место и видит, что там происходит в данных.

Для HUD появился ещё один отладочный инструмент - дамп прозрачности приборной панели по кадрам вокруг каждого зума. Кривая должна плавно идти 1 -> 0 -> 1. Там, где она прыгает, - баг, и видно это в цифрах, без всякого видео.

Что нашлось

Первая вспышка оказалась на стыке кусков. ffmpeg, вырезая кусок из исходника, иногда отдаёт на пару кадров больше, чем просили. Эти лишние кадры выходили за границу куска, где плавное гашение HUD уже не действовало, и получали полную яркость. Два кадра полной яркости посреди затухания - вспышка. Лечение - зажать время каждого кадра в границах его куска.

Вторая вспышка - хитрее. Она появлялась только в одной сессии, где после зума я писал модели сообщение. Между концом зума и началом следующей вырезанной паузы оставался зазор, в котором HUD успевал загореться, а потом снова погаснуть. Функция, которая искала “ближайший вырез после момента t”, не учитывала три частных случая, и один из них - два сообщения оператора в одной сессии. Без JSON это место не нашлось бы: на глаз там видно только “иногда мигает”.

После этих историй появился интеграционный тест на реальной сессии: весь монтаж прогоняется на настоящем логе на 26 ходов, с зумами и оператором, - 43 теста на реальных данных. Каждая пойманная вспышка стала тестом.

Что в итоге

Монтаж - это программа, которая читает лог и делает из двадцати минут стояния пятиминутное видео с речью, приборами, зумами и титрами. Три слоя: кто что делал, какие правила из этого следуют, как это собрать.

А главный урок - про отладку вдвоём с ИИ. Если баг виден только глазами, а исправлять его будет модель, которая видео не смотрит, нужно дать ей те же данные в её формате - и общий язык, чтобы ткнуть пальцем в нужное место. У нас таким языком стали два времени, впечатанные в кадр.

Заключение

Хотите pet-проект с ИИ и есть свободное время - делайте робота. Оглядываясь назад можно подытожить, что пришлось узнать или освежить в памяти:

  • Электроника. Паяльник, провода, питание, H-мост, датчики тока, сервопривод, пьезо-пищалка

  • Микроконтроллеры. C++ без ОС, конфликты таймеров, прерывания, холодный старт датчиков

  • Протоколы. Свой текстовый протокол поверх UART, I2C master/slave, отладка двух плат по отдельности и совместно

  • Датчики. Магнитометр, гироскоп, ИК/УЗ/лазерный дальномер

  • Математика. МНК и линейная регрессия, круговая арифметика, проекция камеры-обскуры

  • Теория управления. ПИД, трение покоя, инерция

  • Фильтры. Медианный, комплементарный, альфа-бета - и понимание, где начинается Калман

  • Зрение и графика. OpenCV, numpy

  • Видео и звук. RTSP, ffmpeg, синхронизация по хлопушке

  • Python. Фоновые потоки, блокировки

  • LLM. Инструменты и структурированный ответ, агентный цикл, контекстное окно, токены и деньги, разница между API четырёх провайдеров, LLMOps

  • Инженерная культура. В программировании: лог как протокол эксперимента, слоистая архитектура, тесты на реальных данных, отладка вдвоём с ИИ и в железе: ровная укладка проводов, надёжная механика.

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

Цена: в бортовом журнале только на хостовую часть набралось больше двухсот часов, и это то, что я записывал. Если времени нет - лучше не начинать. Если есть - это самое весёлое, что можно делать по вечерам.

Про детей

Отдельно скажу про тех, у кого дети ходят в кружок робототехники, как у меня.

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

Борис Михайленко, LLM инженер в поисках работы

Исходники на GitHub

Источник

  • 30.06.26 15:08 wendytaylor015

    My name is Wendy Taylor, I'm from Los Angeles, i want to announce to you Viewer how Capital Crypto Recover help me to restore my Lost Bitcoin, I invested with a Crypto broker without proper research to know what I was hoarding my hard-earned money into scammers, i lost access to my crypto wallet or had your funds stolen? Don’t worry Capital Crypto Recover is here to help you recover your cryptocurrency with cutting-edge technical expertise, With years of experience in the crypto world, Capital Crypto Recover employs the best latest tools and ethical hacking techniques to help you recover lost assets, unlock hacked accounts, Whether it’s a forgotten password, Capital Crypto Recover has the expertise to help you get your crypto back. a security company service that has a 100% success rate in the recovery of crypto assets, i lost wallet and hacked accounts. I provided them the information they requested and they began their investigation. To my surprise, Capital Crypto Recover was able to trace and recover my crypto assets successfully within 24hours. Thank you for your service in helping me recover my $647,734 worth of crypto funds and I highly recommend their recovery services, they are reliable and a trusted company to any individuals looking to recover lost money. Contact email [email protected] OR Telegram @Capitalcryptorecover Call/Text Number +1 (336)390-6684 his contact: [email protected] His website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 30.06.26 15:08 wendytaylor015

    My name is Wendy Taylor, I'm from Los Angeles, i want to announce to you Viewer how Capital Crypto Recover help me to restore my Lost Bitcoin, I invested with a Crypto broker without proper research to know what I was hoarding my hard-earned money into scammers, i lost access to my crypto wallet or had your funds stolen? Don’t worry Capital Crypto Recover is here to help you recover your cryptocurrency with cutting-edge technical expertise, With years of experience in the crypto world, Capital Crypto Recover employs the best latest tools and ethical hacking techniques to help you recover lost assets, unlock hacked accounts, Whether it’s a forgotten password, Capital Crypto Recover has the expertise to help you get your crypto back. a security company service that has a 100% success rate in the recovery of crypto assets, i lost wallet and hacked accounts. I provided them the information they requested and they began their investigation. To my surprise, Capital Crypto Recover was able to trace and recover my crypto assets successfully within 24hours. Thank you for your service in helping me recover my $647,734 worth of crypto funds and I highly recommend their recovery services, they are reliable and a trusted company to any individuals looking to recover lost money. Contact email [email protected] OR Telegram @Capitalcryptorecover Call/Text Number +1 (336)390-6684 his contact: [email protected] His website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 02.07.26 01:22 Lieneke Bonnema

    I highly recommend ResQprofirm for their professional asset recovery services of my $120,000 scammed funds. Their expertise, professionalism, and commitment to achieving results make them a reliable choice for anyone seeking dependable recovery assistance. [email protected], WhatsApp +19852969146, telegram @resqprofirm

  • 02.07.26 01:26 Clara Morin

    I want to extend my deepest appreciation for showing that circumstances do not define one’s potential for greatness. Your support has been a major source of inspiration during my trading journey, and I am sincerely grateful for your insight and mentorship. Thank you so much. [email protected], WhatsApp +19852969146, telegram ResQprofirm

  • 02.07.26 01:31 Robin Hale

    I sincerely want to thank you for demonstrating that anyone can rise above their circumstances and achieve success. Your constant support has been incredibly inspiring during my trading journey, and your wisdom and advice mean so much to me. I appreciate you deeply. [email protected], WhatsApp +19852969146, telegram Resqprofirm

  • 04.07.26 15:32 Fraddy Pual

    There are few companies I trust as much as FUNDSRETRIEVER. When I lost $653,000 in Ethereum to a ruthless scam, I thought my life would never be the same. The betrayal cut deep, but I refused to give up. I searched tirelessly for a legitimate way to recover what was stolen, and finally found FUNDSRETRIEVER—the most competent and compassionate recovery team I could have imagined. They handled my case with precision and care, and in the end, my entire ETH wallet was restored. More than the money, they gave me back my hope and happiness. I'm sharing my story because I want others to know that recovery is possible. If a scam has taken from you, don't hesitate—contact FUNDSRETRIEVER today. Email: FUNDSRETRIEVER1@ Gmail.com | WhatsApp: +1 603-512-1448 | Telegram: @FUNDSRETRIEVER

  • 05.07.26 14:44 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/Text: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 05.07.26 14:44 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/Text: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 06.07.26 16:20 Olga Ognjanović

    Having trouble withdrawing funds from an investment platform? ResQprofirm provides fund recovery assistance for individuals seeking help with investment-related disputes. I reached out to them after experiencing problems with an investment platform, and I appreciated their professionalism and support throughout the process. If you're facing a similar situation, act promptly, keep records of your transactions and communications, and seek assistance from a qualified recovery service or the appropriate authorities. Contact: Email: [email protected] Telegram: @ResQprofirm WhatsApp: +1 985 296 9146

  • 06.07.26 16:31 Joseph Weigl

    Invest wisely and stay cautious. Don't be influenced by promises of unusually high returns or convincing sales pitches from brokers. I learned this the hard way after falling victim to an investment scam that promised huge profits. Fortunately, I acted quickly and reported the incident to a recovery firm for assistance. Contact: Email: [email protected] Telegram: @Resqprofirm WhatsApp: +1 985 296 9146

  • 06.07.26 16:33 Jaran Løvlien

    A heartfelt thank you to RESQPRO FIRM for their commitment and professionalism throughout the investigation of my case. Their team worked diligently and helped recover assets valued at $88,000, which were returned to my wallet. I truly appreciate their support, clear communication, and dedication, and I'm grateful for the assistance I received. Contact: Email: [email protected] Telegram: @Resqprofirm WhatsApp: +1 985 296 9146

  • 07.07.26 18:00 robertalfred175

    CRYPTO SCAM RECOVERY SUCCESSFUL – A TESTIMONIAL OF LOST PASSWORD TO YOUR DIGITAL WALLET BACK. My name is Robert Alfred, Am from Australia. I’m sharing my experience in the hope that it helps others who have been victims of crypto scams. A few months ago, I fell victim to a fraudulent crypto investment scheme linked to a broker company. I had invested heavily during a time when Bitcoin prices were rising, thinking it was a good opportunity. Unfortunately, I was scammed out of $120,000 AUD and the broker denied me access to my digital wallet and assets. It was a devastating experience that caused many sleepless nights. Crypto scams are increasingly common and often involve fake trading platforms, phishing attacks, and misleading investment opportunities. In my desperation, a friend from the crypto community recommended Capital Crypto Recovery Service, known for helping victims recover lost or stolen funds. After doing some research and reading multiple positive reviews, I reached out to Capital Crypto Recovery. I provided all the necessary information—wallet addresses, transaction history, and communication logs. Their expert team responded immediately and began investigating. Using advanced blockchain tracking techniques, they were able to trace the stolen Dogecoin, identify the scammer’s wallet, and coordinate with relevant authorities to freeze the funds before they could be moved. Incredibly, within 24 hours, Capital Crypto Recovery successfully recovered the majority of my stolen crypto assets. I was beyond relieved and truly grateful. Their professionalism, transparency, and constant communication throughout the process gave me hope during a very difficult time. If you’ve been a victim of a crypto scam, I highly recommend them with full confidence contacting: Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text: +1 (336) 390-6684 Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 07.07.26 18:01 robertalfred175

    CRYPTO SCAM RECOVERY SUCCESSFUL – A TESTIMONIAL OF LOST PASSWORD TO YOUR DIGITAL WALLET BACK. My name is Robert Alfred, Am from Australia. I’m sharing my experience in the hope that it helps others who have been victims of crypto scams. A few months ago, I fell victim to a fraudulent crypto investment scheme linked to a broker company. I had invested heavily during a time when Bitcoin prices were rising, thinking it was a good opportunity. Unfortunately, I was scammed out of $120,000 AUD and the broker denied me access to my digital wallet and assets. It was a devastating experience that caused many sleepless nights. Crypto scams are increasingly common and often involve fake trading platforms, phishing attacks, and misleading investment opportunities. In my desperation, a friend from the crypto community recommended Capital Crypto Recovery Service, known for helping victims recover lost or stolen funds. After doing some research and reading multiple positive reviews, I reached out to Capital Crypto Recovery. I provided all the necessary information—wallet addresses, transaction history, and communication logs. Their expert team responded immediately and began investigating. Using advanced blockchain tracking techniques, they were able to trace the stolen Dogecoin, identify the scammer’s wallet, and coordinate with relevant authorities to freeze the funds before they could be moved. Incredibly, within 24 hours, Capital Crypto Recovery successfully recovered the majority of my stolen crypto assets. I was beyond relieved and truly grateful. Their professionalism, transparency, and constant communication throughout the process gave me hope during a very difficult time. If you’ve been a victim of a crypto scam, I highly recommend them with full confidence contacting: Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text: +1 (336) 390-6684 Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 09.07.26 19:06 Toivo Walli

    I lost 8.56btc to a fake Bitcoin mining site, I tried withdrawing but couldn't approved my process, I reported to !R£SQPROFIRM! via °R£SQproFirm°àt°gmail•com° °tEL£°gram=R£SQprofirm °whaT°Zap+198°52°96°91°46

  • 09.07.26 19:10 Misty Alexander

    Ongoing messages demanding more money before approving withdrawals are a major red flag. Stop engaging and report the incident to a trusted re­covery team. For professional support, you can contact R£sQprofirm using °ResQproFirm°àt°g,*ma'il(•)¢m°, TEL£gram ResQprofirm, or |whaTZap| +1-985-296-9146.

  • 09.07.26 19:13 Clara Soto

    Anyone receiving continued requests for additional deposits from a scam platform should immediately cut off communication and submit the case to a reputable re­covery service for investigation. R£sQprofirm is a dependable firm you can reach at °ResQproFirm°àt°g,*ma'il(•)¢om°, TEL£gram ResQprofirm, or |whaTZap| +1-985-296-9146.

  • 12.07.26 03:30 Kora Baltacha

    Time is critical. Act now by reaching out to a reputable, seasoned recovery specialist who will guide you every step of the way. You'll need to submit transaction proof, scammer details, and any other useful information. Armed with this, the experts can trace and attempt to pull your money back from the scammers' hidden accounts or wallets. Best of all, R£sQprofirm provides recovery help without charging any upfront fees. Contact them immediately via Telegram @ResQprofirm, WhatsApp +19852969146, or email [email protected].

  • 12.07.26 03:33 Pahal Mathew

    It's important to move proactively by engaging an experienced recovery specialist. They will assist you throughout the process. To help them, provide: · Transaction evidence · Scammer information · Any additional relevant details The experts will then track and try to retrieve your funds from the scammers' hidden accounts or wallets. R£sQprofirm offers recovery assistance with no upfront fees. Contact: Telegram: @ResQprofirm WhatsApp: +19852969146 Email: [email protected]

  • 13.07.26 23:49 [email protected]

    One of the biggest concerns I have about cryptocurrency is the lack of regulation. It creates opportunities for scammers to invent convincing stories and fraudulent investment schemes. Unfortunately, some social media platforms continue to display these ads because they profit from them, even after users report them.I personally clicked on a Facebook advertisement for a company called Chickenfastmining and ended up losing more than $120,000 in a scam. I reported the ad, but nothing was done. Later, through a Reddit community, I found a recovery service called CYBERBERSPY that, in my personal experience, they helped me recover $110,000 of my lost funds. If you've been a victim of a cryptocurrency scam, don't lose hope. Explore your options carefully, and always verify the legitimacy of any recovery service before trusting them or paying any fees. Based on my own experience, CYBERBERSPY was helpful to me and i was able to recover my funds back, but I encourage everyone to do their own research before using any recovery service.i highly recommend: ([email protected])

  • 15.07.26 11:53 Sarah Green

    Thank you for showing that success is possible regardless of where someone starts. Your encouragement, valuable advice, and continuous support have inspired me throughout my $160,457k crypto investment recovery journey. I truly appreciate your kindness and dedication. Resqprofirm @gmail.com Telegram: Resqprofirm

  • 15.07.26 11:58 Lily Gagné

    I sincerely appreciate you for proving that anyone can overcome challenges and achieve success. Your unwavering support throughout my trading investment scam of $88,890 recovery journey has been truly inspiring, and your guidance and wisdom have meant a great deal to me. Thank you for everything ResQprofirm@ gmail.com, ResQprofirm on the telegram.

  • 16.07.26 21:38 patricialovick86

    How To Recover Your Bitcoin Without Falling Victim To Scams: A  Testimony Experience With Capital Crypto Recover Services, Contact Telegram: @Capitalcryptorecover Dear Everyone, I would like to take a moment to share my positive experience with Capital Crypto Recover Services. Initially, I was unsure if it would be possible to recover my stolen bitcoins. However, with their expertise and professionalism, I was able to fully recover my funds. Unfortunately, many individuals fall victim to scams in the cryptocurrency space, especially those involving fraudulent investment platforms. However, I advise caution, as not all recovery services are legitimate. I personally lost $273,000 worth of Bitcoin from my Binance account due to a deceptive platform. If you have suffered a similar loss, you may be considering crypto recovery, The Capital Crypto Recover is the most knowledgeable and effective Capital Crypto Recovery Services assisted me in recovering my stolen funds within 24 hours, after getting access to my wallet. Their service was not only prompt but also highly professional and effective, and many recovery services may not be trustworthy. Therefore, I highly recommend Capital Crypto Recover to you. i do always research and see reviews about their service, For assistance finding your misplaced cryptocurrency, get in touch with them, They do their jobs quickly and excellently, Stay safe and vigilant in the crypto world. Contact: [email protected]  You can reach them via email at [email protected] OR Call/Text Number +1 (336)390-6684 his contact website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 16.07.26 21:38 patricialovick86

    How To Recover Your Bitcoin Without Falling Victim To Scams: A  Testimony Experience With Capital Crypto Recover Services, Contact Telegram: @Capitalcryptorecover Dear Everyone, I would like to take a moment to share my positive experience with Capital Crypto Recover Services. Initially, I was unsure if it would be possible to recover my stolen bitcoins. However, with their expertise and professionalism, I was able to fully recover my funds. Unfortunately, many individuals fall victim to scams in the cryptocurrency space, especially those involving fraudulent investment platforms. However, I advise caution, as not all recovery services are legitimate. I personally lost $273,000 worth of Bitcoin from my Binance account due to a deceptive platform. If you have suffered a similar loss, you may be considering crypto recovery, The Capital Crypto Recover is the most knowledgeable and effective Capital Crypto Recovery Services assisted me in recovering my stolen funds within 24 hours, after getting access to my wallet. Their service was not only prompt but also highly professional and effective, and many recovery services may not be trustworthy. Therefore, I highly recommend Capital Crypto Recover to you. i do always research and see reviews about their service, For assistance finding your misplaced cryptocurrency, get in touch with them, They do their jobs quickly and excellently, Stay safe and vigilant in the crypto world. Contact: [email protected]  You can reach them via email at [email protected] OR Call/Text Number +1 (336)390-6684 his contact website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 17.07.26 19:24 laimqq90

    I recommend Marie when it comes to recovering lost/stolen ust/bitcoin or any kind of cryptocurrencies' from fake investment platforms because they're well specialized in that area and you'll get your money back in full. I can boldly say this right now based on my prior deal i had with them; she was the only one who was able to recover my lost money $52,760 dollars back to my account, Only * ([email protected] and WhatsApp +1 7127594675 successful in recovering my money. They are the only one who can fully restore your lost funds to your account without any deductions, I really value their work and am recommending her to you today. THANK ME LATER

  • 17.07.26 20:12 martinsjude080

    Needs Online Fraud Help Contact Mighty Hacker Recovery https://mightyhackarrecovery.com I lost $292,900 in Bitcoin after investing with an online mining company. After realizing I had been scammed, I spent a long time searching for ways to recover my funds and contacted several services without success. During my research, I came across Mighty Hacker Recovery through Google and YouTube. What caught my attention was that they said they would not require any upfront payment before providing their recovery service. I decided to contact them to discuss my case and understand their process. Throughout the process, they kept me informed about the progress. After several days, I was asked to provide my Bitcoin wallet address, and my case was concluded. Their fee was handled after the service rather than being requested in advance. If you've been the victim of a cryptocurrency scam, it's important to do your own research, ask questions, and carefully evaluate any recovery service before proceeding. Every case is different, so take the time to verify information and understand the process before making any decisions. For Bitcoin scam recovery, cryptocurrency scam, crypto recovery service, recover stolen Bitcoin, Bitcoin fraud help, blockchain investigation, crypto wallet recovery, online investment scam, digital asset recovery, and crypto scam support. Contact Them on WhatsApp +1 (343) 947-3496 or [email protected] or [email protected] or https://mightyhackarrecovery.com Scam recovery Online fraud help Scam alert Report fraud Fraud investigation Fake website checker Scam checker Identity theft protection Consumer protection Chargeback for scam Wire transfer scam Tech support scam Employment scam Rental scam Shopping scam Email scam WhatsApp scam Telegram scam Facebook scam Instagram scam

  • 18.07.26 17:12 Malthe Larsen

    My experience with OKX has been deeply frustrating. For months, my account withdrawals were restricted with no explanation or resolution. Multiple emails to their support team were ignored, leaving me without answers or reassurance. This complete lack of communication shattered my trust. I ultimately regained access to my funds only through the help of a third-party recovery service, ResQProfirm. What should have been a reliable platform instead made me feel helpless and cut off from my own assets. [email protected], WhatsApp +19852969146, telegram @Resqprofirm

  • 18.07.26 17:42 پریا رضایی

    OKX has been a major disappointment. My withdrawals were restricted for months, and repeated attempts to contact support went unanswered. This silence destroyed my confidence in the platform. I was only able to recover my funds through a third-party service, ResQProfirm. I trusted OKX for its reliability, but the experience left me feeling trapped and helpless. Timely communication and access to one’s own money should be a basic standard. [email protected], WhatsApp +19852969146, telegram: ResQprofirm

  • 18.07.26 17:46 Adem Akışık

    I truly didn’t expect such an outstanding outcome. Recovering my $49,360 felt impossible at first, but ResQprofirm’s dedication and persistence made it happen. I hold their team in the highest regard. [email protected], WhatsApp +19852969146

  • 18.07.26 23:51 bernalzenaida

    WhatsApp https://wa.link/fhle97 Telegram https://msng.link/o?@techcyberforc=tg As cryptocurrency continues to reshape global finance, cybercriminals are finding new ways to exploit investors through scams, hacks, phishing attacks, fake investment platforms, and other forms of digital asset fraud. For many victims, knowing where to turn after a loss can be one of the biggest challenges. Techy Force Cyber Retrieval was founded with one clear mission: to give victims of crypto fraud a fighting chance through professional blockchain investigations and cybersecurity expertise. Our team brings together experienced blockchain analysts, digital forensic specialists, cybersecurity professionals, and legal partners who work collaboratively to investigate cryptocurrency-related crimes. Using advanced blockchain forensic tools and global investigative techniques, we analyze transaction histories, trace digital asset movements where possible, identify valuable investigative leads, and prepare evidence that may assist clients and the appropriate authorities. We believe blockchain should represent transparency, accountability, and trust—not fear. That’s why we’re committed to helping victims understand their options, navigate the investigative process, and take informed action after cryptocurrency fraud. Every case is different, and while no legitimate recovery service can promise a successful recovery, acting quickly and working with experienced professionals can improve the quality of an investigation. At Techy Force Cyber Retrieval, we do more than investigate digital crimes—we advocate for victims, pursue the facts, and help people regain confidence after cryptocurrency fraud. WhatsApp https://wa.link/fhle97 Telegram https://msng.link/o?@techcyberforc=tg Crypto fraud doesn’t have to be the end of the road. It’s where our investigation begins.

  • 19.07.26 04:10 Fraddy Pual

    I can't thank Fundsretriever enough for everything they did for me. My name is Vanessa Conway, and I'm here to tell you my story of how I recovered money I never thought I'd see again. A few months ago, I put a significant amount of money into what looked like a genuine online investment company. At first, it felt real—they showed me fake profits and convinced me to invest even more. But when I tried to cash out, they went quiet and started asking for extra fees. That's when it hit me—I had been scammed. I was heartbroken, frustrated, and didn't know where to turn. That money was my savings—months of hard work gone. Then I found Fundsretriever online. I reached out, hoping for a miracle. Right away, their team made me feel heard. They were responsive, knowledgeable, and walked me through everything. They didn't just take my case—they took it seriously and kept me in the loop every step of the way. I finally felt like I had real experts fighting for me. And guess what? They actually got my money back. It wasn't instant, and it took teamwork, but it happened. When I saw those funds returned, I cried with joy. I'm sharing this so that anyone else out there who's been scammed knows—don't lose hope. Do your research before investing, and stay far away from platforms that promise too much too fast. And if you've already been stung, don't wait—get professional help immediately. Thank you, Fundsretriever, from the bottom of my heart. You didn't just recover my money—you restored my faith. — Vanessa Conway 📧 [email protected] 📱 WhatsApp: +16035121448 💬 Telegram: @Fundsretriever

  • 19.07.26 19:53 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text Number: +1 (336) 390-6684

  • 19.07.26 19:53 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text Number: +1 (336) 390-6684

  • 19.07.26 19:54 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text Number: +1 (336) 390-6684

  • 30.07.26 00:04 Ahmed

    A really cool analysis, thank you. I was especially struck by how strictly the order is defined: data processing and formatting come first, with color only at the very end. This really saves you from the typical mistake of "first a pretty palette, then we figure out what the chart is for." And the palette validator with OKLCH + colorblindness check is absolutely fantastic; you almost never see that in regular tools. By the way, while reading about rank-trajectory and the logarithmic scale, I immediately remembered how convenient it is to analyze dynamics on charts in ExpertOption—I've been trading there for quite some time now. When the data is well visualized, decisions are noticeably easier and more relaxed. I also liked the point about "no more than eight colors" and the dual-axis ban. Strict restrictions sometimes actually produce better results than complete freedom. I'll try this approach myself.

  • 30.07.26 17:27 wendytaylor015

    My name is Wendy Taylor, I'm from Los Angeles, i want to announce to you Viewer how Capital Crypto Recover help me to restore my Lost Bitcoin, I invested with a Crypto broker without proper research to know what I was hoarding my hard-earned money into scammers, i lost access to my crypto wallet or had your funds stolen? Don’t worry Capital Crypto Recover is here to help you recover your cryptocurrency with cutting-edge technical expertise, With years of experience in the crypto world, Capital Crypto Recover employs the best latest tools and ethical hacking techniques to help you recover lost assets, unlock hacked accounts, Whether it’s a forgotten password, Capital Crypto Recover has the expertise to help you get your crypto back. a security company service that has a 100% success rate in the recovery of crypto assets, i lost wallet and hacked accounts. I provided them the information they requested and they began their investigation. To my surprise, Capital Crypto Recover was able to trace and recover my crypto assets successfully within 24hours. Thank you for your service in helping me recover my $647,734 worth of crypto funds and I highly recommend their recovery services, they are reliable and a trusted company to any individuals looking to recover lost money. Contact email [email protected] OR Telegram @Capitalcryptorecover Call/Text Number +1 (336)390-6684 his contact: [email protected] His website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 30.07.26 17:27 wendytaylor015

    My name is Wendy Taylor, I'm from Los Angeles, i want to announce to you Viewer how Capital Crypto Recover help me to restore my Lost Bitcoin, I invested with a Crypto broker without proper research to know what I was hoarding my hard-earned money into scammers, i lost access to my crypto wallet or had your funds stolen? Don’t worry Capital Crypto Recover is here to help you recover your cryptocurrency with cutting-edge technical expertise, With years of experience in the crypto world, Capital Crypto Recover employs the best latest tools and ethical hacking techniques to help you recover lost assets, unlock hacked accounts, Whether it’s a forgotten password, Capital Crypto Recover has the expertise to help you get your crypto back. a security company service that has a 100% success rate in the recovery of crypto assets, i lost wallet and hacked accounts. I provided them the information they requested and they began their investigation. To my surprise, Capital Crypto Recover was able to trace and recover my crypto assets successfully within 24hours. Thank you for your service in helping me recover my $647,734 worth of crypto funds and I highly recommend their recovery services, they are reliable and a trusted company to any individuals looking to recover lost money. Contact email [email protected] OR Telegram @Capitalcryptorecover Call/Text Number +1 (336)390-6684 his contact: [email protected] His website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 31.07.26 16:21 rssllhrnsb

    I learned an important lesson after investing in what appeared to be a genuine opportunity. Unfortunately, I was unable to access my funds, which reinforced the importance of carrying out thorough due diligence, checking whether an investment is appropriately regulated, and seeking qualified professional advice rather than relying solely on online reviews or testimonials. During the process of addressing my case, I worked with Mrs. Doris Ashley, who communicated clearly, provided regular updates, and handled the matter in a professional manner. According to my experience, I have recovered $50,000 so far, while efforts to resolve the remaining balance are still in progress. If you wish to contact her, the details I used are: Mrs. Tatiana Sorina
TEXT : (tatianasorina06 at G.Ma IL ..c 0 m ) Before committing money to any investment, take time to verify the legitimacy of the platform, confirm any relevant regulatory authorisations, and avoid investing more than you can comfortably afford to lose.

  • 01.08.26 15:05 keithwilson9899

    ETHEREUM RECOVERY ASSISTANCE: CAPITAL CRYPTO RECOVER HELPED ME RECOVER $98,000 WORTH OF LOST ETH In cases of cryptocurrency scams, having accurate information and trusted support is essential. I would like to recommend Capital Crypto Recover Service, a professional team that specializes in assisting individuals with the recovery of lost or stolen Bitcoin and Ethereum (ETH). Their experienced experts are dedicated to helping victims of digital asset fraud by carefully analyzing each case, developing strategic recovery plans, Capital Crypto Recover Service knowledgeable team's primary goals are to satisfy clients and offer significant support and working diligently toward fund retrieval. The team is committed to providing reliable assistance and maintaining a high level of client satisfaction. Based on my assessment, their reputation professionalism and a strong commitment to their clients. If you have experienced a cryptocurrency loss, you can contacting them for further assistance Phone (Call/Text): +1 (336) 390-6684 Email: [email protected] Alternate Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 01.08.26 15:05 keithwilson9899

    ETHEREUM RECOVERY ASSISTANCE: CAPITAL CRYPTO RECOVER HELPED ME RECOVER $98,000 WORTH OF LOST ETH In cases of cryptocurrency scams, having accurate information and trusted support is essential. I would like to recommend Capital Crypto Recover Service, a professional team that specializes in assisting individuals with the recovery of lost or stolen Bitcoin and Ethereum (ETH). Their experienced experts are dedicated to helping victims of digital asset fraud by carefully analyzing each case, developing strategic recovery plans, Capital Crypto Recover Service knowledgeable team's primary goals are to satisfy clients and offer significant support and working diligently toward fund retrieval. The team is committed to providing reliable assistance and maintaining a high level of client satisfaction. Based on my assessment, their reputation professionalism and a strong commitment to their clients. If you have experienced a cryptocurrency loss, you can contacting them for further assistance Phone (Call/Text): +1 (336) 390-6684 Email: [email protected] Alternate Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 03.08.26 20:05 Philip

    I was a victim of a crypto theft involving a Pink Drainer, which resulted in the theft of my Wrapped Bitcoin (WBTC) from my Polygon network. The experience was incredibly frustrating and distressing, as I had no idea how to recover my funds. Unfortunately, by the time I noticed the theft, the funds had already been drained to an address that I had no control over, making it seem like an irreversible situation.The attack happened when I clicked on what appeared to be a legitimate link. I didn’t realize at the time that it was a phishing attempt designed to siphon off my private keys and access my wallet. The Pink Drainer, a type of malicious script used by attackers, is specifically designed to exploit such vulnerabilities in crypto wallets. The moment I realized that my WBTC had been drained from my Polygon network. I felt completely helpless, as I didn’t have direct access to the thief's address, and there was no way to reverse the transaction on my own at that point, I started searching for ways to recover my funds, but most resources only offered generic advice that wasn’t practical in this particular case. I quickly realized that if I wanted to have any hope of getting my assets back, I would need professional assistance. After some research, I came across a reliable and trusted recovery team called Aspen Recovery Experts. Their expertise in cryptocurrency recovery, especially in cases like mine, seemed promising.I decided to reach out to Aspen Recovery Experts, and I’m incredibly grateful that I did. Their team of crypto recovery experts was able to help me trace the stolen funds and identify the path the funds took after they left my wallet. Using advanced tools and techniques, they were able to track the transactions on the blockchain, helping me understand where my WBTC had been sent. More importantly, they worked tirelessly to assist me in contacting the necessary parties and even interfaced with blockchain analysts to help facilitate the recovery process.Thanks to their efforts, I was able to successfully recover my stolen funds. The entire process took some time, but the Aspen Recovery Experts dedicated team provided regular updates and kept me informed throughout the process, which gave me a sense of hope and relief during an otherwise stressful time. If you’re ever in a similar situation, I highly recommend reaching out to a trusted recovery team like Aspen Recovery Expertshhh . Their professionalism, knowledge, and expertise were critical in helping me recover my funds and regain control of my crypto assets. Whatsapp : +1 747 231 9036 Telegram : @ prohackerspy Email : [email protected]

  • 03.08.26 20:06 Philip

    I was a victim of a crypto theft involving a Pink Drainer, which resulted in the theft of my Wrapped Bitcoin (WBTC) from my Polygon network. The experience was incredibly frustrating and distressing, as I had no idea how to recover my funds. Unfortunately, by the time I noticed the theft, the funds had already been drained to an address that I had no control over, making it seem like an irreversible situation.The attack happened when I clicked on what appeared to be a legitimate link. I didn’t realize at the time that it was a phishing attempt designed to siphon off my private keys and access my wallet. The Pink Drainer, a type of malicious script used by attackers, is specifically designed to exploit such vulnerabilities in crypto wallets. The moment I realized that my WBTC had been drained from my Polygon network. I felt completely helpless, as I didn’t have direct access to the thief's address, and there was no way to reverse the transaction on my own at that point, I started searching for ways to recover my funds, but most resources only offered generic advice that wasn’t practical in this particular case. I quickly realized that if I wanted to have any hope of getting my assets back, I would need professional assistance. After some research, I came across a reliable and trusted recovery team called Aspen Recovery Experts. Their expertise in cryptocurrency recovery, especially in cases like mine, seemed promising.I decided to reach out to Aspen Recovery Experts, and I’m incredibly grateful that I did. Their team of crypto recovery experts was able to help me trace the stolen funds and identify the path the funds took after they left my wallet. Using advanced tools and techniques, they were able to track the transactions on the blockchain, helping me understand where my WBTC had been sent. More importantly, they worked tirelessly to assist me in contacting the necessary parties and even interfaced with blockchain analysts to help facilitate the recovery process.Thanks to their efforts, I was able to successfully recover my stolen funds. The entire process took some time, but the Aspen Recovery Experts dedicated team provided regular updates and kept me informed throughout the process, which gave me a sense of hope and relief during an otherwise stressful time. If you’re ever in a similar situation, I highly recommend reaching out to a trusted recovery team like Aspen Recovery Expertshhh . Their professionalism, knowledge, and expertise were critical in helping me recover my funds and regain control of my crypto assets. Whatsapp : +1 747 231 9036 Telegram : @ prohackerspy Email : [email protected]

  • 04.08.26 11:05 Kisnoles

    Excellent analysis, thank you. I was particularly struck by how rigidly the skill sets the order: data processing and form come first, with color coming last. This really cures the habit of "first a pretty palette, then we'll figure it out." A palette validator using OKLCH + color blindness + WCAG is something most chart generators lack. And regarding the boundaries of competence, it's very clear. Where there's a self-checking loop (color), you delegate freely. Where there's a heuristic (form, data interpretation), you remain the final filter. This is a universal principle, not just for /dataviz. By the way, when you look at trading dashboards (including those of decent platforms like ExpertOption), it's immediately clear who thought about readability and who just threw in rainbow lines. Tools like this skill could greatly improve the quality of analytics. Thanks again for the detailed analysis – saved.

  • 04.08.26 12:37 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text Number: +1 (336) 390-6684

  • 04.08.26 12:37 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] Call/Text Number: +1 (336) 390-6684

  • 06.08.26 08:11 ROMMYHENDERSON344

    All you need is to hire an expert to help you accomplish that. If there's any need to spy on your partner's phone. From my experience I lacked evidence to confront my husband on my suspicion on his infidelity, until I came across REALCYBERHACKERS which many commend him of assisting them in their spying mission. So I contacted him and he provided me with access into his phone to view all text messages, call logs, WhatsApp messages and even her location. This evidence helped me move him off my life . I recommend you consult REALCYBERHACKERS AT gmail com or whatsapp +14106350697 if you need access to your partner's phone or any kind of hacking, they carry out all kinds of hacking job

  • 06.08.26 13:56 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/Text: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 06.08.26 13:56 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/Text: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 11.08.26 03:43 raymont0714

    I recommend a trusted cybersecurity PRO with experience in authorized device access, security testing, and data recovery. SHE work only with the owner's consent and follow all legal and privacy rules on meta data. With permission, this specialist can recover lost files, check device security offline & online, and review texts, call records, or hidden data (spy or lurk around a cheating partner or colleuge). Strict confidentiality agreements protect the information, and client details remain private. The work is careful, efficient, and suited to complex cases. For help securing or recovering information from a phone or another electronic device, use the details below 2 consult [email protected] +44 7476618364 I trust her secrecy a living witness. Her discretion is unmatched, ensuring your privacy is always maintained

  • 12.08.26 16:37 rssllhrnsb

    I learned an important lesson after investing in what appeared to be a genuine opportunity. Unfortunately, I was unable to access my funds, which reinforced the importance of carrying out thorough due diligence, checking whether an investment is appropriately regulated, and seeking qualified professional advice rather than relying solely on online reviews or testimonials. During the process of addressing my case, I worked with Mrs. Tatiana Sorina , who communicated clearly, provided regular updates, and handled the matter in a professional manner. According to my experience, I have recovered $50,000 so far, while efforts to resolve the remaining balance are still in progress. If you wish to contact her, the details I used are: Mrs. Tatiana Sorina
TEXT : (tatianasorina06 at G_Ma IL dot ..c 0 m)…. Before committing money to any investment, take time to verify the legitimacy of the platform, confirm any relevant regulatory authorisations, and avoid investing more than you can comfortably afford to lose.

  • 16.08.26 01:44 Matt Kegan

    CapitalNode Analytics. They help to investigate and recover stolen digital assets from fake trading platforms. Great firm i must say.

  • 18.08.26 04:59 marcushenderson624

    Bitcoin Recovery Testimonial After falling victim to a cryptocurrency scam group, I lost $354,000 worth of USDT. I thought all hope was lost from the experience of losing my hard-earned money to scammers. I was devastated and believed there was no way to recover my funds. Fortunately, I started searching for help to recover my stolen funds and I came across a lot of testimonials online about Capital Crypto Recovery, an agent who helps in recovery of lost bitcoin funds, I contacted Capital Crypto Recover Service, and with their expertise, they successfully traced and recovered my stolen assets. Their team was professional, kept me updated throughout the process, and demonstrated a deep understanding of blockchain transactions and recovery protocols. They are trusted and very reliable with a 100% successful rate record Recovery bitcoin, I’m grateful for their help and highly recommend their services to anyone seeking assistance with lost crypto. Contact: [email protected] Phone WhatsApp/Text Number: +1 (336) 390-6684 Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 18.08.26 04:59 marcushenderson624

    Bitcoin Recovery Testimonial After falling victim to a cryptocurrency scam group, I lost $354,000 worth of USDT. I thought all hope was lost from the experience of losing my hard-earned money to scammers. I was devastated and believed there was no way to recover my funds. Fortunately, I started searching for help to recover my stolen funds and I came across a lot of testimonials online about Capital Crypto Recovery, an agent who helps in recovery of lost bitcoin funds, I contacted Capital Crypto Recover Service, and with their expertise, they successfully traced and recovered my stolen assets. Their team was professional, kept me updated throughout the process, and demonstrated a deep understanding of blockchain transactions and recovery protocols. They are trusted and very reliable with a 100% successful rate record Recovery bitcoin, I’m grateful for their help and highly recommend their services to anyone seeking assistance with lost crypto. Contact: [email protected] Phone WhatsApp/Text Number: +1 (336) 390-6684 Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 19.08.26 14:50 BAYER7043

    My account was locked, and I couldn’t access my own information until [email protected] +447476618364 whats?up? helped me recover it. This lady hacker was kind and professional, but this experience showed me how risky account lockouts can be. If you’re facing the same problem, do not panic consult her A. S. A. P. Be careful with recovery agents outchea, and research their name, business, and reviews before sharing any details. Never send passwords, security codes, banking information, or copies of your ID unless you’ve confirmed who you’re dealing with. Be wary of promises that sound too good to be true, especially claims that require little information or guarantee instant access with outrageous fees.

  • 20.08.26 11:32 michaeldavenport218

    I was recently scammed out of $53,000 by a fraudulent Bitcoin investment scheme, which added significant stress to my already difficult health issues, as I was also facing cancer surgery expenses. Desperate to recover my funds, I spent hours researching and consulting other victims, which led me to discover the excellent reputation of Capital Crypto Recover, I came across a Google post It was only after spending many hours researching and asking other victims for advice that I discovered Capital Crypto Recovery’s stellar reputation. I decided to contact them because of their successful recovery record and encouraging client testimonials. I had no idea that this would be the pivotal moment in my fight against cryptocurrency theft. Thanks to their expert team, I was able to recover my lost cryptocurrency back. The process was intricate, but Capital Crypto Recovery's commitment to utilizing the latest technology ensured a successful outcome. I highly recommend their services to anyone who has fallen victim to cryptocurrency fraud. For assistance contact [email protected] and on Telegram OR WhatsApp Number +1 (336)390-6684 via email: [email protected] you can visit his website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 20.08.26 11:32 michaeldavenport218

    I was recently scammed out of $53,000 by a fraudulent Bitcoin investment scheme, which added significant stress to my already difficult health issues, as I was also facing cancer surgery expenses. Desperate to recover my funds, I spent hours researching and consulting other victims, which led me to discover the excellent reputation of Capital Crypto Recover, I came across a Google post It was only after spending many hours researching and asking other victims for advice that I discovered Capital Crypto Recovery’s stellar reputation. I decided to contact them because of their successful recovery record and encouraging client testimonials. I had no idea that this would be the pivotal moment in my fight against cryptocurrency theft. Thanks to their expert team, I was able to recover my lost cryptocurrency back. The process was intricate, but Capital Crypto Recovery's commitment to utilizing the latest technology ensured a successful outcome. I highly recommend their services to anyone who has fallen victim to cryptocurrency fraud. For assistance contact [email protected] and on Telegram OR WhatsApp Number +1 (336)390-6684 via email: [email protected] you can visit his website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 23.08.26 20:02 leslieyee

    Excellent analysis by /dataviz! I was particularly struck by how strictly the order is defined: "data meaning first, color last" and how the validator actually adjusts the palette according to OKLCH, color blindness, and WCAG standards. These rules greatly improve the quality of charts. By the way, a similar approach to clean and legible charts is highly valued in trading—for example, on the ExpertOption platform, the interface and price visualization are designed to ensure information is read instantly and without unnecessary noise.

  • 25.08.26 13:44 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 25.08.26 13:44 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 30.08.26 15:37 [email protected]

    Discovering I had been defrauded, I searched online for services claiming to recover stolen ETH. I contacted several companies, but none succeeded. Although some claimed they could trace assets or recover funds, I could not verify their success or recover my money. I later found SYLVESTER BRYANT Recovery through Google. After contacting him, he recovered 450,000,00. He can be reached at [email protected] or WhatsApp at +1 512 577 7957.

  • 30.08.26 15:37 [email protected]

    Discovering I had been defrauded, I searched online for services claiming to recover stolen ETH. I contacted several companies, but none succeeded. Although some claimed they could trace assets or recover funds, I could not verify their success or recover my money. I later found SYLVESTER BRYANT Recovery through Google. After contacting him, he recovered 450,000,00. He can be reached at [email protected] or WhatsApp at +1 512 577 7957.

  • 01.09.26 11:16 lisawerth897

    My Experience With Cryptocurrency — CAPITAL CRYPTO RECOVER I lost over $82,000 in Bitcoin after falling victim to a fraudulent online investment scheme. After realizing I had been scammed, I spent considerable time researching possible ways to recover my funds. During my research, I came across CAPITAL CRYPTO RECOVER and decided to contact them after reading their reported success record and encouraging client positive reviews and testimonials. Their team guided me through the recovery process, and I was grateful to successfully recover my lost cryptocurrency. The experience was challenging, but I appreciated the assistance and support I received throughout the process. I’m sharing my experience in the hope that it may encourage other victims to carefully research their options and verify any recovery service before proceeding. I will forever be thankful to you CAPITAL CRYPTO RECOVER 📧 [email protected] 🌐 Website: recovercapital.wixsite.com/capital-crypto-rec-1 📧 [email protected] 📞 Call/WhatsApp: +1 (336) 390-6684

  • 01.09.26 11:16 lisawerth897

    My Experience With Cryptocurrency — CAPITAL CRYPTO RECOVER I lost over $82,000 in Bitcoin after falling victim to a fraudulent online investment scheme. After realizing I had been scammed, I spent considerable time researching possible ways to recover my funds. During my research, I came across CAPITAL CRYPTO RECOVER and decided to contact them after reading their reported success record and encouraging client positive reviews and testimonials. Their team guided me through the recovery process, and I was grateful to successfully recover my lost cryptocurrency. The experience was challenging, but I appreciated the assistance and support I received throughout the process. I’m sharing my experience in the hope that it may encourage other victims to carefully research their options and verify any recovery service before proceeding. I will forever be thankful to you CAPITAL CRYPTO RECOVER 📧 [email protected] 🌐 Website: recovercapital.wixsite.com/capital-crypto-rec-1 📧 [email protected] 📞 Call/WhatsApp: +1 (336) 390-6684

  • 01.09.26 17:34 Garry42

    Really crazy world. These fraudsters go at any length to steal your hard earned funds. I have been a victim of a bitcoin scam about 7 months back. A Con artist gained access to my cashapp account through a phishing scam. They stole $409,000. I was really devastated. I did everything to get back my funds by contacting the FBI but they claimed there was nothing they could do. A friend told me about a recovery expert. He helps fight against various phishing and investment scams and they were able to help trace and recover my funds even though it took over 2 days. you can reach out to him through recoverydarek@gmail. com . I can guarantee his services are still active.

  • 01.09.26 17:34 Garry42

    Really crazy world. These fraudsters go at any length to steal your hard earned funds. I have been a victim of a bitcoin scam about 7 months back. A Con artist gained access to my cashapp account through a phishing scam. They stole $409,000. I was really devastated. I did everything to get back my funds by contacting the FBI but they claimed there was nothing they could do. A friend told me about a recovery expert. He helps fight against various phishing and investment scams and they were able to help trace and recover my funds even though it took over 2 days. you can reach out to him through recoverydarek@gmail. com . I can guarantee his services are still active.

  • 02.09.26 03:43 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] WhatsApp/Text Number: +1 (336) 390-6684

  • 02.09.26 03:43 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] WhatsApp/Text Number: +1 (336) 390-6684

  • 04.09.26 21:51 Kovengray

    Recovering your lost investment funds as the case might be, is not what you can do alone, you’d require the service of a trained recovery specialist. A recovery specialist is a person or a group of people who are well equipped to work around the brokerage network. They have vast knowledge about the whole network and have the right software and private keys to follow any transaction. I was ripped off trading online to an investment broker, good thing I got every penny back through the help of Gavin ray he’s a genius Contact : Gavinray78 at gmail com or WhatsApp +1 352 322 2096 It is also important to be patient and really calm during the process.

  • 05.09.26 21:38 [email protected]

    I invested 45,000  Euro, and later aggreviated to 198,000 Euro.  I requested  to place ‎Withdrawal of my funds to be paid to my Bank account. But nothing happened I was subjected to pay more fee until I can get my funds on my account, i got in touch with Theodore ryan here on this platform who had helped a lot of people, I followed all instructions and he legally got back my withheld funds, I got threatened by the company that if I don’t pay they will get my account frozen, all thanks to Theodore ryan and I highly recommend him to anyone dealing with an unregulated broker company… contact him on his Gmail - theodoreryan318@  gmail .  com

  • 09.09.26 21:31 lisawerth897

    My Experience With Cryptocurrency — CAPITAL CRYPTO RECOVER I lost over $82,000 in Bitcoin after falling victim to a fraudulent online investment scheme. After realizing I had been scammed, I spent considerable time researching possible ways to recover my funds. During my research, I came across CAPITAL CRYPTO RECOVER and decided to contact them after reading their reported success record and encouraging client positive reviews and testimonials. Their team guided me through the recovery process, and I was grateful to successfully recover my lost cryptocurrency. The experience was challenging, but I appreciated the assistance and support I received throughout the process. I’m sharing my experience in the hope that it may encourage other victims to carefully research their options and verify any recovery service before proceeding. I will forever be thankful to you CAPITAL CRYPTO RECOVER 📧 [email protected] 🌐 Website: recovercapital.wixsite.com/capital-crypto-rec-1 📧 [email protected] 📞 Call/WhatsApp: +1 (336) 390-6684

  • 09.09.26 21:31 lisawerth897

    My Experience With Cryptocurrency — CAPITAL CRYPTO RECOVER I lost over $82,000 in Bitcoin after falling victim to a fraudulent online investment scheme. After realizing I had been scammed, I spent considerable time researching possible ways to recover my funds. During my research, I came across CAPITAL CRYPTO RECOVER and decided to contact them after reading their reported success record and encouraging client positive reviews and testimonials. Their team guided me through the recovery process, and I was grateful to successfully recover my lost cryptocurrency. The experience was challenging, but I appreciated the assistance and support I received throughout the process. I’m sharing my experience in the hope that it may encourage other victims to carefully research their options and verify any recovery service before proceeding. I will forever be thankful to you CAPITAL CRYPTO RECOVER 📧 [email protected] 🌐 Website: recovercapital.wixsite.com/capital-crypto-rec-1 📧 [email protected] 📞 Call/WhatsApp: +1 (336) 390-6684

  • 09.09.26 23:22 Fraddy Pual

    Hearing that these individuals are focusing on other people makes me very sad. I had a similar situation with them and lost a lot of money, but after learning about (Cruxcipherteam @ proton DoT me), whataqq:+168160-15021, telegram: @Cruxcipherteam I was able to get my money back. It's critical that we all be watchful and keep reporting these occurrences.

  • 11.09.26 03:23 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] WhatsApp/Text Number: +1 (336) 390-6684

  • 11.09.26 03:23 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] WhatsApp/Text Number: +1 (336) 390-6684

  • 15.09.26 03:35 elioduncan

    I fell victim to a freelance web development contract scam that ultimately cost me CAD 4,000. It all started when I came across a job posting on Indeed Canada, a popular online job portal. The position seemed perfect: a freelance web developer role for an established company looking for someone to design and build a fully functional e-commerce website. The job promised a high payment of CAD 20,000 upon successful completion, which sounded like a great opportunity for me to gain experience and earn decent pay.The employer, who introduced himself as a project manager from a "well-known" tech company, was very persuasive and professional in our initial communication. He explained that the project involved developing a user-friendly, responsive online store for their client and that they had a strict timeline to meet. He assured me that the payment would be made promptly after completing the tasks. However, before starting the work, he told me that I would need to pay an upfront fee of CAD 4,000 to cover certain software tools and licensing fees required for the project. This was supposedly a part of their company policy for freelance contractors, ensuring access to their premium resources. The idea of working on a professional project, coupled with the promise of a substantial payout, convinced me to pay the upfront fee.As soon as I made the payment, the project manager became increasingly difficult to reach. He initially responded to my emails and provided some vague instructions on what the project would entail, but as time went on, communication slowed to a complete halt. I never received the required tools or any proper project details. My emails went unanswered, and any attempts to contact the company were met with silence. After waiting for weeks, I realized that I had been scammed.Desperate to recover my money, I turned to TechY Force Cyber Retrieval, a service that specializes in helping victims of online scams. They helped me track the payment and took legal steps to pursue the fraudsters. Through their guidance, I was able to recover the full CAD 4,000. TechY Force Cyber Retrieval worked with my bank to reverse the transaction and liaised with the authorities to trace the scammer's details.This was a hard lesson, and I now know to be highly cautious about online job offers that require upfront payments. It is crucial to research companies thoroughly and avoid any job that seems too good to be true, especially when it involves paying money upfront. WhatsApp https://wa.link/2x6ktp Mail. [email protected]

  • 15.09.26 15:45 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 15.09.26 15:45 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 05.10.26 21:26 [email protected]

    I Invested 45,000  Euro, and later aggreviated to 198,000 Euro.  I requested  to place Withdrawal of my funds to be paid to my Bank account. But nothing happened I was subjected to pay more fee until I can get my funds on my account, i got in touch with Theodore ryan here on this platform who had helped a lot of people, I followed all instructions and he legally got back my withheld funds, I got threatened by the company that if I don’t pay they will get my account frozen, all thanks to Theodore ryan and I highly recommend him to anyone dealing with an unregulated broker company… contact him on his Gmail - theodoreryan318@  gmail .  com

  • 06.10.26 06:13 melissathomason573

    Professional Crypto Recovery Testimonial After losing a significant amount of cryptocurrency through a scam on Twitter, I was unsure whether my Bitcoin funds could ever be recovered. The experience was extremely stressful, particularly because I encountered several individuals and services claiming they could help recover my assets, only to discover that some were fraudulent themselves. A friend eventually referred me to CAPITAL CRYPTO RECOVER. Their team handled my case professionally, discreetly, and efficiently. With their assistance, I successfully recovered approximately $130,000 worth of USDT in just over a week. My experience taught me the importance of being extremely cautious when seeking cryptocurrency recovery services, as scammers often target victims a second time. I am grateful to CAPITAL CRYPTO RECOVER for the assistance I received and wanted to share my experience with others who may be facing a similar situation. If you’ve been compromised, don’t lose hope—and be careful of fraudsters posing as saviors. CAPITAL CRYPTO RECOVER are real professionals in crypto recovery. I am a living proof of their effectiveness, you can reach them through Phone (Call/WhatsApp): +1 (336) 390-6684 Email: [email protected] Alternate Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 06.10.26 06:13 melissathomason573

    Professional Crypto Recovery Testimonial After losing a significant amount of cryptocurrency through a scam on Twitter, I was unsure whether my Bitcoin funds could ever be recovered. The experience was extremely stressful, particularly because I encountered several individuals and services claiming they could help recover my assets, only to discover that some were fraudulent themselves. A friend eventually referred me to CAPITAL CRYPTO RECOVER. Their team handled my case professionally, discreetly, and efficiently. With their assistance, I successfully recovered approximately $130,000 worth of USDT in just over a week. My experience taught me the importance of being extremely cautious when seeking cryptocurrency recovery services, as scammers often target victims a second time. I am grateful to CAPITAL CRYPTO RECOVER for the assistance I received and wanted to share my experience with others who may be facing a similar situation. If you’ve been compromised, don’t lose hope—and be careful of fraudsters posing as saviors. CAPITAL CRYPTO RECOVER are real professionals in crypto recovery. I am a living proof of their effectiveness, you can reach them through Phone (Call/WhatsApp): +1 (336) 390-6684 Email: [email protected] Alternate Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 06.10.26 17:44 Darrell1717

    I fell victim of a scam I invested to total of 5thousand into. I know it could be risky but after I trusted this man I was dating online he lured me into investing with him. I know hard I worked of my money so I wanted every way possible to get it back. I really appreciate Blockrecoveryexpert for successfully recovered my funds form this scammer. This is all I can say. You can reachout if you ever need help contact blockrecoveryexpert (at) gmail (dot)com

  • 11.10.26 03:04 Patricia014

    Most recovery companies will take your money again. I personally think they’re the same set of people running all of them. It’s a sad, unending cycle, and so many people fall for cloned websites. The only recovery agent I know is Agent Rottgen Raphael. I’ve visited their physical company address, and they’ll tell you if they can handle your case instead of taking upfront payment when they know they can’t help. I highly appreciate their support in recovering my money from the scammers’ wallet within 24 hours. RottgenRaphael@Gmail. com

  • 12.10.26 19:34 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 12.10.26 19:34 lydiassmith567

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 13.10.26 14:14 lisalisa22

    Legitimate Cryptocurrency Recovery Services: Consult ZEUS CRYPTO RECOVERY SERVICES Zeus Crypto Recovery Services supports individuals exploring options after cryptocurrency losses from fraud, unauthorised transfers, or wallet access issues. Services may include blockchain analysis, wallet tracing, and evidence gathering for investigations. Each case is reviewed. Zeus Crypto Recovery Services is a trusted company with the highest success rate among cryptocurrency recovery services in 2025/2026 and is highly recommended if you have been scammed. ZEUS CRYPTO RECOVERY SERVICES handles case such as Scammed USDT Lost BTC, Coinbase Wallet Forgotten password, ETH and coins, etc. Anything that has to do with cryptocurrency or lost digital assets, ZEUS can help you Do you Need Help? Website https://zeusrecoveryservices.com Mailbox [email protected] WhatsApp number +447798816938 Telegram https://t.me/Zeuscryptorecoveryservices

  • 13.10.26 14:14 lisalisa22

    Legitimate Cryptocurrency Recovery Services: Consult ZEUS CRYPTO RECOVERY SERVICES Zeus Crypto Recovery Services supports individuals exploring options after cryptocurrency losses from fraud, unauthorised transfers, or wallet access issues. Services may include blockchain analysis, wallet tracing, and evidence gathering for investigations. Each case is reviewed. Zeus Crypto Recovery Services is a trusted company with the highest success rate among cryptocurrency recovery services in 2025/2026 and is highly recommended if you have been scammed. ZEUS CRYPTO RECOVERY SERVICES handles case such as Scammed USDT Lost BTC, Coinbase Wallet Forgotten password, ETH and coins, etc. Anything that has to do with cryptocurrency or lost digital assets, ZEUS can help you Do you Need Help? Website https://zeusrecoveryservices.com Mailbox [email protected] WhatsApp number +447798816938 Telegram https://t.me/Zeuscryptorecoveryservices

  • 17.10.26 12:58 melissathomason573

    Professional Crypto Recovery Testimonial After losing a significant amount of cryptocurrency through a scam on Twitter, I was unsure whether my Bitcoin funds could ever be recovered. The experience was extremely stressful, particularly because I encountered several individuals and services claiming they could help recover my assets, only to discover that some were fraudulent themselves. A friend eventually referred me to CAPITAL CRYPTO RECOVER. Their team handled my case professionally, discreetly, and efficiently. With their assistance, I successfully recovered approximately $130,000 worth of USDT in just over a week. My experience taught me the importance of being extremely cautious when seeking cryptocurrency recovery services, as scammers often target victims a second time. I am grateful to CAPITAL CRYPTO RECOVER for the assistance I received and wanted to share my experience with others who may be facing a similar situation. If you’ve been compromised, don’t lose hope—and be careful of fraudsters posing as saviors. CAPITAL CRYPTO RECOVER are real professionals in crypto recovery. I am a living proof of their effectiveness, you can reach them through Phone (Call/WhatsApp): +1 (336) 390-6684 Email: [email protected] Alternate Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 17.10.26 12:58 melissathomason573

    Professional Crypto Recovery Testimonial After losing a significant amount of cryptocurrency through a scam on Twitter, I was unsure whether my Bitcoin funds could ever be recovered. The experience was extremely stressful, particularly because I encountered several individuals and services claiming they could help recover my assets, only to discover that some were fraudulent themselves. A friend eventually referred me to CAPITAL CRYPTO RECOVER. Their team handled my case professionally, discreetly, and efficiently. With their assistance, I successfully recovered approximately $130,000 worth of USDT in just over a week. My experience taught me the importance of being extremely cautious when seeking cryptocurrency recovery services, as scammers often target victims a second time. I am grateful to CAPITAL CRYPTO RECOVER for the assistance I received and wanted to share my experience with others who may be facing a similar situation. If you’ve been compromised, don’t lose hope—and be careful of fraudsters posing as saviors. CAPITAL CRYPTO RECOVER are real professionals in crypto recovery. I am a living proof of their effectiveness, you can reach them through Phone (Call/WhatsApp): +1 (336) 390-6684 Email: [email protected] Alternate Email: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 24.10.26 03:16 lxbfYeaa

    e

  • 24.10.26 03:16 lxbfYeaa

    e

  • 24.10.26 03:16 lxbfYeaa

    e

  • 24.10.26 03:16 lxbfYeaa

    e

  • 24.10.26 03:23 lxbfYeaa

    e

  • 24.10.26 03:23 lxbfYeaa

    e

  • 24.10.26 03:24 lxbfYeaa

    e

  • 25.10.26 14:35 lydiasmitth456

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 25.10.26 14:35 lydiasmitth456

    HIRE A HACKER YOUR STOLEN CRYPTO RECOVERY / BTC / USDT / ETH WITH THE HELP OF CAPITAL CRYPTO RECOVER. I want to share my experience publicly regarding cryptocurrency wallet recovery, I highly recommend you to contact CAPITAL CRYPTO RECOVER, a professional private investigator in the Bitcoin world. They have a certified expert security team specializing in Bitcoin Recovery Services and have helped many people worldwide recover their lost funds. My wife and I were defrauded by an online manipulator posing as an experienced crypto investment professional. We lost $9.2 Million Stolen BTC in cryptocurrency and were left feeling homeless. After spending hours searching for a reliable crypto recovery service, I discovered CAPITAL CRYPTO RECOVER online. By patiently explaining my situation to their team, I was able to recover all my funds. Remarkably, my money was returned to my wallet in less than 24 hours. I am extremely grateful to CAPITAL CRYPTO RECOVER for their excellent assistance—they truly were a godsend in my difficult situation. If you have fallen victim to a cryptocurrency scam, you can reach CAPITAL CRYPTO RECOVER through the following channels Email: [email protected] OR Call/WhatsApp: +1 (336) 390-6684 Contact: [email protected] Website: https://recovercapital.wixsite.com/capital-crypto-rec-1

  • 01:58 KATHLEEN

    Cyberspacetechexpert focuses on recovering stolen cryptocurrency, particularly USDT and bitcoin. She is well-known for helping victims of digital asset theft. Her reputation arises from successful recoveries that have allowed many to regain their lost funds. I witnessed this when $74,000 was taken from me in January. Thanks to the best female hacker Gracias, I recovered the entire amount in just 14 hours. Her prompt response and effective methods relieved my financial burden. Her commitment to helping others is evident. She is always available to offer solutions to those facing similar problems. For assistance, she can be reached via email Cyberspacetechexpert@gmail .com. or speak to her on What App at + 44 7476618364.

  • 02:22 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] WhatsApp/Text Number: +1 (336) 390-6684

  • 02:22 kimberlyhebertt6877

    I invested in bitcoin trading After losing $78.4 USDT) linked to a romance fraud scam worth of cryptocurrency through an online investment platform and later discovered it was a scam. After extensive research for recovery options, I contacted CAPITAL CRYPTO RECOVER based on positive client reviews and recommendations. Their professional security team guided me through the recovery process using advanced technology, and I was able to recover my lost cryptocurrency successfully. I am truly grateful for their support and assistance during such a difficult experience. I will advise you to contact CAPITAL CRYPTO RECOVER helped me recover my funds. For anyone facing similar issues, Website: https://recovercapital.wixsite.com/capital-crypto-rec-1 Email: [email protected] Telegram: @Capitalcryptorecover Contact: [email protected] WhatsApp/Text Number: +1 (336) 390-6684

  • 02:25 KATHLEEN

    Cyberspacetechexpert focuses on recovering stolen cryptocurrency, particularly USDT and bitcoin. She is well-known for helping victims of digital asset theft. Her reputation arises from successful recoveries that have allowed many to regain their lost funds. I witnessed this when $74,000 was taken from me in January. Thanks to the best female hacker Gracias, I recovered the entire amount in just 14 hours. Her prompt response and effective methods relieved my financial burden. Her commitment to helping others is evident. She is always available to offer solutions to those facing similar problems. For assistance, she can be reached via email Cyberspacetechexpert@gmail .com. or speak to her on What App at + 44 7476618364.

Для участия в Чате вам необходим бесплатный аккаунт pro-blockchain.com Войти Регистрация
Есть вопросы?
С вами на связи 24/7
Help Icon