Class: OroGen::Spec::Project

Inherits:
Object
  • Object
show all
Defined in:
lib/orogen/spec/project.rb

Overview

Representation of an oroGen project

Direct Known Subclasses

ROS::Spec::Package

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(loader) ⇒ Project


43
44
45
46
47
48
49
50
51
52
# File 'lib/orogen/spec/project.rb', line 43

def initialize(loader)
    @loader = loader
    @tasks = Hash.new
    @self_tasks = Hash.new
    @deployers = Hash.new
    @define_default_deployments = true
    @enabled_transports = Set.new
    @max_sizes = Hash.new
    @disabled_namespaces = Array.new
end

Instance Attribute Details

#default_task_superclassObject

Returns the TaskContext object for the default task contexts superclass (i.e. RTT::TaskContext)


134
135
136
137
138
139
# File 'lib/orogen/spec/project.rb', line 134

def default_task_superclass
    if @default_task_superclass.nil?
        @default_task_superclass = loader.task_model_from_name "RTT::TaskContext"
    else @default_task_superclass
    end
end

#deployersHash<String,OroGen::Spec::Deployment> (readonly)

This project's deployments


25
26
27
# File 'lib/orogen/spec/project.rb', line 25

def deployers
  @deployers
end

#disabled_namespacesObject (readonly)

returns all the disabled namespaces


33
34
35
# File 'lib/orogen/spec/project.rb', line 33

def disabled_namespaces
  @disabled_namespaces
end

#enabled_transportsSet<String> (readonly)

The set of transport names that are enabled in this project


31
32
33
# File 'lib/orogen/spec/project.rb', line 31

def enabled_transports
  @enabled_transports
end

#loaderObject (readonly)

The loader that should be used to get our dependencies


10
11
12
# File 'lib/orogen/spec/project.rb', line 10

def loader
  @loader
end

#self_tasksHash<String,OroGen::Spec::TaskContext> (readonly)

The tasks defined by this project


22
23
24
# File 'lib/orogen/spec/project.rb', line 22

def self_tasks
  @self_tasks
end

#tasksHash<String,OroGen::Spec::TaskContext> (readonly)

The tasks known to this project


19
20
21
# File 'lib/orogen/spec/project.rb', line 19

def tasks
  @tasks
end

#typekit(create = nil) ⇒ Object


14
15
16
# File 'lib/orogen/spec/project.rb', line 14

def typekit(create = nil)
    @typekit
end

Class Method Details

.blankObject


36
37
38
39
40
41
# File 'lib/orogen/spec/project.rb', line 36

def self.blank
    loader = Loaders::Base.new
    project = Project.new(loader)
    project.default_task_superclass = false
    project
end

.default_deployment_name(task_model_name) ⇒ Object


5
6
7
# File 'lib/orogen/spec/project.rb', line 5

def self.default_deployment_name(task_model_name)
    "orogen_default_#{task_model_name.gsub(/[^\w]/, '_')}"
end

Instance Method Details

#deployment(name, &block) ⇒ Object

Defines a deployment, i.e. an Unix executable in which a certain number of TaskContext are instanciated, associated with threads and triggers and (optionally) connected to each other and/or started.

The statements in the given block are method calls to a Deployment instance, so see the documentation of that class for more information.


262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/orogen/spec/project.rb', line 262

def deployment(name, &block) # :yield:
    if has_deployment?(name)
        raise ArgumentError, "there is already a deployment named '#{name}' in this oroGen project"
    end

    deployer = Spec::Deployment.new(self, name, &block)
    enabled_transports.each do |t|
        deployer.enable_transport(t)
    end
    deployer.instance_eval(&block) if block_given?
    deployers[deployer.name] = deployer
    deployer
end

#disable_namespace(value) ⇒ Object


55
# File 'lib/orogen/spec/project.rb', line 55

def disable_namespace(value); @disabled_namespaces << value end

#each_deployment {|deployment| ... } ⇒ void

This method returns an undefined value.

Enumerate this project's deployments

Yield Parameters:


343
344
345
346
# File 'lib/orogen/spec/project.rb', line 343

def each_deployment
    return enum_for(__method__) if !block_given?
    deployers.each_value(&proc)
end

#enable_namespace(value) ⇒ Object


54
# File 'lib/orogen/spec/project.rb', line 54

def enable_namespace(value); @disabled_namespaces.delete(value) end

#enable_transports(*transport_names) ⇒ Set<String>

