Перейти к содержанию
Fire Monkey от А до Я
  • 0

TLocationSensor - километраж


Alex Bakulin

Вопрос

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

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Модераторы

встроенных нету, по прямой можно рассчитать так

function GetDistance(const aStart, aEnd: TMapCoordinate): Real;
const
  Radius = 6372795;
  PiDiv180 = Pi / 180;
var
  CosLatStart, SinLatStart, CosLatEnd, SinLatEnd, Delta, CosDelta, SinDelta, X, Y: Real;
begin
  try
    CosLatStart := Cos(aStart.Latitude * PiDiv180);
    CosLatEnd := Cos(aEnd.Latitude * PiDiv180);
    SinLatStart := Sin(aStart.Latitude * PiDiv180);
    SinLatEnd := Sin(aEnd.Latitude * PiDiv180);
    Delta := (aEnd.Longitude * PiDiv180) - (aStart.Longitude * PiDiv180);
    CosDelta := Cos(Delta);
    SinDelta := Sin(Delta);
    Y := Sqrt(((CosLatEnd * SinDelta) * (CosLatEnd * SinDelta)) + ((CosLatStart * SinLatEnd - SinLatStart * CosLatEnd * CosDelta)
      * (CosLatStart * SinLatEnd - SinLatStart * CosLatEnd * CosDelta)));
    X := SinLatStart * SinLatEnd + CosLatStart * CosLatEnd * CosDelta;
    Result := Round(ArcTan2(Y, X) * Radius);
  except
    Result := MaxSingle; // сравнивать с MaxSingle, вдруг ошибка произошла
  end;
end;

 

Ссылка на комментарий
  • 0

Спасибо, примерно так и считаю сейчас, но точность не устраивает. Просто сидя на месте можно "намотать" не одну сотню метров, видимо за счет погрешности измерения. Вообще есть еще мысль при каждом OnLocationChange прибавлять к счетчику Distance метров, но боюсь, что работать не будет корректно по той же причине....

Ссылка на комментарий
  • 1

погрешность измерения GPS 10-15 метров в идеальных условиях. нередки случаи и 50-100

соответственно, при каждом измерении размах отклонения может достигнуть (погрешность * 2) м

можно считать это встроенным свойством системы ))

Ссылка на комментарий
  • 0
В 17.04.2017 в 05:57, krapotkin сказал:

можно считать это встроенным свойством системы ))

Я считаю, что это недоработка Embarcadero. У меня работает с такой же погрешностью. А вот приложения на JAVA (язык, который я ненавижу) работают гораздо точнее.

Ссылка на комментарий
  • 0
В 17.04.2017 в 05:57, krapotkin сказал:

погрешность измерения GPS 10-15 метров в идеальных условиях. нередки случаи и 50-100

соответственно, при каждом измерении размах отклонения может достигнуть (погрешность * 2) м

можно считать это встроенным свойством системы ))

У меня есть предположение, что сенсор ловит кроме GPS координаты от телефонных вышек.

Ссылка на комментарий
  • 1

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

даже известные ему WiFi точки берет

пока спутники не нашлись

Ссылка на комментарий
  • 0

Разработал расчетный модуль.
На вход этого модуля подаются:
1. Географические координаты точки назначения X (далее: положение).
2. Положение текущей точки A.
3. Положение предыдущей точки B.
На выходе этого модуля:
1. Угол между AB и AX (<XAB).
2. Угол между AB и истинным (можно и магнитным) Северным полюсом. Направление на СП вычисляется динамически - без компаса.
3. Расстояние по прямой AB (между двумя замерами).
4. Расстояние по прямой AX до точки назначения.
Дал этому модулю 16 контрольных заданий, с которыми он успешно справился!

Соединил этот модуль с GPS-примником. И тут началось!
Задаю положение точки направления. Иду под открытым небом в этом направлении.
Показания этого модуля скачут со страшной силой.
Бывают показания и верными, но редко.

