class OroGen::Spec::TaskContext

Model of a task context, i.e. a task context interface

The corresponding code generation support is done in {Gen::RTT_CPP::TaskContextGeneration}

Constants

STATE_TYPES

Attributes

dynamic_ports[R]

A set of Port objects that can be created at runtime

extensions[R]

Set of extensions registered for this task

Extensions are named objects of arbitrary type that can be used to extend the task context model. If they contain a generate method, this method is also called to add some code generation elements

This is an array (not a hash) so that it keeps order

implemented_classes[R]

A set of classes the TaskContext has to implement as well

name[R]

The task name

project[R]

The oroGen project this task is part of

@return [Project]

superclass[R]

The subclass of TaskContext which should be used to define this class

uses_qt[R]

True if QT is used within this Task

Public Class Methods

apply_default_extensions(task_context) click to toggle source

Apply the currently enabled default extension on the given task context model

# File lib/orogen/spec/task_context.rb, line 89
def apply_default_extensions(task_context)
    default_extensions.each do |ext|
        task_context.send(ext)
    end
end
blank(name = nil) click to toggle source

Returns a blank task context model, possibly with a name

# File lib/orogen/spec/task_context.rb, line 314
def self.blank(name = nil)
    loader = Loaders::Base.new
    project = Project.new(loader)
    project.default_task_superclass = false
    TaskContext.new(project, name)
end
default_extensions() click to toggle source

The set of extensions that should be applied when a task context is created

# File lib/orogen/spec/task_context.rb, line 83
def default_extensions
    @default_extensions_state.last
end
new(project, name = nil, subclasses: project.default_task_superclass) click to toggle source

Create a new task context in the given project and with the given name. If a block is given, it is evaluated in the context of the newly created TaskContext object.

