27.06.2019 Добавление новых сигналов в RTKLIB

Материал из SRNS
Перейти к: навигация, поиск
(Этапы решения)
 
(не показаны 32 промежуточные версии 3 участников)
Строка 1: Строка 1:
 
<summary [ hidden ]>
 
<summary [ hidden ]>
L2 и L5 в nvs.c.
+
[[File:Experiment22.png|center|400px]]
 +
 
 +
Поддержка сигналов L2С и L5 в nvs.c
 
</summary>
 
</summary>
 +
[[File:4287338.jpg|right|200px]]
 +
 +
 +
= Как добавить новые сигналы в nvs.c? =
 +
 +
В статье описан процесс добавления новых сигналов в RTKLIB.
  
{{TOCright}}
 
  
= Это моя статья =
 
 
==Постановка задачи==
 
==Постановка задачи==
Возможности RTKNAVI позволяют отображать сигналы L2С и  L5 - единственным препятствием для этого являлось отсутствие необходимого кода в обрабатывающем фале nvs.c. Проблема решалась в несколько этапов.  
+
 
[[File:Number1.png|400px]]
+
Возможности RTKNAVI позволяют отображать сигналы L2С и  L5 - единственным препятствием для этого являлось отсутствие необходимого кода в обрабатывающем файле nvs.c.  
==Задача и подзадачи==
+
 
# Был изучен протокол информационного взаимодействия СРНС. Конкретно интерес представлял пакет F5, т.к. содержит информацию о типах сигналов. В протоколе эти типы представлены в виде шестнадцатерничных значений, однако , чтобы программа смогла "опознать" соответствующие типы, их необходимо перевести в децимальную систему счисления. Выполняя это простое преобразование, нетрудно убедиться, что сигналу L2C соответствует значение 34, а сигналу L5 - 66. Далее полученные значения добавляются в условие соответствующего цикла, отвечающего за идентификацию навигационных сигналов систем ГЛОНАСС и GPS. На этом этапе программа может "отличить" (но пока не показать!) сигналы L2C и L5 от сигналов системы ГЛОНАСС.  
+
Проблема решалась в несколько этапов c использовнием IDE Embarcadero RAD Studio.
 +
 
 +
[[File:Number1.png|center|1000px]]
 +
 
 +
==Этапы решения==
 +
 
 +
Был изучен протокол информационного взаимодействия NVS BINR с принятым у нас в лаборатории расширением списка сигналов.
 +
 
 +
Конкретно интерес представлял пакет F5, т.к. содержит информацию о типах сигналов. В протоколе эти типы представлены в виде шестнадцатеричных значений, однако , чтобы программа смогла "опознать" соответствующие типы, их необходимо перевести в децимальную систему счисления.  
 +
Выполняя это простое преобразование, нетрудно убедиться, что сигналу L2C соответствует значение 34, а сигналу L5 - 66. Далее полученные значения добавляются в условие соответствующего цикла, отвечающего за идентификацию навигационных сигналов систем ГЛОНАСС и GPS.  
 +
 
 +
