... | ... |
@@ -102,6 +102,51 @@ var deviceClass = { |
102 | 102 |
data.timers.map.singleShot = 1; |
103 | 103 |
data.timers.map.start(); |
104 | 104 |
} |
105 |
+ if (getprop('/instrumentation/tcas/serviceable') != nil) { |
|
106 |
+ m.data.tcas = 0; |
|
107 |
+ if (!contains(data.timers, 'tcas')) { |
|
108 |
+ data.timers.tcas = maketimer ( 1, |
|
109 |
+ func { |
|
110 |
+ var tcas_dirty = []; |
|
111 |
+ var _range = 6; |
|
112 |
+ var _minLevel = -1; |
|
113 |
+ foreach (var ac; props.globals.getNode("/ai/models").getChildren("multiplayer")) { |
|
114 |
+ if (ac.getValue("valid")) { |
|
115 |
+ var range = ac.getNode("radar/range-nm").getValue(); |
|
116 |
+ if (range != nil) { |
|
117 |
+ if (debug.isnan(range) == 0) { |
|
118 |
+ if ( (range > 0) and (range <= _range) ) { |
|
119 |
+ var nTcasThreat = ac.getNode("tcas/threat-level"); |
|
120 |
+ if (nTcasThreat != nil) { |
|
121 |
+ var level = nTcasThreat.getValue(); |
|
122 |
+ if (level > _minLevel) { |
|
123 |
+ var lat = ac.getNode("position/latitude-deg").getValue(); |
|
124 |
+ var lon = ac.getNode("position/longitude-deg").getValue(); |
|
125 |
+ var aAlt = ac.getNode("position/altitude-ft").getValue(); |
|
126 |
+ var vs = ac.getNode("velocities/vertical-speed-fps").getValue(); |
|
127 |
+ var alt = math.floor(((aAlt - data.alt) / 100) + 0.5); |
|
128 |
+ if (debug.isnan(lat) == 0 and |
|
129 |
+ debug.isnan(lon) == 0 and |
|
130 |
+ debug.isnan(vs) == 0 and |
|
131 |
+ debug.isnan(alt) == 0) { |
|
132 |
+ append(tcas_dirty, { |
|
133 |
+ lat: lat, |
|
134 |
+ lon: lon, |
|
135 |
+ vs: vs, |
|
136 |
+ alt: alt, |
|
137 |
+ level: level, |
|
138 |
+ }); |
|
139 |
+ } } } } } } } } |
|
140 |
+ data.tcas = tcas_dirty; |
|
141 |
+ } |
|
142 |
+ ); |
|
143 |
+ data.timers.tcas.start(); |
|
144 |
+ } |
|
145 |
+ } |
|
146 |
+ else { |
|
147 |
+ delete(m.softkeys.bindings.PFD.INSET, 'TRAFFIC'); |
|
148 |
+ delete(m.softkeys.bindings.MFD.MAP, 'TRAFFIC'); |
|
149 |
+ } |
|
105 | 150 |
m.display.showInitProgress(); |
106 | 151 |
|
107 | 152 |
setprop('/instrumentation/zkv1000/' ~ m.name ~ '/status', 1); |
... | ... |
@@ -106,6 +106,7 @@ var displayClass = { |
106 | 106 |
'WindData', 'WindData-OPTN1', 'WindData-OPTN2', 'WindData-OPTN1-HDG', 'WindData-OPTN2-symbol', 'WindData-OPTN2-headwind', 'WindData-OPTN2-crosswind', 'WindData-NODATA', |
107 | 107 |
'AOA', 'AOA-needle', 'AOA-text', 'AOA-approach', |
108 | 108 |
'MFD-navbox', |
109 |
+ 'Traffic', |
|
109 | 110 |
# }}} |
110 | 111 |
); |
111 | 112 |
append(groups.clip, |
... | ... |
@@ -564,6 +565,8 @@ var displayClass = { |
564 | 565 |
.setRotation(-roll * D2R); |
565 | 566 |
me.screenElements['SlipSkid'] |
566 | 567 |
.setTranslation(getprop("/instrumentation/slip-skid-ball/indicated-slip-skid") * 10, 0); |
568 |
+ me.screenElements['Traffic'] |
|
569 |
+ .setVisible(size(data.tcas)); |
|
567 | 570 |
settimer(func me.updateAI(), 0.1); |
568 | 571 |
}, |
569 | 572 |
#}}} |
... | ... |
@@ -37,6 +37,7 @@ var mapClass = { |
37 | 37 |
m.layers.tiles = MapTiles.new(m.device, m.group); |
38 | 38 |
m.layers.route = MapRoute.new(m.device, m.group); |
39 | 39 |
m.layers.navaids = MapNavaids.new(m.device, m.group); |
40 |
+ m.layers.tcas = MapTcas.new(m.device, m.group); |
|
40 | 41 |
|
41 | 42 |
m.mapOrientation = m.device.display.display.createGroup('MapOrientation') |
42 | 43 |
.setVisible(m.visibility); |
... | ... |
@@ -0,0 +1,121 @@ |
1 |
+# vim: set foldmethod=marker foldmarker={{{,}}} : |
|
2 |
+ |
|
3 |
+var TcasItemClass = { |
|
4 |
+# get data from AI and multiplayers {{{ |
|
5 |
+ new : func(canvasGroup, index) { |
|
6 |
+ var m = {parents : [TcasItemClass]}; |
|
7 |
+ m._group = canvasGroup.createChild("group", "TcasItem_" ~ index); |
|
8 |
+ |
|
9 |
+ canvas.parsesvg(m._group, data.zkv1000_reldir ~ "Systems/tcas.svg"); |
|
10 |
+ m._can = { |
|
11 |
+ Alt : [ |
|
12 |
+ m._group.getElementById("Alt_above").setVisible(0), |
|
13 |
+ m._group.getElementById("Alt_below").setVisible(0) |
|
14 |
+ ], |
|
15 |
+ Arrow : [ |
|
16 |
+ m._group.getElementById("Arrow_climb").setVisible(0), |
|
17 |
+ m._group.getElementById("Arrow_descent").setVisible(0) |
|
18 |
+ ] |
|
19 |
+ }; |
|
20 |
+ m._can.ThreadLevel = []; |
|
21 |
+ |
|
22 |
+ for (var i=0; i<4; i+=1) |
|
23 |
+ append(m._can.ThreadLevel, |
|
24 |
+ m._group.getElementById("Thread_Level_" ~ i).setVisible(0)); |
|
25 |
+ |
|
26 |
+ m._colors = [ '#00ffff', '#00ffff', '#ff7f2a', '#ff0000' ]; |
|
27 |
+ |
|
28 |
+ return m; |
|
29 |
+ }, |
|
30 |
+ |
|
31 |
+ setData : func(lat, lon, alt, vs, level) { |
|
32 |
+ me._group.setVisible(1); |
|
33 |
+ me._group.setGeoPosition(lat, lon); |
|
34 |
+ |
|
35 |
+ if (alt == 0) { |
|
36 |
+ me._can.Alt[0].setVisible(0); |
|
37 |
+ me._can.Alt[1].setVisible(0); |
|
38 |
+ } |
|
39 |
+ else { |
|
40 |
+ me._can.Alt[alt < 0] |
|
41 |
+ .setText(sprintf("%+i", alt)) |
|
42 |
+ .set('fill', me._colors[level]) |
|
43 |
+ .setVisible(1); |
|
44 |
+ |
|
45 |
+ me._can.Alt[alt > 0].setVisible(0); |
|
46 |
+ } |
|
47 |
+ |
|
48 |
+ if (vs >= -3 and vs <= 3) { |
|
49 |
+ me._can.Arrow[0].setVisible(0); |
|
50 |
+ me._can.Arrow[1].setVisible(0); |
|
51 |
+ } |
|
52 |
+ else { |
|
53 |
+ me._can.Arrow[vs < -3] |
|
54 |
+ .set('fill', me._colors[level]) |
|
55 |
+ .set('stroke', me._colors[level]) |
|
56 |
+ .setVisible(1); |
|
57 |
+ |
|
58 |
+ me._can.Arrow[vs > 3].setVisible(0); |
|
59 |
+ } |
|
60 |
+ |
|
61 |
+ me._can.ThreadLevel[0].setVisible(level == 0); |
|
62 |
+ me._can.ThreadLevel[1].setVisible(level == 1); |
|
63 |
+ me._can.ThreadLevel[2].setVisible(level == 2); |
|
64 |
+ me._can.ThreadLevel[3].setVisible(level == 3); |
|
65 |
+ me._group.set("z-index", level + 1); |
|
66 |
+ }, |
|
67 |
+}; |
|
68 |
+# }}} |
|
69 |
+ |
|
70 |
+var MapTcas = { |
|
71 |
+# init TCAS layer and update {{{ |
|
72 |
+ new : func(device, group) { |
|
73 |
+ var m = {parents:[MapTcas]}; |
|
74 |
+ if (getprop('/instrumentation/tcas/serviceable') == nil) { |
|
75 |
+ m.update = func; |
|
76 |
+ m.setVisible = func; |
|
77 |
+ } |
|
78 |
+ else { |
|
79 |
+ m.device = device; |
|
80 |
+ m.visibility = 0; |
|
81 |
+ m.group = group.createChild('map', 'tcas') |
|
82 |
+ .setTranslation( |
|
83 |
+ m.device.role == 'MFD' ? (m.device.data.mapview[0] + m.device.data.mapclip.left)/2 : 120, |
|
84 |
+ m.device.role == 'MFD' ? 400 : 600) |
|
85 |
+ .setVisible(m.visibility); |
|
86 |
+ m._item = []; |
|
87 |
+ m._itemIndex = 0; |
|
88 |
+ m._itemCount = 0; |
|
89 |
+# /instrumentation/tcas/inputs/mode |
|
90 |
+ m.MODE = ["Normal","Above","Unlimited","Below"]; |
|
91 |
+ } |
|
92 |
+ return m; |
|
93 |
+ }, |
|
94 |
+ |
|
95 |
+ update : func() { |
|
96 |
+ if (me.device.data.tcas == 0) |
|
97 |
+ return; |
|
98 |
+ me.group._node.getNode('ref-lat', 1).setDoubleValue(data.lat); |
|
99 |
+ me.group._node.getNode('ref-lon', 1).setDoubleValue(data.lon); |
|
100 |
+ me.group._node |
|
101 |
+ .getNode('range', 1).setDoubleValue(me.device.data['range-factor']); |
|
102 |
+ me._itemIndex = 0; |
|
103 |
+ foreach (var ac; data.tcas) { |
|
104 |
+ if (me._itemIndex >= me._itemCount) { |
|
105 |
+ append(me._item, TcasItemClass.new(me.group, me._itemIndex)); |
|
106 |
+ me._itemCount += 1; |
|
107 |
+ } |
|
108 |
+ me._item[me._itemIndex].setData(ac.lat, ac.lon, ac.alt, ac.vs, ac.level); |
|
109 |
+ me._itemIndex += 1; |
|
110 |
+ } |
|
111 |
+ |
|
112 |
+ for (; me._itemIndex < me._itemCount; me._itemIndex += 1) { |
|
113 |
+ me._item[me._itemIndex]._group.setVisible(0); |
|
114 |
+ } |
|
115 |
+ }, |
|
116 |
+ |
|
117 |
+ setVisible : func (v) { |
|
118 |
+ me.group.setVisible(v); |
|
119 |
+ }, |
|
120 |
+}; |
|
121 |
+# }}} |
... | ... |
@@ -61,6 +61,15 @@ var softkeysClass = { |
61 | 61 |
me.device.map.setVisible(0); |
62 | 62 |
me.device.display.screenElements['PFD-Map-bg'].hide(); |
63 | 63 |
}, |
64 |
+ TRAFFIC: func { |
|
65 |
+ me.device.data.tcas = ! me.device.data.tcas; |
|
66 |
+ if (me.device.data.tcas) |
|
67 |
+ me.colored['INSETTRAFFIC'] = me.device.data.tcas; |
|
68 |
+ else |
|
69 |
+ delete(me.colored, 'INSETTRAFFIC'); |
|
70 |
+ me.device.display.updateSoftKeys(); |
|
71 |
+ me.device.map.layers.tcas.setVisible(me.device.data.tcas); |
|
72 |
+ }, |
|
64 | 73 |
hook : func { |
65 | 74 |
me.device.display.screenElements['PFD-Map-bg'].show(); |
66 | 75 |
me.device.map.setVisible(1); |
... | ... |
@@ -492,6 +501,17 @@ var softkeysClass = { |
492 | 501 |
me.device.display.updateSoftKeys(); |
493 | 502 |
}, |
494 | 503 |
}, |
504 |
+ MAP: { |
|
505 |
+ TRAFFIC: func { |
|
506 |
+ me.device.data.tcas = ! me.device.data.tcas; |
|
507 |
+ if (me.device.data.tcas) |
|
508 |
+ me.colored['MAPTRAFFIC'] = me.device.data.tcas; |
|
509 |
+ else |
|
510 |
+ delete(me.colored, 'MAPTRAFFIC'); |
|
511 |
+ me.device.display.updateSoftKeys(); |
|
512 |
+ me.device.map.layers.tcas.setVisible(me.device.data.tcas); |
|
513 |
+ }, |
|
514 |
+ }, |
|
495 | 515 |
}, |
496 | 516 |
}, |
497 | 517 |
}; |
... | ... |
@@ -78,6 +78,7 @@ Please report bug at <seb.marque@free.fr>. |
78 | 78 |
* single-prop EIS: texts displayed, animations for fuel |
79 | 79 |
* ND and map display: synchronized tiles and navaids, range change, map heads up |
80 | 80 |
* rotation and zooming of online maps in-flight |
81 |
+ * simple Traffic Alert Collision Avoidance System (TCAS) |
|
81 | 82 |
* ![][90%] |
82 | 83 |
* TMR/REF Timer ![][done], Vspeeds ![][done], minimums ![][pending] (don't understand the role of this) |
83 | 84 |
* angle of attack display (not sure about calculation): specific for each airplane (see Installation instructions below) |
... | ... |
@@ -239,6 +240,21 @@ Actually there are only two "types of display": MFD or PFD, which is known by th |
239 | 240 |
Other devices as keyboard or non-display can also exists, as long as they don't have a `status` property... |
240 | 241 |
Not sur I'm clear on this point though :) |
241 | 242 |
|
243 |
+## TCAS |
|
244 |
+To enable TCAS you need to make it serviceable in your aircraft before the ZKV1000 being powered on, so the best is to set it in the aircraft configuration files. |
|
245 |
+Actually it checks if the property `/instrumentation/tcas/serviceable` is set to boolean true value. |
|
246 |
+ |
|
247 |
+ <tcas> |
|
248 |
+ <name>tcas</name> |
|
249 |
+ <number>0</number> |
|
250 |
+ <serviceable type='bool'>true</serviceable> |
|
251 |
+ <inputs> |
|
252 |
+ <mode type="int">5</mode> |
|
253 |
+ </inputs> |
|
254 |
+ </tcas> |
|
255 |
+ |
|
256 |
+Moreover it only shows alerts with an annunciation "TRAFFIC" on PFD, and shows icons on maps (MFD and INSET), no decision is taken, no relation with transponder and no evasion scenari and no evasion scenario. |
|
257 |
+ |
|
242 | 258 |
## Map tiles origin |
243 | 259 |
By defaults the maps tiles come from `https://maps.wikimedia.org`, type `osm-intl` (please read [https://www.wikimedia.org/wiki/Maps]()), but you can choose your favorite one if you've got one. I've tested `opentopomap.org` and `thunderforest.com` (my favourite). |
244 | 260 |
You can tell the zkv1000 the tile server, type and eventually apikey by using `--prop:` option while starting FlightGear session: |
... | ... |
@@ -7270,6 +7270,29 @@ |
7270 | 7270 |
id="tspan5048" |
7271 | 7271 |
sodipodi:role="line">000°</tspan></text> |
7272 | 7272 |
</g> |
7273 |
+ <g |
|
7274 |
+ id="Traffic" |
|
7275 |
+ inkscape:label="Traffic" |
|
7276 |
+ transform="translate(198.51279,102.67903)"> |
|
7277 |
+ <rect |
|
7278 |
+ y="-35.178177" |
|
7279 |
+ x="50.959221" |
|
7280 |
+ height="26.620489" |
|
7281 |
+ width="108.00312" |
|
7282 |
+ id="rect3397" |
|
7283 |
+ style="opacity:1;fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> |
|
7284 |
+ <text |
|
7285 |
+ id="text3395" |
|
7286 |
+ y="-13.131604" |
|
7287 |
+ x="56.509609" |
|
7288 |
+ style="font-style:normal;font-weight:normal;font-size:24px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" |
|
7289 |
+ xml:space="preserve"><tspan |
|
7290 |
+ style="fill:#000000;fill-opacity:1" |
|
7291 |
+ y="-13.131604" |
|
7292 |
+ x="56.509609" |
|
7293 |
+ id="tspan3393" |
|
7294 |
+ sodipodi:role="line">TRAFFIC</tspan></text> |
|
7295 |
+ </g> |
|
7273 | 7296 |
<g |
7274 | 7297 |
id="SelectedALT" |
7275 | 7298 |
inkscape:label="SelectedALT" |
... | ... |
@@ -0,0 +1,133 @@ |
1 |
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|
2 |
+<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|
3 |
+ |
|
4 |
+<svg |
|
5 |
+ xmlns:dc="http://purl.org/dc/elements/1.1/" |
|
6 |
+ xmlns:cc="http://creativecommons.org/ns#" |
|
7 |
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|
8 |
+ xmlns:svg="http://www.w3.org/2000/svg" |
|
9 |
+ xmlns="http://www.w3.org/2000/svg" |
|
10 |
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|
11 |
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|
12 |
+ width="50" |
|
13 |
+ height="64" |
|
14 |
+ id="svg2" |
|
15 |
+ version="1.1" |
|
16 |
+ inkscape:version="0.48.4 r9939" |
|
17 |
+ sodipodi:docname="tcas.svg"> |
|
18 |
+ <defs |
|
19 |
+ id="defs4" /> |
|
20 |
+ <sodipodi:namedview |
|
21 |
+ id="base" |
|
22 |
+ pagecolor="#ffffff" |
|
23 |
+ bordercolor="#666666" |
|
24 |
+ borderopacity="1.0" |
|
25 |
+ inkscape:pageopacity="0.0" |
|
26 |
+ inkscape:pageshadow="2" |
|
27 |
+ inkscape:zoom="11.2" |
|
28 |
+ inkscape:cx="0.78607779" |
|
29 |
+ inkscape:cy="33.324257" |
|
30 |
+ inkscape:document-units="px" |
|
31 |
+ inkscape:current-layer="layer1" |
|
32 |
+ showgrid="false" |
|
33 |
+ inkscape:snap-page="true" |
|
34 |
+ inkscape:snap-global="true" |
|
35 |
+ inkscape:snap-bbox="true" |
|
36 |
+ showguides="true" |
|
37 |
+ inkscape:guide-bbox="true" |
|
38 |
+ inkscape:bbox-nodes="true" |
|
39 |
+ inkscape:window-width="1920" |
|
40 |
+ inkscape:window-height="1025" |
|
41 |
+ inkscape:window-x="-2" |
|
42 |
+ inkscape:window-y="-3" |
|
43 |
+ inkscape:window-maximized="1"> |
|
44 |
+ <sodipodi:guide |
|
45 |
+ orientation="1,0" |
|
46 |
+ position="50,35.982143" |
|
47 |
+ id="guide3001" /> |
|
48 |
+ </sodipodi:namedview> |
|
49 |
+ <metadata |
|
50 |
+ id="metadata7"> |
|
51 |
+ <rdf:RDF> |
|
52 |
+ <cc:Work |
|
53 |
+ rdf:about=""> |
|
54 |
+ <dc:format>image/svg+xml</dc:format> |
|
55 |
+ <dc:type |
|
56 |
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|
57 |
+ <dc:title /> |
|
58 |
+ </cc:Work> |
|
59 |
+ </rdf:RDF> |
|
60 |
+ </metadata> |
|
61 |
+ <g |
|
62 |
+ inkscape:label="Ebene 1" |
|
63 |
+ inkscape:groupmode="layer" |
|
64 |
+ id="layer1" |
|
65 |
+ transform="translate(-15,-1020)"> |
|
66 |
+ <text |
|
67 |
+ xml:space="preserve" |
|
68 |
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono" |
|
69 |
+ x="38.328125" |
|
70 |
+ y="1003.079" |
|
71 |
+ id="Alt_above" |
|
72 |
+ sodipodi:linespacing="125%"><tspan |
|
73 |
+ sodipodi:role="line" |
|
74 |
+ id="tspan2989" |
|
75 |
+ x="38.328125" |
|
76 |
+ y="1003.079">+30</tspan></text> |
|
77 |
+ <text |
|
78 |
+ sodipodi:linespacing="125%" |
|
79 |
+ id="Alt_below" |
|
80 |
+ y="1052.1428" |
|
81 |
+ x="38.328125" |
|
82 |
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono" |
|
83 |
+ xml:space="preserve"><tspan |
|
84 |
+ y="1052.1428" |
|
85 |
+ x="38.328125" |
|
86 |
+ id="tspan2993" |
|
87 |
+ sodipodi:role="line">-30</tspan></text> |
|
88 |
+ <path |
|
89 |
+ style="color:#000000;fill:#e8e8d8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
|
90 |
+ d="m 41.3125,16.09375 -5.9375,10.25 4,0 0,21.5 3.84375,0 0,-21.5 4,0 -5.90625,-10.25 z" |
|
91 |
+ transform="translate(0,988.36218)" |
|
92 |
+ id="Arrow_climb" |
|
93 |
+ inkscape:connector-curvature="0" /> |
|
94 |
+ <path |
|
95 |
+ inkscape:connector-curvature="0" |
|
96 |
+ id="Arrow_descent" |
|
97 |
+ d="m 41.3125,1036.2059 -5.9375,-10.25 4,0 0,-21.5 3.84375,0 0,21.5 4,0 -5.90625,10.25 z" |
|
98 |
+ style="color:#000000;fill:#e8e8d8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> |
|
99 |
+ <rect |
|
100 |
+ transform="matrix(0.70710713,-0.70710643,0.70710713,0.70710643,0,0)" |
|
101 |
+ style="color:#000000;fill:none;stroke:#00ffff;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
|
102 |
+ id="Thread_Level_0" |
|
103 |
+ width="20.5061" |
|
104 |
+ height="20.5061" |
|
105 |
+ x="-720.4447" |
|
106 |
+ y="722.56604" /> |
|
107 |
+ <rect |
|
108 |
+ y="722.56604" |
|
109 |
+ x="-720.4447" |
|
110 |
+ height="20.5061" |
|
111 |
+ width="20.5061" |
|
112 |
+ id="Thread_Level_1" |
|
113 |
+ style="color:#000000;fill:#00ffff;stroke:#00ffff;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
|
114 |
+ transform="matrix(0.70710713,-0.70710643,0.70710713,0.70710643,0,0)" /> |
|
115 |
+ <path |
|
116 |
+ sodipodi:type="arc" |
|
117 |
+ style="color:#000000;fill:#ff7f2a;fill-opacity:1;fill-rule:nonzero;stroke:#ff7f2a;stroke-width:2.32758594;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
|
118 |
+ id="Thread_Level_2" |
|
119 |
+ sodipodi:cx="15.714286" |
|
120 |
+ sodipodi:cy="32.125" |
|
121 |
+ sodipodi:rx="11.25" |
|
122 |
+ sodipodi:ry="11.25" |
|
123 |
+ d="m 26.964286,32.125 c 0,6.213203 -5.036797,11.25 -11.25,11.25 -6.2132036,0 -11.2500001,-5.036797 -11.2500001,-11.25 0,-6.213203 5.0367965,-11.25 11.2500001,-11.25 6.213203,0 11.25,5.036797 11.25,11.25 z" |
|
124 |
+ transform="matrix(1.2888897,0,0,1.2888884,-4.2539588,978.95663)" /> |
|
125 |
+ <rect |
|
126 |
+ style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" |
|
127 |
+ id="Thread_Level_3" |
|
128 |
+ width="32" |
|
129 |
+ height="32" |
|
130 |
+ x="-1.6947017e-07" |
|
131 |
+ y="1004.3622" /> |
|
132 |
+ </g> |
|
133 |
+</svg> |
... | ... |
@@ -9,6 +9,7 @@ files_to_load = [ |
9 | 9 |
'maps/route.nas', |
10 | 10 |
'maps/navaids.nas', |
11 | 11 |
'maps/tiles.nas', |
12 |
+ 'maps/tcas.nas', |
|
12 | 13 |
'map.nas', # moves the maps |
13 | 14 |
'display.nas', |
14 | 15 |
'menu.nas', # manage windows |
... | ... |
@@ -34,6 +35,7 @@ var data = { # set of data common to all devices |
34 | 35 |
lat : 0, |
35 | 36 |
lon : 0, |
36 | 37 |
aoa : 0, |
38 |
+ tcas: [], |
|
37 | 39 |
timers : { |
38 | 40 |
'20Hz': maketimer ( |
39 | 41 |
0.05, |