class Orocos::TaskContextBase

Base implementation for Orocos::TaskContext

Constants

RUNNING_STATES

Attributes

attributes[R]

A name => Attribute instance mapping of cached attribute objects

configuration_log[R]

If set, this is a Pocolog::Logfiles object in which the values of properties and attributes should be logged.

Orocos.rb only logs the values that are set from within Ruby. There are no ways to log the values changed from within the task context.

current_state[R]

Returns the last-known state

ior[R]

The IOR of this task context

process[RW]

The underlying process object that represents this node It is non-nil only if this node has been started by orocos.rb

properties[R]

A name => Property instance mapping of cached properties

state_symbols[R]

A mapping from static numeric value to state names

Public Class Methods

connect_to(task,task2,policy = Hash.new, &block) click to toggle source

Connects all output ports with the input ports of given task. If one connection is ambiguous or none of the port is connected an exception is raised. All output ports which does not match any input port are ignored

Instead of a task the method can also be called with a port as argument

# File lib/orocos/task_context_base.rb, line 251
def self.connect_to(task,task2,policy = Hash.new, &block)
    if task2.respond_to? :each_port
        count = 0
        task.each_port do |port|
            next if !port.respond_to? :reader
            if other = task2.find_input_port(port.type,nil)
                port.connect_to other, policy, &block
                count += 1
            end
        end
        if count == 0
            raise NotFound, "#{task.name} has no port matching the ones of #{task2.name}."
        end
    else # assuming task2 is a port
        if port = task.find_output_port(task2.type,nil)
            port.connect_to task2, policy, &block
        else
            raise NotFound, "no port of #{task.name} matches the given port #{task2.name}"
        end
    end
    self
end
find_one_running(*names) click to toggle source

Find one running tasks from the provided names. Raises if there is not exactly one

# File lib/orocos/task_context_base.rb, line 230
def self.find_one_running(*names)
    Orocos.name_service.find_one_running(*names)
end
get(name) → task click to toggle source
get(:provides => interface_name) → task

In the first form, returns the TaskContext instance representing the remote task context with the given name.

In the second form, searches for a task context that implements the given interface. This is doable only if orogen has been used to generate the components.

Raises Orocos::NotFound if the task name does not exist, if no task implements the given interface, or if more than one task does implement the required interface

# File lib/orocos/task_context_base.rb, line 216
def self.get(options, process = nil)
    if options.kind_of?(Hash)
        # Right now, the only allowed option is :provides
        options = Kernel.validate_options options, :provides => nil
        return Orocos.name_service.get_provides(options[:provides].to_str)
    else
        raise ArgumentError, 'no task name' if options.nil?
        name = options.to_str
    end
    result = Orocos.name_service.get(name,{:process => process})
end
new(name, namespace: nil, process: nil, model: nil) click to toggle source

@param [String] name The name of the task. @param [Hash] options The options. @option options [Orocos::Process] :process The process supporting the task @option options [String] :namespace The namespace of the task

# File lib/orocos/task_context_base.rb, line 304
def initialize(name, namespace: nil, process: nil, model: nil)
    @ports = Hash.new
    @properties = Hash.new
    @attributes = Hash.new
    @state_queue = Array.new

    if namespace
        self.namespace, @name = namespace, name
    else
        self.namespace, @name = split_name(name)
        name = @name
    end
    @process    = process

    @process ||= Orocos.enum_for(:each_process).
        find do |p|
            p.task_names.any? { |n| n == name }
        end

    if process
        process.register_task(self)
    end

    if model
        self.model = model
    else
        # Load the model from remote if it is not set yet
        self.model
    end

    if !@state_symbols
        @state_symbols = []
        @state_symbols[STATE_PRE_OPERATIONAL] = :PRE_OPERATIONAL
        @state_symbols[STATE_STOPPED]         = :STOPPED
        @state_symbols[STATE_RUNNING]         = :RUNNING
        @state_symbols[STATE_RUNTIME_ERROR]   = :RUNTIME_ERROR
        @state_symbols[STATE_EXCEPTION]       = :EXCEPTION
        @state_symbols[STATE_FATAL_ERROR]     = :FATAL_ERROR
        @error_states     = Set.new
        @runtime_states   = Set.new
        @exception_states = Set.new
        @fatal_states     = Set.new
        add_default_states
    end
end
reachable?(task_name) click to toggle source

TODO this is bad performance wise it will load the model and all extensions use the nameservice for the check

Returns true if task_name is a TaskContext object that can be reached

