概要 †ffe.nas は、燃費、予測航続距離及び予測後続時間をダイアログで表示します。ダイアログ部分はおまけなので適当ですが、ご勘弁を。 インストール方法 †添付ファイルのソース (ffe.nas) を ~/.fgfs/Nasal/ffe.nas として保存してください (Windows の場合は C:/Documents and Settings/<ユーザ名>/Applciation Data/flightgear.org/Nasal/ffe.nas)。 あとは FlightGear を起動するだけで準備完了です。特に機体側の変更は必要ありません。 使用方法 †起動後、Nasal コンソールから以下のコマンドを入力し Execute ボタンを押せばダイアログが表示されます。 ffe.Dialog.show(); 毎回入力するのは面倒ですので、一度 ESC を押してフライトギアを終了させると、次回からは Nasal コンソールを開くだけで上記コマンドが表示されますので、Execute ボタンを押すだけで起動するようになります。 処理概要 †処理は大きく分けて2つです。1つは燃費等の計算処理で、もう1つはダイアログ表示処理です。 計算処理では、settimer で 5秒毎に表示する3つの値を計算しています。燃費は瞬間燃費のことで「対地速度 / 燃料消費量」とから計算していまして、単位は nm / us-gal (ガロン) です。予測航続距離は「燃費×燃料の残量」でして、単位は us-gal (ガロン) です。要望があればガロン単位に変更します。予想後続時間は「燃料の残量÷燃料消費量」で、書式は HH:MM:SSです。 ソース †このソースは参考に表示しているものです。ダウンロードは下の添付ファイルをクリックして保存してください。 ############################################################################### # ffe.nas by Tatsuhiro Nishioka # - Shows Fuel Efficiency, Estimate Cruise Range, and Estimate Cruise Time. # # Copyright (C) 2008 Tatsuhiro Nishioka (tat dot fgmacosx at gmail dot com) # This file is licensed under the GPL license version 2 or later. # ############################################################################### var Dialog = {}; Dialog.init = func (x = nil, y = nil) { me.x = x; me.y = y; me.bg = [0, 0, 0, 0.3]; me.fg = [[0.9, 0.9, 0.2, 1],[1.0, 1.0, 1.0, 1.0]]; me.name = "Fuel Efficiency"; me.namenode = props.Node.new({"dialog-name" : me.name }); me.dialog = nil; me.node = props.globals.getNode("/sim/gui/dialogs/fuel-efficiency"); me.properties = [ { property : "efficiency", name : "Efficiency", format : "%1.4f", unit : "nm/gal", halign : "right" }, { property : "range", name : "Estinate Cruise Rqnge", format : "%05d", unit : "nm", halign : "right" }, { property : "time", name : "Estimate Cruise Time", format : "%8s", unit : "time", halign : "right" } ]; me.listeners=[]; append(me.listeners, setlistener("/sim/startup/xsize", func { me._redraw() })); append(me.listeners, setlistener("/sim/startup/ysize", func { me._redraw() })); } Dialog.create = func { if (me.dialog != nil) me.close(); me.dialog = gui.Widget.new(); me.dialog.set("name", me.name); if (me.x != nil) me.dialog.set("x", me.x); if (me.y != nil) me.dialog.set("y", me.y); me.dialog.set("layout", "vbox"); me.dialog.set("default-padding", 0); me.dialog.setColor(me.bg[0], me.bg[1], me.bg[2], me.bg[3]); var titlebar=me.dialog.addChild("group"); titlebar.set("layout", "hbox"); titlebar.addChild("empty").set("stretch", 1); titlebar.addChild("text").set("label", "Fuel Efficiency"); var w = titlebar.addChild("button"); w.node.setValues({"pref-width": 16, "pref-height": 16, legend: "", default: 0}); # key: "esc" is no good w.setBinding("nasal", "ffe.Dialog.destroy()"); me.dialog.addChild("hrule"); var content = me.dialog.addChild("group"); content.set("layout", "table"); content.set("defalt-padding", 0); var row = 0; foreach (var property; me.properties) { var col = 0; foreach (var column; ["name", "property", "unit"]) { var w = content.addChild("text"); if (column == "property") { w.node.setValues({row: row, col: col, label: "--------", live : 1, format : property.format, halign : property.halign, property: me.node.getPath() ~ "/" ~ property.property}); } else { var label = property[column]; w.node.setValues({row: row, col: col, label : label, format : "%s", halign : "left"}); } col += 1; } row += 1; } fgcommand("dialog-new", me.dialog.prop()); fgcommand("dialog-show", me.namenode); } Dialog._redraw = func { if (me.dialog != nil) { me.close(); me.create(); } } Dialog.close = func { fgcommand("dialog-close", me.namenode); } Dialog.destroy = func { me.close(); foreach(var l; me.listeners) removelistener(l); delete(gui.dialog, "\"" ~ me.name ~ "\""); } Dialog.show = func { me.init(-2, -2); me.create(); } var FuelEfficiency = {}; FuelEfficiency.new = func(interval) { obj = { parents : [FuelEfficiency] }; obj.speedNode = props.globals.getNode("velocities/groundspeed-kt"); obj.engineRunningNode = props.globals.getNode("engines/engine/running"); obj.interval = interval; obj.fuelFlow = 0; obj.fuelEfficiency = 0; obj.range = 0; settimer(func { obj.update(); }, 5); return obj; } FuelEfficiency.update = func { me.updateFuelEfficiency(); me.calcTotalFuel(); me.estimateCruiseRange(); me.estimateCruiseTime(); settimer(func { me.update(); }, me.interval); } # # calculate fuel efficiency (nm/us-gal) # FuelEfficiency.updateFuelEfficiency = func { var fuelFlow = 0; var groundSpeed = getprop("/velocities/groundspeed-kt"); var engineRunning = getprop("/engines/engine/running"); if (engineRunning == nil) { engineRunning = 0; } else { foreach(var engine; props.globals.getNode("/engines").getChildren("engine")) { fuelFlow += me.getFuelFlow(engine); } } me.fuelFlow = fuelFlow; me.fuelEfficiency = (engineRunning * fuelFlow == 0) ? 0 : (groundSpeed / fuelFlow); setprop("/sim/gui/dialogs/fuel-efficiency/efficiency", me.fuelEfficiency); } FuelEfficiency.getFuelFlow = func(engine) { var flowNode = engine.getNode("fuel-flow-gph"); var flow = 0; if (flowNode != nil) flow = flowNode.getValue(); if (flow == 0 or flowNode == nil) { flowNode = engine.getNode("fuel-flow_pph"); if (flowNode != nil) flow = flowNode.getValue() / 5.92; else flow = 0; } return flow; } # # calculate total fuel (us-gal) # FuelEfficiency.calcTotalFuel = func { var totalFuel = 0; foreach (var tank; props.globals.getNode("/consumables/fuel").getChildren("tank")) { var fuelLevelNode = tank.getNode("level-lb"); if (fuelLevelNode != nil) { totalFuel += fuelLevelNode.getValue() / 5.92; } } setprop("/sim/gui/dialogs/fuel-efficiency/fuel-gal", totalFuel); me.totalFuel = totalFuel; } FuelEfficiency.estimateCruiseRange = func { var range = me.fuelEfficiency * me.totalFuel; setprop("/sim/gui/dialogs/fuel-efficiency/range", range); return range; } FuelEfficiency.estimateCruiseTime = func { var time = 0; if (me.totalFuel > 0) { time = me.totalFuel / me.fuelFlow * 60; } var hour = int(time / 60); var min = int(math.mod(time, 60)); var sec = int(math.mod(time * 60, 60)); setprop("/sim/gui/dialogs/fuel-efficiency/time", sprintf("%02d:%02d:%02d", hour, min, sec)); return } var efficiency = nil; _setlistener("/sim/signals/fdm-initialized", func { efficiency = FuelEfficiency.new(1); }); |