То, что здесь предлагал Равиль Зарипов, на современные телефоны не устанавливается (Android 10). 
Здеcь на форумах предлагалось сделать некий фильтр, который отсекал бы резкие изменения по дистанции. Кроме этого можно добавить фильтр от резкого изменения азимута.Только что здесь понимать под "резкими изменениями".
А программы на JAVA успешно работают без этих прибамбасов.

Может кто знает решение этой проблемы без танцев с бубномна сегодня?
 

Ссылка на комментарий
  • 0

Еще раз о километраже.

Простейшая формула для расчета расстояния по прямой (по дуге большого круга планеты) вот такая
cosduga:=(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(long2 – long1)); //(1)
km:= 6371 * arccos(cosduga);
В ней:
lat1, long1 - широта и долгота точки отправления (прибытия) в радианах
lat2, long2 - широта и долгота точки прибытия (отправления) в радианах
южные широты и западные долготы берутся со знаком минус.

Напомню, что эту формулу можно вывести двумя способами:
1. через чертежи трехгранного угла.
2. через скалярное произведение векторов

Кому этой формулы достаточно - просто вставьте ее в свою программу без заморочек. Она будет работать. Только перед нахождением arccos необходимо предотвратить возможную машинную ошибку, которая обязательно моежет возникнуть, если cosduga, например, будет 1.000000001
cosduga:=min(cosduga,1);
cosduga:=max(cosduga,-1);

"Беда" в том, что эта формула привязана ТОЛЬКО к истинному Северному полюсу.
Можно воспользоваться другой формулой, которая открывает гораздо большие возможности, чем вычисление расстояния.
Сейчас покажу другой способ вычисления расстояния.
Здесь fi - широта, lamda - долгота в радианах.
южные широты и западные долготы берутся со знаком минус.
Поехали.

Следующие шесть строк оформить подпрограммой.

x1:=cos(fi1)*cos(lamda1);
y1:=sin(fi1)*cos(lamda1);
z1:=sin(lamda1);

x2:=cos(fi2)*cos(lamda2);
y2:=sin(fi2)*cos(lamda2);
z2:=sin(lamda2);

cosduga:=x1*x2+y1*y2+z1*z2;// из этой формулы можно получить формулу (1)
cosduga:=min(cosduga,1);
cosduga:=max(cosduga,-1);

km:=arccos(cosduga)/(2*3.1415926)*40000;

Ссылка на комментарий
  • 0
4 часа назад, krapotkin сказал:

пока спутники не нашлись

А Вам знакомо приложение Locus? Там как только устаналивается связь со спутниками, загорается зеленый значок. А спутники видны сразу даже до установления связи с ними.

Ссылка на комментарий
  • 1

тут написано, что проблема сложная и не решается в лоб

https://android-developers.googleblog.com/2020/12/improving-urban-gps-accuracy-for-your.html

можно попробовать оставить только  Manifest.permission.ACCESS_FINE_LOCATION  и исключить Manifest.permission.ACCESS_COARSE_LOCATION

чтобы попадали только данные со спутников 

но вот тут написано, что в современных ОС вы должны это запрашивать, и не факт что получите

https://developer.android.com/training/location/permissions

Ссылка на комментарий
  • 0
2 часа назад, krapotkin сказал:

тут написано, что проблема сложная и не решается в лоб

Текст по ссылкам я обязательно изучу. Попробобовал пока с манифестом. Чем дальше, тем страшнее.

До моего сообщения о скачках (Android 10) манифест был по умоланию, без этих строк. При этом в меню Android для этого приложения я мог руками настроить доступ этого приложения к Wi-Fi и к мобильному интернету.

Затем я добавл в манифест permission.ACCESS_FINE_LOCATION.  В меню Android возможность настройки доступа пропала. Мое приложение, похоже, стало выдавть верные данные настолько, насколько я не на улице, а хожу по комнате. Утром проверю на улице.

Зато доступ этого приложения к интернету пропал. А в дальнейшем мне этот доступ из приложения будет нужен.

Ссылка на комментарий
  • 0
В 26.08.2023 в 00:48, Саша сказал:

Утром проверю на улице.

