Class: OroGen::Spec::Port
- Inherits:
-
Object
- Object
- OroGen::Spec::Port
- Defined in:
- lib/orogen/spec/port.rb
Overview
Generic representation of ports. The actual ports are either instance of InputPort or OutputPort
Direct Known Subclasses
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
The port name.
-
#task ⇒ Object
readonly
The port task.
-
#type ⇒ Object
readonly
The port type.
Class Method Summary collapse
-
.compute_max_marshalling_size(type, max_sizes) ⇒ Object
Returns the maximum size of a marshalled sample coming out of this port.
- .initialize_max_size_sample(path, sample, max_sizes) ⇒ Object
- .resolve_max_size_path(type, name) ⇒ Object
- .validate_max_sizes_spec(resolved_type, values) ⇒ Object
Instance Method Summary collapse
-
#dynamic ⇒ Object
Declares that this port can be connected/disconnected while the task context is running.
-
#dynamic? ⇒ Boolean
True if this is a dynamic port model, false otherwise.
- #each_interface_type {|type| ... } ⇒ Object
-
#initialize(task, name, type, options = Hash.new) ⇒ Port
constructor
A new instance of Port.
-
#max_marshalling_size ⇒ Object
Returns the maximum marshalled size of a sample from this port, as marshalled by typelib.
-
#max_sizes ⇒ Object
:method: max_sizes.
-
#orocos_type_name ⇒ Object
The port name as it is registered on RTT.
- #pretty_print(pp) ⇒ Object
-
#static ⇒ Object
Declares that this port can be connected/disconnected only when the task context is in a non-running state.
-
#static? ⇒ Boolean
True if the task context supports only static connections on this port, and false otherwise.
-
#to_h ⇒ Hash
Converts this model into a representation that can be fed to e.g.
-
#type_name ⇒ Object
The port type name.
Constructor Details
#initialize(task, name, type, options = Hash.new) ⇒ Port
Returns a new instance of Port
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/orogen/spec/port.rb', line 90 def initialize(task, name, type, = Hash.new) if !name.kind_of?(Regexp) name = name.to_s if name !~ /^\w+$/ raise ArgumentError, "port names need to be valid C++ identifiers, i.e. contain only alphanumeric characters and _ (got #{name})" end elsif !type && !dynamic? raise ArgumentError, "only dynamic ports are allowed to have no type" end if type type = task.project.find_interface_type(type) OroGen.validate_toplevel_type(type) if type.name == "/std/vector<double>" Spec.warn "#{type.name} is used as the port type for #{name}, logging it will not be possible" end end @task, @name, @type = task, name, type @doc = nil @max_sizes = Hash.new keep_last_written_value :initial end |
Instance Attribute Details
#name ⇒ Object (readonly)
The port name
9 10 11 |
# File 'lib/orogen/spec/port.rb', line 9 def name @name end |
#task ⇒ Object (readonly)
The port task
7 8 9 |
# File 'lib/orogen/spec/port.rb', line 7 def task @task end |
#type ⇒ Object (readonly)
The port type. It can be nil for dynamic ports
11 12 13 |
# File 'lib/orogen/spec/port.rb', line 11 def type @type end |
Class Method Details
.compute_max_marshalling_size(type, max_sizes) ⇒ Object
Returns the maximum size of a marshalled sample coming out of this port
If the type on this port contains variable-size containers, this method will return nil unless the 'max_sizes' map specifies their size
230 231 232 233 234 235 236 237 |
# File 'lib/orogen/spec/port.rb', line 230 def self.compute_max_marshalling_size(type, max_sizes) sample = type.new path = [] if initialize_max_size_sample(path, sample, max_sizes) sample.to_byte_array(:remove_trailing_skips => false).length end end |
.initialize_max_size_sample(path, sample, max_sizes) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/orogen/spec/port.rb', line 169 def self.initialize_max_size_sample(path, sample, max_sizes) sample_t = sample.class if !(sample_t <= Typelib::Type) || !sample_t.contains?(Typelib::ContainerType) return true end path = path.dup if sample.kind_of?(Typelib::ContainerType) max_size = max_sizes[path.join(".")] if !max_size return false end if path.empty? then path = ["[]"] else path[-1] = "#{path[-1]}[]" end element = sample_t.deference.new if !initialize_max_size_sample(path, element, max_sizes) return false end Typelib.copy(sample, sample.class.of_size(max_size, element)) return true elsif sample.kind_of?(Typelib::ArrayType) if path.empty? then path = ["[]"] else path[-1] = "#{path[-1]}[]" end element = sample_t.deference.new if !initialize_max_size_sample(path, element, max_sizes) return false end sample_t.size.times do |i| sample[i] = element end return true elsif sample.kind_of?(Typelib::CompoundType) path << nil sample_t.each_field do |field_name, _| field = sample.raw_get_field(field_name) path[-1] = field_name if !initialize_max_size_sample(path, field, max_sizes) return false end end return true end raise InternalError, "unknown case in initialize_max_size_sample for #{path.join(".")} of type #{sample_t.name}" end |
.resolve_max_size_path(type, name) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/orogen/spec/port.rb', line 121 def self.resolve_max_size_path(type, name) resolved_type = name.split('.').inject(type) do |resolved_type, element| match_deference = element.match(/(\[\])*$/) if !match_deference.pre_match.empty? resolved_type = resolved_type[match_deference.pre_match] end (match_deference[0].length / 2).times do resolved_type = resolved_type.deference end resolved_type end if !(resolved_type <= Typelib::ContainerType) raise ArgumentError, "#{name} resolves to the #{resolved_type.name} type in #{type.name}, which is not a variable size container" end resolved_type end |
.validate_max_sizes_spec(resolved_type, values) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/orogen/spec/port.rb', line 141 def self.validate_max_sizes_spec(resolved_type, values) values = if values.respond_to?(:to_ary) # values is either [spec] or [vector_size, spec] # This is used by dsl_attribute implementations of # max_sizes if values.size == 1 values[0].to_hash elsif values.size == 2 values[1].to_hash.merge('' => values[0]) end elsif values.respond_to?(:to_hash) # Direct call values.to_hash else raise ArgumentError, "expected a one or two element array or a hash, got #{values.inspect}" end values.each do |name, value| if resolved_type resolve_max_size_path(resolved_type, name) end value.to_int end values end |
Instance Method Details
#dynamic ⇒ Object
Declares that this port can be connected/disconnected while the task context is running. It is the opposite of #static.
This is the default
81 |
# File 'lib/orogen/spec/port.rb', line 81 def dynamic; @static = false end |
#dynamic? ⇒ Boolean
True if this is a dynamic port model, false otherwise
88 |
# File 'lib/orogen/spec/port.rb', line 88 def dynamic?; false end |
#each_interface_type {|type| ... } ⇒ Object
19 20 21 22 |
# File 'lib/orogen/spec/port.rb', line 19 def each_interface_type return enum_for(__method__) if !block_given? yield type end |
#max_marshalling_size ⇒ Object
Returns the maximum marshalled size of a sample from this port, as marshalled by typelib
If the type contains variable-size containers, the result is dependent on the values given to #max_sizes. If not enough is known, this method will return nil.
294 295 296 297 |
# File 'lib/orogen/spec/port.rb', line 294 def max_marshalling_size resolved_type = task.project.intermediate_type_for(type) OutputPort.compute_max_marshalling_size(resolved_type, max_sizes) end |
#max_sizes ⇒ Object
:method: max_sizes
:call-seq:
max_sizes('name.to[].field' => value, 'name.other' => value) => self
max_sizes(10, 'name.to[].field' => value, 'name.other' => value) => self
max_sizes => current size specification
Sets the maximum allowed size for the variable-size containers in
type
. The mapping is given as path.to.field => size, where
[] is used to get elements of an array or variable-size container.
If the port type is a container itself, the second form is used, where the first argument is the container size and the rest specifies its element sizes (and must start with [])
For instance, with the types
struct A
{
std::vector<int> values;
};
struct B
{
std::vector<A> field;
};
Then sizes on a port of type B would be given with
port.max_sizes('field' => 10, 'field[].values' => 20)
while the sizes on a port of type std::vector<A> would be given with
port.max_sizes(10, '[].values' => 20)
Finally, on a port of type std::vector<std::vector<A>>, one would use
port.max_sizes(10, '[]' => 20, '[][].values' => 30)
280 281 282 283 284 285 286 |
# File 'lib/orogen/spec/port.rb', line 280 dsl_attribute :max_sizes do |*values| # Validate that all values are integers and all names map to # known types resolved_type = task.project.intermediate_type_for(type) values = OutputPort.validate_max_sizes_spec(resolved_type, values) @max_sizes.merge(values) end |
#orocos_type_name ⇒ Object
The port name as it is registered on RTT
15 16 17 |
# File 'lib/orogen/spec/port.rb', line 15 def orocos_type_name type.name end |
#pretty_print(pp) ⇒ Object
83 84 85 |
# File 'lib/orogen/spec/port.rb', line 83 def pretty_print(pp) pp.text "[#{self.kind_of?(InputPort) ? "in" : "out"}]#{name}:#{type_name}" end |
#static ⇒ Object
Declares that this port can be connected/disconnected only when the task context is in a non-running state.
The default is that the port is dynamic, i.e. can be connected/disconnected regardless of the task context's state.
See also #dynamic
75 |
# File 'lib/orogen/spec/port.rb', line 75 def static; @static = true end |
#static? ⇒ Boolean
True if the task context supports only static connections on this port, and false otherwise
See #static for more details.
66 |
# File 'lib/orogen/spec/port.rb', line 66 def static?; !!@static end |
#to_h ⇒ Hash
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
type: the type (as marshalled with Typelib::Type#to_h)
direction: either the string 'input' or 'output'
doc: the documentation string
35 36 37 38 39 40 41 42 |
# File 'lib/orogen/spec/port.rb', line 35 def to_h Hash[ direction: (if kind_of?(OutputPort) then 'output' else 'input' end), name: name, type: type.to_h, doc: (doc || "") ] end |
#type_name ⇒ Object
The port type name
13 |
# File 'lib/orogen/spec/port.rb', line 13 def type_name; type.name end |