Module: Syskit::RobyApp::Plugin

Defined in:
lib/syskit/roby_app/plugin.rb

Overview

This gets mixed in Roby::Application when the orocos plugin is loaded. It adds the configuration facilities needed to plug-in orogen projects in Roby.

When in development mode, it will emit the following UI events:

syskit_orogen_config_changed

files under config/orogen/ have been modified, and this affects loaded models. In addition, a text notification is sent to inform a shell user

Defined Under Namespace

Modules: LoadToplevelMethods Classes: OroGenLocation, VariableSizedType

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.toplevel_objectObject

Returns the value of attribute toplevel_object



788
789
790
# File 'lib/syskit/roby_app/plugin.rb', line 788

def toplevel_object
  @toplevel_object
end

Class Method Details

.auto_require_models(app) ⇒ Object



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/syskit/roby_app/plugin.rb', line 451

def self.auto_require_models(app)
    # Load the data services and task models
    prefixes = ['services', 'devices', 'compositions', 'profiles']
    if Roby.app.backward_compatible_naming?
        prefixes << 'blueprints'
    end

    if Syskit.conf.ignore_missing_orogen_projects_during_load?
        ignored_exceptions = [OroGen::NotFound]
    end
    prefixes.each do |prefix_name|
        app.load_all_model_files_in(
            prefix_name, ignored_exceptions: ignored_exceptions)
    end

    # Also require all the available oroGen projects
    app.default_loader.each_available_project_name do |name|
        app.using_task_library name
    end

    if app.auto_load_all? || app.auto_load_all_task_libraries?
        app.auto_load_all_task_libraries
    end
end

.cleanup(app) ⇒ Object

Hook called by the main application to undo what require_models and setup have done



167
168
169
170
171
172
173
174
# File 'lib/syskit/roby_app/plugin.rb', line 167

def self.cleanup(app)
    if app.development_mode?
        app.syskit_remove_configuration_changes_listener
    end

    disconnect_all_process_servers
    stop_local_process_server
end

.clear_config(app) ⇒ Object

Called by the main Roby application to clear all before redoing a setup



447
448
449
# File 'lib/syskit/roby_app/plugin.rb', line 447

def self.clear_config(app)
    Syskit.conf.clear
end

.clear_models(app) ⇒ Object



735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
# File 'lib/syskit/roby_app/plugin.rb', line 735

def self.clear_models(app)
    OroGen.clear

    app.loaded_orogen_projects.clear
    app.default_loader.clear

    # We need to explicitly call Orocos.clear even though it looks
    # like clearing the process servers would be sufficient
    #
    # The reason is that #cleanup only disconnects from the process
    # servers, and is called before #clear_models. However, for
    # "fake" process servers, syskit also assumes that reconnecting
    # to a "new" local process server will have cleared all cached
    # values. This won't work as the process server will not be
    # cleared in addition of being disconnected
    #
    # I (sylvain) chose to not clear on disconnection as it sounds
    # too much like a very bad side-effect to me. Simply explicitly
    # clear the local registries here
    Orocos.clear

    # This needs to be cleared here and not in
    # Component.clear_model. The main reason is that we need to
    # clear them on every component model class,
    # including the models that are markes as permanent
    Syskit::Component.placeholder_models.clear
    Syskit::Component.each_submodel do |sub|
        sub.placeholder_models.clear
    end

    # require_models is where the deployments get loaded, so
    # un-define them here
    Syskit.conf.clear_deployments
end

.connect_to_local_process_server(app) ⇒ Object



554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'lib/syskit/roby_app/plugin.rb', line 554

def self.connect_to_local_process_server(app)
    if !@server_pid
        raise Orocos::RemoteProcesses::Client::StartupFailed, "#connect_to_local_process_server got called but no process server is being started"
    end

    # Wait for the server to be ready
    client = nil
    while !client
        client =
            begin Orocos::RemoteProcesses::Client.new('localhost', @server_port)
            rescue Errno::ECONNREFUSED
                sleep 0.1
                is_running =
                    begin
                        !::Process.waitpid(@server_pid, ::Process::WNOHANG)
                    rescue Errno::ESRCH
                        false
                    end

                if !is_running
                    raise Orocos::RemoteProcesses::Client::StartupFailed, "the local process server failed to start"
                end
                nil
            end
    end

    # Verify that the server is actually ours (i.e. check that there
    # was not one that was still running)
    if client.server_pid != @server_pid
        raise Orocos::RemoteProcesses::Client::StartupFailed, "failed to start the local process server. It seems that there is one still running as PID #{client.server_pid} (was expecting #{@server_pid})"
    end

    # Do *not* manage the log directory for that one ...
    Syskit.conf.register_process_server('localhost', client, app.log_dir)
    client
