class Orocos::TaskContextBase
Base implementation for Orocos::TaskContext
Constants
- RUNNING_STATES
Attributes
A name => Attribute instance mapping of cached attribute objects
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.
Returns the last-known state
The IOR of this task context
The underlying process object that represents this node It is non-nil only if this node has been started by orocos.rb
A name => Property instance mapping of cached properties
A mapping from static numeric value to state names
Public Class Methods
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 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
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
@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
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
# 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
# File lib/orocos/task_context_base.rb, line 355 def basename @name end
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
# 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
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
# File lib/orocos/task_context_base.rb, line 620 def inspect "#<#{self.class}: #{self.class.name}/#{name}>" end
@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
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
The full name of the task context
# File lib/orocos/task_context_base.rb, line 351 def name map_to_namespace(@name) end
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
# 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
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
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
# 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
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
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
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
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
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
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
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
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
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
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
# File lib/orocos/task_context_base.rb, line 836 def to_h Hash[ name: name, model: model.to_h, state: state ] end
# File lib/orocos/task_context_base.rb, line 616 def to_s "#<TaskContextBase: #{self.class.name}/#{name}>" end
@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