TaskContext objects should not be created directly. You should use {Project#task_context} for that.

Calls superclass method
# File lib/orogen/spec/task_context.rb, line 327
def initialize(project, name = nil, subclasses: project.default_task_superclass)
    @project  = project

    if subclasses
        @superclass =
            if subclasses.respond_to?(:to_str)
                project.task_model_from_name subclasses
            else
                subclasses
            end
        @default_activity  = @superclass.default_activity.dup
        @required_activity = @superclass.required_activity?
    else
        @superclass = false
        default_activity 'triggered'
        @required_activity = false
    end

    @implemented_classes = []
    @name = name

    # This is an array, as we don't want to have it reordered
    # unnecessarily
    @states = Array.new

    @properties = Hash.new
    @attributes = Hash.new
    @operations = Hash.new
    @output_ports = Hash.new
    @input_ports  = Hash.new
    @dynamic_ports = Array.new
    @event_ports = Hash.new
    @initial_state = 'Stopped'
    @default_extensions = Array.new
    @fixed_initial_state = false
    @needs_configuration = false

    ## WARN: this must be kept an array so that the generation order
    ## WARN: is deterministic
    @extensions = Array.new

    super()

    if block_given?
        instance_eval(&proc)
    end
end
pop_default_extensions_state() click to toggle source

Pop the extensions enabled at this level, reverting to the list before the last call to {#push_default_extensions_state}

# File lib/orogen/spec/task_context.rb, line 77
def pop_default_extensions_state
    @default_extensions_state.pop if @default_extensions_state.size > 1
end
push_default_extensions_state(extensions) click to toggle source

Make the given list of extensions the default until the next {#pop_default_extensions_state}

Default extensions are the extensions that are enabled when a task context is created. This method allows to locally override the set of extensions

@param [Array<String>] extensions

# File lib/orogen/spec/task_context.rb, line 71
def push_default_extensions_state(extensions)
    @default_extensions_state.push(extensions.dup)
end

Public Instance Methods

abstract() click to toggle source

Call to declare that this task model is not meant to run in practice

# File lib/orogen/spec/task_context.rb, line 176
def abstract; @abstract = true; end
abstract?() click to toggle source

True if this task model is only meant to declare an interface, and should not be deployed

# File lib/orogen/spec/task_context.rb, line 179
def abstract?; @abstract end
all_attributes → set_of_attributes click to toggle source

Returns the set of all attributes that are defined on this task context

# File lib/orogen/spec/task_context.rb, line 961
            
all_dynamic_ports → set_of_ports click to toggle source

Returns the set of all dynamic ports that are defined on this task context

# File lib/orogen/spec/task_context.rb, line 883
            
all_input_ports → set_of_ports click to toggle source

Returns the set of all static input ports that are defined on this task context

# File lib/orogen/spec/task_context.rb, line 909
            
all_output_ports → set_of_ports click to toggle source

Returns the set of all static output ports that are defined on this task context

# File lib/orogen/spec/task_context.rb, line 935
            
all_ports() click to toggle source
# File lib/orogen/spec/task_context.rb, line 1126
def all_ports
    all_input_ports + all_output_ports
end
all_properties → set_of_properties click to toggle source

Returns the set of all properties that are defined on this task context

# File lib/orogen/spec/task_context.rb, line 987
            
ancestors() click to toggle source

Returns the task context models that are in this model's ancestry

# File lib/orogen/spec/task_context.rb, line 379
def ancestors
    m = self
    result = [self]
    while m = m.superclass
        result << m
    end
    result
end
attribute(name, type, default_value = nil) click to toggle source

Create a new attribute with the given name, type and default value for this task. This returns an Attribute instance representing the new attribute, whose methods can be used to configure it further. type is the type name for that attribute.

@example

attribute('device_name', '/std/string/, '').
    doc 'the device name to connect to'
# File lib/orogen/spec/task_context.rb, line 534
def attribute(name, type, default_value = nil)
    @attributes[name] = att = configuration_object(Attribute, name, type, default_value)
    Spec.load_documentation(att, /attribute/)
    att
end
configuration_object(klass, name, type, default_value) click to toggle source
# File lib/orogen/spec/task_context.rb, line 540
def configuration_object(klass, name, type, default_value)
    name = OroGen.verify_valid_identifier(name)
    check_uniqueness(name)

    begin
        type = project.find_interface_type(type)
    rescue Typelib::NotFound => e
        raise ConfigError, "invalid type #{type}: #{e.message}", e.backtrace
    end

    if default_value
        accepted = [Numeric, Symbol, String, TrueClass, FalseClass].
            any? { |valid_klass| default_value.kind_of?(valid_klass) }
        if !accepted
            raise ArgumentError, "default values for #{klass.name.downcase} can be specified only for simple types (numeric, string and boolean)"
        end
        begin
            Typelib.from_ruby(default_value, type)
        rescue Typelib::UnknownConversionRequested => e
            raise ArgumentError, e.message, e.backtrace
        end
    end

    klass.new(self, name, type, default_value)
end
default_activity 'activity_type', *args click to toggle source

The kind of activity that should be used by default. This is the name of the corresponding method on the deployment objects (:periodic, :aperiodic, :slave, :irq_driven, :fd_driven)

This is a default value, i.e. the use of such an activity is not mandatory. If required_activity is set to true, then this activity is the only kind of activity that can be used with this task context.

See also required_activity

# File lib/orogen/spec/task_context.rb, line 292
dsl_attribute :default_activity do |type, *args|
    if required_activity? && @default_activity
        raise ArgumentError, "the #{default_activity[0]} activity is required, you cannot change it"
    end

    type = type.to_sym
    if !ACTIVITY_TYPES.has_key?(type)
        raise ArgumentError, "#{type} is not a valid activity type"
    end
    [type, *args]
end
dynamic_input_port name_regex, typename click to toggle source

Declares that a port whose name matches name_regex can be declared at runtime, with the type. This is not used by orogen himself, but can be used by potential users of the orogen specification.

# File lib/orogen/spec/task_context.rb, line 1200
def dynamic_input_port(name, type)
    dynamic_ports << DynamicInputPort.new(self, name, type)
    dynamic_ports.last
end
dynamic_output_port name_regex, typename click to toggle source

Declares that a port whose name matches name_regex can be declared at runtime, with the type. This is not used by orogen himself, but can be used by potential users of the orogen specification.

# File lib/orogen/spec/task_context.rb, line 1211
def dynamic_output_port(name, type)
    dynamic_ports << DynamicOutputPort.new(self, name, type)
    dynamic_ports.last
end
each_attribute(only_self = false) { |attribute| } click to toggle source

Yields all attributes that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 953
            
each_dynamic_port(only_self = false) { |port| } click to toggle source

:method: #each_dynamic_input_port

Yields all dynamic input ports that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 837
def each_dynamic_input_port(only_self = false)
    return enum_for(:each_dynamic_input_port, only_self) if !block_given?
    each_dynamic_port do |port|
        if port.kind_of?(InputPort)
            yield(port)
        end
    end
end
each_dynamic_output_port(only_self = false) { |port| } click to toggle source

:method: #each_dynamic_output_port

Yields all dynamic output ports that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 852
def each_dynamic_output_port(only_self = false)
    return enum_for(:each_dynamic_output_port, only_self) if !block_given?
    each_dynamic_port do |port|
        if port.kind_of?(OutputPort)
            yield(port)
        end
    end
end
each_dynamic_port(only_self = false) { |port| } click to toggle source

Yields all dynamic ports that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 868
            
each_error_state() click to toggle source

Enumerates all error states defined for this task context

See also each_runtime_state, each_exception_state, each_fatal_state, and each_state

# File lib/orogen/spec/task_context.rb, line 691
            
each_exception_state() click to toggle source

Enumerates all error states defined for this task context

See also each_runtime_state, each_fatal_state, each_error_state and each_state

# File lib/orogen/spec/task_context.rb, line 698
            
each_extension(with_subclasses = true) { |ext| ... } click to toggle source

Enumerates the extensions registered on this task model, as (name, extension_object) pairs

# File lib/orogen/spec/task_context.rb, line 122
def each_extension(with_subclasses = true, &block)
    if !block_given?
        return enum_for(:each_extension, with_subclasses)
    end

    seen = Set.new
    klass = self
    begin
        klass.extensions.each do |ext|
            if !seen.include?(ext.name)
                seen << ext.name
                yield(ext)
            end
        end
        klass = klass.superclass
    end while (klass && with_subclasses)
end
each_fatal_state() click to toggle source

Enumerates all error states defined for this task context

See also each_runtime_state, each_exception_state, each_error_state and each_state

# File lib/orogen/spec/task_context.rb, line 705
            
each_input_port { |port| } click to toggle source

Yields all static input ports that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 901
            
each_interface_type() { |t| ... } click to toggle source

Enumerate all the types that are used on this component's interface

# File lib/orogen/spec/task_context.rb, line 1414
def each_interface_type
    return enum_for(__method__) if !block_given?

    seen = Set.new
    (all_properties + all_attributes + all_operations + all_ports + all_dynamic_ports).
        each do |obj|
            if !seen.include?(obj)
                obj.each_interface_type { |t| yield(t) }
                seen << obj
            end
        end
end
each_output_port { |port| } click to toggle source

Yields all static output ports that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 927
            
each_port(&block) click to toggle source

Enumerates both the input and output ports

# File lib/orogen/spec/task_context.rb, line 1135
def each_port(&block)
    if !block_given?
        return enum_for(:each_port, &block)
    end

    each_input_port(&block)
    each_output_port(&block)
end
each_property(only_self = false) { |property| } click to toggle source

Yields all properties that are defined on this task context.

# File lib/orogen/spec/task_context.rb, line 979
            
each_runtime_state() click to toggle source

Enumerates all the runtime states

See also each_error_state, each_exception_state, each_fatal_state and each_state

# File lib/orogen/spec/task_context.rb, line 684
            
each_state(with_superclass: true, &block) click to toggle source

Enumerates each state defined on this task context.

@param [Boolean] with_superclass whether only states defined on

this level of the task hierarchy should be enumerated, or the
states from the superclass too.

@yieldparam [String] name the state name @yieldparam [Symbol] type the state type, one of {STATE_TYPES}

# File lib/orogen/spec/task_context.rb, line 726
def each_state(with_superclass: true, &block)
    return enum_for(__method__) if !block

    if superclass && with_superclass
        superclass.each_state(&block)
    end
    @states.each(&block)
end
error_states(*state_names) click to toggle source

Declares a certain number of runtime error states

This method will do nothing if it defines a state that is already defined by one of the superclasses.

See runtime_states, exception_states, each_state, each_error_state

# File lib/orogen/spec/task_context.rb, line 779
def error_states(*state_names)
    state_names.each do |name|
        define_state(name, :error)
    end
end
exception_states(*state_names) click to toggle source

Declares a certain number of exception states

This method will do nothing if it defines a state that is already defined by one of the superclasses.

See runtime_states, fatal_states, error_states, each_state, each_error_state

# File lib/orogen/spec/task_context.rb, line 791
def exception_states(*state_names)
    state_names.each do |name|
        define_state(name, :exception)
    end
end
extended_state_support() click to toggle source

Asks orogen to implement the extended state support interface in the Base class. This adds:

* a 'state' output port in which the current task's state is written
* an enumeration type named CLASS_NAME_STATES in which one value
  is defined for each states

Note that, for all of this to work, it is actually required that all the hooks overloaded in the task's class call their parent in the call chain.

# File lib/orogen/spec/task_context.rb, line 612
def extended_state_support
    state_port = find_port("state")
    if state_port
        if state_port.kind_of?(InputPort)
            raise ArgumentError, 
                "there is already an input port called 'state', cannot enable extended state support"
        elsif state_port.type != project.find_type("/int32_t")
            raise ArgumentError, 
                "there is already an output port called 'state', but it is not of type 'int' (found #{state_port.type_name}"
        end
    else
        output_port('state', '/int32_t').
            triggered_once_per_update
    end

    # Force typekit generation. The typekit code will take care of
    # generating the state enumeration type for us
    project.typekit(true)

    @extended_state_support = true
end
extended_state_support?() click to toggle source

True if the extended state support is enabled

# File lib/orogen/spec/task_context.rb, line 635
def extended_state_support?
    @extended_state_support || (superclass.extended_state_support? if superclass)
end
extension(name, with_subclasses = true) click to toggle source

Returns the extension named name, or raises ArgumentError if none is registered with that name

# File lib/orogen/spec/task_context.rb, line 151
def extension(name, with_subclasses = true)
    if ext = find_extension(name, with_subclasses)
        ext
    else raise ArgumentError, "no extension registered under the name '#{name}'"
    end
end
fatal_states(*state_names) click to toggle source

Declares a certain number of fatal error states

This method will do nothing if it defines a state that is already defined by one of the superclasses.

See runtime_states, error_states, each_state, each_error_state

# File lib/orogen/spec/task_context.rb, line 803
def fatal_states(*state_names)
    state_names.each do |name|
        define_state(name, :fatal)
    end
end
fd_driven() click to toggle source

Declares that this task context is designed to be woken up when new data is available on a I/O file descriptor. The resulting task must also use the #fd_driven activity, which is done by default.

The only thing you have to do in the implementation is therefore

task = task("MyDFDrivenTask").
    start

To configure the activity, you will need to declare the FDs you want to watch in the configureHook():

RTT::extras::FileDescriptorActivity* fd_activity =
    getActivity<RTT::extras::FileDescriptorActivity>();
if (fd_activity)
    fd_activity->watch(my_fd);

Don't forget to remove all watches in cleanupHook with

RTT::extras::FileDescriptorActivity* fd_activity =
    getActivity<RTT::extras::FileDescriptorActivity>();
if (fd_activity)
    fd_activity->clearAllWatches();
# File lib/orogen/spec/task_context.rb, line 1312
def fd_driven
    default_activity "fd_driven"
    needs_configuration
end
fd_driven?() click to toggle source

True if this task context's default activity is a FD-driven activity

# File lib/orogen/spec/task_context.rb, line 1318
def fd_driven?
    default_activity.first == :fd_driven
end
find_dynamic_input_ports(name, type) click to toggle source

Returns the set of dynamic input port definitions that match the given name and type pair. If type is nil, the type is ignored in the matching.

# File lib/orogen/spec/task_context.rb, line 1227
def find_dynamic_input_ports(name, type)
    if type
        type = project.find_type(type)
    end
    each_dynamic_input_port.find_all { |p| (!type || !p.type || p.type == type) && p.name === name }
end
find_dynamic_output_ports(name, type) click to toggle source

Returns the set of dynamic output port definitions that match the given name and type pair. If type is nil, the type is ignored in the matching.

# File lib/orogen/spec/task_context.rb, line 1244
def find_dynamic_output_ports(name, type)
    if type
        type = project.find_type(type)
    end
    each_dynamic_output_port.find_all { |p| (!type || !p.type || p.type == type) && p.name === name }
end
find_extension(name, with_subclasses = true) click to toggle source

Returns the extension named name, or nil if there is none

# File lib/orogen/spec/task_context.rb, line 141
def find_extension(name, with_subclasses = true)
    if result = extensions.find { |ext| ext.name == name }
        result
    elsif with_subclasses && superclass
        superclass.find_extension(name, true)
    end
end
find_port(name, type = nil) click to toggle source

Finds a port with the given name, and optionally type

Returns nil if there are none

See also find_input_port and find_output_port

# File lib/orogen/spec/task_context.rb, line 1149
def find_port(name, type = nil)
    p = find_input_port(name) || find_output_port(name)
    if !type || (p && p.type == type)
        return p
    end
end
fixed_initial_state() click to toggle source

Declares that the initial state of this class cannot be specified. For orogen-declared tasks, it is the same as needs_configuration?. This mechanism is here for classes that have not been generated by orogen and either have a no way to specify the initial state, or a non-standard one.

# File lib/orogen/spec/task_context.rb, line 1379
def fixed_initial_state; @fixed_initial_state = true end
fixed_initial_state?() click to toggle source

If true, then the initial state of this class cannot be specified. For orogen-declared tasks, it is the same as needs_configuration?. This mechanism is here for classes that have not been generated by orogen and either have a no way to specify the initial state, or a non-standard one.

# File lib/orogen/spec/task_context.rb, line 1372
def fixed_initial_state?; @fixed_initial_state || needs_configuration? || (superclass.fixed_initial_state? if superclass) end
has_dynamic_attributes?() click to toggle source

Return true if this task interface has an dynamic property.

# File lib/orogen/spec/task_context.rb, line 1187
def has_dynamic_attributes?
    self_attributes.each do |p|
        return true if p.dynamic?
    end
    return false
end
has_dynamic_input_port?(name, type = nil) click to toggle source

Returns true if there is an input port definition that match the given name and type pair. If type is nil, the type is ignored in the matching.

# File lib/orogen/spec/task_context.rb, line 1237
def has_dynamic_input_port?(name, type = nil)
    !find_dynamic_input_ports(name, type).empty?
end
has_dynamic_output_port?(name, type = nil) click to toggle source

Returns true if an output port of the given name and type could be created at runtime.

# File lib/orogen/spec/task_context.rb, line 1253
def has_dynamic_output_port?(name, type = nil)
    !find_dynamic_output_ports(name, type).empty?
end
has_dynamic_port?(name, type) click to toggle source

Returns true if there is a dynamic port definition that matches the given name and type pair.

If type is nil, the type is ignored in the matching.

# File lib/orogen/spec/task_context.rb, line 1220
def has_dynamic_port?(name, type)
    has_dynamic_input_port?(name, type) || has_dynamic_output_port?(name, type)
end
has_dynamic_properties?() click to toggle source

Return true if this task interface has an dynamic property.

# File lib/orogen/spec/task_context.rb, line 1179
def has_dynamic_properties?
    self_properties.each do |p|
        return true if p.dynamic?
    end
    return false
end
has_extension?(name, with_subclasses = true) click to toggle source

True if an extension with the given name has been registered

# File lib/orogen/spec/task_context.rb, line 107
def has_extension?(name, with_subclasses = true); !!find_extension(name, with_subclasses) end
has_input_port?(name) click to toggle source

Returns true if this task interface has a port named 'name'. If a type is given, the corresponding port will be matched against that type as well

# File lib/orogen/spec/task_context.rb, line 1166
def has_input_port?(name)
    !!find_input_port(name)
end
has_output_port?(name) click to toggle source

Returns true if this task interface has a port named 'name'. If a type is given, the corresponding port will be matched against that type as well

# File lib/orogen/spec/task_context.rb, line 1173
def has_output_port?(name)
    !!find_output_port(name)
end
has_port?(name, type = nil) click to toggle source

Returns true if this task interface has a port named 'name'. If a type is given, the corresponding port will be matched against that type as well

# File lib/orogen/spec/task_context.rb, line 1159
def has_port?(name, type = nil)
    !!find_port(name, type)
end
has_property?(name) click to toggle source

True if this task has a property with that name

# File lib/orogen/spec/task_context.rb, line 585
def has_property?(name)
    !!find_property(name)
end
hidden_operation(name, body=nil) click to toggle source

Defines an operation whose implementation is in the Base class (i.e. “hidden” from the user)

# File lib/orogen/spec/task_context.rb, line 820
def hidden_operation(name, body=nil)
    op = operation(name)
    op.hidden = true
    if body
        OroGen.warn "body argument for hidden_operation '#{self.name}'.'#{name}' is deprecated, please set the body during generation phase"
        OroGen.warn "If you call this from a plugin, define the implementation within your :early_register_for_generation method"
        op.base_body(body)
    end
    op
end
implements(name, include_file = nil) click to toggle source

Declares that this task context is also a subclass of the following class. name does not have to be a task context class.

# File lib/orogen/spec/task_context.rb, line 217
def implements(name, include_file = nil)
    @implemented_classes << [name, include_file]
end
implements?(name) click to toggle source

True if the task context implements a parent class which matches name. name can either be a string or a regular expression.

# File lib/orogen/spec/task_context.rb, line 223
def implements?(name)
    ancestor_names = ancestors.map(&:name)
    self.name == name ||
        ancestor_names.include?(name)
end
initialize_copy(from) click to toggle source
# File lib/orogen/spec/task_context.rb, line 375
def initialize_copy(from)
end
input_port 'name', '/type' click to toggle source

Add a new write port with the given name and type, and returns the corresponding InputPort object.

See also output_port

# File lib/orogen/spec/task_context.rb, line 1058
def input_port(name, type, options = Hash.new)
    name = OroGen.verify_valid_identifier(name)
    check_uniqueness(name)
    options = Kernel.validate_options options,
        :class => InputPort

    @input_ports[name] = port = options[:class].new(self, name, type)
    Spec.load_documentation(port, /input_port/)
    port
end
inspect() click to toggle source
# File lib/orogen/spec/task_context.rb, line 159
def inspect; to_s end
loader() click to toggle source

The loader that has been used to load this task context

@return [Loaders::Base]

# File lib/orogen/spec/task_context.rb, line 52
def loader; project.loader end
make_property_dynamic(name) click to toggle source

Make an existing property dynamic

@return [Property] the property object

# File lib/orogen/spec/task_context.rb, line 592
def make_property_dynamic(name)
    prop = find_property(name)
    if !prop
        raise ArgumentError, "The requested property " + name + " could not be found"
    end
    property = @properties[name] = prop.dup
    property.task = self
    property.dynamic
    property
end
merge_ports_from(other_model, name_mappings = Hash.new) click to toggle source

Add in self the ports of other_model that don't exist.

Raises ArgumentError if other_model has ports whose name is used in self, but for which the definition is different.

# File lib/orogen/spec/task_context.rb, line 470
def merge_ports_from(other_model, name_mappings = Hash.new)
    other_model.each_port do |p|
        if target_name = name_mappings[p.name]
            p = p.dup
            p.instance_variable_set(:@name, target_name.to_str)
        end

        if has_port?(p.name)
            self_port = find_port(p.name)
            if self_port.class != p.class
                raise ArgumentError, "cannot merge as #{self_port.name} is a #{self_port.class} in #{self} and a #{p.class} in #{other_model}"
            elsif self_port.type != p.type
                raise ArgumentError, "cannot merge as #{self_port.name} is of type #{self_port.type} in #{self} and of type #{p.type} in #{other_model}"
            end
        elsif p.kind_of?(OutputPort)
            @output_ports[p.name] = p
        elsif p.kind_of?(InputPort)
            @input_ports[p.name] = p
        end
    end
    other_model.each_dynamic_port do |p|
        existing = each_dynamic_port.find_all do |self_p|
            p.name == self_p.name
        end
        if !existing.any? { |self_p| self_p.type == p.type }
            self.dynamic_ports << p.dup
        end
    end
end
needs_configuration() click to toggle source

Declares that this task needs to be configured before it is started (i.e. its initial state will be PreOperational instead of Stopped).

If fixed_initial_state? returns true, then this method raises ArgumentError. This is done so that it is possible to declare that some task contexts's implementation require the initial state to be either PreOperational or Stopped.

# File lib/orogen/spec/task_context.rb, line 517
def needs_configuration
    if superclass && superclass.fixed_initial_state? && !superclass.needs_configuration?
        raise ArgumentError, "cannot change the start state of this task context: the superclass #{superclass.name} does not allow it"
    elsif fixed_initial_state? && !needs_configuration?
        raise ArgumentError, "cannot change the start state of this task context: #fixed_initial_state has been specified for it"
    end
    @needs_configuration = true
end
needs_configuration?() click to toggle source

If true, the task context will start in the PreOperational state, and will not be able to run until configure() has been called and returned true.

When subclassing, it is NOT possible to have a subclass starting in the Stopped state while its superclass starts from PreOperational.

# File lib/orogen/spec/task_context.rb, line 507
def needs_configuration?; @needs_configuration || (superclass.needs_configuration? if superclass) end
new_operations() click to toggle source

Operations that are added by this task context (i.e. operations that are defined there but are not present in the superclass)

# File lib/orogen/spec/task_context.rb, line 1026
def new_operations
    super_names = superclass.all_operations.map(&:name).to_set
    @operations.values.find_all do |t|
        !super_names.include?(t)
    end
end
operation(name) click to toggle source

Create a new operation with the given name. Use the returned Operation object to configure it further

# File lib/orogen/spec/task_context.rb, line 811
def operation(name)
    name = OroGen.verify_valid_identifier(name)
    @operations[name] = op = Operation.new(self, name)
    Spec.load_documentation(op, /operation/)
    op
end
output_port 'name', '/type' click to toggle source

Add a new write port with the given name and type, and returns the corresponding OutputPort object.

See also input_port

# File lib/orogen/spec/task_context.rb, line 1040
def output_port(name, type, options = Hash.new)
    name = OroGen.verify_valid_identifier(name)
    check_uniqueness(name)
    options = Kernel.validate_options options,
        :class => OutputPort

    @output_ports[name] = port = options[:class].new(self, name, type)
    Spec.load_documentation(port, /output_port/)
    port
end
periodic(period) click to toggle source

Declares that this task should be deployed using a default periodic activity, with the given period

# File lib/orogen/spec/task_context.rb, line 306
def periodic(period)
    default_activity :periodic, period
end
port_driven(*names) click to toggle source

Declares that this task context is designed to be woken up when new data is available on one of the given ports (or all already defined ports if no names are given).

# File lib/orogen/spec/task_context.rb, line 1263
def port_driven(*names)
    default_activity 'triggered'
    names = names.map { |n| n.to_s }
    relevant_ports =
        if names.empty? then all_input_ports
        else
            names.map do |n|
                obj = find_input_port(n)
                if !obj
                    if has_output_port?(n)
                        raise ArgumentError, "#{n} is an output port of #{self.name}, only input ports can be used in #port_driven"
                    else
                        raise ArgumentError, "#{n} is not a port of #{self.name}"
                    end
                end
                obj
            end
        end

    relevant_ports.each do |port|
        port.trigger_port = true
        @event_ports[port.name] = port
    end
end
pretty_print(pp) click to toggle source
# File lib/orogen/spec/task_context.rb, line 404
def pretty_print(pp)
    pp.text "------- #{name} ------"
    pp.breakable
    if doc
        first_line = true
        doc.split("\n").each do |line|
            pp.breakable if !first_line
            first_line = false
            pp.text "# #{line}"
        end
        pp.breakable
        pp.text "# "
    else
        pp.text "no documentation defined for this task context model"
    end
    pp.breakable
    pp.text "subclass of #{superclass.name} (the superclass elements are displayed below)"
    pp.breakable
    triggers = all_event_ports
    if !triggers.empty?
        pp.text "Triggered on input: #{triggers.map(&:name).join(", ")}"
        pp.breakable
    end
    if needs_configuration?
        pp.text "Needs configuration"
    else
        pp.text "Does NOT need configuration"
    end
    pp.breakable

    pretty_print_interface(pp, "Ports", each_port.to_a)
    pretty_print_interface(pp, "Dynamic Ports", each_dynamic_port.to_a)
    pretty_print_interface(pp, "Properties", each_property.to_a)
    pretty_print_interface(pp, "Attributes", each_attribute.to_a)
    pretty_print_interface(pp, "Operations", each_operation.to_a)

    extensions.each do |ext|
        pp.breakable
        pp.text "Extension: #{ext.name}"
        pp.nest(2) do
            pp.breakable
            ext.pretty_print(pp)
        end
    end
end
pretty_print_interface(pp, name, set) click to toggle source
# File lib/orogen/spec/task_context.rb, line 388
def pretty_print_interface(pp, name, set)
    if set.empty?
        pp.text "No #{name.downcase}"
    else
        pp.text name
        pp.nest(2) do
            set = set.to_a.sort_by { |p| p.name.to_s }
            set.each do |element|
                pp.breakable
                element.pretty_print(pp)
            end
        end
    end
    pp.breakable
end
property(name, type, default_value = nil) click to toggle source

Create a new property with the given name, type and default value for this task. This returns the Property instance representing the new property, whose methods can be used to configure the property further. type is the type name for that property. It can be either in Typelib notation (/std/string) or in C++ notation (std::string). This type must be defined either by the project's own typekit, or by typekits imported with Project#load_typekit.

@example

property('device_name', '/std/string/, '').
    doc 'the device name to connect to'
# File lib/orogen/spec/task_context.rb, line 578
def property(name, type, default_value = nil)
    @properties[name] = prop = configuration_object(Property, name, type, default_value)
    Spec.load_documentation(prop, /property/)
    prop
end
register_extension(obj) click to toggle source

Registers an extension with the given name. Raises ArgumentError if there is already one.

# File lib/orogen/spec/task_context.rb, line 111
def register_extension(obj)
    if (old = find_extension(obj.name, false)) && old != obj
        raise ArgumentError, "there is already an extension called #{obj.name}: #{old}"
    else
        extensions << obj
        obj.registered_on(self)
    end
end
reports(*state_names) click to toggle source

Declares a certain number of reports

This method will do nothing if it defines a report that is already defined by one of the superclasses.

# File lib/orogen/spec/task_context.rb, line 757
def reports(*state_names)
    runtime_states(*state_names)
end
required_activity 'activity_type', *args click to toggle source

The kind of activity that must be used for this task context. This is the name of the corresponding method on the deployment objects. See ACTIVITY_TYPES for the list of known activity types.

See also default_activity

# File lib/orogen/spec/task_context.rb, line 268
dsl_attribute :required_activity do |type, *args|
    if respond_to?(type.to_sym)
        send(type.to_sym, *args)
    else
        default_activity type, *args
    end
    self.required_activity = true
end
required_activity?() click to toggle source

True if the current value of #default_activity is actually required by the task context implementation

# File lib/orogen/spec/task_context.rb, line 256
attr_predicate :required_activity?, true
ro_ptr(name) click to toggle source

This method is an easier way use boost::shared_ptr in a task context interface. For instance, instead of writing

input_port 'image', '/RTT/ReadOnlyPointer</Image>'

you can write

input_port 'image', ro_ptr('/Image')

Additionally, this method makes sure that the corresponding type is actually defined on the project's typekit.

# File lib/orogen/spec/task_context.rb, line 1108
def ro_ptr(name)
    base_type = project.resolve_type(name)

    full_name = "/RTT/extras/ReadOnlyPointer<#{base_type.name}>"
    begin
        project.resolve_type(full_name)
    rescue Typelib::NotFound
        # HACK: this is needed for the codegen part. Will have to go
        # HACK: away once we migrate the codegen part to the
        # HACK: loading infrastructure
        if project.typekit(true).respond_to?(:ro_ptr)
            project.typekit(true).ro_ptr(name)
            project.resolve_type(full_name)
        else raise
        end
    end
end
root_model() click to toggle source

Declares that this task context is a root model and does not have a superclass

# File lib/orogen/spec/task_context.rb, line 211
def root_model
    @superclass = nil
end
runtime_states(*state_names) click to toggle source

Declares a certain number of runtime states

This method will do nothing if it defines a state that is already defined by one of the superclasses.

See error_states, exception_states, each_state, each_runtime_state

# File lib/orogen/spec/task_context.rb, line 767
def runtime_states(*state_names)
    state_names.each do |name|
        define_state(name, :runtime)
    end
end
self_attributes → set_of_attributes click to toggle source

Returns the set of attributes that are added at this level of the model hierarchy. I.e. attributes that are defined on this task context, but not on its parent models.

# File lib/orogen/spec/task_context.rb, line 970
enumerate_inherited_map("attribute", "attributes")
self_dynamic_ports → set_of_ports click to toggle source

Returns the set of dynamic ports that are added at this level of the model hierarchy. I.e. ports that are defined on this task context, but not on its parent models.

# File lib/orogen/spec/task_context.rb, line 892
enumerate_inherited_set("dynamic_port", "dynamic_ports")
self_input_ports → set_of_ports click to toggle source

Returns the set of static input ports that are added at this level of the model hierarchy. I.e. ports that are defined on this task context, but not on its parent models.

# File lib/orogen/spec/task_context.rb, line 918
enumerate_inherited_map("input_port", "input_ports")
self_output_ports → set_of_ports click to toggle source

Returns the set of static output ports that are added at this level of the model hierarchy. I.e. ports that are defined on this task context, but not on its parent models.

# File lib/orogen/spec/task_context.rb, line 944
enumerate_inherited_map("output_port", "output_ports")
self_ports() click to toggle source
# File lib/orogen/spec/task_context.rb, line 1130
def self_ports
    self_input_ports + self_output_ports
end
self_properties → set_of_properties click to toggle source

Returns the set of properties that are added at this level of the model hierarchy. I.e. properties that are defined on this task context, but not on its parent models.

# File lib/orogen/spec/task_context.rb, line 996
enumerate_inherited_map("property", "properties")
shared_ptr(name) click to toggle source

This method is an easier way use boost::shared_ptr in a task context interface. For instance, instead of writing

input_port 'image', '/boost/shared_ptr</Image>'

you can write

input_port 'image', shared_ptr('/Image')

Additionally, this method makes sure that the corresponding type is actually defined on the project's typekit.

# File lib/orogen/spec/task_context.rb, line 1080
def shared_ptr(name)
    base_type = project.resolve_type(name)
    full_name = "/boost/shared_ptr<#{base_type.name}>"
    begin
        project.resolve_type(full_name)
    rescue Typelib::NotFound
        # HACK: this is needed for the codegen part. Will have to go
        # HACK: away once we migrate the codegen part to the
        # HACK: loading infrastructure
        if project.typekit(true).respond_to?(:shared_ptr)
            project.typekit(true).shared_ptr(name)
            project.resolve_type(full_name)
        else raise
        end
    end
end
state?(name) click to toggle source

Returns true if the given state name is already used

# File lib/orogen/spec/task_context.rb, line 640
def state?(name)
    state_kind(name) || (superclass.state?(name.to_s) if superclass)
end
subclasses(task_context) click to toggle source

Declares that this task context is a subclass of the following TaskContext class. task_context can either be a class name or a TaskContext instance. In both cases, it must be defined in the scope of the enclosing Project object – i.e. either defined in it, or imported by a OroGen::Spec::Project#using_task_library call.

# File lib/orogen/spec/task_context.rb, line 189
def subclasses(task_context)
    OroGen.warn_deprecated __method__, "in #{project.name}: use task_context \"Name\", subclasses: \"Parent\" do .. end instead"

    if task_context.respond_to?(:to_str)
        if @superclass && (@superclass != project.default_task_superclass)
            raise OroGen::ConfigError, "#{@name} tries to subclass #{task_context} "+
                "while there is already #{@superclass.name}"
        end
        @superclass = project.task_model_from_name task_context
    else
        @superclass = task_context
    end
    if !superclass
        raise ArgumentError, "no such task context #{task_context}"
    end

    @default_activity  = @superclass.default_activity.dup
    @required_activity = @superclass.required_activity?
end
to_dot() click to toggle source

Generate a graphviz fragment to represent this task

# File lib/orogen/spec/task_context.rb, line 1323
def to_dot
    html_escape = lambda { |s| s.gsub(/</, "&lt;").gsub(/>/, "&gt;") }
    html_table  = lambda do |title, lines|
        label  = "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n"
        label << "  <TR><TD>#{title}</TD></TR>\n"
        label << "  <TR><TD>\n"
        label << lines.join("<BR/>\n")
        label << "  </TD></TR>\n"
        label << "</TABLE>"
    end
        
    result = ""
    result << "  node [shape=none,margin=0,height=.1];"

    label = ""
    label << "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\">\n"
    label << "  <TR><TD>#{name}</TD></TR>"

    properties = all_properties.
        map { |p| "#{p.name} [#{html_escape[p.type_name]}]" }
    if !properties.empty?
        label << "  <TR><TD>#{html_table["Properties", properties]}</TD></TR>"
    end


    input_ports = all_ports.
        find_all { |p| p.kind_of?(InputPort) }.
        map { |p| "#{p.name} [#{html_escape[p.type_name]}]" }
    if !input_ports.empty?
        label << "  <TR><TD>#{html_table["Input ports", input_ports]}</TD></TR>"
    end

    output_ports =all_ports.
        find_all { |p| p.kind_of?(OutputPort) }.
        map { |p| "#{p.name} [#{html_escape[p.type_name]}]" }
    if !output_ports.empty?
        label << "  <TR><TD>#{html_table["Output ports", output_ports]}</TD></TR>"
    end

    label << "</TABLE>"
    result << "  t#{object_id} [label=<#{label}>]"
    result
end
to_h() click to toggle source

Converts this model into a representation that can be fed to e.g. a JSON dump, that is a hash with pure ruby key / values.

The generated hash has the following keys:

name: the name
superclass: the name of this model's superclass (if there is
  one)
states: the list of defined states, as formatted by
  {each_state}
ports: the list of ports, as formatted by {Port#to_h}
properties: the list of properties, as formatted by
  {ConfigurationObject#to_h}
attributes: the list of attributes, as formatted by
  {ConfigurationObject#to_h}
operations: the list of operations, as formatted by
  {Operation#to_h}

@return [Hash]

# File lib/orogen/spec/task_context.rb, line 1400
def to_h
    Hash[
        name: name,
        superclass: superclass.name,
        states: each_state.to_a,
        ports: each_port.map(&:to_h),
        properties: each_property.map(&:to_h),
        attributes: each_attribute.map(&:to_h),
        operations: each_operation.map(&:to_h)
    ]
end
to_s() click to toggle source
# File lib/orogen/spec/task_context.rb, line 158
def to_s; "#<OroGen::Spec::TaskContext: #{name}>" end
toplevel_states(*state_names) click to toggle source

Define the state machine's toplevel states, usually used only on a root model

# File lib/orogen/spec/task_context.rb, line 747
def toplevel_states(*state_names)
    state_names.each do |name|
        define_state(name, :toplevel)
    end
end
self_operations → set_of_operations click to toggle source

:operation: self_operations

Returns the set of operations that are added at this level of the model hierarchy. I.e. operations that are either newly defined on this task context, or overload operations from the parent models.

# File lib/orogen/spec/task_context.rb, line 1022
enumerate_inherited_map("operation", "operations")
use_qt() click to toggle source
# File lib/orogen/spec/task_context.rb, line 181
def use_qt; @uses_qt = true; end
uses_qt?() click to toggle source
# File lib/orogen/spec/task_context.rb, line 182
def uses_qt?; @uses_qt; end
worstcase_processing_time → value click to toggle source
worstcase_processing_time value

Sets or gets the worst-case computation time (i.e. time spent in 'update') for this task context. This should usually not be set in the oroGen file, but in the supervision/deployment code, since the actual computation time will depend on the system.

The time is given in seconds

# File lib/orogen/spec/task_context.rb, line 247
dsl_attribute :worstcase_processing_time do |value|
    Float(value)
end