Я работаю с данными АИС (автоматической системы идентификации) для определения местоположения судов. Я смог выполнить это руководство , чтобы успешно декодировать почти весь бит информации (по сравнению с онлайн-декодированием, выполненным здесь ).
Однако у меня возникла проблема с частью долготы. Я думаю , что это связано с тем, что десятичное значение отрицательно, но я не могу понять, что нужно изменить в моем коде, чтобы сделать его правильным.
Версия TLDR : как получить из двоичной строки 1101001000001001001110010000 в десятичное значение -48196720 (или 48196720)?
Полная версия :
данные об игрушке:
library(dplyr)
library(tidyr)
library(stringr)
# choose an example - two strings are provided.
# The first string shows the issue with the longitude,
# whereas the second string (where longitude is positive) has no issue
s <- "15E3tB001;J@BLPaK5j7qFA406;d"
# s <- "133m@ogP00PD;88MD5MTDww@2D7k"
### for input into the online decoder - use these:
# !AIVDM,1,1,,A,14eG;o@034o8sd<L9i:a;WF>062D,0*7D
# !AIVDM,1,1,,A,133m@ogP00PD;88MD5MTDww@2D7k,0*46
temp <- data.frame(V6 = s) %>%
# splitting the AIS info into separate characters
mutate(char_split = str_split(V6,pattern=""))
temp$Text <- apply(temp, 1, function(x) paste(unlist(x$char_split), collapse = ","))
temp <- temp %>%
select(-char_split) %>%
# and then into separate columns
separate(Text, into = paste0("v", 1:43, sep = ""), sep = ",", fill = "right")
ASCII <- temp %>%
select(v1:v43)
# translating to ASCII
ASCII <- apply(ASCII, c(1, 2), function(x) utf8ToInt(x))
# translating to 6-bit
ASCII <- apply(ASCII, c(1, 2), function(x) ifelse(x <= 88, x - 48, x - 48 - 8))
Как только данные находятся в ASCII, нужно перевести в двоичный файл
# making binary
Binary <- apply(ASCII, c(1, 2), function(x){ paste(rev(as.integer(intToBits(x))[1:6]), collapse = "")})
# pasting all the binary info into a single string
temp$Binary <- apply(Binary, 1, function(x) paste(x, collapse = "" ))
temp <- temp %>%
select(V6, Binary) %>%
# selecting bits of the single binary string,
#and translating back to decimal, as per the guide
mutate(MMSI = strtoi(substr(Binary, 9, 38), base = 2),
SOG = strtoi(substr(Binary, 50, 60), base = 2)/10,
Accuracy = strtoi(substr(Binary, 61, 61), base = 2),
Lon = strtoi(substr(Binary, 62, 89), base = 2)/600000,
Lat = strtoi(substr(Binary, 90, 116), base = 2)/600000,
COG = strtoi(substr(Binary, 117, 128), base = 2)/10,
Heading = strtoi(substr(Binary, 129, 137), base = 2))
выход:
select(temp, -Binary, -V6)
при сравнении с онлайн-декодером все совпадает, кроме долготы. В декодере результат равен 80,3278667 (хотя на самом деле он равен -80,3278667), а мой - 367,0646. Пытаясь провести обратный инжиниринг, я смотрю на соответствующую подстроку temp$Binary
:
mine <- substr(temp$Binary, 62, 89)
RevEng <- -80.3278667 * 600000
binaryLogic:::as.binary(as.integer(RevEng), signed = FALSE)
mine
Так что, похоже, значение RevEng соответствует правому концу моей двоичной строки, но я не могу понять, почему оно не соответствует полной двоичной строке или что делать отсюда ...