end

.disable_engine_in_roby(roby_engine, *handlers) ⇒ Object



713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
# File 'lib/syskit/roby_app/plugin.rb', line 713

def self.disable_engine_in_roby(roby_engine, *handlers)
    if @handler_ids
        handlers.each do |h|
            roby_engine.remove_propagation_handler(@handler_ids.delete(h))
        end

        begin
            yield
        ensure
            all_handlers = roby_engine_propagation_handlers
            handlers.each do |h|
                @handler_ids[h] = roby_engine.add_propagation_handler(all_handlers[h][1], &all_handlers[h][0])
            end
        end
    else yield
    end
end

.disconnect_all_process_serversObject

Disconnects from all process servers



605
606
607
608
609
610
611
612
# File 'lib/syskit/roby_app/plugin.rb', line 605

def self.disconnect_all_process_servers
    process_servers = Syskit.conf.each_process_server_config.map(&:name)
    process_servers.each do |name|
        next if name =~ /-sim$/
        ps = Syskit.conf.remove_process_server(name)
        ps.client.disconnect
    end
end

.enableObject



790
791
792
793
794
795
796
797
798
799
800
# File 'lib/syskit/roby_app/plugin.rb', line 790

def self.enable
    ::Robot.include Syskit::RobyApp::RobotExtension
    ::Roby.conf.syskit = Syskit.conf

    OroGen.load_orogen_plugins('syskit')
    Roby.app.filter_out_patterns << Regexp.new(Regexp.quote(OroGen::OROGEN_LIB_DIR))
    Roby.app.filter_out_patterns << Regexp.new(Regexp.quote(Orocos::OROCOSRB_LIB_DIR))
    Roby.app.filter_out_patterns << Regexp.new(Regexp.quote(Typelib::TYPELIB_LIB_DIR))
    Roby.app.filter_out_patterns << Regexp.new(Regexp.quote(Syskit::SYSKIT_LIB_DIR))
    toplevel_object.extend LoadToplevelMethods
end

.finalize_model_loading(app) ⇒ Object



248
249
250
251
252
# File 'lib/syskit/roby_app/plugin.rb', line 248

def self.finalize_model_loading(app)
    if toplevel_object.respond_to?(:global_profile)
        app.app_module::Actions::Main.use_profile toplevel_object.global_profile
    end
end

.fixed_size_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


826
827
828
# File 'lib/syskit/roby_app/plugin.rb', line 826

def self.fixed_size_type?(type)
    !type.contains?(Typelib::ContainerType)
end

.globally_sized_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


830
831
832
833
# File 'lib/syskit/roby_app/plugin.rb', line 830

def self.globally_sized_type?(type)
    sizes = Orocos.max_sizes_for(type)
    !sizes.empty? && OroGen::Spec::Port.compute_max_marshalling_size(type, sizes)
end

.has_local_process_server?Boolean

Returns:

  • (Boolean)


550
551
552
# File 'lib/syskit/roby_app/plugin.rb', line 550

def self.has_local_process_server?
    @server_pid
end

.load_base_config(app) ⇒ Object

Hook called by the main application in Application#load_base_config



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/syskit/roby_app/plugin.rb', line 35

def self.load_base_config(app)
    options = app.options
    conf = Syskit.conf
    if options = options['syskit']
        conf.prefix = options['prefix']
        conf.exclude_from_prefixing.concat(options['exclude_from_prefixing'] || [])
        conf.sd_domain = options['sd_domain']
        conf.publish_on_sd.concat(options['publish_on_sd'] || [])
    end

    if app.testing?
        require 'syskit/test'
    end

    Orocos.disable_sigchld_handler = true
end

.load_default_models(app) ⇒ Object



476
477
478
479
480
481
482
# File 'lib/syskit/roby_app/plugin.rb', line 476

def self.load_default_models(app)
    ['services.rb', 'devices.rb', 'compositions.rb', 'profiles.rb'].each do |root_file|
        if path = app.find_file('models', root_file, path: [app.app_dir], order: :specific_first)
            require path
        end
    end
end

.plug_engine_in_roby(roby_engine) ⇒ Object



680
681
682
683
684
685
686
# File 'lib/syskit/roby_app/plugin.rb', line 680

def self.plug_engine_in_roby(roby_engine)
    handler_ids = Hash.new
    roby_engine_propagation_handlers.each do |name, (m, options)|
        handler_ids[name] = roby_engine.add_propagation_handler(options, &m)
    end
    handler_ids
end

.plug_handler_in_roby(roby_engine, *handlers) ⇒ Object



695
696
697
698
699
700
701
# File 'lib/syskit/roby_app/plugin.rb', line 695

def self.plug_handler_in_roby(roby_engine, *handlers)
    handlers.each do |handler_name|
        m, options = roby_engine_propagation_handlers.fetch(handler_name)
        next if @handler_ids.has_key?(handler_name)
        @handler_ids[handler_name] = roby_engine.add_propagation_handler(options, &m)
    end
end

.prepare(app) ⇒ Object

Hook called by the main application to prepare for execution



177
178
179
# File 'lib/syskit/roby_app/plugin.rb', line 177

def self.prepare(app)
    @handler_ids = plug_engine_in_roby(app.execution_engine)
end

.require_models(app) ⇒ Object

Hook called by the main application in Application#setup after the main setup hooks have been called



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/syskit/roby_app/plugin.rb', line 145

def self.require_models(app)
    setup_loaders(app)

    app.extra_required_task_libraries.each do |name|
        app.using_task_library name
    end
    app.extra_required_typekits.each do |name|
        app.import_types_from name
    end

    if !app.permanent_requirements.empty?
        toplevel_object.extend SingleFileDSL
        app.execution_engine.once do
            app.permanent_requirements.each do |req|
                app.plan.add_mission_task(req.as_plan)
            end
        end
    end
end

.roby_engine_propagation_handlersObject



667
668
669
670
671
672
673
674
675
676
677
678
# File 'lib/syskit/roby_app/plugin.rb', line 667

def self.roby_engine_propagation_handlers
    handlers = Hash.new
    handlers[:update_deployment_states] = [
        Runtime.method(:update_deployment_states), type: :external_events, description: 'syskit:update_deployment_states']
    handlers[:update_task_states] = [
        Runtime.method(:update_task_states), type: :external_events, description: 'syskit:update_task_states']
    handlers[:connection_management] = [
        Runtime::ConnectionManagement.method(:update), type: :propagation, late: true, description: 'syskit:connection_management_update']
    handlers[:apply_requirement_modifications] = [
        Runtime.method(:apply_requirement_modifications), type: :propagation, late: true, description: 'syskit:apply_requirement_modifications']
    handlers
end

.root_modelsObject



731
732
733
# File 'lib/syskit/roby_app/plugin.rb', line 731

def self.root_models
    [Syskit::Component, Syskit::Actions::Profile]
end

.setup(app) ⇒ Object

Hook called by the main application at the beginning of Application#setup



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/syskit/roby_app/plugin.rb', line 53

