308
edits
No edit summary |
|||
Line 86: | Line 86: | ||
The F-15 I think is the reference implementation of my three main Nasal optimisation techniques; | The F-15 I think is the reference implementation of my three main Nasal optimisation techniques; | ||
== Emesary real time executive == | |||
The following code can be used to provide a basic and yet sophisticated way to run Nasal code in a scheduled (per frame or at a suitable rate) and in a managed way (i.e. something knows which modules are registered) | |||
Each module that wish to be executes needs to implement itself as a receiver or have a receiver wrapper (as follows). Generally I prefer to use a receiver wrapper as it helps to isolate the code that does the work from the code that interfaces to the scheduler. | |||
var ModuleRecipient = | |||
{ | |||
new: func(_ident) | |||
{ | |||
var new_class = emesary.Recipient.new(_ident); | |||
new_class.Object = nil; | |||
new_class.Receive = func(notification) | |||
{ | |||
if (notification.NotificationType == "FrameNotification") | |||
{ | |||
if (new_class.Object == nil) | |||
new_class.Object = ModuleObject.new(); | |||
if (!math.mod(notifications.frameNotification.FrameCount,2)){ | |||
new_class.Object.update(notification); | |||
} | |||
return emesary.Transmitter.ReceiptStatus_OK; | |||
} | |||
return emesary.Transmitter.ReceiptStatus_NotProcessed; | |||
}; | |||
return new_class; | |||
}, | |||
}; | |||
emesary.GlobalTransmitter.Register(ModuleRecipient.new("MODULE-NAME")); | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="nasal"> | |||
#--------------------------------------------------------------------------- | |||
# | |||
# Title : Emesary based real time executive | |||
# | |||
# File Type : Implementation File | |||
# | |||
# Description : Uses emesary notifications to permit nasal subsystems to | |||
# : be invoked in a controlled manner. | |||
# | |||
# Author : Richard Harrison (richard@zaretto.com) | |||
# | |||
# Creation Date : 4 June 2018 | |||
# | |||
# Version : 1.0 | |||
# | |||
# Copyright (C) 2018 Richard Harrison Released under GPL V2 | |||
# | |||
#---------------------------------------------------------------------------*/ | |||
# to add properties to the FrameNotification simply send a FrameNotificationAddProperty | |||
# to the global transmitter. This will be received by the frameNotifcation object and | |||
# included in the update. | |||
#emesary.GlobalTransmitter.NotifyAll(notifications.FrameNotificationAddProperty.new("MODULE", "wow","gear/gear[0]/wow")); | |||
#emesary.GlobalTransmitter.NotifyAll(notifications.FrameNotificationAddProperty.new("MODULE", "engine_n2", "engines/engine[0]/n2")); | |||
# | |||
# | |||
# real time exec loop. | |||
var frame_inc = 0; | |||
var cur_frame_inc = 0.03; | |||
var rtExec_loop = func | |||
{ | |||
# | |||
notifications.frameNotification.fetchvars(); | |||
if (!notifications.frameNotification.running){ | |||
return; | |||
} | |||
notifications.frameNotification.dT = notifications.frameNotification.elapsed_seconds - notifications.frameNotification.curT; | |||
if (notifications.frameNotification.dT > 1.0) | |||
notifications.frameNotification.curT = notifications.frameNotification.elapsed_seconds; | |||
if (notifications.frameNotification.FrameCount >= 16) { | |||
notifications.frameNotification.FrameCount = 0; | |||
} | |||
emesary.GlobalTransmitter.NotifyAll(notifications.frameNotification); | |||
# | |||
notifications.frameNotification.FrameCount = notifications.frameNotification.FrameCount + 1; | |||
# adjust exec rate based on frame rate. | |||
if (notifications.frameNotification.frame_rate_worst < 5) { | |||
frame_inc = 0.25;#4 Hz | |||
} elsif (notifications.frameNotification.frame_rate_worst < 10) { | |||
frame_inc = 0.125;#8 Hz | |||
} elsif (notifications.frameNotification.frame_rate_worst < 15) { | |||
frame_inc = 0.10;#10 Hz | |||
} elsif (notifications.frameNotification.frame_rate_worst < 20) { | |||
frame_inc = 0.075;#13.3 Hz | |||
} elsif (notifications.frameNotification.frame_rate_worst < 25) { | |||
frame_inc = 0.05;#20 Hz | |||
} elsif (notifications.frameNotification.frame_rate_worst < 40) { | |||
frame_inc = 0.0333;#30 Hz | |||
} else { | |||
frame_inc = 0.02;#50 Hz | |||
} | |||
if (frame_inc != cur_frame_inc) { | |||
cur_frame_inc = frame_inc; | |||
} | |||
execTimer.restart(cur_frame_inc); | |||
} | |||
# setup the properties to monitor for this system | |||
input = { | |||
frame_rate : "/sim/frame-rate", | |||
frame_rate_worst : "/sim/frame-rate-worst", | |||
elapsed_seconds : "/sim/time/elapsed-sec", | |||
}; | |||
foreach (var name; keys(input)) { | |||
emesary.GlobalTransmitter.NotifyAll(notifications.FrameNotificationAddProperty.new("EXEC", name, input[name])); | |||
} | |||
setlistener("sim/signals/fdm-initialized", func { | |||
notifications.frameNotification.running = 1; | |||
}); | |||
notifications.frameNotification.running = 0; | |||
notifications.frameNotification.dT = 0; # seconds | |||
notifications.frameNotification.curT = 0; | |||
var execTimer = maketimer(cur_frame_inc, rtExec_loop); | |||
execTimer.simulatedTime = 1; | |||
setlistener("/sim/signals/fdm-initialized", func { | |||
print("M_exec: starting"); | |||
execTimer.start() | |||
}); | |||
# | |||
# Turn on the automatic overrun detection - this will notify on the console | |||
# if any recipient takes more than the allocated (9ms) amount of time | |||
emesary.GlobalTransmitter.OverrunDetection(9); # warn at 9ms | |||
</syntaxhighlight> | |||
== FrameNotification == | == FrameNotification == | ||
Line 93: | Line 236: | ||
Use the FrameNotificationAddProperty to request that certain properties are contained within the FrameNotification. | Use the FrameNotificationAddProperty to request that certain properties are contained within the FrameNotification. | ||
<syntaxhighlight lang="nasal"> | |||
notifications.FrameNotificationAddProperty.new("F15-HUD", **[HASH-Name]**, **[property-string]**) | notifications.FrameNotificationAddProperty.new("F15-HUD", **[HASH-Name]**, **[property-string]**) | ||
</syntaxhighlight> | |||
e.g. | e.g. | ||
Line 179: | Line 324: | ||
------ | ------ | ||
== props.UpdateManager == | == props.UpdateManager == | ||
edits