Сообщество Engee

Применение триангуляции к модели движения ТС по маршруту

Автор
avatar-bogoslmbogoslm
Notebook

Реализация алгоритмов треангуляционного позиционирования объекта

Введение

В рамках данного раздела реализовано три вида алгоритмов треангуляции - три подхода к решению задачи треангуляции.

  • Суммарно-дальномерный подход

    • Реализован в модели test_classic.engee
  • Разностно-дальномерный подход

    • Реализован в модели test_diff.engee
  • Квази-дальномерный подход

    • Реализован в модели test_classic_time_corr.engee

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

Реализованы блоки:

  • Для каждого из трех подходов расчет положения объекта на основании входных данных - расстояния до вышек в метрах (при желании легко использовать для расстояний в секундах на C - скорость света)

  • Псевдо-датчик расстояния от объекта до вышки

  • Блок оценки ошибки

Снимок экрана 2025-11-18 в 19.05.16.png
Рассмотрим эти модели.

test_classic.engee

Снимок экрана 2025-11-18 в 19.00.53.png

test_diff.engee

Снимок экрана 2025-11-18 в 19.06.55.png

test_classic_time_corr.engee

Снимок экрана 2025-11-18 в 19.08.19.png

Блоки выполнены при помощи маскированных блоков engee а также engee function, внутри которых реализован алгоритм на языке julia

Построим графики моделирования
In [ ]:
m = engee.load("$(@__DIR__)/test_classic.engee", force=true)
res = engee.run(m)
engee.close(m)
In [ ]:
plot(
    collect(res.dict["calc_x"]).value,
    collect(res.dict["calc_y"]).value,
    collect(res.dict["calc_z"]).value,
    lw = 2, color=:red, label="calc_traj"
)
plot!(
    collect(res.dict["x_true.1"]).value,
    collect(res.dict["y_true.1"]).value,
    collect(res.dict["z_true.1"]).value,
    lw = 1, color=:blue, label="real_traj",
)
Out[0]:
In [ ]:
plot(
    collect(res.dict["abs_x"]).value, label="abs_x"
)
plot!(
    collect(res.dict["abs_y"]).value, label="abs_y"
)
plot!(
    collect(res.dict["abs_z"]).value, label="abs_z"
)
plot!(
    collect(res.dict["rel_x"]).value, label="rel_x"
)
plot!(
    collect(res.dict["rel_y"]).value, label="rel_y"
)
plot!(
    collect(res.dict["rel_z"]).value, label="rel_z",
    title="Ошибки"
)
Out[0]:
In [ ]:
m = engee.load("$(@__DIR__)/test_diff.engee", force=true)
res = engee.run(m)
engee.close(m)
In [ ]:
plot(
    collect(res.dict["x_calc"]).value,
    collect(res.dict["y_calc"]).value,
    collect(res.dict["z_calc"]).value,
    lw = 2, color=:red, label="calc_traj"
)
plot!(
    collect(res.dict["x"]).value,
    collect(res.dict["y"]).value,
    collect(res.dict["z"]).value,
    lw = 1, color=:blue, label="real_traj",
)
Out[0]:
In [ ]:
plot(
    collect(res.dict["abs_x"]).value, label="abs_x"
)
plot!(
    collect(res.dict["abs_y"]).value, label="abs_y"
)
plot!(
    collect(res.dict["abs_z"]).value, label="abs_z"
)
plot!(
    collect(res.dict["rel_x"]).value, label="rel_x"
)
plot!(
    collect(res.dict["rel_y"]).value, label="rel_y"
)
plot!(
    collect(res.dict["rel_z"]).value, label="rel_z",
    title="Ошибки"
)
Out[0]:
In [ ]:
m = engee.load("$(@__DIR__)/test_classic_time_corr.engee", force=true)
res = engee.run(m)
engee.close(m)
In [ ]:
plot(
    collect(res.dict["calc_x"]).value,
    collect(res.dict["calc_y"]).value,
    collect(res.dict["calc_z"]).value,
    lw = 2, color=:red, label="calc_traj"
)
plot!(
    collect(res.dict["x_true.1"]).value,
    collect(res.dict["y_true.1"]).value,
    collect(res.dict["z_true.1"]).value,
    lw = 1, color=:blue, label="real_traj",
)
Out[0]:
In [ ]:
plot(
    collect(res.dict["abs_x"]).value, label="abs_x"
)
plot!(
    collect(res.dict["abs_y"]).value, label="abs_y"
)
plot!(
    collect(res.dict["abs_z"]).value, label="abs_z"
)
plot!(
    collect(res.dict["rel_x"]).value, label="rel_x"
)
plot!(
    collect(res.dict["rel_y"]).value, label="rel_y"
)
plot!(
    collect(res.dict["rel_z"]).value, label="rel_z",
    title="Ошибки"
)
Out[0]:

Мы наблюдаем ограниченные скачки относительных (rel) ошибок в областях пересечения координатой нуля. Это ожидаемое поведение, данный выброс учитывать не нужно.

Итог

Алгоритмы прошли первые тесты, и их можно опробовать на реальной модели

Сборка модели беспилотного карьерного ТС

Соберем модель карьерного ТС первого порядка. Рассмотрим файл vehicle_dynamics_test.engee Входами данной модели являются сигналы воздействия на рулевое колесо и на педаль газа/тормоза (в данной модели это один сигнал). Проведем моделирование на базовых ступенчатых воздействиях.

Поведение модели зависит от сохраненных данных карты. для данного примера возьмем карту - ровную поверхность 100м x 100м Добавим параметры при помощи обратных вызовов модели.

Снимок экрана 2025-11-18 в 19.43.36.png
Снимок экрана 2025-11-18 в 19.43.48.png
In [ ]:
m = engee.load("$(@__DIR__)/vehicle_dynamics_test.engee", force=true)
engee.run(m)
engee.close(m)
In [ ]:
pos_vect = collect(pos).value

plot(
    map(x->x[1], pos_vect),
    map(x->x[3], pos_vect), 
    map(x->x[2], pos_vect),
    lw=2, color=:red
)
Out[0]: