Class: Roby::StateField

Inherits:
OpenStruct show all
Defined in:
lib/roby/state/state_model.rb

Overview

Representation of a level in the current state

Direct Known Subclasses

StateSpace

Constant Summary

Constants inherited from OpenStruct

OpenStruct::FORBIDDEN_NAMES, OpenStruct::FORBIDDEN_NAMES_RX, OpenStruct::NOT_OVERRIDABLE, OpenStruct::NOT_OVERRIDABLE_RX

Instance Attribute Summary collapse

Attributes inherited from OpenStruct

#__parent_name, #__parent_struct

Instance Method Summary collapse

Methods inherited from OpenStruct

#__merge, #__parent, #__root, #__root?, #_dump, _load, #alias, #alias?, #attach_child, #attach_model, #attach_to, #attached?, #clear, #clear_model, #create_subfield, #delete, #detached!, #each_member, #empty?, #filter, #freeze, #get, #global_filter, #has_method?, #member?, #new_model, #on_change, #path, #pretty_print, #respond_to_missing?, #set, #stable!, #stable?, #to_hash, #update, #updated

Constructor Details

#initialize(model = nil, attach_to = nil, attach_name = nil) ⇒ StateField

Returns a new instance of StateField.



145
146
147
148
149
150
151
152
153
154
155
# File 'lib/roby/state/state_model.rb', line 145

def initialize(model = nil, attach_to = nil, attach_name = nil)
    unless attach_to
        # We are root, initialize last_known and data_sources
        @last_known = StateLastValueField.new
        @data_sources = StateDataSourceField.new
    end

    super(model, attach_to, attach_name)

    install_type_checking_filter(model) if model
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Reimplemented from OpenStruct



189
190
191
192
193
194
195
# File 'lib/roby/state/state_model.rb', line 189

def method_missing(name, *args)
    if name =~ /(.*)=$/ && (data_source = data_sources.get($1))
        raise ArgumentError,
              "cannot explicitely set a field for which a data source exists"
    end
    super
end

Instance Attribute Details

#data_sourcesObject (readonly)

Returns a structure that gives access to the data sources for the members of this struct. I.e.

state.pose.data_sources.position

will give the data source for state.pose.position if there is one.

Due to the use of open structures, one should always check for the presence of the field first with

if state.pose.data_sources.position?
   # do something with state.pose.data_sources.position
end

Note that the models are accessible from any level, i.e. state.model.pose.position is an equivalent of the above example.



143
144
145
# File 'lib/roby/state/state_model.rb', line 143

def data_sources
  @data_sources
end

#last_knownObject (readonly)

Returns a structure that gives access to the last known values for the members of this struct. I.e.

state.pose.last_known.position

is the last value known for state.pose.position

Note that the last known values are accessible from any level, i.e. state.last_known.pose.position is an equivalent of the above example.



125
126
127
# File 'lib/roby/state/state_model.rb', line 125

def last_known
  @last_known
end

#modelObject (readonly)

Returns a structure that gives access to the models of the members of this struct. I.e.

state.pose.model.position

is the model for state.pose.position

Due to the use of open structures, one should always check for the presence of the field first with

if state.pose.model.position?
   # do something with state.pose.model.position
end

Note that the models are accessible from any level, i.e. state.model.pose.position is an equivalent of the above example.



114
115
116
# File 'lib/roby/state/state_model.rb', line 114

def model
  @model
end

Instance Method Details

#__get(name, create_substruct = true) ⇒ Object

Reimplemented from OpenStruct

It disables automatic substruct creation for state variables for which a data source exists



201
202
203
204
205
206
207
208
209
# File 'lib/roby/state/state_model.rb', line 201

def __get(name, create_substruct = true)
    if (source = data_sources.get(name)) &&
       !source.kind_of?(StateDataSourceField)
        # Don't create a substruct, we know that this subfield should be
        # populated by the data source
        create_substruct = false
    end
    super(name, create_substruct)
end

#attachObject



182
183
184
185
186
# File 'lib/roby/state/state_model.rb', line 182

def attach
    super
    @last_known.attach
    @data_sources.attach
end

#create_modelObject



223
224
225
# File 'lib/roby/state/state_model.rb', line 223

def create_model
    StateModel.new
end

#install_type_checking_filter(model) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/roby/state/state_model.rb', line 157

def install_type_checking_filter(model)
    # If we do have a model, verify that the assigned values match
    # the model's type
    global_filter do |name, value|
        field_model = model.get(name)
        field_type = field_model&.type

        if field_type && !(field_type === value)
            raise ArgumentError,
                  "field #{name} is expected to have values of "\
                  "type #{field_type.name}, #{value} is of type "\
                  "#{value.class}"
        end
        value
    end
end


174
175
176
177
178
179
180
# File 'lib/roby/state/state_model.rb', line 174

def link_to(parent, name)
    super
    @last_known = parent.last_known.get(name) ||
                  StateLastValueField.new(nil, parent.last_known, name)
    @data_sources = parent.data_sources.get(name) ||
                    StateDataSourceField.new(nil, parent.data_sources, name)
end

#readObject

Read each subfield that have a source, and update both their last_known and current value.



213
214
215
216
217
218
219
220
221
# File 'lib/roby/state/state_model.rb', line 213

def read
    data_sources.each_member do |field_name, field_source|
        new_value = field_source.read
        set(field_name, new_value)
        if new_value
            last_known.set(field_name, new_value)
        end
    end
end

#to_sObject



93
94
95
96
# File 'lib/roby/state/state_model.rb', line 93

def to_s
    "#<StateField:#{object_id} path=#{path.join('/')} "\
    "fields=#{@members.keys.sort.join(',')}>"
end