Module: Roby

Included in:
Test
Defined in:
lib/roby.rb,
lib/roby.rb,
lib/roby/app.rb,
lib/roby/plan.rb,
lib/roby/task.rb,
lib/roby/yard.rb,
lib/roby/droby.rb,
lib/roby/event.rb,
lib/roby/hooks.rb,
lib/roby/actions.rb,
lib/roby/cli/log.rb,
lib/roby/promise.rb,
lib/roby/queries.rb,
lib/roby/support.rb,
lib/roby/version.rb,
lib/roby/app/base.rb,
lib/roby/app/rake.rb,
lib/roby/cli/base.rb,
lib/roby/cli/main.rb,
lib/roby/test/dsl.rb,
lib/roby/app/debug.rb,
lib/roby/interface.rb,
lib/roby/relations.rb,
lib/roby/test/self.rb,
lib/roby/test/spec.rb,
lib/roby/disposable.rb,
lib/roby/exceptions.rb,
lib/roby/gui/styles.rb,
lib/roby/singletons.rb,
lib/roby/state/task.rb,
lib/roby/task_event.rb,
lib/roby/tasks/null.rb,
lib/roby/test/error.rb,
lib/roby/test/tools.rb,
lib/roby/app/scripts.rb,
lib/roby/app/vagrant.rb,
lib/roby/cli/display.rb,
lib/roby/models/task.rb,
lib/roby/plan_object.rb,
lib/roby/queries/any.rb,
lib/roby/test/common.rb,
lib/roby/transaction.rb,
lib/roby/actions/task.rb,
lib/roby/cli/gen_main.rb,
lib/roby/coordination.rb,
lib/roby/gui/stepping.rb,
lib/roby/interface/v1.rb,
lib/roby/interface/v2.rb,
lib/roby/or_generator.rb,
lib/roby/plan_service.rb,
lib/roby/queries/none.rb,
lib/roby/state/events.rb,
lib/roby/task_service.rb,
lib/roby/tasks/simple.rb,
lib/roby/tasks/thread.rb,
lib/roby/and_generator.rb,
lib/roby/droby/logfile.rb,
lib/roby/droby/marshal.rb,
lib/roby/droby/peer_id.rb,
lib/roby/interface/job.rb,
lib/roby/queries/index.rb,
lib/roby/queries/query.rb,
lib/roby/tasks/timeout.rb,
lib/roby/tasks/virtual.rb,
lib/roby/template_plan.rb,
lib/roby/test/testcase.rb,
lib/roby/actions/action.rb,
lib/roby/cli/exceptions.rb,
lib/roby/droby/droby_id.rb,
lib/roby/interface/base.rb,
lib/roby/interface/core.rb,
lib/roby/task_arguments.rb,
lib/roby/test/assertion.rb,
lib/roby/actions/library.rb,
lib/roby/app/robot_names.rb,
lib/roby/app/test_server.rb,
lib/roby/cli/gen/helpers.rb,
lib/roby/event_generator.rb,
lib/roby/executable_plan.rb,
lib/roby/gui/log_display.rb,
lib/roby/interface/async.rb,
lib/roby/interface/async.rb,
lib/roby/relations/graph.rb,
lib/roby/relations/space.rb,
lib/roby/schedulers/null.rb,
lib/roby/standard_errors.rb,
lib/roby/test/assertions.rb,
lib/roby/test/tasks/goto.rb,
lib/roby/until_generator.rb,
lib/roby/app/plugins/rake.rb,
lib/roby/app/robot_config.rb,
lib/roby/decision_control.rb,
lib/roby/droby/exceptions.rb,
lib/roby/droby/timepoints.rb,
lib/roby/droby/v5/builtin.rb,
lib/roby/droby/v5/peer_id.rb,
lib/roby/execution_engine.rb,
lib/roby/filter_generator.rb,
lib/roby/interface/v1/tcp.rb,
lib/roby/interface/v2/tcp.rb,
lib/roby/models/arguments.rb,
lib/roby/schedulers/basic.rb,
lib/roby/schedulers/state.rb,
lib/roby/state/conf_model.rb,
lib/roby/state/goal_model.rb,
lib/roby/actions/interface.rb,
lib/roby/app/test_reporter.rb,
lib/roby/coordination/base.rb,
lib/roby/coordination/task.rb,
lib/roby/droby/v5/droby_id.rb,
lib/roby/event_constraints.rb,
lib/roby/gui/task_state_at.rb,
lib/roby/interface/command.rb,
lib/roby/models/task_event.rb,
lib/roby/state/open_struct.rb,
lib/roby/state/state_model.rb,
lib/roby/test/run_planners.rb,
lib/roby/app/cucumber/world.rb,
lib/roby/coordination/child.rb,
lib/roby/coordination/event.rb,
lib/roby/distributed_object.rb,
lib/roby/droby/event_logger.rb,
lib/roby/droby/identifiable.rb,
lib/roby/droby/marshallable.rb,
lib/roby/droby/rebuilt_plan.rb,
lib/roby/gui/chronicle_view.rb,
lib/roby/gui/exception_view.rb,
lib/roby/gui/relations_view.rb,
lib/roby/gui/scheduler_view.rb,
lib/roby/interface/rest/api.rb,
lib/roby/interface/v1/async.rb,
lib/roby/interface/v2/async.rb,
lib/roby/models/plan_object.rb,
lib/roby/queries/op_matcher.rb,
lib/roby/queries/or_matcher.rb,
lib/roby/coordination/script.rb,
lib/roby/droby/event_logging.rb,
lib/roby/droby/logfile/index.rb,
lib/roby/droby/v5/droby_dump.rb,
lib/roby/gui/plan_dot_layout.rb,
lib/roby/interface/interface.rb,
lib/roby/interface/rest/task.rb,
lib/roby/interface/rest/test.rb,
lib/roby/interface/v1/client.rb,
lib/roby/interface/v1/server.rb,
lib/roby/interface/v2/client.rb,
lib/roby/interface/v2/server.rb,
lib/roby/models/task_service.rb,
lib/roby/queries/and_matcher.rb,
lib/roby/queries/not_matcher.rb,
lib/roby/schedulers/temporal.rb,
lib/roby/test/aruba_minitest.rb,
lib/roby/test/event_reporter.rb,
lib/roby/test/teardown_plans.rb,
lib/roby/app/cucumber/helpers.rb,
lib/roby/coordination/actions.rb,
lib/roby/droby/logfile/client.rb,
lib/roby/droby/logfile/reader.rb,
lib/roby/droby/logfile/server.rb,
lib/roby/droby/logfile/writer.rb,
lib/roby/droby/object_manager.rb,
lib/roby/droby/plan_rebuilder.rb,
lib/roby/droby/timepoints_ctf.rb,
lib/roby/droby/v5/droby_class.rb,
lib/roby/droby/v5/droby_model.rb,
lib/roby/gui/chronicle_widget.rb,
lib/roby/gui/model_views/task.rb,
lib/roby/gui/object_info_view.rb,
lib/roby/interface/exceptions.rb,
lib/roby/interface/v2/channel.rb,
lib/roby/queries/matcher_base.rb,
lib/roby/queries/task_matcher.rb,
lib/roby/schedulers/reporting.rb,
lib/roby/task_event_generator.rb,
lib/roby/test/minitest_plugin.rb,
lib/roby/transaction/proxying.rb,
lib/roby/actions/models/action.rb,
lib/roby/coordination/calculus.rb,
lib/roby/droby/remote_droby_id.rb,
lib/roby/interface/rest/server.rb,
lib/roby/interface/v2/protocol.rb,
lib/roby/test/expect_execution.rb,
lib/roby/test/minitest_helpers.rb,
lib/roby/test/roby_app_helpers.rb,
lib/roby/test/tasks/empty_task.rb,
lib/roby/actions/models/library.rb,
lib/roby/coordination/task_base.rb,
lib/roby/event_structure/signal.rb,
lib/roby/interface/rest/helpers.rb,
lib/roby/interface/v1/async/log.rb,
lib/roby/interface/v2/async/log.rb,
lib/roby/relations/models/graph.rb,
lib/roby/tasks/external_process.rb,
lib/roby/test/droby_log_helpers.rb,
lib/roby/test/minitest_reporter.rb,
lib/roby/transaction/task_proxy.rb,
lib/roby/app/cucumber/controller.rb,
lib/roby/droby/null_event_logger.rb,
lib/roby/droby/v5/droby_constant.rb,
lib/roby/state/open_struct_model.rb,
lib/roby/test/robot_test_helpers.rb,
lib/roby/actions/models/interface.rb,
lib/roby/coordination/models/base.rb,
lib/roby/coordination/models/root.rb,
lib/roby/coordination/models/task.rb,
lib/roby/coordination/task_script.rb,
lib/roby/droby/v5/remote_droby_id.rb,
lib/roby/task_structure/conflicts.rb,
lib/roby/coordination/models/child.rb,
lib/roby/coordination/models/event.rb,
lib/roby/gui/plan_rebuilder_widget.rb,
lib/roby/interface/command_library.rb,
lib/roby/interface/v1/shell_client.rb,
lib/roby/interface/v2/shell_client.rb,
lib/roby/queries/plan_query_result.rb,
lib/roby/task_structure/dependency.rb,
lib/roby/task_structure/planned_by.rb,
lib/roby/coordination/action_script.rb,
lib/roby/coordination/fault_handler.rb,
lib/roby/coordination/models/script.rb,
lib/roby/event_structure/forwarding.rb,
lib/roby/event_structure/precedence.rb,
lib/roby/interface/command_argument.rb,
lib/roby/interface/v1/droby_channel.rb,
lib/roby/queries/code_error_matcher.rb,
lib/roby/queries/local_query_result.rb,
lib/roby/task_structure/executed_by.rb,
lib/roby/cli/log/flamegraph_renderer.rb,
lib/roby/coordination/models/actions.rb,
lib/roby/coordination/models/capture.rb,
lib/roby/event_structure/causal_link.rb,
lib/roby/queries/plan_object_matcher.rb,
lib/roby/test/execution_expectations.rb,
lib/roby/test/validate_state_machine.rb,
lib/roby/actions/models/method_action.rb,
lib/roby/coordination/models/variable.rb,
lib/roby/interface/v1/async/interface.rb,
lib/roby/interface/v2/async/interface.rb,
lib/roby/relations/fork_merge_visitor.rb,
lib/roby/actions/models/interface_base.rb,
lib/roby/app/autotest_console_reporter.rb,
lib/roby/coordination/models/arguments.rb,
lib/roby/interface/v1/shell_subcommand.rb,
lib/roby/interface/v2/shell_subcommand.rb,
lib/roby/relations/task_relation_graph.rb,
lib/roby/transaction/plan_object_proxy.rb,
lib/roby/coordination/models/exceptions.rb,
lib/roby/gui/task_display_configuration.rb,
lib/roby/interface/v1/async/job_monitor.rb,
lib/roby/interface/v1/subcommand_client.rb,
lib/roby/interface/v2/async/job_monitor.rb,
lib/roby/interface/v2/subcommand_client.rb,
lib/roby/relations/event_relation_graph.rb,
lib/roby/transaction/plan_service_proxy.rb,
lib/roby/coordination/script_instruction.rb,
lib/roby/coordination/task_state_machine.rb,
lib/roby/interface/v1/async/ui_connector.rb,
lib/roby/interface/v2/async/ui_connector.rb,
lib/roby/queries/event_generator_matcher.rb,
lib/roby/queries/localized_error_matcher.rb,
lib/roby/coordination/fault_handling_task.rb,
lib/roby/gui/model_views/action_interface.rb,
lib/roby/queries/transaction_query_result.rb,
lib/roby/coordination/action_state_machine.rb,
lib/roby/coordination/fault_response_table.rb,
lib/roby/coordination/models/action_script.rb,
lib/roby/coordination/models/fault_handler.rb,
lib/roby/interface/v1/async/action_monitor.rb,
lib/roby/interface/v2/async/action_monitor.rb,
lib/roby/transaction/event_generator_proxy.rb,
lib/roby/actions/models/coordination_action.rb,
lib/roby/gui/relations_view/relations_canvas.rb,
lib/roby/interface/v1/async/new_job_listener.rb,
lib/roby/interface/v2/async/new_job_listener.rb,
lib/roby/queries/execution_exception_matcher.rb,
lib/roby/relations/directed_relation_support.rb,
lib/roby/coordination/models/task_from_action.rb,
lib/roby/event_structure/temporal_constraints.rb,
lib/roby/queries/task_event_generator_matcher.rb,
lib/roby/relations/models/task_relation_graph.rb,
lib/roby/coordination/models/task_from_as_plan.rb,
lib/roby/coordination/models/task_from_variable.rb,
lib/roby/transaction/task_event_generator_proxy.rb,
lib/roby/coordination/models/action_state_machine.rb,
lib/roby/coordination/models/fault_response_table.rb,
lib/roby/relations/incremental_transitive_closure.rb,
lib/roby/coordination/models/task_with_dependencies.rb,
lib/roby/relations/models/directed_relation_support.rb,
lib/roby/relations/bidirectional_directed_adjacency_graph.rb,
lib/roby/coordination/models/task_from_instanciation_object.rb,
lib/roby/droby/enable.rb