После всех изменений в манифесте проверил на улице. Работает чуточку лучше. Возможно, что идет отражение сигнала от домов. Остается еще попробовать установить ActivitiType в Navigation.

 

PS

Стою в открытом поле на месте. Скачки и по расстоянию (до 38 метров) и по азимуту. Либо спутники так видят, либо TLocationSensor в Embarcadero работает калечно.

Изменено пользователем Саша
Дополнение
Ссылка на комментарий
  • 1
8 часов назад, Саша сказал:

TLocationSensor в Embarcadero работает калечно

Так и есть, используй слушатель (LocationListener) или по таймеру запрашивайте местоположение по java.

Ссылка на комментарий
  • 0
5 минут назад, OnePeople сказал:

Так и есть, используй слушатель (LocationListener) или по таймеру запрашивайте местоположение по java.

Спасибо! Но я не знаю, что такое LocationListener. Мне сейчас хотябы со службой разобраться. В виндовсе службы идут как по масмлу, а  андроиде труба. А как состтыковаьб JAVA и Delphi - для меня темный лес.

Ссылка на комментарий
  • 0
10 минут назад, Саша сказал:

В виндовсе службы идут как по масмлу, а  андроиде труба.

В итоге мне нужно приложение такой структуры.

Хост - с моим расчетным модулем, описанным здесь 8 постов выше. Сервис - который В ПОТОКЕ периодически запрашивает метоположение и передает его хосту. Причем, Сервис это должен делать и при неактивном хосте, так как сервис еще кроме этого  должен передавать местоположение на FTP - сервер.

Ссылка на комментарий
  • 1

несмотря на то что все хотят сделать из телефона GPS трекер с фоновым опросом, Google и производители кастомных оболочек хором говорят "хрена вам"

поэтому нужен целый комплекс мероприятий

вот гитхаб по словам GPS Delphi

https://github.com/gilsondelima/GPS-SENSOR-ANDROID

а вот статья про сервисы

https://habr.com/ru/companies/usetech/articles/754756/

Ссылка на комментарий
  • 1
  TMyLocatioListner = class(TJavaLocal, JLocationListener)
  private
    [weak] FParent : TForm1;
  public
    constructor Create(AParent : TForm1);
    Destructor Destroy; Override;
    procedure onFlushComplete(requestCode: Integer); cdecl;
    procedure onLocationChanged(Location: Jlocation); overload; cdecl;
    procedure onLocationChanged(Location: JList); overload; cdecl;
    procedure onProviderDisabled(Provider: JString); cdecl;
    procedure onProviderEnabled(Provider: JString); cdecl;
    procedure onStatusChanged(provider: JString; status: Integer; extras: JBundle); cdecl;
   end;

constructor TMyLocatioListner.Create(AParent : TForm1);
begin
     inherited Create;
     FParent := AParent;
end;

destructor TMyLocatioListner.Destroy;
begin
 //
  inherited;
end;

procedure TMyLocatioListner.onFlushComplete(requestCode: Integer);
begin
//
end;

procedure TMyLocatioListner.onLocationChanged(Location: JList);
begin
 //
end;

procedure TMyLocatioListner.onLocationChanged(Location: Jlocation);
begin
//
end;

procedure TMyLocatioListner.onProviderDisabled(Provider: JString);
begin
   //
end;

procedure TMyLocatioListner.onProviderEnabled(Provider: JString);
begin
  //
end;

procedure TMyLocatioListner.onStatusChanged(provider: JString; status: Integer;
  extras: JBundle);
begin
   //
end;


   try
    LocationListner:= TMyLocatioListner.Create(Self);
    LocationManagerObject := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);
    if LocationManagerObject <> nil then
      LocationManager := TJLocationManager.Wrap((LocationManagerObject as ILocalObject).GetObjectID);
    if LocationManager <> nil then
      LocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 0, 0, LocationListner, TJLooper.JavaClass.getMainLooper);
    except
     LogCAAdd('LocationListner except ');
   end;