def self.setup(app)
    # We have our own loader, avoid clashing
    Orocos.default_loader.export_types = false
    # But, for the time being, default_loader might be equal to
    # Orocos.default_loader, so reset the export_types flag to the
    # desired value
    app.default_loader.export_types = Syskit.conf.export_types?

    # This is a HACK. We should be able to specify it differently
    if app.testing? && app.auto_load_models?
        app.auto_load_all_task_libraries = true
    end

    if app.development_mode?
        require 'listen'
        app.syskit_listen_to_configuration_changes
    end

    if app.testing?
        Syskit.conf.logs.disable_conf_logging
        Syskit.conf.logs.disable_port_logging
    end

    unless Syskit.conf.only_load_models?
        Syskit.conf.logs.create_configuration_log(
            File.join(app.log_dir, 'properties'))
    end

    if Syskit.conf.define_default_process_managers? && Syskit.conf.only_load_models?
        fake_client = Configuration::ModelOnlyServer.new(app.default_loader)
        Syskit.conf.register_process_server(
            'ruby_tasks', fake_client, app.log_dir, host_id: 'syskit')
        Syskit.conf.register_process_server(
            'unmanaged_tasks', fake_client, app.log_dir, host_id: 'syskit')
        Syskit.conf.register_process_server(
            'ros', fake_client, app.log_dir, host_id: 'syskit')
    elsif Syskit.conf.define_default_process_managers?
        Syskit.conf.register_process_server('ruby_tasks',
            Orocos::RubyTasks::ProcessManager.new(app.default_loader),
            app.log_dir, host_id: 'syskit')

        Syskit.conf.register_process_server(
            'unmanaged_tasks', UnmanagedTasksManager.new, app.log_dir)

        Syskit.conf.register_process_server(
            'ros', Orocos::ROS::ProcessManager.new(app.ros_loader),
            app.log_dir)
    end

    if Orocos.orocos_logfile
        ENV['ORO_LOGFILE'] = Orocos.orocos_logfile
    else
        ENV['ORO_LOGFILE'] = File.join(app.log_dir, "orocos.orocosrb-#{::Process.pid}.txt")
    end

    if Syskit.conf.only_load_models?
        Orocos.load
        if Orocos::ROS.available?
            Orocos::ROS.load
        end
    else
        # Change to the log dir so that the IOR file created by
        # the CORBA bindings ends up there
        Dir.chdir(app.log_dir) do
            Orocos.initialize
            if Orocos::ROS.enabled?
                Orocos::ROS.initialize
                Orocos::ROS.roscore_start(:wait => true)
            end
        end
    end

    start_local_process_server =
        Syskit.conf.define_default_process_managers? &&
        !Syskit.conf.only_load_models? &&
        !Syskit.conf.disables_local_process_server? &&
        !(app.single? && app.simulation?)

    if start_local_process_server
        start_local_process_server(redirect: Syskit.conf.redirect_local_process_server?)
        connect_to_local_process_server(app)
    else
        fake_client = Configuration::ModelOnlyServer.new(app.default_loader)
        Syskit.conf.register_process_server('localhost', fake_client, app.log_dir, host_id: 'syskit')
    end

    rtt_core_model = app.default_loader.task_model_from_name("RTT::TaskContext")
    Syskit::TaskContext.define_from_orogen(rtt_core_model, register: true)
end

.setup_loaders(app) ⇒ Object



335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/syskit/roby_app/plugin.rb', line 335

def self.setup_loaders(app)
    all_files =
        app.find_files_in_dirs("models", "ROBOT", "pack", "orogen", :all => app.auto_load_all?, :order => :specific_first, :pattern => /\.orogen$/)
    all_files.reverse.each do |path|
        name = File.basename(path, ".orogen")
        app.orogen_pack_loader.register_orogen_file path, name
    end

    all_files =
        app.find_files_in_dirs("models", "ROBOT", "pack", "orogen", :all => app.auto_load_all?, :order => :specific_first, :pattern => /\.typelist$/)
    all_files.reverse.each do |path|
        name = File.basename(path, ".typelist")
        dir  = File.dirname(path)
        app.orogen_pack_loader.register_typekit dir, name
    end

    app.ros_loader.search_path.
        concat(Roby.app.find_dirs('models', 'ROBOT', 'orogen', 'ros', :all => app.auto_load_all?, :order => :specific_first))
    app.ros_loader.packs.
        concat(Roby.app.find_dirs('models', 'ROBOT', 'pack', 'ros', :all => true, :order => :specific_last))
end

.setup_rest_interface(app, rest_api) ⇒ Object



849
850
851
852
# File 'lib/syskit/roby_app/plugin.rb', line 849

def self.setup_rest_interface(app, rest_api)
    require 'syskit/roby_app/rest_api'
    rest_api.mount REST_API => '/syskit'
end

.shutdown(app) ⇒ Object

Hook called by the main application to undo what prepare did



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/syskit/roby_app/plugin.rb', line 182

def self.shutdown(app)
    remaining = Orocos.each_process.to_a
    if !remaining.empty?
        Syskit.warn "killing remaining Orocos processes: #{remaining.map(&:name).join(", ")}"
        Orocos::Process.kill(remaining)
    end

    if @handler_ids
        unplug_engine_from_roby(@handler_ids.values, app.execution_engine)
        @handler_ids = nil
    end
end

.start_local_process_server(port = 0, redirect: true) ⇒ Object

Start a process server on the local machine, and register it in Syskit.process_servers under the 'localhost' name