# File lib/orocos/task_context_base.rb, line 240
def self.reachable?(task_name)
    Orocos.name_service.task_reachable? task_name
end

Public Instance Methods

add_default_states() click to toggle source
# File lib/orocos/task_context_base.rb, line 635
def add_default_states
    @error_states   << :RUNTIME_ERROR << :FATAL_ERROR << :EXCEPTION
    @runtime_states << :RUNNING << :RUNTIME_ERROR
    @exception_states << :EXCEPTION
    @fatal_states     << :FATAL_ERROR
end
basename() click to toggle source
# File lib/orocos/task_context_base.rb, line 355
def basename
    @name
end
connect_to(task,policy = Hash.new) click to toggle source

Connects all output ports with the input ports of given task. If one connection is ambiguous or none of the port is connected an exception is raised. All output ports which does not match any input port are ignored

Instead of a task the method can also be called with a port as argument

# File lib/orocos/task_context_base.rb, line 612
def connect_to(task,policy = Hash.new)
    TaskContextBase.connect_to(self,task,policy)
end
doc() click to toggle source

Returns a documentation string describing the task If no documentation is available it returns nil

# File lib/orocos/task_context_base.rb, line 585
def doc
    model.doc if model
end
doc?() click to toggle source

Returns true if a documentation about the task is available otherwise it returns false

# File lib/orocos/task_context_base.rb, line 443
def doc?
    (doc && !doc.empty?)
end
each_attribute { |a| ... } → task click to toggle source

Enumerates the attributes that are available on this task, as instances of Orocos::Attribute

# File lib/orocos/task_context_base.rb, line 394
def each_attribute(&block)
    if !block_given?
        return enum_for(:each_attribute)
    end

    names = attribute_names
    names.each do |name|
        yield(attribute(name))
    end
end
each_input_port { |p| ... } → task click to toggle source

Enumerates the input ports that are available on this task, as instances of Orocos::InputPort

# File lib/orocos/task_context_base.rb, line 550
def each_input_port
    each_port do |p|
        yield(p) if p.respond_to?(:writer)
    end
end
each_operation { |a| ... } → task click to toggle source

Enumerates the operation that are available on this task, as instances of Orocos::Operation

# File lib/orocos/task_context_base.rb, line 364
def each_operation(&block)
    if !block_given?
        return enum_for(:each_operation)
    end
    names = operation_names
    names.each do |name|
        yield(operation(name))
    end
end
each_output_port { |p| ... } → task click to toggle source

Enumerates the input ports that are available on this task, as instances of Orocos::OutputPort

# File lib/orocos/task_context_base.rb, line 561
def each_output_port
    each_port do |p|
        yield(p) if p.respond_to?(:reader)
    end
end
each_port { |p| ... } → task click to toggle source

Enumerates the ports that are available on this task, as instances of either Orocos::InputPort or Orocos::OutputPort

# File lib/orocos/task_context_base.rb, line 410
def each_port(&block)
    if !block_given?
        return enum_for(:each_port)
    end

    port_names.each do |name|
        yield(port(name))
    end
    self
end
each_property { |a| ... } → task click to toggle source

Enumerates the properties that are available on this task, as instances of Orocos::Attribute

# File lib/orocos/task_context_base.rb, line 379
def each_property(&block)
    if !block_given?
        return enum_for(:each_property)
    end
    names = property_names
    names.each do |name|
        yield(property(name))
    end
end
error?() click to toggle source

Returns true if the task is in an error state (runtime or fatal)

# File lib/orocos/task_context_base.rb, line 477
def error?
    error_state?(peek_current_state)
end
error_state?(sym) click to toggle source

True if the given symbol is the name of an error state

# File lib/orocos/task_context_base.rb, line 458
def error_state?(sym); @error_states.include?(sym) end
exception?() click to toggle source

Returns true if the task is in an exceptional state

# File lib/orocos/task_context_base.rb, line 488
def exception?
    exception_state?(peek_current_state)
end
exception_state?(sym) click to toggle source

True if the given symbol is the name of an exception state

# File lib/orocos/task_context_base.rb, line 460
def exception_state?(sym); @exception_states.include?(sym) end
fatal_error?() click to toggle source

Returns true if the task is in a fatal error state

# File lib/orocos/task_context_base.rb, line 492
def fatal_error?
    fatal_error_state?(peek_current_state)
end
fatal_error_state?(sym) click to toggle source

True if the given symbol is the name of a fatal error state

# File lib/orocos/task_context_base.rb, line 462
def fatal_error_state?(sym); @fatal_states.include?(sym) end
has_attribute?(name) click to toggle source

