-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathads_frequency.rb
129 lines (109 loc) · 4.46 KB
/
ads_frequency.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
module ADS_B
class Decoder
def parse_segment_msg(msg)
return msg.to_s(2)[0..4],
msg.to_s(2)[5..7],
msg.to_s(2)[8..31],
msg.to_s(2)[32..87],
msg.to_s(2)[88..111]
end
=begin
///////////////////////////////
//// Identification trame ////
////////////////////////////
=end
def parse_me_trame_identification_aircraft(me)
return me[0..4], me[5..7],
[me[8..13], me[14..19],
me[20..25], me[26..31],
me[32..37], me[38..43],
me[44..49], me[50..55]]
end
def is_identification_tc(me)
return true if me[0..4].to_i(2) <= 4 && me[0..4].to_i(2) >= 1
end
def decode_icao_value(identification_trame_me)
tc, ca, c = parse_me_trame_identification_aircraft(identification_trame_me)
if(is_identification_tc(identification_trame_me))
c.map.with_index do |char, i|
if(char.to_i(2) >= 1 && char.to_i(2) <= 26)
c[i] = ((char.to_i(2)-1 & 31) + 65).chr
else
c[i] = (char.to_i(2) != 32 ? char.to_i(2).chr : "_")
end
end
return true, tc.to_i(2), ca.to_i(2), c.join
else
return "NOT_VALID_IDENTIFICATION_AIRCRAFT_ME", nil, nil, nil
end
end
=begin
///////////////////////////////////
//// End Identification trame ////
/////////////////////////////////
=end
=begin
///////////////////////////////
//// Position trame ////
////////////////////////////
=end
def parse_position_me_trame(me_trame)
return me_trame[0..4],me_trame[5..6],
me_trame[7], me_trame[8..19],
me_trame[20], me_trame[21],
me_trame[22..38], me_trame[39..55]
end
def mod(x, y)
return x-y*((x/y).floor)
end
def nl(lat)
return ((2*Math::PI)/(Math.acos(1-((1-Math.cos(Math::PI/(2*15)))/(Math.cos((Math::PI/180)*lat)**2))))).floor
end
def global_unambiguous_position(me1, me2)
tc1, ss1, saf1, alt1, t1, f1, lat_pcr1, long_pcr1 = self.parse_position_me_trame(me1)
tc2, ss2, saf2, alt2, t2, f2, lat_pcr2, long_pcr2 = self.parse_position_me_trame(me2)
#calculate hint of lat
j = (59*lat_pcr1.to_i(2)/2**17-60*lat_pcr2.to_i(2)/2**17+1/2).floor
#decode lat even
lat_even = (360/60.to_f)*((j%60)+lat_pcr1.to_i(2)/(2**17).to_f)
lat_odd = (360/59.to_f)*((j%59)+lat_pcr2.to_i(2)/(2**17).to_f)
lat = lat_even
if(nl(lat) == nl(lat_odd))
m = (long_pcr1.to_i(2)/2**17*(nl(lat)-1)-long_pcr2.to_i(2)/2**17*nl(lat)+1/2).floor
n = [nl(lat), 1].max
long = (360/n.to_f)*((m%n)+long_pcr1.to_i(2)/(2**17).to_f)
return lat, long
end
end
def decode_position_globally(trame_even, trame_odd)
df_even, ca_even, icao_even, me_even, pi_even = self.parse_segment_msg(trame_even)
df_odd, ca_odd, icao_odd, me_odd, pi_odd = self.parse_segment_msg(trame_odd)
return global_unambiguous_position(me_even, me_odd)
end
def decode_locally_unambiguous_position(trame, lat_ref, long_ref)
tc1, ss1, saf1, alt1, t1, f1, lat_pcr1, long_pcr1 = self.parse_position_me_trame(trame.to_s(2))
dLat = (360/60)
#Equation to get latitude zone index
j = (lat_ref/dLat).floor + (((lat_ref%dLat)/dLat)-(lat_pcr1.to_i(2)/2**17)+(1/2)).floor
lat = dLat*(j+(lat_pcr1.to_i(2)/2**17))
puts lat
end
=begin
///////////////////////////////
//// End Position trame ////
////////////////////////////
=end
def decode(msg)
if(msg.to_s(2).length == 112)
df, ca, icao, me, pi = self.parse_segment_msg(msg)
if(self.is_identification_tc(me))
return (error, tc, ca, name = self.decode_icao_value(me))
end
else
return "NOT_VALID_LENGTH_TRAME", nil
end
end
end
end
dec = ADS_B::Decoder.new
dec.decode_locally_unambiguous_position(0x8D40621D58C382D690C8AC2863A7, 52.258, 3.918)