Применение триангуляции к модели движения ТС по маршруту
Реализация алгоритмов треангуляционного позиционирования объекта
Введение
В рамках данного раздела реализовано три вида алгоритмов треангуляции - три подхода к решению задачи треангуляции.
-
Суммарно-дальномерный подход
- Реализован в модели
test_classic.engee
- Реализован в модели
-
Разностно-дальномерный подход
- Реализован в модели
test_diff.engee
- Реализован в модели
-
Квази-дальномерный подход
- Реализован в модели
test_classic_time_corr.engee
- Реализован в модели
Все блоки, реализованные для данных моделей добавлены в nglib - пользовательскую библиотеку, так что при желании их можно удобно использовать в других моделях.
Реализованы блоки:
-
Для каждого из трех подходов расчет положения объекта на основании входных данных - расстояния до вышек в метрах (при желании легко использовать для расстояний в секундах на
C- скорость света) -
Псевдо-датчик расстояния от объекта до вышки
-
Блок оценки ошибки

Рассмотрим эти модели.
test_classic.engee

test_diff.engee

test_classic_time_corr.engee

Блоки выполнены при помощи маскированных блоков engee а также engee function, внутри которых реализован алгоритм на языке julia
Построим графики моделирования
Суммарно-Дальномерный
sim_model = engee.load("$(@__DIR__)/test_classic.engee", force=true)
res = engee.run(sim_model)
engee.close(sim_model)
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",
)
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="Ошибки"
)
Разностно-Дальномерный
sim_model = engee.load("$(@__DIR__)/test_diff.engee", force=true)
res = engee.run(sim_model)
engee.close(sim_model)
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",
)
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="Ошибки"
)
Квази-Дальномерный
sim_model = engee.load("$(@__DIR__)/test_classic_time_corr.engee", force=true)
res = engee.run(sim_model)
engee.close(sim_model)
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",
)
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="Ошибки"
)
Мы наблюдаем ограниченные скачки относительных (rel) ошибок в областях пересечения координатой нуля. Это ожидаемое поведение, данный выброс учитывать не нужно.
Таким образом алгоритмы прошли первые тесты, и их можно опробовать на реальной модели
Сборка модели беспилотного карьерного ТС
Соберем модель карьерного ТС. Рассмотрим файл vehicle_dynamics_test.engee Входами данной модели являются сигналы воздействия на рулевое колесо и на педаль газа/тормоза (в данной модели это один сигнал). Проведем моделирование на базовых ступенчатых воздействиях.
Поведение модели зависит от сохраненных данных карты. для данного примера возьмем карту - ровную поверхность 100м x 100м Добавим параметры при помощи обратных вызовов модели.


sim_model = engee.load("$(@__DIR__)/vehicle_dynamics_test.engee", force=true)
engee.run(sim_model)
engee.close(sim_model)
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
)
Сборка модели системы управления для беспилотного карьерного ТС
Соберем систему управления для карьерного беспилотного ТС. Модель управления вместе с моделью ТС реализована в файле simple_veh_model.engee. Рассмотрим ее.

Модель состоит из нескольких частей. Выдача маршрута - на основании данных карты, заданного маршрута и текущего положения ТС. Управление рулевым колесом, на основании выдаваемого маршрута и управление скоростью (разгон и торможение) на основании выдаваемого маршрута и сигнала рулевого управления.
Смоделируем движение транспортного средства по маршруту, представляющему собой диагональ на плоскости. В начальный момент времени ТС располагается в левом верхнем углу и стоит по направлению влево.
Проведем моделирование данной системы. Увидим, что реальная траектория движения ТС сходится к желаемой. При этом системе также присуща и колебательность.
sim_model = engee.load("$(@__DIR__)/simple_veh_model.engee", force=true)
engee.run(sim_model)
engee.close(sim_model);
pos_vect_route = collect(pos_by_route).value
plot(
map(x->x[1], pos_vect_route),
map(x->x[3], pos_vect_route),
map(x->x[2], pos_vect_route),
lw=2, color=:red
)
plot!(
route[:, 1],
route[:, 2],
[1.31 for _=1:length(route[:, 1])],
lw=1, color=:blue
)
Моделирование движения ТС по данным от триангуляционных датчиков
Интегрируем систему расчета положения объекта в модель ТС и его САУ.
Расположим вышки с четырех сторон плоскости. Передадим так называемой подсистеме, отвечающей за выдачу маршрута не истинное значение положения объекта, получаемое от модели ТС, а значение, рассчитанное на основании данных с псевдо-датчиков расстояний до вышек и алгоритмов триангуляции.
Рассмотрим модель simple_veh_model_with_positioning.engee

