Class: Roby::StateSpace
- Inherits:
-
StateField
- Object
- OpenStruct
- StateField
- Roby::StateSpace
- Defined in:
- lib/roby/state/state_model.rb,
lib/roby/state/events.rb
Overview
Implementation of the state representation at runtime.
It gives access to three views to the state:
* the current values are directly accessible from this state object
* the last known value is stored in last_known.path.to.value
* the state model is stored in model.path.to.value
* the current data source for a state variable is stored in
data_sources.path.to.value
Constant Summary
Constants inherited from OpenStruct
OpenStruct::FORBIDDEN_NAMES, OpenStruct::FORBIDDEN_NAMES_RX, OpenStruct::NOT_OVERRIDABLE, OpenStruct::NOT_OVERRIDABLE_RX
Instance Attribute Summary
Attributes inherited from OpenStruct
#__parent_name, #__parent_struct, #model
Instance Method Summary collapse
-
#_dump(lvl = -1)) ⇒ Object
Implementation of marshalling with Ruby’s Marshal.
-
#at(options) ⇒ Object
Returns an event which emits when the given state is reached.
- #create_subfield(name) ⇒ Object
- #deep_copy ⇒ Object
-
#export(*names) ⇒ Object
Declares that only the given names should be marshalled, instead of marshalling every field.
-
#export_all ⇒ Object
Declares that all the state fields should be marshalled.
-
#export_none ⇒ Object
Declares that no state fields should be marshalled.
-
#initialize(model = nil) ⇒ StateSpace
constructor
A new instance of StateSpace.
-
#on_delta(spec) ⇒ Object
Create an event which will be emitted everytime some state parameters vary more than the given deltas.
-
#reset_when(event, state_name = nil, &block) ⇒ Object
Installs a condition at which the event should be reset.
- #simulation? ⇒ Boolean
- #testing? ⇒ Boolean
-
#trigger_when(*state_path, &block) ⇒ Object
Returns a state event that emits the first time the block returns true.
Methods inherited from StateField
#__get, #attach, #create_model, #data_sources, #last_known, #link_to, #method_missing, #model, #read, #to_s
Methods inherited from OpenStruct
#__get, #__merge, #__parent, #__respond_to__, #__root, #__root?, _load, #alias, #attach, #attach_child, #attach_model, #attach_to, #attached?, #clear, #clear_model, #create_model, #delete, #detached!, #each_member, #empty?, #filter, #freeze, #get, #global_filter, #has_method?, #link_to, #method_missing, #new_model, #on_change, #path, #pretty_print, #respond_to?, #set, #stable!, #stable?, #to_hash, #update, #updated
Constructor Details
#initialize(model = nil) ⇒ StateSpace
Returns a new instance of StateSpace.
230 231 232 233 |
# File 'lib/roby/state/state_model.rb', line 230 def initialize(model = nil) @exported_fields = nil super(model) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Roby::StateField
Instance Method Details
#_dump(lvl = -1)) ⇒ Object
Implementation of marshalling with Ruby’s Marshal
Only the fields that can be marshalled will be saved. Any other field will silently be ignored.
Which fields get marshalled can be controlled with #export_all, #export_none and #export. The default is to marshal all fields.
280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/roby/state/state_model.rb', line 280 def _dump(lvl = -1) if !@exported_fields super else marshalled_members = @exported_fields.map do |name| value = @members[name] [name, Marshal.dump(value)] rescue nil end marshalled_members.compact! Marshal.dump([marshalled_members, @aliases]) end end |
#at(options) ⇒ Object
Returns an event which emits when the given state is reached. For now, the following state variables are available:
t-
time as a Time object
See TimePointEvent
90 91 92 93 94 95 |
# File 'lib/roby/state/events.rb', line 90 def at() = , t: nil if time = [:t] trigger_when { Time.now >= time } end end |
#create_subfield(name) ⇒ Object
268 269 270 271 |
# File 'lib/roby/state/state_model.rb', line 268 def create_subfield(name) model = if self.model then self.model.get(name) end StateField.new(model, self, name) end |
#deep_copy ⇒ Object
293 294 295 296 297 298 |
# File 'lib/roby/state/state_model.rb', line 293 def deep_copy exported_fields, @exported_fields = @exported_fields, Set.new Marshal.load(Marshal.dump(self)) ensure @exported_fields = exported_fields end |
#export(*names) ⇒ Object
Declares that only the given names should be marshalled, instead of marshalling every field. It is cumulative, i.e. if multiple calls to #export follow each other then the fields get added to the list of exported fields instead of replacing it.
If #export_all has been called, a call to #export cancels it.
See also #export_none and #export_all
263 264 265 266 |
# File 'lib/roby/state/state_model.rb', line 263 def export(*names) @exported_fields ||= Set.new @exported_fields.merge names.map { |n| n.to_s }.to_set end |
#export_all ⇒ Object
Declares that all the state fields should be marshalled. This is the default
It cancels any list of fields exported with #export
See also #export_none and #export
251 252 253 |
# File 'lib/roby/state/state_model.rb', line 251 def export_all @exported_fields = nil end |
#export_none ⇒ Object
Declares that no state fields should be marshalled. The default is to export everything
It cancels any list of fields exported with #export
See also #export_all and #export
241 242 243 |
# File 'lib/roby/state/state_model.rb', line 241 def export_none @exported_fields = Set.new end |
#on_delta(spec) ⇒ Object
Create an event which will be emitted everytime some state parameters vary more than the given deltas. The following state parameters are available:
t-
time in seconds
d-
distance in meters
yaw-
heading in radians
For instance:
Roby.state.on_delta d: 10, t: 20
will emit everytime the robot moves more than 10 meters AND more than 20 seconds have elapsed.
If more than once specification is given, the resulting event is combined with the & operator. This can be changed by setting the :or option to ‘true’.
Roby.state.on_delta d: 10, t: 20, or: true
See DeltaEvent and its subclasses.
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 |
# File 'lib/roby/state/events.rb', line 23 def on_delta(spec) or_aggregate = spec.delete(:or) events = spec.map do |name, value| unless klass = DeltaEvent.event_types[name] raise "unknown delta type #{name}. Known types are #{DeltaEvent.event_types.keys}" end ev = klass.new ev.threshold = value ev end if events.size > 1 result = if or_aggregate then OrGenerator.new else AndGenerator.new end result.on { |ev| result.reset } def result.or(spec); DeltaEvent.or(spec, self) end events.each { |ev| result << ev } result else events.first end end |
#reset_when(event, state_name = nil, &block) ⇒ Object
Installs a condition at which the event should be reset
76 77 78 79 80 81 82 83 |
# File 'lib/roby/state/events.rb', line 76 def reset_when(event, state_name = nil, &block) reset_event = trigger_when(state_name, &block) reset_event.add_causal_link event reset_event.armed = !event.armed? event.on { |ev| reset_event.reset } reset_event.on { |ev| event.reset } reset_event end |
#simulation? ⇒ Boolean
301 |
# File 'lib/roby/state/state_model.rb', line 301 def simulation?; Roby.app.simulation? end |
#testing? ⇒ Boolean
300 |
# File 'lib/roby/state/state_model.rb', line 300 def testing?; Roby.app.testing? end |
#trigger_when(*state_path, &block) ⇒ Object
Returns a state event that emits the first time the block returns true
The block is given the value of the specified state value state_name. For instance, with
event = State.position.trigger_when(:x) do |value|
value > 23
end
event will be emitted once if the X value of the position gets greater than 23. One can also specify a reset condition with
State.position.reset_when(event, :x) do |value|
value < 20
end
66 67 68 69 70 71 72 73 |
# File 'lib/roby/state/events.rb', line 66 def trigger_when(*state_path, &block) if !block_given? raise ArgumentError, "#trigger_when expects a block" end state_path.map!(&:to_s) StateConditionEvent.new(self, state_path, block) end |