Enable the given transports


328
329
330
331
332
333
334
335
336
337
# File 'lib/orogen/spec/project.rb', line 328

def enable_transports(*transport_names)
    new_transports = transport_names.to_set - enabled_transports
    @enabled_transports |= new_transports
    new_transports.each do |name|
        deployers.each do |d|
            d.enable_transport(name)
        end
    end
    new_transports
end

#external_task_context(name, subclasses: default_task_superclass, **options, &block) ⇒ Object

Declares a task context that has not been generated by oroGen


181
182
183
184
185
186
187
188
189
# File 'lib/orogen/spec/project.rb', line 181

def external_task_context(name, subclasses: default_task_superclass, **options, &block)
    component_class = options.fetch(:class, TaskContext)

    new_task = component_class.new(self, "#{self.name}::#{name}", subclasses: subclasses)
    new_task.instance_eval(&block) if block_given?
    tasks[new_task.name] = new_task
    loader.loaded_task_models[new_task.name] = new_task
    new_task
end

#find_deployment_by_name(name) ⇒ Deployment?

Returns the deployment model with the given name


250
251
252
# File 'lib/orogen/spec/project.rb', line 250

def find_deployment_by_name(name)
    deployers[name]
end

#find_interface_type(name) ⇒ Object


238
239
240
# File 'lib/orogen/spec/project.rb', line 238

def find_interface_type(name)
    loader.resolve_interface_type(name)
end

#find_task_context(name) ⇒ Object

Deprecated.

use #task_model_from_name instead


214
215
216
217
218
# File 'lib/orogen/spec/project.rb', line 214

def find_task_context(name)
    task_model_from_name(name)
rescue OroGen::TaskModelNotFound => e
    raise ArgumentError, e.message, e.backtrace
end

#find_type(name) ⇒ Object


234
235
236
# File 'lib/orogen/spec/project.rb', line 234

def find_type(name)
    loader.resolve_type(name)
end

#has_deployment?(name) ⇒ Boolean

True if there is a deployment with the given name in this oroGen project


222
223
224
# File 'lib/orogen/spec/project.rb', line 222

def has_deployment?(name)
    deployers.has_key?(name)
end

#import_types_from(typekit) ⇒ Object


198
199
200
201
202
203
# File 'lib/orogen/spec/project.rb', line 198

def import_types_from(typekit)
    if typekit.respond_to?(:to_str) && !loader.has_typekit?(typekit)
        return
    end
    using_typekit(typekit)
end

#intermediate_type_for(type) ⇒ Object


242
243
244
# File 'lib/orogen/spec/project.rb', line 242

def intermediate_type_for(type)
    loader.intermediate_type_for(type)
end

#max_sizes(typename = nil, *values, &block) ⇒ Object

Adds some max size specification for a given type

See OutputPort#max_sizes for a complete description of this functionality. The sizes specified through this global method are applied on every port of the provided type


94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/orogen/spec/project.rb', line 94

def max_sizes(typename = nil, *values, &block)
    if !typename && values.empty?
        return @max_sizes
    end

    type  = find_type(typename)
    # Cannot completely validate the spec, since we may not yet have
    # the m-types. Do what we can, we'll do full blown validation
    # later
    sizes = Port.validate_max_sizes_spec(nil, values)
    @max_sizes[type.name] ||= Hash.new
    @max_sizes[type.name].merge!(sizes, &block)
end

#nameString #name(new_name) ⇒ self

Gets or sets the project's name


65
66
67
68
69
70
# File 'lib/orogen/spec/project.rb', line 65

dsl_attribute :name do |new|
    if !new.respond_to?(:to_str)
        raise ArgumentError, 'name should be a string'
    end
    new
end

#namespace_disabled?(value) ⇒ Boolean


56
# File 'lib/orogen/spec/project.rb', line 56

def namespace_disabled?(value); @disabled_namespaces.include?(value) end

#pretty_print(pp) ⇒ Object

Displays the content of this oroGen project in a nice form


301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/orogen/spec/project.rb', line 301

def pretty_print(pp) # :nodoc:
    if !self_tasks.empty?
        pp.text "  Task Contexts:"
        pp.nest(4) do
            pp.breakable
            pp.seplist(self_tasks.values.sort_by(&:name)) do |t|
                t.pretty_print(pp)
            end
        end
    end

    if !deployers.empty?
        pp.breakable if !self_tasks.empty?
        pp.text "  Deployers:"
        pp.nest(4) do
            pp.breakable
            pp.seplist(deployers.values.sort_by(&:name)) do |d|
                d.pretty_print(pp)
            end
        end
    end