Проведем моделирование данной системы с тремя видами датчиков.
В виду того, что нужно менять блоки для симуляции, выполним запуск симуляции при помощи GUI интерфейса, здесь же приведем только графики, наложив также график движения не использующий данные алгоритмы. Также предположим, что данные с вышек зашумлены из-за разного рода техинических ограничений
Суммарно-дальномерный подход
Будем выбирать высокую точность поиска для визуализации возможных систематических ошибок алгоритмов позиционирования.
# pos_vect_1 = collect(pos_by_sensors).value
plot(
map(x->x[1], pos_vect_1),
map(x->x[3], pos_vect_1),
map(x->x[2], pos_vect_1),
lw=2, color=:red
)
plot!(
map(x->x[1], pos_vect_route),
map(x->x[3], pos_vect_route),
map(x->x[2], pos_vect_route),
color=:blue
)
plot(sum.(abs.(pos_vect_1 .- pos_vect_route)), title="Отклонение от траектории")
Разностно-дальномерный
# pos_vect_2 = collect(pos_by_sensors).value
plot(
map(x->x[1], pos_vect_2),
map(x->x[3], pos_vect_2),
map(x->x[2], pos_vect_2),
lw=2, color=:red
)
plot!(
map(x->x[1], pos_vect_route),
map(x->x[3], pos_vect_route),
map(x->x[2], pos_vect_route),
color=:blue
)
plot(sum.(abs.(pos_vect_2 .- pos_vect_route)), title="Отклонение от траектории")
Квази-дальномерный
pos_vect_3 = collect(pos_by_sensors).value
plot(
map(x->x[1], pos_vect_3),
map(x->x[3], pos_vect_3),
map(x->x[2], pos_vect_3),
lw=2, color=:red
)
plot!(
map(x->x[1], pos_vect_route),
map(x->x[3], pos_vect_route),
map(x->x[2], pos_vect_route),
color=:blue
)
plot(sum.(abs.(pos_vect_3 .- pos_vect_route)), title="Отклонение от траектории")
Итог
Проведя моделирование получили схожие графики ошибок. Это означает что ошибка возникает в первую очередь из-за шума, и только во вторую - из-за ошибок, связных с точностью алгоритма. больше всего шум влияет на точность позиционирования при квази-дальномерном подходе.
Моделирование по реальному маршруту реальной карты карьера
Проведем аналогичное моделирование для модели карьерного ТС воспользовавшись картой реального карьера. Расположим вышки по углам карьера.
Для движения модели по более сложному маршруту нужно усовершенствовать логику управления и эмуляцию шумов.
- Добавим шумы в каждый сигнал с вышки отдельно
- Каждый ПИ регулятор снабдим логикой сброса чтобы избежать накопления ошибки от предыдущих звеньев маршрута
- Передадим карту в нужные блоки через импортирование файла во внутрь с использованием пользовательского написание структуры engee function.
Также стоит заметить, что координаты для вышек переданы в соответствии с внутренней системой координат объекта.

Выберем следующее расположение вышек для суммарно-дальномерного подхода к задаче триангуляции
|
№ |
X |
Y |
Z |
|
1 |
-460 |
-460 |
40 |
|
2 |
-460 |
460 |
20 |
|
3 |
460 |
-460 |
20 |
|
4 |
460 |
460 |
60 |
include("$(@__DIR__)/tower_params.jl")
include("$(@__DIR__)/map_params.jl")
include("$(@__DIR__)/car_params.jl");
sim_model = engee.load("$(@__DIR__)/simple_veh_model_with_positioning.engee", force=true)
engee.run(sim_model)
engee.close(sim_model)
Получим график измерений с датчиков положения объекта при движении объекта (карьерного ТС) по маршруту, ориентируясь на показания датчиков
pos_vect_4 = collect(pos_by_sensors).value[1:10:end]
plot(
map(x->x[1], pos_vect_4),
map(x->-x[3], pos_vect_4),
map(x->x[2], pos_vect_4),
lw=4, color=:red
)