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
A set of Port objects that can be created at runtime
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
A set of classes the TaskContext has to implement as well
The task name
The oroGen project this task is part of
@return [Project]
The subclass of TaskContext which should be used to define this class
True if QT is used within this Task
Public Class Methods
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
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
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
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.
# 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 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
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
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
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
Returns the set of all attributes that are defined on this task context
# File lib/orogen/spec/task_context.rb, line 961
Returns the set of all dynamic ports that are defined on this task context
# File lib/orogen/spec/task_context.rb, line 883
Returns the set of all static input ports that are defined on this task context
# File lib/orogen/spec/task_context.rb, line 909
Returns the set of all static output ports that are defined on this task context
# File lib/orogen/spec/task_context.rb, line 935
# File lib/orogen/spec/task_context.rb, line 1126 def all_ports all_input_ports + all_output_ports end
Returns the set of all properties that are defined on this task context
# File lib/orogen/spec/task_context.rb, line 987
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
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
# 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
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
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
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
Yields all attributes that are defined on this task context.
# File lib/orogen/spec/task_context.rb, line 953
: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
: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
Yields all dynamic ports that are defined on this task context.
# File lib/orogen/spec/task_context.rb, line 868
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
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
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
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
Yields all static input ports that are defined on this task context.
# File lib/orogen/spec/task_context.rb, line 901
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
Yields all static output ports that are defined on this task context.
# File lib/orogen/spec/task_context.rb, line 927
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
Yields all properties that are defined on this task context.
# File lib/orogen/spec/task_context.rb, line 979
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
# File lib/orogen/spec/task_context.rb, line 375 def initialize_copy(from) end
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
# File lib/orogen/spec/task_context.rb, line 159 def inspect; to_s end
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 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
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
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
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
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
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
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
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
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
# 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
# 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
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
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
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
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
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
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
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
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
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")
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")
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")
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")
# File lib/orogen/spec/task_context.rb, line 1130 def self_ports self_input_ports + self_output_ports end
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")
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
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
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(/</, "<").gsub(/>/, ">") } 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
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
# File lib/orogen/spec/task_context.rb, line 158 def to_s; "#<OroGen::Spec::TaskContext: #{name}>" end
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
: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")
# File lib/orogen/spec/task_context.rb, line 181 def use_qt; @uses_qt = true; end
# File lib/orogen/spec/task_context.rb, line 182 def uses_qt?; @uses_qt; end
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