2 способ

   try
    LocationListner:= TMyLocatioListner.Create(Self);
    LocationManagerNative := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);
    if LocationManagerNative <> nil then
      LocationManager := TJLocationManager.Wrap((LocationManagerNative as ILocalObject).GetObjectID);
    if LocationManager <> nil then
      LocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 0, 0, LocationListner, TJLooper.JavaClass.getMainLooper);
    except
     LogCAAdd('LocationListner except ');
   end;

   if LocationManager <> nil then
     begin
       criteria := TJCriteria.JavaClass.init;
       criteria.setSpeedAccuracy(TJCriteria.JavaClass.ACCURACY_HIGH);
       criteria.setAccuracy(TJCriteria.JavaClass.ACCURACY_FINE);
       criteria.setAltitudeRequired(true);
       criteria.setBearingRequired(true);
       criteria.setSpeedRequired(true);
       if  locationManager.isProviderEnabled(TJLocationManager.JavaClass.GPS_PROVIDER) = false then
         begin
            Intent := TJIntent.Create;
            Intent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_LOCATION_SOURCE_SETTINGS);
            TAndroidHelper.Activity.startActivity(Intent);
         end;
     end;


            provider := locationManager.getBestProvider(criteria, true);
            location := LocationManager.getLastKnownLocation(provider);
            if location <> nil then
              begin
                dLatitude := location.getLatitude;
                dLongitude := location.getLongitude;
                dBearing := location.getBearing;

 

Изменено пользователем OnePeople
Ссылка на комментарий
  • 0
19 часов назад, krapotkin сказал:

несмотря на то что все хотят сделать из телефона GPS трекер с фоновым опросом, Google и производители кастомных оболочек хором говорят "хрена вам"

А производители кастомных оболочек не боятся, что их пошлют на хрен? У меня есть информация, что Play Market не размещает у себя приложения, которые вычисляют местоположение в ФОНОВОМ режиме. Но такие проиложения можно разрабатывать в своих интересах. А если хочешь продавать такие программы, то это можно делать и минуя Play Market: посвящай свой сайт этой программе и продавай.

Ссылка на комментарий
  • 0
3 минуты назад, krapotkin сказал:

чувствуется, что статью по ссылке вы не читали )

Статью еще не изучал, но закладки провел у себя крассной нитью. В ближайшее время ОБЯЗАТЕЛЬНО изучу. Столько много информации приходится лопатить на эту тему, что даже не знаю с чего начать.

Ссылка на комментарий
  • 0
В 28.08.2023 в 20:21, krapotkin сказал:

чувствуется, что статью по ссылке вы не читали )

Статью изучил досканально. Палки в колеса конкретные!

В 29.08.2023 в 06:45, OnePeople сказал:

Вообще бы не парились

Скачал. Ошибки при компиляции: не хватает некоторых файлов, но с этим буду разбираться. А вот в FMX, которые там в USES не хватает каких то методов. Но там, похоже, файлы пропатченные.

На днях проехал 500 км. Испытывал свой сенсор. Помехи есть, но пока терпимые. Помехи уменьшились после совета krapotkin. В своем приложении сделал возможность настраивать Distance и Accuracy. И менял их в разных комбинациях. У сенсора на эти настройки ноль эмоций, фунт презренья. И при Distance=1  и при Distance=500 (при разных Accuracy) расстояние между замерами 15-28 метров. Скорость движения при этом была 70-95 км/ч.

А вопрос такой: есть ли возможность получать координаты с сенсора принудительно, а не ждать, пока сработает LocationChanged?

 

 

Ссылка на комментарий
  • 0
27 минут назад, krapotkin сказал:

в мобильных системах в принципе не будет синхронных операций

все через подписку на события

Спасибо! А тут еще может быть неприятная ситуация при расчете скорости. Работа кода внутри LocationChanged занимает какое-то время, хотя и мизерное.  Может ли сработать сенсор еще раз, пока не отработал кода внутри LocationChanged? Может быть придется использовать какой-то флаг,  по которому будет выполнятся exit на входе этого события до тех пор, пока не отработает хвост? То есть аналогично тому, как блокируют повторный запуск потока.

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...