Class: Orocos::RubyTasks::TaskContext

Inherits:
TaskContext show all
Defined in:
lib/orocos/ruby_tasks/task_context.rb,
ext/rorocos/ruby_task_context.cc

Overview

A TaskContext that lives inside this Ruby process

For now, it has very limited functionality: mainly managing ports

Direct Known Subclasses

StubTaskContext

Defined Under Namespace

Classes: LocalTaskContext

Constant Summary

Constants inherited from TaskContextBase

TaskContextBase::RUNNING_STATES

Constants included from Namespace

Namespace::DELIMATOR

Instance Attribute Summary

Attributes inherited from TaskContext

#logger

Attributes inherited from TaskContextBase

#attributes, #configuration_log, #current_state, #ior, #process, #properties, #state_symbols

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from TaskContext

#==, #apply_conf, #apply_conf_file, #attribute, #attribute_names, #callop, #cleanup, #configure, #connect_to, corba_wrap, #create_property_log_stream, #disconnect_from, #do_attribute_names, #do_attribute_read, #do_attribute_read_string, #do_attribute_type_name, #do_attribute_write, #do_attribute_write_string, #do_cleanup, #do_configure, #do_has_operation?, #do_has_port?, #do_operation_call, #do_operation_names, #do_operation_send, #do_port, #do_port_names, #do_property_names, #do_property_read, #do_property_read_string, #do_property_type_name, #do_property_write, #do_property_write_string, #do_real_name, #do_reset_exception, #do_start, #do_state, #do_stop, #has_operation?, #log_all_configuration, #log_all_ports, #model, #operation, #operation_argument_types, #operation_names, #operation_return_types, #peek_state, #ping, #port, #port_names, #property, #property_names, #raw_property, #reset_exception, #resolve_connection_from, #resolve_disconnection_from, #rtt_state, #save_conf, #sendop, #start, #state_reader, state_transition_call, #stop, #tid, #to_async, #to_proxy, #to_s, #wait_for_state

Methods inherited from TaskContextBase

#add_default_states, #available_states, #basename, connect_to, #connect_to, #doc, #doc?, #each_attribute, #each_input_port, #each_operation, #each_output_port, #each_port, #each_property, #error?, #error_state?, #exception?, #exception_state?, #fatal_error?, #fatal_error_state?, find_one_running, get, get_provides, #has_attribute?, #has_operation?, #has_property?, #implements?, #info, #input_port, #input_port_model, #inspect, #method_missing, #model, #model=, #name, #on_localhost?, #output_port, #output_port_model, #peek_current_state, #peek_state, #ports, #pre_operational?, #pretty_print, reachable?, #reachable?, #ready?, #running?, #runtime_error?, #runtime_state?, #state, #state_changed?, #states, #to_h, #to_s, #toplevel_state

Methods included from Namespace

#basename, #map_to_namespace, #namespace, #namespace=, #same_namespace?, #split_name, split_name, validate_namespace_name, #verify_same_namespace

Methods included from PortsSearchable

#find_all_input_ports, #find_all_output_ports, #find_all_ports, #find_input_port, #find_output_port, #find_port

Methods included from TaskContextBaseAbstract

#attribute, #attribute_names, #operation, #operation_names, #ping, #port, #port_names, #property, #property_names, #rtt_state

Constructor Details

#initialize(ior, name: self.name, **other_options) ⇒ TaskContext

Returns a new instance of TaskContext



65
66
67
68
69
70
# File 'lib/orocos/ruby_tasks/task_context.rb', line 65

def initialize(ior, name: self.name, **other_options)
    @local_ports = Hash.new
    @local_properties = Hash.new
    @local_attributes = Hash.new
    super(ior, name: name, **other_options)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Orocos::TaskContextBase

Class Method Details

.from_orogen_model(name, orogen_model) ⇒ TaskContext

Creates a new local task context that fits the given oroGen model

Returns:



25
26
27
# File 'lib/orocos/ruby_tasks/task_context.rb', line 25

def self.from_orogen_model(name, orogen_model)
    new(name, model: orogen_model)
end

.new(name, options = Hash.new, &block) ⇒ TaskContext