Returns true if name is the name of a attribute on this task context

# File lib/orocos/task_context_base.rb, line 422
def has_attribute?(name)
    attribute_names.include?(name.to_str)
end
has_operation?(name) click to toggle source

Returns true if this task context has a command with the given name

# File lib/orocos/task_context_base.rb, line 432
def has_operation?(name)
    operation_names.include?(name.to_str)
end
has_port?(name) click to toggle source

Returns true if this task context has a port with the given name

# File lib/orocos/task_context_base.rb, line 437
def has_port?(name)
    port_names.include?(name.to_str)
end
has_property?(name) click to toggle source

Returns true if this task context has either a property or an attribute with the given name

# File lib/orocos/task_context_base.rb, line 427
def has_property?(name)
    property_names.include?(name.to_str)
end
implements?(class_name) click to toggle source

True if this task's model is a subclass of the provided class name

This is available only if the deployment in which this task context runs has been generated by orogen.

# File lib/orocos/task_context_base.rb, line 684
def implements?(class_name)
    model && model.implements?(class_name)
end
info() click to toggle source

Returns the Orogen specification object for this task instance. This is available only if the deployment in which this task context runs has been generated by orogen and this deployment has been started by this Ruby instance

To get the Orogen specification for the task context itself (an OroGen::Spec::TaskContext instance), use {#model}.

@return [OroGen::Spec::TaskDeployment] @see model

# File lib/orocos/task_context_base.rb, line 577
def info
    if process
        @info ||= process.orogen.task_activities.find { |act| act.name == name }
    end
end
input_port(name) click to toggle source
# File lib/orocos/task_context_base.rb, line 522
def input_port(name)
    p = port(name)
    if p.respond_to?(:writer)
        return p
    else
        raise InterfaceObjectNotFound.new(self, name), "#{name} is an output port of #{self.name}, was expecting an input port"
    end
end
input_port_model(name) click to toggle source

Resolves the model of a port

@return [OroGen::Spec::InputPort,nil]

# File lib/orocos/task_context_base.rb, line 701
def input_port_model(name)
    if port_model = model.each_input_port.find { |p| p.name == name }
        port_model
    else model.find_dynamic_input_ports(name, nil).first
    end
end
inspect() click to toggle source
# File lib/orocos/task_context_base.rb, line 620
def inspect
    "#<#{self.class}: #{self.class.name}/#{name}>"
end
model() click to toggle source

@return [OroGen::Spec::TaskContext,nil] the oroGen model that describes this node

# File lib/orocos/task_context_base.rb, line 670
def model
    if @model
        @model
    elsif info && info.context
        self.model = info.context
    else
        nil
    end
end
model=(model) click to toggle source

load all informations from the model

# File lib/orocos/task_context_base.rb, line 643
def model=(model)
    if model
        @model = model

        @state_symbols = model.each_state.map { |name, type| name.to_sym }
        @error_states  = model.each_state.
            map { |name, type| name.to_sym if (type == :error || type == :exception || type == :fatal) }.
            compact.to_set
        @exception_states  = model.each_state.
            map { |name, type| name.to_sym if type == :exception }.
            compact.to_set
        @runtime_states = model.each_state.
            map { |name, type| name.to_sym if (type == :error || type == :runtime) }.
            compact.to_set
        @fatal_states = model.each_state.
            map { |name, type| name.to_sym if type == :fatal }.
            compact.to_set

        if ext = Orocos.extension_modules[model.name]
            ext.each { |m_ext| extend(m_ext) }
        end
        add_default_states
    else @model = nil
    end
end
name() click to toggle source

The full name of the task context

# File lib/orocos/task_context_base.rb, line 351
def name
    map_to_namespace(@name)
end
on_localhost?() click to toggle source

True if it is known that this task runs on the local machine

This requires the process handling to be done by orocos.rb (the method checks if the process runs on the local machine)

# File lib/orocos/task_context_base.rb, line 451
def on_localhost?
    process && process.on_localhost?
end
output_port(name) click to toggle source
# File lib/orocos/task_context_base.rb, line 531
def output_port(name)
    p = port(name)
    if p.respond_to?(:reader)
        return p
    else
        raise InterfaceObjectNotFound.new(self, name), "#{name} is an input port of #{self.name}, was expecting an output port"
    end
end
output_port_model(name) click to toggle source

Resolves the model of a port

@return [OroGen::Spec::OutputPort,nil]

# File lib/orocos/task_context_base.rb, line 691
def output_port_model(name)
    if port_model = model.each_output_port.find { |p| p.name == name }
        port_model
    else model.find_dynamic_output_ports(name, nil).first
    end
end
peek_current_state() click to toggle source

This is meant to be used internally Returns the current task's state without “hiding” any state change to the task's user.

This is meant to be used internally

# File lib/orocos/task_context_base.rb, line 510
def peek_current_state
    peek_state.last || @current_state
end
peek_state() click to toggle source
# File lib/orocos/task_context_base.rb, line 514
def peek_state
    current_state = rtt_state
    if (@state_queue.empty? && current_state != @current_state) || (@state_queue.last != current_state)
        @state_queue << current_state
    end
    @state_queue
end
ports() click to toggle source

Returns an array of all the ports defined on this task context

# File lib/orocos/task_context_base.rb, line 541
def ports
    enum_for(:each_port).to_a
end
pre_operational?() click to toggle source

Returns true if the task is pre-operational

# File lib/orocos/task_context_base.rb, line 465
def pre_operational?
    peek_current_state && peek_current_state == :PRE_OPERATIONAL
end
reachable?() click to toggle source

Returns true if the remote task context can still be reached through and false otherwise.

# File lib/orocos/task_context_base.rb, line 598
def reachable?
    ping
    true
rescue RuntimeError
    false
end
ready?() click to toggle source

Returns true if the task has been configured.

# File lib/orocos/task_context_base.rb, line 475
def ready?; peek_current_state && (peek_current_state != :PRE_OPERATIONAL) end
running?() click to toggle source

Returns true if the task is in a state where code is executed. This includes of course the running state, but also runtime error states.

# File lib/orocos/task_context_base.rb, line 471
def running?
    runtime_state?(peek_current_state)
end
runtime_error?() click to toggle source

Returns true if the task is in a runtime error state

# File lib/orocos/task_context_base.rb, line 481
def runtime_error?
    state = self.peek_current_state
    error_state?(state) &&
        !exception_state?(state) &&
        !fatal_error_state?(state)
end
runtime_state?(sym) click to toggle source

True if the given symbol is the name of a runtime state

# File lib/orocos/task_context_base.rb, line 456
def runtime_state?(sym); @runtime_states.include?(sym) end
state(return_current = true) click to toggle source

Returns the state of the task, as a symbol. The possible values for all task contexts are:

:PRE_OPERATIONAL
:STOPPED
:ACTIVE
:RUNNING
:RUNTIME_WARNING
:RUNTIME_ERROR
:FATAL_ERROR

If the component is an oroGen component on which custom states have been defined, these custom states are also reported with their name. For instance, after the orogen definition

runtime_states "CUSTOM_RUNTIME"

state will return :CUSTOM_RUNTIME if the component goes into that state.

If return_current is true, the current component state is returned. Otherwise, only the next state in the state queue is returned. This is only valid for oroGen components with extended state support (for which all state changes are saved instead of only the last one)

# File lib/orocos/task_context_base.rb, line 732
def state(return_current = true)
    peek_state
    if @state_queue.empty?
        @current_state
    elsif return_current
        @current_state = @state_queue.last
        @state_queue.clear 
    else
        @current_state = @state_queue.shift
    end
    @current_state
end
state_changed?() click to toggle source

True if we got a state change announcement

# File lib/orocos/task_context_base.rb, line 591
def state_changed?
    peek_state
    !@state_queue.empty?
end
states() click to toggle source

Returns all states which were received since the last call and sets the current state to the last one.

# File lib/orocos/task_context_base.rb, line 747
def states
    peek_state
    if !@state_queue.empty?
        @current_state = @state_queue.last
        @state_queue,old = [],@state_queue
        old
    else
        []
    end
end
to_h() click to toggle source
# File lib/orocos/task_context_base.rb, line 836
def to_h
    Hash[
        name: name,
        model: model.to_h,
        state: state
    ]
end
to_s() click to toggle source
# File lib/orocos/task_context_base.rb, line 616
def to_s
    "#<TaskContextBase: #{self.class.name}/#{name}>"
end
toplevel_state(state) click to toggle source

@return [Symbol] the toplevel state that corresponds to state, i.e.

the value returned by #rtt_state when #state returns 'state'
# File lib/orocos/task_context_base.rb, line 626
def toplevel_state(state)
    if exception_state?(state) then :EXCEPTION
    elsif fatal_state?(state) then :FATAL_ERROR
    elsif error_state?(state) then :RUNTIME_ERROR
    elsif runtime_state?(state) then :RUNNING
    else state
    end
end