На этом этапе программа может "отличить" (но пока не показать! Как добиться их отображения рассказано ниже) сигналы L2C и L5 от сигналов системы ГЛОНАСС.  
  
 
<source lang=C>for (i=0,p+=27;(i<nsat) && (n<MAXOBS); i++,p+=30) {
 
<source lang=C>for (i=0,p+=27;(i<nsat) && (n<MAXOBS); i++,p+=30) {
Строка 16: Строка 33:
 
sys = (U1(p)==1 || U1(p)==33)?SYS_GLO:((U1(p)==2 || U1(p)==34 ||U1(p)==66)?SYS_GPS:((U1(p)==4)?SYS_SBS:SYS_NONE)); </source>
 
sys = (U1(p)==1 || U1(p)==33)?SYS_GLO:((U1(p)==2 || U1(p)==34 ||U1(p)==66)?SYS_GPS:((U1(p)==4)?SYS_SBS:SYS_NONE)); </source>
  
# Теперь же возникла другая подзадача - необходимо, чтобы L2C и L5 и L1 могли идентифицироваться и впоследствии отображаться независимо друг от друга. В предыдущей версии программы стояла аналогичная проблема с разделением сигналов L1С/А и L2OF для системы ГЛОНАСС.  Там она была решена введением воспомогательной переменной "bandnum", которая принимала значение, равное 1 исключительно при поступлении типа сигнала L2OF и нулевые при всех остальных. В текущей задаче можно использовать эту переменную для идентификации L2C, поэтому достаточно лишь дополнить условие, при котором переменная принимает единичное значение. Теперь она принимает это значение уже при для двух типов сигналов '''разных''' навигационных систем. Далее выполняем аналогичные действия для сигнала L5 и вводим воспомогательную перменную "initnum", которая принимает значение 2 (почему именно 2 будет сказано ниже).
+
 
 +
Теперь же возникла другая подзадача - необходимо, чтобы L2C и L5 и L1 могли идентифицироваться и впоследствии отображаться независимо друг от друга.  
 +
 
 +
В предыдущей версии программы стояла аналогичная проблема с разделением сигналов L1OF и L2OF для системы ГЛОНАСС.  Там она была решена введением вспомогательной переменной "bandnum", которая принимала значение, равное 1 исключительно при поступлении типа сигнала L2OF и нулевые при всех остальных. В текущей задаче можно использовать эту переменную для идентификации L2C, поэтому достаточно лишь дополнить условие, при котором переменная принимает единичное значение.  
 +
 
 +
Теперь она принимает это значение уже при для двух типов сигналов '''разных''' навигационных систем. Далее выполняем аналогичные действия для сигнала L5 и вводим вспомогательную переменную "initnum", которая принимает значение 2 (почему именно 2 будет сказано ниже).
  
 
<source lang=C> if (U1(p)==66) {
 
<source lang=C> if (U1(p)==66) {
Строка 29: Строка 51:
 
bandnum = 0;</source>  
 
bandnum = 0;</source>  
  
# Далее необходимо обеспечить вывод соответствующих выходных переменных (P, L, D) на форму приложения. Для этого необходимо выполнить редактирование соответствующего участка кода с использованием введенных воспомогательных переменных. При нулевых значениях обеих переменных данные будут выводиться, в , соответственно P[0], L[0], D[0] (которые соответствуют сигналу L1), в остальных столбцах (при данном значении строки, соответствующей конкретному спутнику) происходит заполнение нулевыми значениями. Для простоты операцию "И" можно заменить суммой, которая будет принимать нулевое значение только при одновременных ( в одной итерации) нулевых значении значениях переменных "bandnum" и "initnum". Если же хотя бы одна из воспомогательных переменных принимает ненулевое значение, то далее на форму осуществляется вывод значений для частотных диапазонов либо L2(bandnum =1), либо L5 (initnum = 2). Ниже представлен фрагмент кода с выводом на форму значений L для сигналов L1, L2 и L5.
+
 
 +
Далее необходимо обеспечить вывод соответствующих выходных переменных (P, L, D) на форму приложения.  
 +
 
 +
Для этого необходимо выполнить редактирование соответствующего участка кода с использованием введенных вспомогательных переменных. При нулевых значениях обеих переменных данные будут выводиться, в , соответственно P[0], L[0], D[0] (которые соответствуют сигналу L1), в остальных столбцах (при данном значении строки, соответствующей конкретному спутнику) происходит заполнение нулевыми значениями. Для простоты операцию "И" можно заменить суммой, которая будет принимать нулевое значение только при одновременных ( в одной итерации) нулевых значении значениях переменных "bandnum" и "initnum".  
 +
 
 +
Если же хотя бы одна из вспомогательных переменных принимает ненулевое значение, то далее на форму осуществляется вывод значений для частотных диапазонов либо L2(bandnum =1), либо L5 (initnum = 2). Ниже представлен фрагмент кода с выводом на форму значений L для сигналов L1, L2 и L5.
  
 
<source lang=C>if (sys==SYS_GPS) {
 
<source lang=C>if (sys==SYS_GPS) {
Строка 49: Строка 76:
 
} } </source>
 
} } </source>
  
Аналогично используем воспомогательные переменные для разделения значений дальности (P) и доплеровской частоты (D). Здесь и играет роль в упрощении редактирования (и как следствие, получаем меньшую разницу с исходным кодом) кода выбор в качестве ненулевого значения переменной initnum 2. Здесь переменная сразу задает нужный столбец, минуя предусловий с отдельным прописыванием значений столбцов, как это было в случае с L.  
+
 
 +
Аналогично используем вспомогательные переменные для разделения значений дальности (P) и доплеровской частоты (D).  
 +
 
 +
Здесь и играет роль в упрощении редактирования (и как следствие, получаем меньшую разницу с исходным кодом) кода выбор в качестве ненулевого значения переменной initnum 2. Здесь переменная сразу задает нужный столбец, минуя предусловий с отдельным прописыванием значений столбцов, как это было в случае с L.  
  
 
<source lang=C>if (initnum == 0) {
 
<source lang=C>if (initnum == 0) {
Строка 86: Строка 116:
 
}
 
}
 
  } </source>
 
  } </source>