526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
# File 'lib/syskit/roby_app/plugin.rb', line 526

def self.start_local_process_server(port = 0, redirect: true)
    if Syskit.conf.process_servers['localhost']
        raise ArgumentError, "there is already a process server called 'localhost' running"
    end

    if !File.exists?(Roby.app.log_dir)
        FileUtils.mkdir_p(Roby.app.log_dir)
    end

    tcp_server = TCPServer.new('127.0.0.1', 0)
    spawn_options = Hash[tcp_server => tcp_server, chdir: Roby.app.log_dir, pgroup: true]
    if redirect
        spawn_options[:err] = :out
        spawn_options[:out] = File.join(Roby.app.log_dir, 'local_process_server.txt')
    end

    @server_pid  = Kernel.spawn \
        'syskit', 'process_server', "--fd=#{tcp_server.fileno}", "--log-dir=#{Roby.app.log_dir}", "--debug",
        spawn_options
    @server_port = tcp_server.local_address.ip_port
    tcp_server.close
    nil
end

.stop_local_process_serverObject

Stop the process server started by start_local_process_server if one is running



593
594
595
596
597
598
599
600
601
602
# File 'lib/syskit/roby_app/plugin.rb', line 593

def self.stop_local_process_server
    return if !has_local_process_server?

    ::Process.kill('INT', @server_pid)
    begin
        ::Process.waitpid(@server_pid)
        @server_pid = nil
    rescue Errno::ESRCH
    end
end

.unplug_engine_from_roby(handler_ids = @handler_ids, roby_engine) ⇒ Object



688
689
690
691
692
693
# File 'lib/syskit/roby_app/plugin.rb', line 688

def self.unplug_engine_from_roby(handler_ids = @handler_ids, roby_engine)
    handler_ids.delete_if do |handler_id|
        roby_engine.remove_propagation_handler(handler_id)
        true
    end
end

.unplug_handler_from_roby(roby_engine, *handlers) ⇒ Object



703
704
705
706
707
708
709
710
711
# File 'lib/syskit/roby_app/plugin.rb', line 703

def self.unplug_handler_from_roby(roby_engine, *handlers)
    if @handler_ids
        handlers.each do |h|
            if h_id = @handler_ids.delete(h)
                roby_engine.remove_propagation_handler(h_id)
            end
        end
    end
end

.validate_all_port_types_have_fixed_size(only_warn: false, ignore: []) ⇒ Object



835
836
837
838
839
840
841
842
843
844
845
846
847
# File 'lib/syskit/roby_app/plugin.rb', line 835

def self.validate_all_port_types_have_fixed_size(only_warn: false, ignore: [])
    with_global_size = Set.new
    Syskit::Component.each_submodel do |component_m|
        next if component_m.abstract?

        component_m.each_input_port do |p|
            validate_port_has_fixed_size(p, with_global_size, only_warn: only_warn, ignore: ignore)
        end
        component_m.each_output_port do |p|
            validate_port_has_fixed_size(p, with_global_size, only_warn: only_warn, ignore: ignore)
        end
    end
end

.validate_port_has_fixed_size(port, with_global_size, only_warn: false, ignore: []) ⇒ Object



804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
# File 'lib/syskit/roby_app/plugin.rb', line 804

def self.validate_port_has_fixed_size(port, with_global_size, only_warn: false, ignore: [])
    return if with_global_size.include?(port.type)
    if fixed_size_type?(port.type) || globally_sized_type?(port.type)
        with_global_size << port.type
        return
    end

    port = port.to_component_port
    if ignore.include?(port.type)
        return
    elsif size = port.max_marshalling_size
        size
    else
        msg = "marshalled size of port #{port} cannot be inferred"
        if only_warn
            ::Robot.warn msg
        else
            raise VariableSizedType, msg
        end
    end
end

Instance Method Details

#auto_load_all_task_librariesObject

Loads all available oroGen projects



328
329
330
331
332
333
# File 'lib/syskit/roby_app/plugin.rb', line 328

def auto_load_all_task_libraries
    self.auto_load_all_task_libraries = true
    default_loader.each_available_project_name do |name|
        using_task_library(name)
    end
end

#auto_load_all_task_libraries=(value) ⇒ Object

If true, syskit is loading all available oroGen projects on this system. It is set automatically by #syskit_load_all to ensure that everything is reloaded when the app reloads its models



