module Roby
The main namespace for the Roby
library. The namespace is divided as follows:
Roby
-
core namespace for the
Roby
kernel Roby::Actions
-
basic tools for plan generation
- Roby::Transactions
-
implementation of transactions. Transactions represent a
change in the main plan, and can be distributed among different plan managers.
Roby::EventStructure
-
main namespace for event relations. The methods listed
in the documentation of EventStructure
are actually methods of Roby::EventGenerator
Roby::TaskStructure
-
main namespace for task relations. The methods listed in
the documentation of TaskStructure
are actually methods of Roby::Task
Constants
- BIN_DIR
- Conf
The main configuration object
- EventStructure
- LOG_SYMBOLIC_TO_NUMERIC
- NullTask
For backward-compatibility only
- ROBY_LIB_DIR
- ROBY_ROOT_DIR
- RX_IN_FRAMEWORK
Regular expression that matches backtrace paths that are within the
Roby
framework- RX_IN_METARUBY
- RX_IN_UTILRB
- RX_REQUIRE
Regular expression that matches backtrace paths that are require lines
- SelfTest
- State
The main state object
- TaskService
- TaskStructure
- VERSION
- VirtualTask
For backward-compatibility
Attributes
The one and only ConfModel
object
The one and only StateSpace
object
Public Class Methods
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
# File lib/roby/relations.rb, line 57 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
The one and only Application
object
# File lib/roby/singletons.rb, line 7 def app @app ||= Application.new end
# File lib/roby/exceptions.rb, line 14 def self.color(string, *colors) colorizer.decorate(string, *colors) end
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}
# File lib/roby/singletons.rb, line 54 def control app.plan.execution_engine.control end
# File lib/roby/exceptions.rb, line 18 def self.disable_colors @colorizer = Pastel.new(enabled: false) end
# File lib/roby/exceptions.rb, line 493 def self.display_exception(io = STDOUT, e = nil, filter_backtraces = nil) if !filter_backtraces.nil? old_filter_backtraces = Roby.app.filter_backtraces? Roby.app.filter_backtraces = filter_backtraces end if !block_given? if !e raise ArgumentError, "expected an exception object as no block was given" end do_display_exception(io, e) e else yield false end rescue Interrupt, SystemExit raise rescue Exception => e if e.user_error? io.print color(e.message, :bold, :red) else do_display_exception(io, e) end e ensure if !filter_backtraces.nil? Roby.app.filter_backtraces = old_filter_backtraces end end
# File lib/roby/exceptions.rb, line 439 def self.do_display_exception(io, e) if colorizer.enabled? do_display_exception_formatted(io, e) else do_display_exception_raw(io, e) end if e.respond_to?(:original_exceptions) e.original_exceptions.each do |original_e| do_display_exception(io, original_e) end end end
# File lib/roby/exceptions.rb, line 470 def self.do_display_exception_formatted(io, e) first_line = true io.puts "" format_exception(e).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 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
# File lib/roby/exceptions.rb, line 453 def self.do_display_exception_raw(io, e) first_line = true io.puts format_exception(e).each do |line| if first_line io.puts line first_line = false else io.puts " #{line}" end end format_exception(BacktraceFormatter.new(e)).each do |line| io.puts line end true end
Make the main engine call block
during each propagation step. See ExecutionEngine#each_cycle
# File lib/roby/execution_engine.rb, line 2617 def self.each_cycle(&block); execution_engine.each_cycle(&block) end
# File lib/roby/exceptions.rb, line 26 def self.enable_colors @colorizer = Pastel.new(enabled: true) end
# File lib/roby/exceptions.rb, line 22 def self.enable_colors_if_available @colorizer = Pastel.new end
@deprecated use {Roby.execution_engine} instead
# File lib/roby/singletons.rb, line 68 def engine Roby.warn_deprecated "Roby.engine is deprecated, use Roby.execution_engine instead" app.execution_engine end
# File lib/roby/support.rb, line 128 def self.error_deprecated(msg, caller_depth = 1) Roby.fatal "Deprecation Error: #{msg} at #{caller[1, caller_depth].join("\n")}" raise NotImplementedError end
Install a periodic handler on the main engine
# File lib/roby/execution_engine.rb, line 2620 def self.every(duration, options = Hash.new, &block); execution_engine.every(duration, options, &block) end
Execute the given block during the event propagation step of the main engine. See ExecutionEngine#execute
# File lib/roby/execution_engine.rb, line 2634 def self.execute execution_engine.execute do yield end end
# File lib/roby/exceptions.rb, line 208 def self.filter_backtrace(original_backtrace = nil, force: false, display_full_framework_backtraces: false) filter_out = Roby.app.filter_out_patterns 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 if (Roby.app.filter_backtraces? || force) && original_backtrace app_dir = Roby.app.app_dir 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.any? { |rx| rx =~ 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.any? { |rx| rx =~ line } got_user_line ||= is_user if !got_user_line || is_user case line when /^\(eval\):\d+:in `each(?:_handler)?'/ else line end end end end end backtrace.compact! if app_dir backtrace = backtrace.map do |line| line.gsub(/^#{app_dir}\/?/, './') end end backtrace.concat backtrace_bottom if original_backtrace.size == backtrace.size && !display_full_framework_backtraces # The backtrace is only within the framework, make it empty backtrace = [] end end backtrace || original_backtrace || [] end
# File lib/roby/exceptions.rb, line 526 def self.flatten_exception(e) result = [e].to_set if e.respond_to?(:original_exceptions) e.original_exceptions.each do |orig_e| result.merge(flatten_exception(orig_e)) end end result end
# File lib/roby/exceptions.rb, line 379 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
# File lib/roby/exceptions.rb, line 314 def self.format_exception(exception, with_original_exceptions: true) message = format_one_exception(exception) if with_original_exceptions && exception.respond_to?(:original_exceptions) exception.original_exceptions.each do |original_e| message.concat(format_exception(original_e, with_original_exceptions: true)) end end message end
# File lib/roby/exceptions.rb, line 296 def self.format_one_exception(exception) message = begin PP.pp(exception, "") rescue Exception => formatting_error begin "error formatting exception\n" + exception.full_message + "\nplease report the formatting error: \n" + formatting_error.full_message rescue Exception => formatting_error "\nerror formatting exception\n" + formatting_error.full_message end end message.split("\n") end
# File lib/roby/support.rb, line 101 def self.format_time(time, format = 'hms') if format == 'sec' time.to_f.to_s elsif format == 'hms' "#{time.strftime('%H:%M:%S.%3N')}" else "#{time.strftime(format)}" end end
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.
@example initialize an argument from the task's parent
MyTaskModel.new(arg: Task.from(:parent_task).parent_arg)
# File lib/roby/task_arguments.rb, line 402 def self.from(object) DelayedArgumentFromObject.new(object) end
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))
# File lib/roby/task_arguments.rb, line 425 def self.from_conf from_state(Conf) end
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))
# File lib/roby/task_arguments.rb, line 413 def self.from_state(state_object = State) DelayedArgumentFromState.new(state_object) end
True if the current thread is the execution thread of the main engine
See ExecutionEngine#inside_control?
# File lib/roby/execution_engine.rb, line 2625 def self.inside_control?; execution_engine.inside_control? end
# File lib/roby/exceptions.rb, line 388 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
# File lib/roby/exceptions.rb, line 417 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
# File lib/roby/exceptions.rb, line 366 def self.log_exception(e, logger, level, with_original_exceptions: true) return if !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
# File lib/roby/exceptions.rb, line 394 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 if filter backtrace = filter_backtrace(backtrace) end 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
# File lib/roby/exceptions.rb, line 332 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
# File lib/roby/exceptions.rb, line 345 def self.log_pp(obj, logger, level) return if !log_level_enabled?(logger, level) message = begin PP.pp(obj, "") rescue Exception => formatting_error begin "error formatting object\n" + obj + "\nplease report the formatting error: \n" + formatting_error.full_message rescue Exception => formatting_error "\nerror formatting object\n" + formatting_error.full_message end end message.split("\n").each do |line| logger.send(level, line) end end
Defines a global exception handler on the main plan. See also Plan#on_exception
# File lib/roby/singletons.rb, line 76 def self.on_exception(matcher, &handler); Roby.app.plan.on_exception(matcher, &handler) end
Execute the given block in the main plan's propagation context, but don't wait for its completion like Roby.execute
does
# File lib/roby/execution_engine.rb, line 2613 def self.once; execution_engine.once { yield } end
True if the current thread is not the execution thread of the main engine
See ExecutionEngine#outside_control?
# File lib/roby/execution_engine.rb, line 2630 def self.outside_control?; execution_engine.outside_control? end
The main plan
It is always the same as Roby.app
.plan
@return [Plan]
# File lib/roby/singletons.rb, line 22 def plan; app.plan end
# File lib/roby/exceptions.rb, line 285 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
The main scheduler
It is always the same as Roby.plan
.execution_engine.scheduler
# File lib/roby/singletons.rb, line 38 def scheduler app.plan.execution_engine.scheduler end
Sets the main scheduler
It is always the same as Roby.plan
.execution_engine.scheduler
# File lib/roby/singletons.rb, line 45 def scheduler=(scheduler) app.plan.execution_engine.scheduler = scheduler end
Blocks until the main engine has executed at least one cycle. See ExecutionEngine#wait_one_cycle
# File lib/roby/execution_engine.rb, line 2642 def self.wait_one_cycle; execution_engine.wait_one_cycle end
Stops the current thread until the given even is emitted. If the event becomes unreachable, an UnreachableEvent
exception is raised.
See ExecutionEngine#wait_until
# File lib/roby/execution_engine.rb, line 2648 def self.wait_until(ev, &block); execution_engine.wait_until(ev, &block) end
# File lib/roby/support.rb, line 120 def self.warn_deprecated(msg, caller_depth = 1) 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