не
+
 
 +
 
 
Последний штрих - необходимо дополнить участок кода, отвечающий за заполнение элементов таблицы формы нулями. В предыдущей версии там уже была учтена переменная bandnum, осталось учесть введенную переменную initnum. Заполнение нулями столбцов происходит, если обе переменные равны нулю.
 
Последний штрих - необходимо дополнить участок кода, отвечающий за заполнение элементов таблицы формы нулями. В предыдущей версии там уже была учтена переменная bandnum, осталось учесть введенную переменную initnum. Заполнение нулями столбцов происходит, если обе переменные равны нулю.
  
Строка 96: Строка 127:
 
                 raw->obs.data[n].code[j]=CODE_NONE;
 
                 raw->obs.data[n].code[j]=CODE_NONE;
 
             } </source>
 
             } </source>
После проведения компиляции, убеждаемся, что нет синтаксических ошибок.  
+
После проведения компиляции, убеждаемся, что нет синтаксических ошибок.
  
 
== Эксперимент ==
 
== Эксперимент ==
  
С использованием двух приемников были записаны логи и проверена работоспособность измененной программы. Нетрудно увидеть, что программа работает корректно и выдает ожидаемый результат - есть отображение сигналов L2 и L5.
+
С использованием двух приемников были записаны логи и проверена работоспособность измененной программы.  
 
+
[[File:Experiment1.png|400px]]
+
   
+
* a
+
* b
+
* c
+
 
+
'''bold'''
+
 
+
''italic''
+
 
+
'''''bold italic'''
+
 
+
 
+
  
 +
'''Приемник №1''':
  
 +
Нетрудно увидеть, что программа работает корректно и выдает ожидаемый результат - есть отображение сигналов L2 и L5.
  
 +
[[File:Experiment1.png|center|1000px]]
  
  
 +
'''Приемник №2''':
  
 +
Схожий эксперимент был проведен со вторым приемником, только на сей раз L5 уже не увидеть - этот приемник не поддерживает его прием.
  
 +
[[File:Experiment2.png|center|1000px]]
  
  
 +
{|align="center"
 +
|-valign="top"
 +
|[[File:Experiment22.png|center|600px]]
 +
|[[File:Experiment23.png|center|400px]]
 +
|}
  
 +
== Ссылки ==
 +
