(C)
Aswin - блогер из Дании, регулярно публикующий свои заметки на блоге NXT Time. Недавно опубликовал очень интересный материал - он показал, как с помощью двух датчиков расстояния (он использовал стандартные NXT Ultrasonic датчики) можно с допустимой точностью определить местоположение предмета. Для определения местоположения как раз и использовался метод триангуляции.
В качестве экспериментальной установки он использовал следующую конструкцию:

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

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

Аналогичную формулу легко можно получить и для другого датчика. Следует отметить, что моторы в лабораторном устройстве, установлены таким образом не случайно - это немного позволяет упростить программу - при таком расположении они будут поворачивать датчик ровно на то значение угла, которое определяется формулой.
Автор также делиться видео, демонстрирующим, что его подход работает:
Есть мнение, что подобный подход используется в роботе "Глазастик", подготовленный для Международной Робототехнической Олимпиады командой ФМЛ №239 г. Санкт-Петербург.
Но вернемся, к первоначальному устройству... Хотя автор и использует язык программирования Java для программирования своей лабораторной установки, код достаточно прост для понимания и может быть легко интерпретирован в другие языки программирования. Единственное, нужно отметить, что в виртуальная машина leJOS, используемая автором на NXT блоке, предоставляет продвинутые средства для использования сенсора расстояния - в ней есть автоматическая фильтрация показаний, так что в программу уже поступают более "надежные" показания.
![]() | Понятие триангуляция знакомо многим, кто хоть раз разбирался как работают GPS приемникиили тем, кто изучал что такое радиопеленгация. На самом деле это понятие пришло из геометрии и геодезии. Но сейчас пойдет речь именно о триангуляции, как способе определения координат или местоположении предмета. |
В качестве экспериментальной установки он использовал следующую конструкцию:


Автор также делиться видео, демонстрирующим, что его подход работает:
Есть мнение, что подобный подход используется в роботе "Глазастик", подготовленный для Международной Робототехнической Олимпиады командой ФМЛ №239 г. Санкт-Петербург.
Но вернемся, к первоначальному устройству... Хотя автор и использует язык программирования Java для программирования своей лабораторной установки, код достаточно прост для понимания и может быть легко интерпретирован в другие языки программирования. Единственное, нужно отметить, что в виртуальная машина leJOS, используемая автором на NXT блоке, предоставляет продвинутые средства для использования сенсора расстояния - в ней есть автоматическая фильтрация показаний, так что в программу уже поступают более "надежные" показания.
package lejos.nxt.sensor.example;
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.Motor;
import lejos.nxt.NXTRegulatedMotor;
import lejos.nxt.SensorPort;
import lejos.nxt.sensor.filter.AdditionFilter;
import lejos.nxt.sensor.sensor.LcUltrasonic;
import lejos.util.Delay;
public class TwoUSSensors {
// Коэффициент для П-регулятора, управляющего моторами
static final int P=5;
// Погрешность измерения
static final double MARGIN=0.8;
// Максимальное расстояние определения
static final float MAXRANGE=150;
// Минимальный угол, на который могут повернуться сенсоры, чтобы не попасть
// в зону видимости друг друга
static final int MINANGLE=25;
// Дистанция между двумя сенсорами - измеряется от осей мотора
static final double b=20.5;
// Смещение датчика от оси мотора
static final float SENSOROFFSET=2.5f;
// Инициализация датчиков и фильтров
static final LcUltrasonic sensorA=new LcUltrasonic(SensorPort.S1);
static final LcUltrasonic sensorC=new LcUltrasonic(SensorPort.S4);
static final AdditionFilter corrrectedA=new AdditionFilter(sensorA,SENSOROFFSET);
static final AdditionFilter corrrectedC=new AdditionFilter(sensorC,SENSOROFFSET);
static final NXTRegulatedMotor C=Motor.C;
static final NXTRegulatedMotor A=Motor.A;
// Место запуска основной программы
public static void main(String[] args) {
Object run=new TwoUSSensors();
}
public TwoUSSensors() {
double targetC=0, targetA=0;
double a,c;
// Перевести датчики в режим PING (single shot)
// подробнее на http://nxttime.wordpress.com/2012/09/12/the-ultrasonic-sensor/
sensorA.setMode(LcUltrasonic.MODE_PING);
sensorC.setMode(LcUltrasonic.MODE_PING);
// Перевести датчики в начальное положение
C.rotateTo(90, true);
A.rotateTo(90, false);
Delay.msDelay(500);
// Выполнять программу до нажатия кнопки
while(!Button.ESCAPE.isDown()) {
// Получить данные от датчиков
c=corrrectedA.fetchSample();
a=corrrectedС.fetchSample();
LCD.clear();
LCD.drawString(" A C", 0, 0);
LCD.drawString("dist", 0, 1);
LCD.drawString("dist'", 0, 2);
LCD.drawString("target", 0, 3);
LCD.drawString("error", 0, 4);
LCD.drawString("state", 0, 5);
LCD.drawInt((int) c, 7, 1);
LCD.drawInt((int) a, 12, 1);
if (a>MAXRANGE && c> MAXRANGE) {
// Датчики ничего не видят перед собой
targetA = Math.PI/2;
targetC = Math.PI/2;
LCD.drawString("-", 7, 5);
LCD.drawString("-", 12, 5);
}
else {
// Есть предмет в области видимости датчиков.
// Исходя из правила что a+c>b можно определить видят датчики
// два разных предмета или один
if (Math.abs(a-c)>b*MARGIN) {
// Датчики видят два разных предмета - выбираем ближайший
if (a<c) {
// Ближайший перед датчиком С
LCD.drawString("-", 7, 5);
LCD.drawString("+", 12, 5);
targetC =Math.toRadians(C.getPosition());
// расстояние от датчика А до предмета
c = Math.sqrt(a*a+b*b-2*a*b*Math.cos(targetC));
targetA = Math.acos((a*a-b*b-c*c)/(-2*c*b));
}
else {
// Ближайший перед датчиком A
LCD.drawString("+", 7, 5);
LCD.drawString("-", 12, 5);
targetA =Math.toRadians(A.getPosition());
// расстояние от датчика А до предмета
a=Math.sqrt(b*b+c*c-2*b*c*Math.cos(targetA));
targetC =Math.acos((c*c-a*a-b*b)/(-2*a*b));
}
LCD.drawInt((int) c, 7, 2);
LCD.drawInt((int) a, 12, 2);
}
else {
// Датчики видят один предмет
LCD.drawString("+", 7, 5);
LCD.drawString("+", 12, 5);
targetC =Math.acos((c*c-a*a-b*b)/(-2*a*b));
targetA =Math.acos((a*a-b*b-c*c)/(-2*c*b));
}
}
LCD.drawInt((int) Math.toDegrees(targetA),7,3);
LCD.drawInt((int) Math.toDegrees(targetC),12,3);
// К какой позиции нужно повернуть моторы
LCD.drawInt(rotateTo(A, targetA),7,4);
LCD.drawInt(rotateTo(C, targetC),12,4);
Delay.msDelay(20);
}
// Перед окончанием программы - вернуться в начальное положение
A.setSpeed(200);
C.setSpeed(200);
C.rotateTo(0, true);
A.rotateTo(0, false);
Delay.msDelay(500);
}
// Функция поворота двигателя на заданную позицию. Поворот выполняется через
// регулирование мощности на моторе. Чем ближе требуемая позиция, тем меньше мощность.
int rotateTo(NXTRegulatedMotor motor,double target){
int targetDeg=(int) Math.toDegrees(target);
if (targetDeg<MINANGLE) target=MINANGLE;
int error=targetDeg-motor.getPosition();
if (Math.abs(error)<=1) return error;
motor.setSpeed(error*P);
motor.rotateTo(targetDeg, true);
return error;
}
Комментариев нет:
Отправить комментарий