325
# File 'lib/syskit/roby_app/plugin.rb', line 325

attr_predicate :auto_load_all_task_libraries?, true

#auto_load_all_task_libraries?Boolean

If true, syskit is loading all available oroGen projects on this system. It is set automatically by #syskit_load_all to ensure that everything is reloaded when the app reloads its models

Returns:

  • (Boolean)


325
# File 'lib/syskit/roby_app/plugin.rb', line 325

attr_predicate :auto_load_all_task_libraries?, true

#autodiscover_tests_in?(path) ⇒ Boolean

Returns:

  • (Boolean)


509
510
511
512
513
514
515
516
517
518
519
520
521
522
# File 'lib/syskit/roby_app/plugin.rb', line 509

def autodiscover_tests_in?(path)
    if File.basename(path) == 'orogen'
        search_path.each do |base_path|
            if File.join(base_path, 'test', 'orogen') == path
                return false
            end
        end
    end

    if defined? super
        super
    else true
    end
end

#default_loaderObject



195
196
197
198
199
200
201
202
203
204
205
# File 'lib/syskit/roby_app/plugin.rb', line 195

def default_loader
    if !@default_loader
        @default_loader = Orocos.default_loader
        default_loader.on_project_load do |project|
            project_define_from_orogen(project)
        end
        orogen_pack_loader
        ros_loader
    end
    @default_loader
end

#default_orogen_projectObject



219
220
221
# File 'lib/syskit/roby_app/plugin.rb', line 219

def default_orogen_project
    @default_orogen_project ||= OroGen::Spec::Project.new(default_loader)
end

#default_pkgconfig_loaderObject



207
208
209
# File 'lib/syskit/roby_app/plugin.rb', line 207

def default_pkgconfig_loader
    Orocos.default_pkgconfig_loader
end

#deployment_define_from_orogen(deployer) ⇒ Object

Loads the oroGen deployment model for the given name and returns the corresponding syskit model

Parameters:

  • options (Hash)

    a customizable set of options



652
653
654
655
656
657
658
# File 'lib/syskit/roby_app/plugin.rb', line 652

def deployment_define_from_orogen(deployer)
    if Deployment.has_model_for?(deployer)
        Deployment.find_model_by_orogen(deployer)
    else
        Deployment.define_from_orogen(deployer, :register => true)
    end
end

#import_types_from(typekit_name) ⇒ Object

Loads the required typekit model by its name



485
486
487
# File 'lib/syskit/roby_app/plugin.rb', line 485

def import_types_from(typekit_name)
    default_loader.typekit_model_from_name(typekit_name)
end

#load_component_extension(name) ⇒ String?

Load the component extension file associated with this an oroGen project

Parameters:

  • name (String)

    the orogen project name

Returns:

  • (String, nil)

    either a file that got required, or nil if none was



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/syskit/roby_app/plugin.rb', line 306

def load_component_extension(name)
    # If we are loading under Roby, get the plugins for the orogen
    # project
    return if !Syskit.conf.load_component_extensions?

    file = find_file('models', 'orogen', "#{name}.rb", order: :specific_first) ||
        find_file('tasks', 'orogen', "#{name}.rb", order: :specific_first) ||
        find_file('tasks', 'components', "#{name}.rb", order: :specific_first)
    return unless file

    Roby::Application.info "loading task extension #{file}"
    if require(file)
        file
    end
end

#load_orogen_project(name, options = Hash.new) ⇒ Object

Deprecated.

use #using_task_library instead



505
506
507
# File 'lib/syskit/roby_app/plugin.rb', line 505

def load_orogen_project(name, options = Hash.new)
    using_task_library(name, options)
end

#loaded_orogen_project?(name) ⇒ Boolean

Returns true if the given orogen project has already been loaded by #load_orogen_project

Returns:

  • (Boolean)


256
# File 'lib/syskit/roby_app/plugin.rb', line 256

def loaded_orogen_project?(name); loaded_orogen_projects.has_key?(name) end

#loaded_orogen_projectsHash<String,OroGen::Spec::Project>

Returns the set of projects loaded so far

Returns:

  • (Hash<String,OroGen::Spec::Project>)

    the set of projects loaded so far



239
# File 'lib/syskit/roby_app/plugin.rb', line 239

attribute(:loaded_orogen_projects) { Hash.new }