[https://github.com/Korogodin/RTKLIB Отсюда был взят исходный код]
  
 +
[https://github.com/Divkonv/RTKLIB  Код с изменениями]
  
 +
[https://github.com/Divkonv/RTKLIB_bin Сборки exe-шников с учетом изменений]
  
  
  
 
{{wl-publish: 2019-06-27 06:00:00 +0000 | Mutasov }}
 
{{wl-publish: 2019-06-27 06:00:00 +0000 | Mutasov }}

Текущая версия на 23:19, 27 июня 2019

4287338.jpg


Содержание

[править] Как добавить новые сигналы в nvs.c?

В статье описан процесс добавления новых сигналов в RTKLIB.


[править] Постановка задачи

Возможности RTKNAVI позволяют отображать сигналы L2С и L5 - единственным препятствием для этого являлось отсутствие необходимого кода в обрабатывающем файле nvs.c.

Проблема решалась в несколько этапов c использовнием IDE Embarcadero RAD Studio.

Number1.png

[править] Этапы решения

Был изучен протокол информационного взаимодействия NVS BINR с принятым у нас в лаборатории расширением списка сигналов.

Конкретно интерес представлял пакет F5, т.к. содержит информацию о типах сигналов. В протоколе эти типы представлены в виде шестнадцатеричных значений, однако , чтобы программа смогла "опознать" соответствующие типы, их необходимо перевести в децимальную систему счисления. Выполняя это простое преобразование, нетрудно убедиться, что сигналу L2C соответствует значение 34, а сигналу L5 - 66. Далее полученные значения добавляются в условие соответствующего цикла, отвечающего за идентификацию навигационных сигналов систем ГЛОНАСС и GPS.

На этом этапе программа может "отличить" (но пока не показать! Как добиться их отображения рассказано ниже) сигналы L2C и L5 от сигналов системы ГЛОНАСС.

for (i=0,p+=27;(i<nsat) && (n<MAXOBS); i++,p+=30) {
                raw->obs.data[n].time  = time;
                sys = (U1(p)==1 || U1(p)==33)?SYS_GLO:((U1(p)==2 || U1(p)==34 ||U1(p)==66)?SYS_GPS:((U1(p)==4)?SYS_SBS:SYS_NONE));


Теперь же возникла другая подзадача - необходимо, чтобы L2C и L5 и L1 могли идентифицироваться и впоследствии отображаться независимо друг от друга.

В предыдущей версии программы стояла аналогичная проблема с разделением сигналов L1OF и L2OF для системы ГЛОНАСС. Там она была решена введением вспомогательной переменной "bandnum", которая принимала значение, равное 1 исключительно при поступлении типа сигнала L2OF и нулевые при всех остальных. В текущей задаче можно использовать эту переменную для идентификации L2C, поэтому достаточно лишь дополнить условие, при котором переменная принимает единичное значение.

Теперь она принимает это значение уже при для двух типов сигналов разных навигационных систем. Далее выполняем аналогичные действия для сигнала L5 и вводим вспомогательную переменную "initnum", которая принимает значение 2 (почему именно 2 будет сказано ниже).

        if (U1(p)==66) {
                        initnum = 2; /* L5 */
                }
                else {
                        initnum = 0;
                }
                if (U1(p)==33 || U1(p)==34) {
                        bandnum = 1; /* L2 */
        } else
                        bandnum = 0;


Далее необходимо обеспечить вывод соответствующих выходных переменных (P, L, D) на форму приложения.

Для этого необходимо выполнить редактирование соответствующего участка кода с использованием введенных вспомогательных переменных. При нулевых значениях обеих переменных данные будут выводиться, в , соответственно P[0], L[0], D[0] (которые соответствуют сигналу L1), в остальных столбцах (при данном значении строки, соответствующей конкретному спутнику) происходит заполнение нулевыми значениями. Для простоты операцию "И" можно заменить суммой, которая будет принимать нулевое значение только при одновременных ( в одной итерации) нулевых значении значениях переменных "bandnum" и "initnum".

Если же хотя бы одна из вспомогательных переменных принимает ненулевое значение, то далее на форму осуществляется вывод значений для частотных диапазонов либо L2(bandnum =1), либо L5 (initnum = 2). Ниже представлен фрагмент кода с выводом на форму значений L для сигналов L1, L2 и L5.

if (sys==SYS_GPS) {
                        if (bandnum+initnum == 0) {
                                raw->obs.data[n].L[0]  =  Lb - toff*(FREQ1); }
                                else {
                                if (initnum == 2) {
                                raw->obs.data[n].L[2]  =  Lb - toff*(FREQ5); }
                                else {
                                raw->obs.data[n].L[1]  =  Lb - toff*(FREQ2); }
                                }

                } else {
                  if (bandnum == 0) {
                  raw->obs.data[n].L[0]  =  Lb - toff*(FREQ1_GLO+DFRQ1_GLO*carrNo);
                  }
                  else {
                  raw->obs.data[n].L[1]  = Lb - toff*(FREQ2_GLO+DFRQ2_GLO*carrNo);
                } }


Аналогично используем вспомогательные переменные для разделения значений дальности (P) и доплеровской частоты (D).

Здесь и играет роль в упрощении редактирования (и как следствие, получаем меньшую разницу с исходным кодом) кода выбор в качестве ненулевого значения переменной initnum 2. Здесь переменная сразу задает нужный столбец, минуя предусловий с отдельным прописыванием значений столбцов, как это было в случае с L.

if (initnum == 0) {
                raw->obs.data[n].P[bandnum]    = (Pb-dTowFrac)*CLIGHT*0.001 - toff*CLIGHT; /* in ms, needs to be converted */
                raw->obs.data[n].D[bandnum]    =  (float)Db; }
                else {
                raw->obs.data[n].P[initnum]    = (Pb-dTowFrac)*CLIGHT*0.001 - toff*CLIGHT; /* in ms, needs to be converted */
                raw->obs.data[n].D[initnum]    =  (float)Db; }


Действия, аналогичные изложенным выше для L выполняем для I.

if (bandnum+initnum == 0) {
                        raw->obs.data[n].code[0] = CODE_L1C;
                        raw->obs.data[n].sat = sat;
                } else {
                        if(sys==SYS_GPS) {
                        if(initnum == 2) {
                        raw->obs.data[n].code[initnum] = CODE_L5I;
                        }
                        else {
                        if(bandnum == 1) {
                        raw->obs.data[n].code[initnum] = CODE_L2C;
                  }
                        else {
                        raw->obs.data[n].code[initnum] = CODE_L1C;
                        }
                 }
                }
                        else{
                         if(bandnum == 1) {
                         raw->obs.data[n].code[bandnum] = CODE_L2C; }
                         else {
                         raw->obs.data[n].code[bandnum] = CODE_L1C;
                        }
                         }
                          }


Последний штрих - необходимо дополнить участок кода, отвечающий за заполнение элементов таблицы формы нулями. В предыдущей версии там уже была учтена переменная bandnum, осталось учесть введенную переменную initnum. Заполнение нулями столбцов происходит, если обе переменные равны нулю.

if (bandnum == 0 && initnum == 0)
            for (j=1;j<NFREQ+NEXOBS;j++) {
                raw->obs.data[n].L[j]=raw->obs.data[n].P[j]=0.0;
                raw->obs.data[n].D[j]=0.0;
                raw->obs.data[n].SNR[j]=raw->obs.data[n].LLI[j]=0;
                raw->obs.data[n].code[j]=CODE_NONE;
            }

После проведения компиляции, убеждаемся, что нет синтаксических ошибок.

[править] Эксперимент

С использованием двух приемников были записаны логи и проверена работоспособность измененной программы.

Приемник №1:

Нетрудно увидеть, что программа работает корректно и выдает ожидаемый результат - есть отображение сигналов L2 и L5.

Experiment1.png


Приемник №2:

Схожий эксперимент был проведен со вторым приемником, только на сей раз L5 уже не увидеть - этот приемник не поддерживает его прием.

Experiment2.png


Experiment22.png
Experiment23.png

[править] Ссылки

Отсюда был взят исходный код

Код с изменениями

Сборки exe-шников с учетом изменений



[ Хронологический вид ]Комментарии

(нет элементов)

Войдите, чтобы комментировать.

Персональные инструменты
Пространства имён

Варианты
Действия
SRNS Wiki
Рабочие журналы
Приватный файлсервер
QNAP Сервер
Инструменты