Creates a new ruby task context with the given name

Parameters:

  • name (String)

    the task name

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/orocos/ruby_tasks/task_context.rb', line 33

def self.new(name, options = Hash.new, &block)
    options, _ = Kernel.filter_options options,
        model: nil,
        project: OroGen::Spec::Project.new(Orocos.default_loader)

    project = options.delete(:project)
    if block && !options[:model]
        model = OroGen::Spec::TaskContext.new(project, name)
        model.instance_eval(&block)
        options[:model] = model
    end

    local_task = LocalTaskContext.new(name)
    if options[:model] && options[:model].name
        local_task.model_name = options[:model].name
    end

    remote_task = super(local_task.ior, name: name, **options)
    local_task.instance_variable_set :@remote_task, remote_task
    remote_task.instance_variable_set :@local_task, local_task

    if options[:model]
        remote_task.setup_from_orogen_model(options[:model])
    else
        remote_task.model.extended_state_support
    end
    remote_task
rescue ::Exception
    local_task.dispose if local_task
    raise
end

Instance Method Details

#create_attribute(name, type, options = Hash.new) ⇒ Property

Creates a new attribute on this task context

Parameters:

  • name (String)

    the attribute name

  • type (Model<Typelib::Type>, String)

    the type or type name

  • options (Hash) (defaults to: Hash.new)

    a customizable set of options

Options Hash (options):

  • :init (Boolean) — default: true

    if true, the new attribute will be initialized with a fresh sample. Otherwise, it is left alone. This is mostly to avoid crashes / misbehaviours in case smart pointers are used

Returns:



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/orocos/ruby_tasks/task_context.rb', line 141

def create_attribute(name, type, options = Hash.new)
    options = Kernel.validate_options options, :init => true

    Orocos.load_typekit_for(type, false)
    orocos_type_name = Orocos.find_orocos_type_name_by_type(type)
    Orocos.load_typekit_for(orocos_type_name, true)

    local_attribute = @local_task.do_create_attribute(Attribute, name, orocos_type_name)
    @local_attributes[local_attribute.name] = local_attribute
    @attributes[local_attribute.name] = local_attribute
    if options[:init]
        local_attribute.write(local_attribute.new_sample)
    end
    local_attribute
end

#create_input_port(name, orocos_type_name, options = Hash.new) ⇒ Object

Create a new input port on this task context

Parameters:

  • name (String)

    the port name. It must be unique among all port types

  • orocos_type_name (String)

    the name of the port's type, as recognized by Orocos. In most cases, it is the same than the typelib type name

  • options (Hash) (defaults to: Hash.new)

    a customizable set of options

Options Hash (options):

  • :permanent (Boolean)

    if true (the default), the port will be stored permanently on the task. Otherwise, it will be removed as soon as the port object gets garbage collected by Ruby

  • :class (Class)

    the class that should be used to represent the port on the Ruby side. Do not change unless you know what you are doing



85
86
87
88
# File 'lib/orocos/ruby_tasks/task_context.rb', line 85

def create_input_port(name, orocos_type_name, options = Hash.new)
    options, other_options = Kernel.filter_options options, :class => LocalInputPort
    create_port(false, options[:class], name, orocos_type_name, other_options)
end

#create_output_port(name, orocos_type_name, options = Hash.new) ⇒ Object

Create a new output port on this task context

Parameters:

  • name (String)

    the port name. It must be unique among all port types

  • orocos_type_name (String)

    the name of the port's type, as recognized by Orocos. In most cases, it is the same than the typelib type name

  • options (Hash) (defaults to: Hash.new)

    a customizable set of options

Options Hash (options):

  • :permanent (Boolean)

    if true (the default), the port will be stored permanently on the task. Otherwise, it will be removed as soon as the port object gets garbage collected by Ruby

  • :class (Class)

    the class that should be used to represent the port on the Ruby side. Do not change unless you know what you are doing



103
104
105
106
# File 'lib/orocos/ruby_tasks/task_context.rb', line 103

def create_output_port(name, orocos_type_name, options = Hash.new)
    options, other_options = Kernel.filter_options options, :class => LocalOutputPort
    create_port(true, options[:class], name, orocos_type_name, other_options)