#local_only=(value) ⇒ Object

:attr: local_only?

True if this application should not try to contact other machines/servers



665
# File 'lib/syskit/roby_app/plugin.rb', line 665

attr_predicate :local_only?, true

#local_only?Object

:attr: local_only?

True if this application should not try to contact other machines/servers



665
# File 'lib/syskit/roby_app/plugin.rb', line 665

attr_predicate :local_only?, true

#orogen_pack_loaderObject



211
212
213
# File 'lib/syskit/roby_app/plugin.rb', line 211

def orogen_pack_loader
    @orogen_pack_loader ||= OroGen::Loaders::Files.new(default_loader)
end

#permanent_requirementsArray<InstanceRequirements>

Set of requirements that should be added to the running system. This is meant to be used only by “syskit scripts” through SingleFileDSL

Returns:



246
# File 'lib/syskit/roby_app/plugin.rb', line 246

attribute(:permanent_requirements) { Array.new }

#project_define_from_orogen(orogen) ⇒ Object

Registers all objects contained in a given oroGen project

Parameters:

  • orogen (OroGen::Spec::Project)

    the oroGen project that should be added to the Syskit side



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/syskit/roby_app/plugin.rb', line 264

def project_define_from_orogen(orogen)
    return if loaded_orogen_projects.has_key?(orogen.name)
    Syskit.info "loading oroGen project #{orogen.name}"

    tasks = orogen.self_tasks.each_value.map do |task_def|
        syskit_model =
            if !TaskContext.has_model_for?(task_def)
                Syskit::TaskContext.define_from_orogen(task_def, register: true)
            else
                Syskit::TaskContext.model_for(task_def)
            end

        syskit_model.configuration_manager.reload
        syskit_model
    end


    if file = load_component_extension(orogen.name)
        tasks.each do |t|
            t.definition_location = [OroGenLocation.new(file, 1, nil)]
            t.extension_file = file
        end
    end

    orogen.each_deployment do |deployer_model|
        deployment_define_from_orogen(deployer_model)
    end
    orogen
end

#ros_loaderObject



215
216
217
# File 'lib/syskit/roby_app/plugin.rb', line 215

def ros_loader
    @ros_loader ||= OroGen::ROS::Loader.new(default_loader)
end

#syskit_has_pending_configuration_changes?Boolean

Verifies whether the configuration on disk and the configurations currently loaded in the running deployments are identical

Returns:

  • (Boolean)


378
379
380
381
382
383
# File 'lib/syskit/roby_app/plugin.rb', line 378

def syskit_has_pending_configuration_changes?
    TaskContext.each_submodel do |model|
        return true if model.configuration_manager.changed_on_disk?
    end
    false
end

#syskit_listen_to_configuration_changesObject



357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/syskit/roby_app/plugin.rb', line 357

def syskit_listen_to_configuration_changes
    dirs = find_dirs('config', 'orogen', 'ROBOT', all: true, order: :specific_last)
    return if dirs.empty?

    @conf_listener = Listen.to(*dirs) do |modified, added, removed|
        if syskit_has_pending_configuration_changes?
            notify 'syskit', 'INFO', 'oroGen configuration files changed on disk. In the shell, reload with #reload_config and reconfigure affected running components with #redeploy'
            ui_event 'syskit_orogen_config_changed'
        end
    end
    @conf_listener.start
end

#syskit_pending_reloaded_configurations(Array,Array)