Overview

rubocop:disable Style/ClassAndModuleChildren

Defined Under Namespace

Modules: Actions, App, CLI, Coordination, DRoby, EventConstraints, EventStructure, ExceptionHandlingObject, GUI, Hooks, Interface, Models, Pos, Queries, Rake, Relations, Schedulers, TaskStateHelper, TaskStructure, Tasks, Test, Tools, UserExceptionWrapper, YARD Classes: Aborting, ActionStateTransitionFailed, AndGenerator, Application, BacktraceFormatter, ChildFailedError, CodeError, CommandFailed, CommandRejected, ConfModel, ConfigError, Control, DecisionControl, DefaultArgument, DelayedArgument, DelayedArgumentFromObject, DelayedArgumentFromState, DeltaEvent, Disposable, DistributedObject, EmissionFailed, EmissionRejected, Event, EventCanceled, EventGenerator, EventHandlerError, EventNotControlable, EventNotExecutable, EventPreconditionFailed, ExceptionBase, ExecutablePlan, ExecutionEngine, ExecutionException, ExecutionQuitError, FailedExceptionHandler, FailedToStart, FilterGenerator, FinalizedPlanObject, GoalModel, GoalSpace, GoalVariableModel, InternalError, InternalTaskError, InvalidReplace, InvalidTransaction, LocalizedError, MissionFailedError, ModelViolation, NoSuchChild, NotMarshallable, OpenStruct, OpenStructModel, OrGenerator, OwnershipError, PermanentTaskError, PhaseMismatch, Plan, PlanObject, PlanService, PlanningFailedError, PosDeltaEvent, Promise, PromiseInFinishedTask, PropagationError, QuarantinedTaskError, RelationFailedError, RemotePeerMismatch, ReusingGarbage, StateConditionEvent, StateDataSourceField, StateEvent, StateField, StateLastValueField, StateMachineDefinitionContext, StateModel, StateSpace, StateVariableModel, SynchronousEventProcessingMultipleErrors, Task, TaskArguments, TaskEmergencyTermination, TaskEvent, TaskEventGenerator, TaskEventNotExecutable, TaskNotExecutable, TaskStateMachine, TemplatePlan, ThreadMismatch, TimeDeltaEvent, ToplevelTaskError, Transaction, UnreachableEvent, UntilGenerator, UserError, YawDeltaEvent

