Измерение расстояния с помощью GPS, запрограммированного на Arduino

Кто из присутствующих пробовал измерять пройденное расстояние до и после с помощью GPS? Я буду использовать код из команды Distance_between библиотеки TinyGPS без постоянных значений широты и долготы,

вот так:

static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002

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

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

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
Этот пример кода демонстрирует обычное использование объекта TinyGPS++ (TinyGPSPlus).
Он требует использования SoftwareSerial и предполагает, что у вас есть
Устройство GPS с последовательным интерфейсом 4800 бод, подключенное к контактам 4 (rx) и 3 (tx).
*/
 static const int RXPin = 4, TXPin = 3;
 static const uint32_t GPSBaud = 4800;

  // Объект TinyGPS++
TinyGPSPlus gps;

 // Последовательное соединение с устройством GPS
SoftwareSerial ss(RXPin, TXPin);

void setup()
{
 Serial.begin(115200);
 ss.begin(GPSBaud);

     Serial.println(F("FullExample.ino"));
     Serial.println(F("An extensive example of many interesting     TinyGPS++ features"));
  Serial.print(F("Testing TinyGPS++ library v. "));                    Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
  Serial.println(F("Sats HDOP Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars     Sentences Checksum"));
     Serial.println(F("          (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
           Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));
}

void loop()
{
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ?        TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);

  unsigned long distanceKmToLondon =
   (unsigned long)TinyGPSPlus::distanceBetween(
     gps.location.lat(),
     gps.location.lng(),
     LONDON_LAT, 
     LONDON_LON) / 1000;
     printInt(distanceKmToLondon, gps.location.isValid(), 9);

     double courseToLondon =
    TinyGPSPlus::courseTo(
     gps.location.lat(),
     gps.location.lng(),
     LONDON_LAT, 
     LONDON_LON);

   printFloat(courseToLondon, gps.location.isValid(), 7, 2);

   const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

   printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

   printInt(gps.charsProcessed(), true, 6);
   printInt(gps.sentencesWithFix(), true, 10);
   printInt(gps.failedChecksum(), true, 9);
   Serial.println();

   smartDelay(1000);

   if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
   }

  // Эта пользовательская версия delay() гарантирует, что объект GPS
  // "кормят".
  static void smartDelay(unsigned long ms)
  {
  unsigned long start = millis();
  do 
  {
   while (ss.available())
    gps.encode(ss.read());
    } while (millis() - start < ms);
    }

    static void printFloat(float val, bool valid, int len, int prec)
     {
   if (!valid)
   {
    while (len-- > 1)
    Serial.print('*');
    Serial.print(' ');
    }
    else
    {
   Serial.print(val, prec);
   int vi = abs((int)val);
   int flen = prec + (val < 0.0 ? 2 : 1); // . и -
   flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
   for (int i=flen; i<len; ++i)
   Serial.print(' ');
   }
   smartDelay(0);
  }

 static void printInt(unsigned long val, bool valid, int len)
 {
  char sz[32] = "*****************";
  if (valid)
  sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
   sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
  }

  static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
  {
  if (!d.isValid())
   {
   Serial.print(F("********** "));
   }
   else
   {
   char sz[32];
   sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
   Serial.print(sz);
    }

    if (!t.isValid())
    {
    Serial.print(F("******** "));
    }
    else
    {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
    }

    printInt(d.age(), d.isValid(), 5);
    smartDelay(0);
    }

    static void printStr(const char *str, int len)
    {
    int slen = strlen(str);
    for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
    smartDelay(0);
    }

, 👍0


2 ответа


1

Вот тут и появляются эти ужасные уроки математики.

Вы знаете, те, на которые никто не обращал внимания, потому что вы думали: "Где в реальном мире я когда-нибудь захочу это знать?" Что ж, именно здесь вы хотели бы узнать об этом.

Расстояние между двумя точками на двумерной плоскости (например, на карте) можно рассматривать как две вершины прямоугольного треугольника.

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

В языке C такие вычисления выполнить довольно просто. Вы можете найти X и Y, вычитая две долготы и масштабируя их для логарифмической окружности Земли, где вы находитесь. Вы можете сделать широты аналогичным образом:

float X = ((long2 - long1) * 24901 * cos(lat1)) / 360.0
float Y = ((lat2 - lat1) * 24860) / 360.0

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

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

float X2 = X * X;
float Y2 = Y * Y;

Тогда вы можете получить квадратный корень:

float Distance = sqrt(X2 + Y2);

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

О, и код полностью, если хотите:

float X = ((long2 - long1) * 24901 * cos(lat1)) / 360.0
float Y = ((lat2 - lat1) * 24860) / 360.0
float X2 = X * X;
float Y2 = Y * Y;
float Distance = sqrt(X2 + Y2);
,

Это хорошо, но вдоль разных линий широты расстояние не одинаково для заданного угла, даже для идеальной сферы. 15 градусов у полюсов короче 15 градусов у экватора. Я думаю, что он должен вычислить длину дуги, чтобы получить X, используя ((long2 - long1)*2*pi*Earth radius*cos (lat1))/360 и Y можно получить аналогичным образом, за исключением того, что косинус не должен присутствовать, @SoreDakeNoKoto

@Majenko Спасибо, что поделились своей блестящей идеей, но я уже пытался это сделать, и, к сожалению, это не сработает, поскольку мы знали, что Земля не идеально сферическая. Я пытаюсь понять, как мне найти расстояние, исходя из технической формы Земли. Пожалуйста, смотрите указанное выше., @Georgina Pattinson

Д'О, ты совершенно прав. Я совершенно упустил это из виду. Я обновлю ответ утром., @Majenko

Если вы собираетесь использовать длину окружности, то в уравнении не должно быть 2*pi; это уже часть окружности, @SoreDakeNoKoto

@TisteAndii Еще рано, и я еще не сделал свой первый глоток кофе. Опять же, совершенно верно., @Majenko

Эх, к сожалению кофе здесь не при чем :(, @SoreDakeNoKoto


0

Меня всегда раздражало отсутствие двойного (64-битного) типа в мире Arduino и, следовательно, проблемы с правильным вычислением расстояния, азимута и точки назначения по GPS.

В следующей библиотеке используется Float64 & Math64 libs, а также добавляет несколько быстрых и очень быстрых реализаций тригонометрических функций, а также быстрые и обычные версии GPS расстояния, азимута и точки назначения GPS.

Не стесняйтесь использовать его — и любая помощь в его улучшении приветствуется!

https://github.com/vtomanov/Gps64

,