end

#resolve_interface_type(type) ⇒ Object


230
231
232
# File 'lib/orogen/spec/project.rb', line 230

def resolve_interface_type(type)
    loader.resolve_interface_type(type)
end

#resolve_type(type) ⇒ Object


226
227
228
# File 'lib/orogen/spec/project.rb', line 226

def resolve_type(type)
    loader.resolve_type(type)
end

#simple_deployment(name, klass) ⇒ Object

Create a deployment called name with one task of type klass also called name.

The returned value allows to set up the task. For instance, to deploy a periodic task one would do

simple_deployment("task", "Task").
    periodic(0.001)

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/orogen/spec/project.rb', line 284

def simple_deployment(name, klass)
    has_logger = loader.has_project?('logger')
    if has_logger
        using_task_library "logger"
    end

    result = nil
    deployment name do
        result = task name, klass
        if has_logger
            add_default_logger
        end
    end
    result
end

#task_context(name, subclasses: default_task_superclass, **options, &block) ⇒ Object

Creates a new task context class of this name. The generated class is defined in the project's namespace. Therefore

name "test_project"
task_context "SpecificTask" do
  .. task context specification ..
end

defines a test_project::SpecificTask class.

Task contexts are represented as instances of TaskContext. See the documentation of that class for more details.


153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/orogen/spec/project.rb', line 153

def task_context(name, subclasses: default_task_superclass, **options, &block)
    if namespace_disabled?(name.split("::")[0..-2].join("::"))
        return
    end

    if name == self.name
        raise ArgumentError, "a task cannot have the same name as the project"
    elsif name !~ /^(\w+::)*\w+$/
        raise ArgumentError, "task names need to be valid C++ identifiers, i.e. contain only alphanumeric characters and _ (got #{name})"
    end

    name = OroGen.verify_valid_identifier(name)

    task = external_task_context(name, subclasses: subclasses, **options, &block)
    task.extended_state_support
    self_tasks[task.name] = task

    if !task.abstract? && define_default_deployments?
        simple_deployment(Project.default_deployment_name(task.name), task.name)
    end

    task
end

#task_model_from_name(name) ⇒ Spec::TaskContext

Returns the task model object corresponding to a model name

Raises:


206
207
208
209
210
211
# File 'lib/orogen/spec/project.rb', line 206

def task_model_from_name(name)
    if name !~ /::/
        name = "#{self.name}::#{name}"
    end
    tasks[name] || loader.task_model_from_name(name)
end

#to_sObject


348
349
350
# File 'lib/orogen/spec/project.rb', line 348

def to_s
    "#<#{self.class}: name=#{name} loader=#{loader}>"
end

#using_task_library(tasklib) ⇒ Project

Makes the tasks defined by the given task library known to this project


122
123
124
125
126
127
128
# File 'lib/orogen/spec/project.rb', line 122

def using_task_library(tasklib)
    if tasklib.respond_to?(:to_str)
        tasklib = loader.task_library_model_from_name(tasklib)
    end
    tasks.merge! tasklib.self_tasks
    tasklib
end

#using_typekit(typekit) ⇒ Object


191
192
193
194
195
196
# File 'lib/orogen/spec/project.rb', line 191

def using_typekit(typekit)
    if typekit.respond_to?(:to_str)
        loader.typekit_model_from_name(typekit)
    else loader.register_typekit_objects(typekit)
    end
end

#validate_max_sizes_specObject


108
109
110
111
112
113
114
115
# File 'lib/orogen/spec/project.rb', line 108

def validate_max_sizes_spec
    @max_sizes.dup.each do |type, sizes|
        type = intermediate_type_for(type)
        sizes = Port.validate_max_sizes_spec(type, sizes)
        @max_sizes[type.name] ||= Hash.new
        @max_sizes[type.name].merge!(sizes)
    end
end

#versionString #version(new_version) ⇒ String

Gets or sets the project's version

Overloads:

  • #versionString

    The version number of this project. Defaults to “0.0”


81
82
83
84
85
86
87
# File 'lib/orogen/spec/project.rb', line 81

dsl_attribute(:version) do |name|
    name = name.to_s
    if name !~ /^\d/
        raise ArgumentError, "version strings must start with a number (had: #{name})"
    end
    name
end