end

#create_property(name, type, options = Hash.new) ⇒ Property

Creates a new property on this task context

Parameters:

  • name (String)

    the property name

  • type (Model<Typelib::Type>, String)

    the type or type name

  • options (Hash) (defaults to: Hash.new)

    a customizable set of options

Options Hash (options):

  • :init (Boolean) — default: true

    if true, the new property will be initialized with a fresh sample. Otherwise, it is left alone. This is mostly to avoid crashes / misbehaviours in case smart pointers are used

Returns:



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/orocos/ruby_tasks/task_context.rb', line 166

def create_property(name, type, options = Hash.new)
    options = Kernel.validate_options options, :init => true

    Orocos.load_typekit_for(type, false)
    orocos_type_name = Orocos.find_orocos_type_name_by_type(type)
    Orocos.load_typekit_for(orocos_type_name, true)

    local_property = @local_task.do_create_property(Property, name, orocos_type_name)
    @local_properties[local_property.name] = local_property
    @properties[local_property.name] = local_property
    if options[:init]
        local_property.write(local_property.new_sample)
    end
    local_property
end

#disposeObject

Deregisters this task context.

This is done automatically when the object is garbage collected. However, it is sometimes better to do this explicitely, for instance to avoid the name clash warning.



123
124
125
# File 'lib/orocos/ruby_tasks/task_context.rb', line 123

def dispose
    @local_task.dispose
end

#exceptionObject

Transition to an exception state



128
129
130
# File 'lib/orocos/ruby_tasks/task_context.rb', line 128

def exception
    @local_task.exception
end

#has_port?(name) ⇒ Boolean

Returns:

  • (Boolean)


235
236
237
# File 'lib/orocos/ruby_tasks/task_context.rb', line 235

def has_port?(name)
    @local_ports.has_key?(name) || super
end

#raw_port(name) ⇒ Object



239
240
241
# File 'lib/orocos/ruby_tasks/task_context.rb', line 239

def raw_port(name)
    @local_ports[name] || super
end

#remove_port(port) ⇒ void

This method returns an undefined value.

Remove the given port from this task's interface

Parameters:



112
113
114
115
116
# File 'lib/orocos/ruby_tasks/task_context.rb', line 112

def remove_port(port)
    @local_ports.delete(port.name)
    port.disconnect_all # don't wait for the port to be garbage collected by Ruby
    @local_task.do_remove_port(port.name)
end

#setup_from_orogen_model(orogen_model) ⇒ void

This method returns an undefined value.

Sets up the interface of this task context so that it matches the given oroGen model

Parameters:

  • orogen_model (OroGen::Spec::TaskContext)

    the oroGen model



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/orocos/ruby_tasks/task_context.rb', line 187

def setup_from_orogen_model(orogen_model)
    new_properties, new_outputs, new_inputs = [], [], []
    remove_outputs, remove_inputs = [], []

    orogen_model.each_property do |p|
        if has_property?(p.name)
            if property(p.name).orocos_type_name != p.orocos_type_name
                raise IncompatibleInterface, "cannot adapt the interface of #{self} to match the model in #{orogen_model}: #{self} already has a property called #{p.name}, but with a different type"
            end
        else new_properties << p
        end
    end
    orogen_model.each_input_port do |p|
        if has_port?(p.name)
            existing_port = port(p.name)
            if existing_port.orocos_type_name != p.orocos_type_name
                remove_inputs << existing_port
                new_inputs << p
            end
        else new_inputs << p
        end
    end
    orogen_model.each_output_port do |p|
        if has_port?(p.name)
            existing_port = port(p.name)
            if existing_port.orocos_type_name != p.orocos_type_name
                remove_outputs << existing_port
                new_outputs << p
            end
        else new_outputs << p
        end
    end

    remove_inputs.each { |p| remove_port p }
    remove_outputs.each { |p| remove_port p }
    new_properties.each do |p|
        create_property(p.name, p.type)
    end
    new_inputs.each do |p|
        create_input_port(p.name, p.type)
    end
    new_outputs.each do |p|
        create_output_port(p.name, p.type)
    end
    @model = orogen_model
    nil
end