Constant Summary collapse

BIN_DIR =
File.expand_path(File.join("..", "bin"), __dir__)
RX_IN_FRAMEWORK =

Regular expression that matches backtrace paths that are within the Roby framework

/^((?:\s*\(druby:\/\/.+\)\s*)?#{Regexp.quote(ROBY_LIB_DIR)}\/)|^\(eval\)|^\/usr\/lib\/ruby/.freeze
RX_IN_METARUBY =
/^(?:\s*\(druby:\/\/.+\)\s*)?#{Regexp.quote(MetaRuby::LIB_DIR)}\//.freeze
RX_IN_UTILRB =
/^(?:\s*\(druby:\/\/.+\)\s*)?#{Regexp.quote(Utilrb::LIB_DIR)}\//.freeze
RX_REQUIRE =

Regular expression that matches backtrace paths that are require lines

/in `(gem_original_)?require'$/.freeze
VoidClass =
Class.new
Void =
VoidClass.new.freeze
VERSION =
"3.1.0"
ROBY_LIB_DIR =
File.expand_path(File.join(File.dirname(__FILE__), ".."))
ROBY_ROOT_DIR =
File.expand_path(File.join(ROBY_LIB_DIR, ".."))
SelfTest =
Test::Self
FORMAT_EXCEPTION_RECURSION_GUARD_KEY =
"roby-format-exception-recursion-guard"
LOG_SYMBOLIC_TO_NUMERIC =
State =

The main state object

Roby.state
Conf =

The main configuration object

Roby.conf
NullTask =

For backward-compatibility only

Tasks::Null
TaskService =
Models::TaskServiceModel.new
VirtualTask =

For backward-compatibility

Tasks::Virtual

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.colorizerObject (readonly)

Returns the value of attribute colorizer.



17
18
19
# File 'lib/roby/exceptions.rb', line 17

def colorizer
  @colorizer
end

.confObject (readonly)

The one and only ConfModel object



17
18
19
# File 'lib/roby/singletons.rb', line 17

def conf
  @conf
end

.deprecation_warnings_are_errorsObject

Returns the value of attribute deprecation_warnings_are_errors.



164
165
166
# File 'lib/roby/support.rb', line 164

def deprecation_warnings_are_errors
  @deprecation_warnings_are_errors
end

.enable_deprecation_warningsObject

Returns the value of attribute enable_deprecation_warnings.



164
165
166
# File 'lib/roby/support.rb', line 164

def enable_deprecation_warnings
  @enable_deprecation_warnings
end

.stateObject (readonly)

The one and only StateSpace object



14
15
16
# File 'lib/roby/singletons.rb', line 14

def state
  @state
end

Class Method Details

.appObject

The one and only Application object



9
10
11
# File 'lib/roby/singletons.rb', line 9

def app
    @app ||= Application.new
end

.color(string, *colors) ⇒ Object



20
21
22
# File 'lib/roby/exceptions.rb', line 20

def self.color(string, *colors)
    colorizer.decorate(string, *colors)
end

.controlObject

The control / policy object

This is the object that defines the core execution policies (e.g. what to do if the dependency of a non-running task stops). See DecisionControl



58
59
60
# File 'lib/roby/singletons.rb', line 58

def control
    app.plan.execution_engine.control
end

.control=(object) ⇒ Object

Sets the control / policy object

This is the object that defines the core execution policies (e.g. what to do if the dependency of a non-running task stops). See DecisionControl



67
68
69
# File 'lib/roby/singletons.rb', line 67

def control=(object)
    app.plan.execution_engine.control = object
end

.disable_colorsObject



24
25
26
# File 'lib/roby/exceptions.rb', line 24

def self.disable_colors
    @colorizer = Pastel.new(enabled: false)
end

.display_exception(io = STDOUT, e = nil, filter_backtraces = Roby.app.filter_backtraces?, backtrace: true, skip_identical_backtraces: true) ⇒ Object



595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
# File 'lib/roby/exceptions.rb', line 595

def self.display_exception(
    io = STDOUT, e = nil,
    filter_backtraces = Roby.app.filter_backtraces?,
    backtrace: true,
    skip_identical_backtraces: true
)
    old_filter_backtraces = Roby.app.filter_backtraces?
    Roby.app.filter_backtraces = filter_backtraces

    if block_given?
        begin
            yield
            nil
        rescue Interrupt, SystemExit
            raise
        rescue Exception => e
            if e.user_error?
                io.print color(e.message, :bold, :red)
            else
                do_display_exception(
                    io, e,
                    backtrace: backtrace,
                    skip_identical_backtraces: skip_identical_backtraces
                )
            end
            e
        end
    elsif !e
        raise ArgumentError, "expected an exception object as no block was given"
    else
        do_display_exception(
            io, e,
            backtrace: backtrace,
            skip_identical_backtraces: skip_identical_backtraces
        )
        e
    end
ensure
    Roby.app.filter_backtraces = old_filter_backtraces
end

.disposable(*disposables, &block) ⇒ Object



36
37
38
# File 'lib/roby/disposable.rb', line 36

def self.disposable(*disposables, &block)
    Disposable.new(*disposables, &block)
end

.do_display_exception(io, exception, skip_identical_backtraces: true, backtrace: true) ⇒ Object



516
517
518
519
520
521
522
523
524
525
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/roby/exceptions.rb', line 516

def self.do_display_exception(
    io, exception, skip_identical_backtraces: true, backtrace: true
)
    all = [exception]
    if exception.respond_to?(:original_exceptions)
        all += exception.original_exceptions.to_a
    end

    if skip_identical_backtraces
        last_backtrace = nil
        all =
            all
            .reverse
            .map do |e|
                skip = (last_backtrace == e.backtrace)
                last_backtrace = e.backtrace
                [e, skip]
            end
            .reverse
    end

    all.each do |e, skip_backtrace|
        if colorizer.enabled?
            do_display_exception_formatted(
                io, e, backtrace: backtrace && !skip_backtrace
            )
        else
            do_display_exception_raw(
                io, e, backtrace: backtrace && !skip_backtrace
            )
        end
    end
end

.do_display_exception_formatted(io, e, backtrace: true) ⇒ Object



570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# File 'lib/roby/exceptions.rb', line 570

def self.do_display_exception_formatted(io, e, backtrace: true)
    first_line = true
    io.puts ""
    format_exception(e, with_original_exceptions: false).each do |line|
        if first_line
            io.print color("= ", :bold, :red)
            io.puts color(line, :bold, :red)
            first_line = false
        else
            io.print color("| ", :bold, :red)
            io.puts line
        end
    end

    return unless backtrace

    io.puts color("= Backtrace", :bold, :red)
    format_exception(BacktraceFormatter.new(e)).each do |line|
        io.print color("| ", :bold, :red)
        io.puts line
    end
    io.puts color("= ", :bold, :red)
    true
end

.do_display_exception_raw(io, e, backtrace: true) ⇒ Object



550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/roby/exceptions.rb', line 550

def self.do_display_exception_raw(io, e, backtrace: true)
    first_line = true
    io.puts
    format_exception(e, with_original_exceptions: false).each do |line|
        if first_line
            io.puts line
            first_line = false
        else
            io.puts "  #{line}"
        end
    end

    return unless backtrace

    format_exception(BacktraceFormatter.new(e)).each do |line|
        io.puts line
    end
    true
end

.each_cycle(&block) ⇒ Object

Make the main engine call block during each propagation step. See ExecutionEngine#each_cycle



2770
2771
2772
# File 'lib/roby/execution_engine.rb', line 2770

def self.each_cycle(&block)
    execution_engine.each_cycle(&block)
end

.enable_colorsObject



32
33
34
# File 'lib/roby/exceptions.rb', line 32

def self.enable_colors
    @colorizer = Pastel.new(enabled: true)
end

.enable_colors_if_availableObject



28
29
30
# File 'lib/roby/exceptions.rb', line 28

def self.enable_colors_if_available
    @colorizer = Pastel.new
end

.engineObject

Deprecated.

use execution_engine instead



72
73
74
75
# File 'lib/roby/singletons.rb', line 72

def engine
    Roby.warn_deprecated "Roby.engine is deprecated, use Roby.execution_engine instead"
    app.execution_engine
end

.error_deprecated(msg, caller_depth = 1) ⇒ Object

Raises:

  • (NotImplementedError)


178
179
180
181
# File 'lib/roby/support.rb', line 178

def self.error_deprecated(msg, caller_depth = 1)
    Roby.fatal "Deprecation Error: #{msg} at #{caller[1, caller_depth].join("\n")}"
    raise NotImplementedError
end

.every(duration, options = {}, &block) ⇒ Object

Install a periodic handler on the main engine



2775
2776
2777
# File 'lib/roby/execution_engine.rb', line 2775

def self.every(duration, options = {}, &block)
    execution_engine.every(duration, options, &block)
end

.execute(&block) ⇒ Object

Execute the given block during the event propagation step of the main engine. See ExecutionEngine#execute



2795
2796
2797
# File 'lib/roby/execution_engine.rb', line 2795

def self.execute(&block)
    execution_engine.execute(&block)
end

.execution_engineExecutionEngine

The main execution engine

It is always the same as Roby.plan.execution_engine

Note that it is nil until the Roby application is configured

Returns:



35
36
37
# File 'lib/roby/singletons.rb', line 35

def execution_engine
    app.execution_engine
end

.filter_backtrace(original_backtrace = nil, force: false, display_full_framework_backtraces: false) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
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
293
294
295
296
297
298
299
300
301
302
# File 'lib/roby/exceptions.rb', line 224

def self.filter_backtrace(
    original_backtrace = nil,
    force: false, display_full_framework_backtraces: false
)
    return [] unless original_backtrace || block_given?

    if !original_backtrace && block_given?
        begin
            return yield
        rescue Exception => e
            filtered = filter_backtrace(
                e.backtrace,
                force: force,
                display_full_framework_backtraces: display_full_framework_backtraces
            )
            raise e, e.message, filtered
        end
    end

    return original_backtrace unless Roby.app.filter_backtraces? || force

    filter_out = Roby.app.filter_out_patterns
    original_backtrace = original_backtrace.dup

    # First, read out the "bottom" of the backtrace: search for the
    # first backtrace line that is within the framework
    backtrace_bottom = []
    while !original_backtrace.empty? &&
          filter_out.none? { |rx| rx.match?(original_backtrace.last) }
        backtrace_bottom.unshift original_backtrace.pop
    end

    got_user_line = false
    backtrace = original_backtrace.enum_for(:each_with_index).map do |line, idx|
        case line
        when /in `poll_handler'$/
            got_user_line = true
            line.gsub(/:in.*/, ":in the polling handler")
        when /in `event_command_(\w+)'$/
            got_user_line = true
            line.gsub(/:in.*/, ":in command for '#{$1}'")
        when /in `event_handler_(\w+)_(?:[a-f0-9]+)'$/
            got_user_line = true
            line.gsub(/:in.*/, ":in event handler for '#{$1}'")
        else
            if original_backtrace.size > idx + 4 &&
               original_backtrace[idx + 1] =~ /in `call'$/ &&
               original_backtrace[idx + 2] =~ /in `call_handlers'$/ &&
               original_backtrace[idx + 3] =~ /`each'$/ &&
               original_backtrace[idx + 4] =~ /`each_handler'$/

                got_user_line = true
                line.gsub(/:in /, ":in event handler, ")
            else
                is_user = filter_out.none? { |rx| rx.match?(line) }
                got_user_line ||= is_user
                if !got_user_line || is_user
                    case line
                    when /^\(eval\):\d+:in `each(?:_handler)?'/
                        nil
                    else
                        line
                    end
                end
            end
        end
    end

    backtrace.compact!
    backtrace = make_backtrace_relative_to_app_dir(backtrace)
    backtrace.concat backtrace_bottom

    if original_backtrace.size == backtrace.size && !display_full_framework_backtraces
        # The backtrace is only within the framework, make it empty
        return []
    end

    backtrace
end

.find_in_path(cmd) ⇒ Object

Cross-platform way of finding a file in the $PATH.

which('ruby') #=> /usr/bin/ruby


186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/roby/support.rb', line 186

def self.find_in_path(cmd)
    return cmd if cmd =~ (/#{File::SEPARATOR}/) && File.file?(cmd)

    exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
    ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
        exts.each do |ext|
            exe = File.join(path, "#{cmd}#{ext}")
            return exe if File.file?(exe)
        end
    end
    nil
end

.flatten_exception(e) ⇒ Object



636
637
638
639
640
641
642
643
644
645
646
647
648
649
# File 'lib/roby/exceptions.rb', line 636

def self.flatten_exception(e)
    result = [e].to_set

    if e.kind_of?(ExecutionException)
        result.merge(flatten_exception(e.exception))
    end

    if e.respond_to?(:each_original_exception)
        e.each_original_exception do |orig_e|
            result.merge(flatten_exception(orig_e))
        end
    end
    result
end

.format_backtrace(e, filter: Roby.app.filter_backtraces?) ⇒ Object



438
439
440
441
442
443
444
445
# File 'lib/roby/exceptions.rb', line 438

def self.format_backtrace(e, filter: Roby.app.filter_backtraces?)
    backtrace = e.backtrace
    if filter
        backtrace = filter_backtrace(backtrace)
    end

    format_exception(BacktraceFormatter.new(e, backtrace))
end

.format_exception(exception, with_original_exceptions: true, with_backtrace: false) ⇒ Array<String>

Format an exception into an array of strings (lines)

Returns:

  • (Array<String>)


365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/roby/exceptions.rb', line 365

def self.format_exception(exception, with_original_exceptions: true, with_backtrace: false)
    format_exception_recursion_guard(exception) do
        message = format_one_exception(exception)
        message += format_backtrace(exception) if with_backtrace
        return message unless with_original_exceptions
        return message unless exception.respond_to?(:original_exceptions)

        original_exception_msgs = exception.original_exceptions.flat_map do |original_e|
            format_exception(
                original_e,
                with_original_exceptions: true,
                with_backtrace: with_backtrace
            )
        end
        message + original_exception_msgs
    end
end

.format_exception_recursion_guard(key) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Helper for format_exception that breaks infinite recursion loops

Parameters:

  • key

    the recursion key. The method verifies that this key has not yet been used in the current call stack

Returns:

  • (Array<String>)

    the message, line-by-line. Either [<…>] if a recursion has been detected, or the value returned by the given block



347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/roby/exceptions.rb', line 347

def self.format_exception_recursion_guard(key)
    if (recursion_guard_set = Thread.current[FORMAT_EXCEPTION_RECURSION_GUARD_KEY])
        return ["<...>"] unless recursion_guard_set.add?(key)
    else
        recursion_guard_set = Set.new
        recursion_guard_set.compare_by_identity
        recursion_guard_set << key
        Thread.current[FORMAT_EXCEPTION_RECURSION_GUARD_KEY] = recursion_guard_set
    end

    yield
ensure
    recursion_guard_set.delete(key)
end

.format_one_exception(exception) ⇒ Object



321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/roby/exceptions.rb', line 321

def self.format_one_exception(exception)
    message =
        begin
            PP.pp(exception, "".dup)
        rescue Exception => e
            begin
                "error formatting exception\n  #{exception.full_message}"\
                "\nplease report the formatting error:\n  #{e.full_message}"
            rescue Exception => e
                "error formatting exception\n  #{e.full_message}"
            end
        end

    message.split("\n")
end

.format_time(time, format = "hms") ⇒ Object



102
103
104
105
106
107
108
109
110
111
# File 'lib/roby/support.rb', line 102

def self.format_time(time, format = "hms")
    case format
    when "sec"
        time.to_f.to_s
    when "hms"
        time.strftime("%H:%M:%S.%3N")
    else
        time.strftime(format)
    end
end

.from(object) ⇒ Object

Use to specify that a task argument should be initialized from an object’s attribute.

For instance,

task.new(goal: Roby.from(State).pose.position))

will set the task’s ‘goal’ argument from State.pose.position *at the time the task is started*

It can also be used as default argument values (in which case Task.from can be used instead of Roby.from):

class MyTask < Roby::Task
  argument :goal, default: from(State).pose.position
end

If the provided object is nil, the receiver will be the task itself.

Examples:

initialize an argument from the task’s parent

MyTaskModel.new(arg: Task.from(:parent_task).parent_arg)


765
766
767
# File 'lib/roby/task_arguments.rb', line 765

def self.from(object)
    DelayedArgumentFromObject.new(object)
end

.from_confObject

Use to specify that a task argument should be initialized from a value in the Conf object. The value will be taken at the point in time where the task is executed.

For instance:

task.new(goal: Roby.from_state.pose.position))


788
789
790
# File 'lib/roby/task_arguments.rb', line 788

def self.from_conf
    from_state(Conf)
end

.from_state(state_object = State) ⇒ Object

Use to specify that a task argument should be initialized from a value in the State

For instance:

task.new(goal: Roby.from_state.pose.position))


776
777
778
# File 'lib/roby/task_arguments.rb', line 776

def self.from_state(state_object = State)
    DelayedArgumentFromState.new(state_object)
end

.inside_control?Boolean

True if the current thread is the execution thread of the main engine

See ExecutionEngine#inside_control?

Returns:

  • (Boolean)


2782
2783
2784
# File 'lib/roby/execution_engine.rb', line 2782

def self.inside_control?
    execution_engine.inside_control?
end

.log_all_threads_backtraces(logger, level) ⇒ Object



482
483
484
485
486
487
488
489
# File 'lib/roby/exceptions.rb', line 482

def self.log_all_threads_backtraces(logger, level)
    current = Thread.current
    Thread.list.each do |thr|
        current = " CURRENT" if current == thr
        logger.send level, "Thread #{thr}#{current}"
        log_callers(thr.backtrace, logger, level)
    end
end

.log_backtrace(e, logger, level, filter: Roby.app.filter_backtraces?) ⇒ Object



447
448
449
450
451
# File 'lib/roby/exceptions.rb', line 447

def self.log_backtrace(e, logger, level, filter: Roby.app.filter_backtraces?)
    format_backtrace(e, filter: filter).each do |line|
        logger.send(level, line)
    end
end

.log_callers(callers, logger, level) ⇒ Object



474
475
476
477
478
479
480
# File 'lib/roby/exceptions.rb', line 474

def self.log_callers(callers, logger, level)
    logger = logger.logger if logger.respond_to?(:logger)

    logger.nest(2, level) do
        callers.each { |line| logger.send(level, line) }
    end
end

.log_error(e, logger, level, with_backtrace: true) ⇒ Object



491
492
493
494
495
496
497
# File 'lib/roby/exceptions.rb', line 491

def self.log_error(e, logger, level, with_backtrace: true)
    if e.respond_to?(:backtrace) && with_backtrace
        log_exception_with_backtrace(e, logger, level)
    else
        log_exception(e, logger, level)
    end
end

.log_exception(e, logger, level, with_original_exceptions: true) ⇒ Object



425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/roby/exceptions.rb', line 425

def self.log_exception(e, logger, level, with_original_exceptions: true)
    return unless log_level_enabled?(logger, level)

    first_line = true
    format_exception(e, with_original_exceptions: with_original_exceptions).each do |line|
        if first_line
            line = color(line, :bold, :red)
            first_line = false
        end
        logger.send(level, line)
    end
end

.log_exception_with_backtrace(e, logger, level, filter: Roby.app.filter_backtraces?, with_original_exceptions: true) ⇒ Object



453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/roby/exceptions.rb', line 453

def self.log_exception_with_backtrace(e, logger, level, filter: Roby.app.filter_backtraces?, with_original_exceptions: true)
    log_exception(e, logger, level, with_original_exceptions: false)
    logger.send level, color("= Backtrace", :bold, :red)

    backtrace = e.backtrace
    backtrace = filter_backtrace(backtrace) if filter
    if !backtrace || backtrace.empty?
        logger.send level, color("= No backtrace", :bold, :red)
    else
        logger.send level, color("= ", :bold, :red)
        log_backtrace(e, logger, level)
        logger.send level, color("= ", :bold, :red)
    end

    if with_original_exceptions && e.respond_to?(:original_exceptions)
        e.original_exceptions.each do |orig_e|
            log_exception_with_backtrace(orig_e, logger, level, with_original_exceptions: true)
        end
    end
end

.log_level_enabled?(logger, level) ⇒ Boolean

Returns:

  • (Boolean)


391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/roby/exceptions.rb', line 391

def self.log_level_enabled?(logger, level)
    logger_level = if logger.respond_to?(:log_level)
                       logger.log_level
                   else
                       logger.level
                   end

    if numeric_level = LOG_SYMBOLIC_TO_NUMERIC.index(level.to_sym)
        logger_level <= numeric_level
    else
        raise ArgumentError, "#{level} is not a valid log level, log levels are #{LOG_SYMBOLIC_TO_NUMERIC.map(&:inspect).join(', ')}"
    end
end

.log_pp(obj, logger, level) ⇒ Object



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/roby/exceptions.rb', line 405

def self.log_pp(obj, logger, level)
    return unless log_level_enabled?(logger, level)

    message =
        begin
            PP.pp(obj, "".dup)
        rescue Exception => e
            begin
                "error formatting object\n  #{obj}\n"\
                "please report the formatting error:\n  #{e.full_message}"
            rescue Exception => e
                "\nerror formatting object\n  #{e.full_message}"
            end
        end

    message.split("\n").each do |line|
        logger.send(level, line)
    end
end

.make_backtrace_relative_to_app_dir(backtrace) ⇒ Object



304
305
306
307
308
# File 'lib/roby/exceptions.rb', line 304

def self.make_backtrace_relative_to_app_dir(backtrace)
    return backtrace unless (app_dir = Roby.app.app_dir)

    backtrace.map { |line| line.gsub(/^#{app_dir}\/?/, "./") }
end

.monotonic_timeFloat

Time in seconds since an arbitrary point in time, unaffected by time corrections

Use this time for e.g. compute timeouts or durations since a certain timepoint

Returns:

  • (Float)


216
217
218
# File 'lib/roby/support.rb', line 216

def self.monotonic_time
    Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

.null_disposableObject



40
41
42
# File 'lib/roby/disposable.rb', line 40

def self.null_disposable
    Disposable::Null.new
end

.on_exception(matcher, &handler) ⇒ Object

Defines a global exception handler on the main plan. See also Plan#on_exception



80
81
82
# File 'lib/roby/singletons.rb', line 80

def self.on_exception(matcher, &handler)
    Roby.app.plan.on_exception(matcher, &handler)
end

.once(&block) ⇒ Object

Execute the given block in the main plan’s propagation context, but don’t wait for its completion like Roby.execute does

See ExecutionEngine#once



2764
2765
2766
# File 'lib/roby/execution_engine.rb', line 2764

def self.once(&block)
    execution_engine.once(&block)
end

.outside_control?Boolean

True if the current thread is not the execution thread of the main engine

See ExecutionEngine#outside_control?

Returns:

  • (Boolean)


2789
2790
2791
# File 'lib/roby/execution_engine.rb', line 2789

def self.outside_control?
    execution_engine.outside_control?
end

.planPlan

The main plan

It is always the same as Roby.app.plan

Returns:



24
25
26
# File 'lib/roby/singletons.rb', line 24

def plan
    app.plan
end

.poll_state_events(plan) ⇒ Object

Registered on the execution engines to call the #poll method of state events



105
106
107
108
109
110
111
# File 'lib/roby/state/events.rb', line 105

def self.poll_state_events(plan) # :nodoc:
    for ev in plan.free_events
        if ev.kind_of?(StateEvent) && ev.enabled?
            ev.poll
        end
    end
end

.pretty_print_backtrace(pp, backtrace, **options) ⇒ Object



310
311
312
313
314
315
316
317
318
319
# File 'lib/roby/exceptions.rb', line 310

def self.pretty_print_backtrace(pp, backtrace, **options)
    if backtrace && !backtrace.empty?
        pp.nest(2) do
            filter_backtrace(backtrace, **options).each do |line|
                pp.breakable
                pp.text line
            end
        end
    end
end

.RelationSpace(klass) ⇒ Object

Creates a new relation space which applies on klass. If a block is given, it is eval’d in the context of the new relation space instance



59
60
61
62
63
64
65
# File 'lib/roby/relations.rb', line 59

def self.RelationSpace(klass)
    klass.include Relations::DirectedRelationSupport
    klass.extend  Relations::Models::DirectedRelationSupport
    relation_space = Relations::Space.new
    relation_space.apply_on klass
    relation_space
end

.sanitize_keywords(keywords) ⇒ Object



147
148
149
150
151
152
153
154
155
156
# File 'lib/roby/support.rb', line 147

def self.sanitize_keywords(keywords)
    hash = {}
    keywords.delete_if do |k, v|
        unless k.kind_of?(Symbol)
            hash[k] = v
            true
        end
    end
    hash
end

.sanitize_keywords_to_array(array, keywords) ⇒ Object

Helper to handle Ruby 2.7 behavior when mixing symbols and non-symbols in “last arg used as keyword hash”

Under Ruby 2.7, the call

def provides(*ary, **kw)
end
provides "some" => "mapping", as: "name"

Will pass all arguments to the keywords splat. This method extracts them again, adding the resulting hash to the ary argument if there are any, and doing nothing otherwise (for backward and forward compatibility)



125
126
127
128
# File 'lib/roby/support.rb', line 125

def self.sanitize_keywords_to_array(array, keywords)
    hash = sanitize_keywords(keywords)
    array << hash unless hash.empty?
end

.sanitize_keywords_to_hash(hash, keywords) ⇒ Object

Helper to handle Ruby 2.7 behavior when mixing symbols and non-symbols in “last arg used as keyword hash”

Under Ruby 2.7, the call

def provides(hash = {}, **kw)
end
provides "some" => "mapping", as: "name"

Will pass all arguments to the keywords splat. This method extracts them again, merging resulting hash into the hash argument if there are any, and doing nothing otherwise (for backward and forward compatibility)



142
143
144
145
# File 'lib/roby/support.rb', line 142

def self.sanitize_keywords_to_hash(hash, keywords)
    extracted = sanitize_keywords(keywords)
    hash.merge!(extracted) unless extracted.empty?
end

.schedulerObject

The main scheduler

It is always the same as Roby.plan.execution_engine.scheduler



42
43
44
# File 'lib/roby/singletons.rb', line 42

def scheduler
    app.plan.execution_engine.scheduler
end

.scheduler=(scheduler) ⇒ Object

Sets the main scheduler

It is always the same as Roby.plan.execution_engine.scheduler



49
50
51
# File 'lib/roby/singletons.rb', line 49

def scheduler=(scheduler)
    app.plan.execution_engine.scheduler = scheduler
end

.wait_one_cycleObject

Blocks until the main engine has executed at least one cycle. See ExecutionEngine#wait_one_cycle



2801
2802
2803
# File 'lib/roby/execution_engine.rb', line 2801

def self.wait_one_cycle
    execution_engine.wait_one_cycle
end

.wait_until(ev, &block) ⇒ Object

Stops the current thread until the given even is emitted. If the event becomes unreachable, an UnreachableEvent exception is raised.

See ExecutionEngine#wait_until



2809
2810
2811
# File 'lib/roby/execution_engine.rb', line 2809

def self.wait_until(ev, &block)
    execution_engine.wait_until(ev, &block)
end

.warn_deprecated(msg, caller_depth = 5) ⇒ Object



169
170
171
172
173
174
175
176
# File 'lib/roby/support.rb', line 169

def self.warn_deprecated(msg, caller_depth = 5)
    if deprecation_warnings_are_errors
        error_deprecated(msg, caller_depth)
    elsif enable_deprecation_warnings
        Roby.warn "Deprecation Warning: #{msg} "\
                  "at #{caller[1, caller_depth].join("\n  ")}"
    end
end

.which(cmd) ⇒ Object

Cross-platform way of finding an executable in the $PATH.

which('ruby') #=> /usr/bin/ruby


202
203
204
205
206
# File 'lib/roby/support.rb', line 202

def self.which(cmd)
    return unless (path = find_in_path(cmd))

    path if File.executable?(path)
end