Returns the names of the TaskContext that will need to be reconfigured on the next deployment (either #redeploy or transition)

Returns:

  • ((Array,Array))

    the list of all task names for tasks whose configuration has changed, and the subset of these tasks that are currently running



430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/syskit/roby_app/plugin.rb', line 430

def syskit_pending_reloaded_configurations
    pending_reconfigurations = Array.new
    pending_running_reconfigurations = Array.new
    plan.find_tasks(Deployment).each do |deployment_task|
        pending = deployment_task.pending_reconfigurations
        deployment_task.each_executed_task do |t|
            if pending.include?(t.orocos_name)
                pending_running_reconfigurations << t.orocos_name
            end
        end
        pending_reconfigurations.concat(pending)
    end
    return pending_reconfigurations, pending_running_reconfigurations
end

#syskit_reload_config(Array,Array)

Reloads the configuration files

This only modifies the configuration loaded internally, but does not change the configuration of existing task contexts. The new configuration will only be applied after the next deployment

Returns:

  • ((Array,Array))

    the names of the components whose configuration changed, and the subset of those that are currently running

See Also:



395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/syskit/roby_app/plugin.rb', line 395

def syskit_reload_config
    needs_reconfiguration = []
    running_needs_reconfiguration = []
    TaskContext.each_submodel do |model|
        next if !model.concrete_model?
        changed_sections = model.configuration_manager.reload
        plan.find_tasks(Deployment).each do |deployment_task|
            deployment_task.mark_changed_configuration_as_not_reusable(
                model => changed_sections).each do |orocos_name|

                needs_reconfiguration << orocos_name
                deployment_task.each_executed_task do |t|
                    if t.orocos_name == orocos_name
                        running_needs_reconfiguration << orocos_name
                    end
                end
                notify 'syskit', 'INFO', "task #{orocos_name} needs reconfiguration"
            end
        end
    end

    if !running_needs_reconfiguration.empty?
        notify 'syskit', 'INFO', "#{running_needs_reconfiguration.size} running tasks configuration changed. In the shell, use 'redeploy' to trigger reconfiguration."
    end
    ui_event 'syskit_orogen_config_reloaded', needs_reconfiguration,
        running_needs_reconfiguration
    needs_reconfiguration
end

#syskit_remove_configuration_changes_listenerObject



370
371
372
373
374
# File 'lib/syskit/roby_app/plugin.rb', line 370

def syskit_remove_configuration_changes_listener
    if @conf_listener
        @conf_listener.stop
    end
end

#syskit_start_all_deployments(on: nil, except_on: "unmanaged_tasks") ⇒ Object

Start all deployments

Parameters:

  • on (String, nil)

    the name of the process server on which deployments should be started. If nil, all servers are considered



633
634
635
636
637
638
639
640
641
642
643
# File 'lib/syskit/roby_app/plugin.rb', line 633

def syskit_start_all_deployments(on: nil, except_on: "unmanaged_tasks")
    existing_deployments = plan.find_tasks(Syskit::Deployment).
        not_finished.
        find_all { |d| d.reusable? }.
        map(&:process_name).to_set

    Syskit.conf.each_configured_deployment(on: on, except_on: except_on) do |configured_deployment|
        next if existing_deployments.include?(configured_deployment.process_name)
        plan.add_permanent_task(configured_deployment.new)
    end
end

#syskit_utility_component?(task_context) ⇒ Boolean

Returns:

  • (Boolean)


294
295
296
297
298
# File 'lib/syskit/roby_app/plugin.rb', line 294

def syskit_utility_component?(task_context)
    if defined?(OroGen::Logger::Logger)
        task_context.kind_of?(OroGen::Logger::Logger)
    end
end

#using_deployment(name, loader: default_loader) ⇒ Object

Loads the oroGen deployment model for the given name and returns the corresponding syskit model



616
617
618
619
620
621
# File 'lib/syskit/roby_app/plugin.rb', line 616

def using_deployment(name, loader: default_loader)
    # This loads the underlying orogen project which causes the
    # deployer to be registered
    deployment_model = loader.deployment_model_from_name(name)
    Deployment.find_model_by_orogen(deployment_model)
end

#using_ros_launcher(name, options = Hash.new) ⇒ Object

Loads the oroGen deployment model based on a ROS launcher file



624
625
626
627
# File 'lib/syskit/roby_app/plugin.rb', line 624

def using_ros_launcher(name, options = Hash.new)
    options = Kernel.validate_options options, :loader => ros_loader
    using_deployment(name, options)
end

#using_ros_package(name, options = Hash.new) ⇒ Object

Loads the required ROS package



499
500
501
502
# File 'lib/syskit/roby_app/plugin.rb', line 499

def using_ros_package(name, options = Hash.new)
    options = Kernel.validate_options options, :loader => ros_loader
    using_task_library(name, options)
end

#using_task_library(name, options = Hash.new) ⇒ OroGen::Spec::Project

Load the specified oroGen project and register the task contexts and deployments they contain.

Returns:

  • (OroGen::Spec::Project)


493
494
495
496
# File 'lib/syskit/roby_app/plugin.rb', line 493

def using_task_library(name, options = Hash.new)
    options = Kernel.validate_options options, :loader => default_loader
    options[:loader].project_model_from_name(name)
end