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

Attributes inherited from OpenStruct

#__parent_name, #__parent_struct

Instance Method Summary collapse

Methods inherited from OpenStruct

#__merge, #__parent, #__respond_to__, #__root, #__root?, #_dump, _load, #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?, #new_model, #on_change, #path, #pretty_print, #respond_to?, #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.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/roby/state/state_model.rb', line 144

def initialize(model = nil, attach_to = nil, attach_name = nil)
    if !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)

    if model
        # If we do have a model, verify that the assigned values match
        # the model's type
        global_filter do |name, value|
            if (field_model = model.get(name)) && (field_type = field_model.type)
                if !(field_type === value)
                    raise ArgumentError, "field #{name} is expected to have values of type #{field_type.name}, #{value} is of type #{value.class}"
                end
            end
            value
        end
    end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Reimplemented from OpenStruct



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

def method_missing(name, *args)
    if name =~ /(.*)=$/
        if data_source = data_sources.get($1)
            raise ArgumentError, "cannot explicitely set a field for which a data source exists"
        end
    end
    super
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



195
196
197
198
199
200
201
202
# File 'lib/roby/state/state_model.rb', line 195

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
    return super(name, create_substruct)
end

#attachObject



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

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

#create_modelObject



216
217
218
# File 'lib/roby/state/state_model.rb', line 216

def create_model
    StateModel.new
end

#data_sourcesObject

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.



140
141
142
# File 'lib/roby/state/state_model.rb', line 140

def data_sources
    @data_sources
end

#last_knownObject

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.



119
120
121
# File 'lib/roby/state/state_model.rb', line 119

def last_known
    @last_known
end


167
168
169
170
171
172
173
# File 'lib/roby/state/state_model.rb', line 167

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

#modelObject

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.



106
107
108
# File 'lib/roby/state/state_model.rb', line 106

def model
    @model
end

#readObject

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



206
207
208
209
210
211
212
213
214
# File 'lib/roby/state/state_model.rb', line 206

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



86
87
88
# File 'lib/roby/state/state_model.rb', line 86

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