Встроенная цифровая карта для управления роботом

Итак, я создаю этот проект для школы. Это простой робот с Arduino MEGA 2560, и в основном я создаю цифровую карту, загружаю ее в программу Arduino, и тогда робот может управлять. Тем не менее, я столкнулся с некоторыми проблемами, пытаясь реализовать свою идею. Ошибки синтаксического анализа в основном. И я хочу знать, есть ли другой подход.

Итак, на данный момент моя цифровая карта работает следующим образом:

С помощью C# и Visual Studio IDE я создал программу, с помощью которой я могу создать карту. По сути, я создаю соединения (линии/дороги), и соединение имеет начальную и конечную точки, срединную точку и метку (что это такое). Итак, каждый токен информации о подключении выглядит примерно так:

"Соединение[x1: 0, y1: 0|x2: 13, y2: 0|xm: 6,5, ym: 0|метка: Ничего]" "Соединение[x1: 13, y1: 0|x2: 13, y2: 28|xm: 13, ym: 14|метка: библиотека]"

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

Изменить:

Что касается реализации и хранения карты, то она такая:

Итак, у меня есть класс Vertex. Это в основном эквивалент точки и хранения (x, y) значений.

class Vertex {
  public:
    int x;
    int y;

    Vertex(int _x, int _y) {
       x = _x;
       y = _y;
    }
};

Тогда есть класс соединения. Он хранит начальную вершину, конечную вершину, срединную вершину и метку (строку). Вот так:

class Connection {
  Vertex v1();
  Vertex v2();
  Vertex median();
  String label;

  public:
    Connection(Vertex _v1, Vertex _v2, Vertex _median, String _label) {
        v1() =  Vertex(_v1.x, _v1.y);
        v2() =  Vertex(_v2.x, _v2.y);
        median() = Vertex(_median.x, _median.y);
        String label = _label;
  }
};

И, наконец, есть класс карты, в котором пользователь передает информационные маркеры, созданные моим приложением для создания карт, созданным в Visual Studio, и это работает следующим образом:

#include "Connection.h"

class Map {
  public:
    Map(string infoTokens[]) {
      //Я импортирую информационные токены сюда.
    }

    void drawMap(MCUFRIEND_kbv tft, String ) {
      //Это совсем другая функция, она просто для рисования карты
        on top of the TFT screen that I have on my robot.
    }

    void driveTo(Vertex rP, String destinationLabel) {
      //Здесь я вожу своего робота, когда пользователь просит перейти в
        destination and provides the label.
    }
};

Что касается импорта информационных токенов (информации карты), я просто выполняю некоторые манипуляции со строками, например, на этом "Соединение[x1: 0, y1: 0|x2: 13, y2: 0|xm: 6,5, ym: 0|метка: Ничего]" и получить всю информацию в требуемых типах данных. Что касается импорта, это ничего не меняет, потому что я много раз проверял свою функцию (не представленную здесь), и она работает блестяще. Мой вопрос заключается в том, как использовать эту информацию для управления роботом.

, 👍0

Обсуждение

Вы хотите дать роботу команду «перейти к позиции 6, 3» или «добраться до библиотеки» (последний использует метку вместо физического местоположения)?, @chrisl

А вам нужна кратчайшая связь с целью через вашу уличную сеть?, @chrisl

Я хочу, чтобы он использовал команду «перейти к позиции 6,3», так как это было бы более полезно. И да, реализация кратчайшего возможного расстояния была бы отличной идеей., @Gaurav Mall

Не могли бы вы показать реализацию вашего объекта класса, чтобы мы могли увидеть, как хранятся данные?, @chrisl

Добавил запрошенную вами информацию. Надеюсь, это то, что вам нужно, и может дать мне решение. Спасибо!, @Gaurav Mall


1 ответ


Лучший ответ:

1

Вы смогли создать пользовательскую структуру данных из своей строки, но кажется, что соединения, хранящиеся в классе Map, не связаны. Таким образом, карта на самом деле не представляет структуру «уличной» сети. Я бы предложил другой подход:

Вместо определения соединений вы можете определить узлы вашей сети (где встречаются 2 или более улиц). Для каждого узла вы сохраняете позицию (x, y) (или экземпляр вашего класса вершин), метку (например, «библиотека») и массив указателей на другие объекты узла. В коде это может выглядеть так (я не упомянул методы):

class Node {
    Vertex pos;
    char label[25];
    Node *connections[6];
}

Экскурсия: Если вы не знаете, что такое указатели в C/C++, вот краткое введение. Вам определенно следует больше узнать об этом в Интернете.

Переменная-указатель содержит адрес другой переменной в ОЗУ. Вы можете изменить этот адрес и позволить указателю указывать на другую переменную. Переменная помечается как указатель знаком * в объявлении. Вы можете получить адрес переменной (для установки указателя на эту переменную) через оператор &: pointer = &variable . Если вы разыменовываете указатель (написав * перед именем указателя), вы можете работать со значением, на которое указывает указатель. Каждая переменная-указатель имеет тип. Это тип объекта, на который он указывает. Объявление указателя int *var позволяет var указывать на переменные int. Если типом является class или struct и вы хотите получить доступ к членам цели (куда она указывает), вы можете использовать сокращенную версию pointer-> ;участник.


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

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

Класс Map может содержать массив Nodes. Вы можете перебрать все узлы в массиве, если вам нужно, или вы можете пройти через сеть с помощью указателей.


Фактический алгоритм поиска пути с наименьшим расстоянием перемещения здесь сильно выходит за рамки. Сделать это эффективно может быть сложной задачей. Вы можете изучить эти алгоритмы в Интернете. Самый простой способ — протестировать все различные пути в вашей программе (фактически не перемещая робота), сохранить необходимое расстояние для каждого пути, а затем выбрать путь на основе этого. Вам нужно будет написать условие завершения, чтобы ни одно соединение не выполнялось дважды по одному и тому же пути (что означало бы какой-то цикл). Также имейте в виду, что для этого потребуется все больше и больше времени вычислений по мере роста вашей сети. Если он остается небольшим и вам не нужны очень быстрые вычисления, этого может быть достаточно. Если ваша реализация является рекурсивной, вы также должны учитывать, что каждая рекурсия занимает память в стеке. Вы не хотите выходить из памяти.

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

,

Большое спасибо. Именно то, что мне нужно. Я застрял в попытке реализовать идею, основанную исключительно на координатах, и закончил ничем. Это было именно то решение, которое я искал. Спасибо!, @Gaurav Mall