roby 0.8.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.deep-cover.rb +3 -0
- data/.gitattributes +1 -0
- data/.gitignore +24 -0
- data/.simplecov +10 -0
- data/.travis.yml +17 -0
- data/.yardopts +4 -0
- data/Gemfile +15 -0
- data/README.md +11 -0
- data/Rakefile +47 -177
- data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
- data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
- data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
- data/benchmark/{genom.rb → attic/genom.rb} +0 -0
- data/benchmark/attic/transactions.rb +62 -0
- data/benchmark/plan_basic_operations.rb +28 -0
- data/benchmark/relations/graph.rb +63 -0
- data/benchmark/ruby/identity.rb +18 -0
- data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
- data/benchmark/ruby/yield_vs_block.rb +35 -0
- data/benchmark/run +5 -0
- data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
- data/benchmark/transactions.rb +99 -51
- data/bin/roby +38 -197
- data/bin/roby-display +14 -0
- data/bin/roby-log +3 -176
- data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
- data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
- data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
- data/doc/guide/{src → attic}/abstraction/index.page +1 -1
- data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
- data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
- data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
- data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
- data/doc/guide/attic/cycle/error_handling.page +98 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
- data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
- data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
- data/doc/guide/{src → attic}/cycle/index.page +1 -1
- data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
- data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
- data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
- data/doc/guide/attic/plans/building_plans.page +89 -0
- data/doc/guide/attic/plans/code.page +192 -0
- data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
- data/doc/guide/attic/plans/index.page +7 -0
- data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
- data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
- data/doc/guide/attic/plans/querying_plans.page +5 -0
- data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
- data/doc/guide/config.yaml +7 -4
- data/doc/guide/ext/extended_menu.rb +29 -0
- data/doc/guide/ext/init.rb +6 -0
- data/doc/guide/ext/rdoc_links.rb +7 -6
- data/doc/guide/src/advanced_concepts/history.page +5 -0
- data/doc/guide/src/advanced_concepts/index.page +11 -0
- data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
- data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
- data/doc/guide/src/advanced_concepts/transactions.page +5 -0
- data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
- data/doc/guide/src/base.template +96 -0
- data/doc/guide/src/basics_shell_header.txt +5 -7
- data/doc/guide/src/building/action_coordination.page +96 -0
- data/doc/guide/src/building/actions.page +124 -0
- data/doc/guide/src/building/file_layout.page +71 -0
- data/doc/guide/src/building/index.page +50 -0
- data/doc/guide/src/building/patterns.page +86 -0
- data/doc/guide/src/building/patterns_forwarding.png +0 -0
- data/doc/guide/src/building/patterns_forwarding.svg +277 -0
- data/doc/guide/src/building/runtime.page +95 -0
- data/doc/guide/src/building/task_models.page +94 -0
- data/doc/guide/src/building/tasks.page +284 -0
- data/doc/guide/src/concepts/error_handling.page +100 -0
- data/doc/guide/src/concepts/exception_propagation.png +0 -0
- data/doc/guide/src/concepts/exception_propagation.svg +445 -0
- data/doc/guide/src/concepts/execution.page +85 -0
- data/doc/guide/src/concepts/execution.png +0 -0
- data/doc/guide/src/concepts/execution.svg +573 -0
- data/doc/guide/src/concepts/execution_cycle.png +0 -0
- data/doc/guide/src/concepts/garbage_collection.page +57 -0
- data/doc/guide/src/concepts/index.page +27 -0
- data/doc/guide/src/concepts/plans.page +101 -0
- data/doc/guide/src/concepts/policy.page +31 -0
- data/doc/guide/src/concepts/reactor.page +61 -0
- data/doc/guide/src/concepts/simple_plan_example.png +0 -0
- data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
- data/doc/guide/src/default.template +9 -74
- data/doc/guide/src/event_relations/forward.page +71 -0
- data/doc/guide/src/event_relations/index.page +12 -0
- data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
- data/doc/guide/src/event_relations/signal.page +55 -0
- data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
- data/doc/guide/src/htmldoc.metainfo +21 -8
- data/doc/guide/src/index.page +8 -3
- data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
- data/doc/guide/src/installation/publications.page +14 -0
- data/doc/guide/src/{introduction → installation}/videos.page +14 -7
- data/doc/guide/src/interacting/index.page +16 -0
- data/doc/guide/src/interacting/run.page +33 -0
- data/doc/guide/src/interacting/shell.page +95 -0
- data/doc/guide/src/plugins/creating_plugins.page +72 -0
- data/doc/guide/src/plugins/index.page +27 -5
- data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
- data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
- data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
- data/doc/guide/src/style_screen.css +687 -0
- data/doc/guide/src/task_relations/dependency.page +107 -0
- data/doc/guide/src/task_relations/executed_by.page +77 -0
- data/doc/guide/src/task_relations/index.page +12 -0
- data/doc/guide/src/task_relations/new_relations.page +119 -0
- data/doc/guide/src/task_relations/planned_by.page +46 -0
- data/doc/guide/src/tutorial/app.page +117 -0
- data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
- data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
- data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
- data/doc/guide/src/tutorial/events.page +195 -0
- data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
- data/doc/guide/src/tutorial/index.page +13 -0
- data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/tutorial/relations_display.page +153 -0
- data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
- data/doc/guide/src/tutorial/shell.page +121 -0
- data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
- data/doc/guide/src/tutorial/tasks.page +374 -0
- data/lib/roby.rb +102 -47
- data/lib/roby/actions.rb +17 -0
- data/lib/roby/actions/action.rb +80 -0
- data/lib/roby/actions/interface.rb +45 -0
- data/lib/roby/actions/library.rb +23 -0
- data/lib/roby/actions/models/action.rb +224 -0
- data/lib/roby/actions/models/coordination_action.rb +58 -0
- data/lib/roby/actions/models/interface.rb +22 -0
- data/lib/roby/actions/models/interface_base.rb +294 -0
- data/lib/roby/actions/models/library.rb +12 -0
- data/lib/roby/actions/models/method_action.rb +90 -0
- data/lib/roby/actions/task.rb +114 -0
- data/lib/roby/and_generator.rb +125 -0
- data/lib/roby/app.rb +2795 -829
- data/lib/roby/app/autotest_console_reporter.rb +138 -0
- data/lib/roby/app/base.rb +21 -0
- data/lib/roby/app/cucumber.rb +2 -0
- data/lib/roby/app/cucumber/controller.rb +439 -0
- data/lib/roby/app/cucumber/helpers.rb +280 -0
- data/lib/roby/app/cucumber/world.rb +32 -0
- data/lib/roby/app/debug.rb +136 -0
- data/lib/roby/app/gen.rb +2 -0
- data/lib/roby/app/rake.rb +178 -38
- data/lib/roby/app/robot_config.rb +9 -0
- data/lib/roby/app/robot_names.rb +115 -0
- data/lib/roby/app/run.rb +3 -2
- data/lib/roby/app/scripts.rb +72 -0
- data/lib/roby/app/scripts/autotest.rb +173 -0
- data/lib/roby/app/scripts/display.rb +2 -0
- data/lib/roby/app/scripts/restart.rb +52 -0
- data/lib/roby/app/scripts/results.rb +17 -8
- data/lib/roby/app/scripts/run.rb +155 -24
- data/lib/roby/app/scripts/shell.rb +147 -62
- data/lib/roby/app/scripts/test.rb +107 -22
- data/lib/roby/app/test_reporter.rb +74 -0
- data/lib/roby/app/test_server.rb +159 -0
- data/lib/roby/app/vagrant.rb +47 -0
- data/lib/roby/backports.rb +16 -0
- data/lib/roby/cli/display.rb +190 -0
- data/lib/roby/cli/exceptions.rb +17 -0
- data/lib/roby/cli/gen/actions/class.rb +5 -0
- data/lib/roby/cli/gen/actions/test.rb +6 -0
- data/lib/roby/cli/gen/app/.yardopts +6 -0
- data/lib/roby/cli/gen/app/README.md +28 -0
- data/lib/roby/cli/gen/app/Rakefile +15 -0
- data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
- data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
- data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
- data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
- data/lib/roby/cli/gen/class/class.rb +6 -0
- data/lib/roby/cli/gen/class/test.rb +7 -0
- data/lib/roby/cli/gen/helpers.rb +203 -0
- data/lib/roby/cli/gen/module/module.rb +5 -0
- data/lib/roby/cli/gen/module/test.rb +6 -0
- data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
- data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
- data/lib/roby/cli/gen/task/class.rb +44 -0
- data/lib/roby/cli/gen/task/test.rb +6 -0
- data/lib/roby/cli/gen_main.rb +120 -0
- data/lib/roby/cli/log.rb +276 -0
- data/lib/roby/cli/log/flamegraph.html +499 -0
- data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
- data/lib/roby/cli/main.rb +153 -0
- data/lib/roby/coordination.rb +60 -0
- data/lib/roby/coordination/action_script.rb +25 -0
- data/lib/roby/coordination/action_state_machine.rb +125 -0
- data/lib/roby/coordination/actions.rb +106 -0
- data/lib/roby/coordination/base.rb +145 -0
- data/lib/roby/coordination/calculus.rb +40 -0
- data/lib/roby/coordination/child.rb +28 -0
- data/lib/roby/coordination/event.rb +29 -0
- data/lib/roby/coordination/fault_handler.rb +25 -0
- data/lib/roby/coordination/fault_handling_task.rb +13 -0
- data/lib/roby/coordination/fault_response_table.rb +110 -0
- data/lib/roby/coordination/models/action_script.rb +64 -0
- data/lib/roby/coordination/models/action_state_machine.rb +224 -0
- data/lib/roby/coordination/models/actions.rb +191 -0
- data/lib/roby/coordination/models/arguments.rb +55 -0
- data/lib/roby/coordination/models/base.rb +176 -0
- data/lib/roby/coordination/models/capture.rb +86 -0
- data/lib/roby/coordination/models/child.rb +35 -0
- data/lib/roby/coordination/models/event.rb +41 -0
- data/lib/roby/coordination/models/exceptions.rb +42 -0
- data/lib/roby/coordination/models/fault_handler.rb +219 -0
- data/lib/roby/coordination/models/fault_response_table.rb +77 -0
- data/lib/roby/coordination/models/root.rb +22 -0
- data/lib/roby/coordination/models/script.rb +283 -0
- data/lib/roby/coordination/models/task.rb +184 -0
- data/lib/roby/coordination/models/task_from_action.rb +50 -0
- data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
- data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
- data/lib/roby/coordination/models/task_from_variable.rb +27 -0
- data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
- data/lib/roby/coordination/models/variable.rb +32 -0
- data/lib/roby/coordination/script.rb +200 -0
- data/lib/roby/coordination/script_instruction.rb +12 -0
- data/lib/roby/coordination/task.rb +45 -0
- data/lib/roby/coordination/task_base.rb +69 -0
- data/lib/roby/coordination/task_script.rb +293 -0
- data/lib/roby/coordination/task_state_machine.rb +308 -0
- data/lib/roby/decision_control.rb +33 -21
- data/lib/roby/distributed_object.rb +76 -0
- data/lib/roby/droby.rb +17 -0
- data/lib/roby/droby/droby_id.rb +6 -0
- data/lib/roby/droby/enable.rb +153 -0
- data/lib/roby/droby/event_logger.rb +189 -0
- data/lib/roby/droby/event_logging.rb +57 -0
- data/lib/roby/droby/exceptions.rb +14 -0
- data/lib/roby/droby/identifiable.rb +22 -0
- data/lib/roby/droby/logfile.rb +141 -0
- data/lib/roby/droby/logfile/client.rb +176 -0
- data/lib/roby/droby/logfile/file_format.md +97 -0
- data/lib/roby/droby/logfile/index.rb +117 -0
- data/lib/roby/droby/logfile/reader.rb +139 -0
- data/lib/roby/droby/logfile/server.rb +199 -0
- data/lib/roby/droby/logfile/writer.rb +114 -0
- data/lib/roby/droby/marshal.rb +264 -0
- data/lib/roby/droby/marshallable.rb +12 -0
- data/lib/roby/droby/null_event_logger.rb +25 -0
- data/lib/roby/droby/object_manager.rb +205 -0
- data/lib/roby/droby/peer_id.rb +6 -0
- data/lib/roby/droby/plan_rebuilder.rb +373 -0
- data/lib/roby/droby/rebuilt_plan.rb +160 -0
- data/lib/roby/droby/remote_droby_id.rb +6 -0
- data/lib/roby/droby/timepoints.rb +205 -0
- data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
- data/lib/roby/droby/timepoints_ctf.rb +125 -0
- data/lib/roby/droby/v5.rb +14 -0
- data/lib/roby/droby/v5/builtin.rb +120 -0
- data/lib/roby/droby/v5/droby_class.rb +45 -0
- data/lib/roby/droby/v5/droby_constant.rb +81 -0
- data/lib/roby/droby/v5/droby_dump.rb +1026 -0
- data/lib/roby/droby/v5/droby_id.rb +44 -0
- data/lib/roby/droby/v5/droby_model.rb +82 -0
- data/lib/roby/droby/v5/peer_id.rb +10 -0
- data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
- data/lib/roby/event.rb +79 -957
- data/lib/roby/event_constraints.rb +835 -0
- data/lib/roby/event_generator.rb +1047 -0
- data/lib/roby/event_structure/causal_link.rb +6 -0
- data/lib/roby/event_structure/forwarding.rb +6 -0
- data/lib/roby/event_structure/precedence.rb +7 -0
- data/lib/roby/event_structure/signal.rb +8 -0
- data/lib/roby/event_structure/temporal_constraints.rb +640 -0
- data/lib/roby/exceptions.rb +446 -152
- data/lib/roby/executable_plan.rb +549 -0
- data/lib/roby/execution_engine.rb +1997 -950
- data/lib/roby/filter_generator.rb +26 -0
- data/lib/roby/gui/chronicle_view.rb +225 -0
- data/lib/roby/gui/chronicle_widget.rb +925 -0
- data/lib/roby/gui/dot_id.rb +11 -0
- data/lib/roby/gui/exception_view.rb +44 -0
- data/lib/roby/gui/log_display.rb +273 -0
- data/lib/roby/gui/model_views.rb +2 -0
- data/lib/roby/gui/model_views/action_interface.rb +53 -0
- data/lib/roby/gui/model_views/task.rb +47 -0
- data/lib/roby/gui/model_views/task.rhtml +41 -0
- data/lib/roby/gui/object_info_view.rb +89 -0
- data/lib/roby/gui/plan_dot_layout.rb +427 -0
- data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
- data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
- data/lib/roby/gui/relations_view.rb +278 -0
- data/lib/roby/gui/relations_view/relations.ui +139 -0
- data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
- data/lib/roby/gui/relations_view/relations_config.rb +292 -0
- data/lib/roby/gui/relations_view/relations_view.ui +53 -0
- data/lib/roby/gui/scheduler_view.css +24 -0
- data/lib/roby/gui/scheduler_view.rb +46 -0
- data/lib/roby/gui/scheduler_view.rhtml +53 -0
- data/lib/roby/gui/stepping.rb +93 -0
- data/lib/roby/gui/stepping.ui +181 -0
- data/lib/roby/gui/styles.rb +81 -0
- data/lib/roby/gui/task_display_configuration.rb +42 -0
- data/lib/roby/gui/task_state_at.rb +38 -0
- data/lib/roby/hooks.rb +26 -0
- data/lib/roby/interface.rb +136 -469
- data/lib/roby/interface/async.rb +20 -0
- data/lib/roby/interface/async/action_monitor.rb +188 -0
- data/lib/roby/interface/async/interface.rb +498 -0
- data/lib/roby/interface/async/job_monitor.rb +213 -0
- data/lib/roby/interface/async/log.rb +238 -0
- data/lib/roby/interface/async/new_job_listener.rb +79 -0
- data/lib/roby/interface/async/ui_connector.rb +183 -0
- data/lib/roby/interface/client.rb +553 -0
- data/lib/roby/interface/command.rb +24 -0
- data/lib/roby/interface/command_argument.rb +16 -0
- data/lib/roby/interface/command_library.rb +92 -0
- data/lib/roby/interface/droby_channel.rb +174 -0
- data/lib/roby/interface/exceptions.rb +22 -0
- data/lib/roby/interface/interface.rb +655 -0
- data/lib/roby/interface/job.rb +47 -0
- data/lib/roby/interface/rest.rb +10 -0
- data/lib/roby/interface/rest/api.rb +29 -0
- data/lib/roby/interface/rest/helpers.rb +24 -0
- data/lib/roby/interface/rest/server.rb +212 -0
- data/lib/roby/interface/server.rb +154 -0
- data/lib/roby/interface/shell_client.rb +468 -0
- data/lib/roby/interface/shell_subcommand.rb +24 -0
- data/lib/roby/interface/subcommand_client.rb +35 -0
- data/lib/roby/interface/tcp.rb +168 -0
- data/lib/roby/models/arguments.rb +112 -0
- data/lib/roby/models/plan_object.rb +83 -0
- data/lib/roby/models/task.rb +835 -0
- data/lib/roby/models/task_event.rb +62 -0
- data/lib/roby/models/task_service.rb +78 -0
- data/lib/roby/or_generator.rb +88 -0
- data/lib/roby/plan.rb +1751 -864
- data/lib/roby/plan_object.rb +611 -0
- data/lib/roby/plan_service.rb +200 -0
- data/lib/roby/promise.rb +332 -0
- data/lib/roby/queries.rb +23 -0
- data/lib/roby/queries/and_matcher.rb +32 -0
- data/lib/roby/queries/any.rb +27 -0
- data/lib/roby/queries/code_error_matcher.rb +58 -0
- data/lib/roby/queries/event_generator_matcher.rb +9 -0
- data/lib/roby/queries/execution_exception_matcher.rb +165 -0
- data/lib/roby/queries/index.rb +165 -0
- data/lib/roby/queries/localized_error_matcher.rb +149 -0
- data/lib/roby/queries/matcher_base.rb +107 -0
- data/lib/roby/queries/none.rb +27 -0
- data/lib/roby/queries/not_matcher.rb +30 -0
- data/lib/roby/queries/op_matcher.rb +8 -0
- data/lib/roby/queries/or_matcher.rb +30 -0
- data/lib/roby/queries/plan_object_matcher.rb +363 -0
- data/lib/roby/queries/query.rb +188 -0
- data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
- data/lib/roby/queries/task_matcher.rb +344 -0
- data/lib/roby/relations.rb +42 -678
- data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
- data/lib/roby/relations/directed_relation_support.rb +268 -0
- data/lib/roby/relations/event_relation_graph.rb +19 -0
- data/lib/roby/relations/fork_merge_visitor.rb +154 -0
- data/lib/roby/relations/graph.rb +533 -0
- data/lib/roby/relations/models/directed_relation_support.rb +11 -0
- data/lib/roby/relations/models/graph.rb +75 -0
- data/lib/roby/relations/models/task_relation_graph.rb +18 -0
- data/lib/roby/relations/space.rb +380 -0
- data/lib/roby/relations/task_relation_graph.rb +20 -0
- data/lib/roby/robot.rb +85 -38
- data/lib/roby/schedulers/basic.rb +155 -25
- data/lib/roby/schedulers/null.rb +20 -0
- data/lib/roby/schedulers/reporting.rb +31 -0
- data/lib/roby/schedulers/state.rb +129 -0
- data/lib/roby/schedulers/temporal.rb +91 -0
- data/lib/roby/singletons.rb +87 -0
- data/lib/roby/standalone.rb +4 -2
- data/lib/roby/standard_errors.rb +405 -82
- data/lib/roby/state.rb +6 -3
- data/lib/roby/state/conf_model.rb +5 -0
- data/lib/roby/state/events.rb +181 -95
- data/lib/roby/state/goal_model.rb +77 -0
- data/lib/roby/state/open_struct.rb +591 -0
- data/lib/roby/state/open_struct_model.rb +68 -0
- data/lib/roby/state/pos.rb +45 -45
- data/lib/roby/state/shapes.rb +11 -11
- data/lib/roby/state/state_model.rb +303 -0
- data/lib/roby/state/task.rb +43 -0
- data/lib/roby/support.rb +88 -148
- data/lib/roby/task.rb +1361 -1750
- data/lib/roby/task_arguments.rb +428 -0
- data/lib/roby/task_event.rb +127 -0
- data/lib/roby/task_event_generator.rb +337 -0
- data/lib/roby/task_service.rb +6 -0
- data/lib/roby/task_structure/conflicts.rb +104 -0
- data/lib/roby/task_structure/dependency.rb +932 -0
- data/lib/roby/task_structure/error_handling.rb +118 -0
- data/lib/roby/task_structure/executed_by.rb +234 -0
- data/lib/roby/task_structure/planned_by.rb +90 -0
- data/lib/roby/tasks/aggregator.rb +37 -0
- data/lib/roby/tasks/external_process.rb +275 -0
- data/lib/roby/tasks/group.rb +27 -0
- data/lib/roby/tasks/null.rb +19 -0
- data/lib/roby/tasks/parallel.rb +43 -0
- data/lib/roby/tasks/sequence.rb +88 -0
- data/lib/roby/tasks/simple.rb +21 -0
- data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
- data/lib/roby/tasks/timeout.rb +17 -0
- data/lib/roby/tasks/virtual.rb +55 -0
- data/lib/roby/template_plan.rb +7 -0
- data/lib/roby/test/aruba_minitest.rb +74 -0
- data/lib/roby/test/assertion.rb +16 -0
- data/lib/roby/test/assertions.rb +490 -0
- data/lib/roby/test/common.rb +368 -591
- data/lib/roby/test/dsl.rb +149 -0
- data/lib/roby/test/error.rb +18 -0
- data/lib/roby/test/event_reporter.rb +83 -0
- data/lib/roby/test/execution_expectations.rb +1134 -0
- data/lib/roby/test/expect_execution.rb +151 -0
- data/lib/roby/test/minitest_helpers.rb +166 -0
- data/lib/roby/test/roby_app_helpers.rb +200 -0
- data/lib/roby/test/run_planners.rb +155 -0
- data/lib/roby/test/self.rb +112 -0
- data/lib/roby/test/spec.rb +198 -0
- data/lib/roby/test/tasks/empty_task.rb +4 -4
- data/lib/roby/test/tasks/goto.rb +28 -27
- data/lib/roby/test/teardown_plans.rb +100 -0
- data/lib/roby/test/testcase.rb +239 -307
- data/lib/roby/test/tools.rb +159 -155
- data/lib/roby/test/validate_state_machine.rb +75 -0
- data/lib/roby/transaction.rb +1125 -0
- data/lib/roby/transaction/event_generator_proxy.rb +63 -0
- data/lib/roby/transaction/plan_object_proxy.rb +99 -0
- data/lib/roby/transaction/plan_service_proxy.rb +43 -0
- data/lib/roby/transaction/proxying.rb +120 -0
- data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
- data/lib/roby/transaction/task_proxy.rb +135 -0
- data/lib/roby/until_generator.rb +30 -0
- data/lib/roby/version.rb +5 -0
- data/lib/roby/yard.rb +169 -0
- data/lib/yard-roby.rb +1 -0
- data/manifest.xml +32 -6
- data/roby.gemspec +59 -0
- metadata +788 -587
- data/Manifest.txt +0 -321
- data/NOTES +0 -4
- data/README.txt +0 -166
- data/TODO.txt +0 -146
- data/app/README.txt +0 -24
- data/app/Rakefile +0 -8
- data/app/config/ROBOT.rb +0 -5
- data/app/config/init.rb +0 -33
- data/app/config/roby.yml +0 -3
- data/app/controllers/ROBOT.rb +0 -2
- data/app/planners/ROBOT/main.rb +0 -6
- data/app/planners/main.rb +0 -5
- data/app/scripts/distributed +0 -3
- data/app/scripts/generate/bookmarks +0 -3
- data/app/scripts/replay +0 -3
- data/app/scripts/results +0 -3
- data/app/scripts/run +0 -3
- data/app/scripts/server +0 -3
- data/app/scripts/shell +0 -3
- data/app/scripts/test +0 -3
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby-shell +0 -25
- data/doc/guide/src/basics/app.page +0 -139
- data/doc/guide/src/basics/index.page +0 -11
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/relations_display.page +0 -203
- data/doc/guide/src/basics/shell.page +0 -102
- data/doc/guide/src/default.css +0 -319
- data/doc/guide/src/introduction/index.page +0 -29
- data/doc/guide/src/introduction/publications.page +0 -14
- data/doc/guide/src/relations/dependency.page +0 -89
- data/doc/guide/src/relations/index.page +0 -12
- data/ext/droby/dump.cc +0 -175
- data/ext/droby/extconf.rb +0 -3
- data/ext/graph/algorithm.cc +0 -746
- data/ext/graph/extconf.rb +0 -7
- data/ext/graph/graph.cc +0 -575
- data/ext/graph/graph.hh +0 -183
- data/ext/graph/iterator_sequence.hh +0 -102
- data/ext/graph/undirected_dfs.hh +0 -226
- data/ext/graph/undirected_graph.hh +0 -421
- data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
- data/lib/roby/app/scripts/replay.rb +0 -31
- data/lib/roby/app/scripts/server.rb +0 -18
- data/lib/roby/basic_object.rb +0 -151
- data/lib/roby/config.rb +0 -14
- data/lib/roby/distributed.rb +0 -36
- data/lib/roby/distributed/base.rb +0 -448
- data/lib/roby/distributed/communication.rb +0 -875
- data/lib/roby/distributed/connection_space.rb +0 -616
- data/lib/roby/distributed/distributed_object.rb +0 -206
- data/lib/roby/distributed/drb.rb +0 -62
- data/lib/roby/distributed/notifications.rb +0 -531
- data/lib/roby/distributed/peer.rb +0 -555
- data/lib/roby/distributed/protocol.rb +0 -529
- data/lib/roby/distributed/proxy.rb +0 -343
- data/lib/roby/distributed/subscription.rb +0 -311
- data/lib/roby/distributed/transaction.rb +0 -498
- data/lib/roby/external_process_task.rb +0 -225
- data/lib/roby/graph.rb +0 -160
- data/lib/roby/log.rb +0 -3
- data/lib/roby/log/chronicle.rb +0 -303
- data/lib/roby/log/console.rb +0 -74
- data/lib/roby/log/data_stream.rb +0 -275
- data/lib/roby/log/dot.rb +0 -279
- data/lib/roby/log/event_stream.rb +0 -161
- data/lib/roby/log/file.rb +0 -396
- data/lib/roby/log/gui/basic_display.ui +0 -83
- data/lib/roby/log/gui/basic_display_ui.rb +0 -89
- data/lib/roby/log/gui/chronicle.rb +0 -26
- data/lib/roby/log/gui/chronicle_view.rb +0 -40
- data/lib/roby/log/gui/chronicle_view.ui +0 -70
- data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
- data/lib/roby/log/gui/data_displays.rb +0 -171
- data/lib/roby/log/gui/data_displays.ui +0 -155
- data/lib/roby/log/gui/data_displays_ui.rb +0 -146
- data/lib/roby/log/gui/notifications.rb +0 -26
- data/lib/roby/log/gui/relations.rb +0 -269
- data/lib/roby/log/gui/relations.ui +0 -123
- data/lib/roby/log/gui/relations_ui.rb +0 -120
- data/lib/roby/log/gui/relations_view.rb +0 -185
- data/lib/roby/log/gui/relations_view.ui +0 -149
- data/lib/roby/log/gui/relations_view_ui.rb +0 -144
- data/lib/roby/log/gui/replay.rb +0 -366
- data/lib/roby/log/gui/replay_controls.rb +0 -206
- data/lib/roby/log/gui/replay_controls.ui +0 -282
- data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
- data/lib/roby/log/gui/runtime.rb +0 -130
- data/lib/roby/log/hooks.rb +0 -186
- data/lib/roby/log/logger.rb +0 -203
- data/lib/roby/log/notifications.rb +0 -244
- data/lib/roby/log/plan_rebuilder.rb +0 -468
- data/lib/roby/log/relations.rb +0 -1084
- data/lib/roby/log/server.rb +0 -547
- data/lib/roby/log/sqlite.rb +0 -47
- data/lib/roby/log/timings.rb +0 -233
- data/lib/roby/plan-object.rb +0 -371
- data/lib/roby/planning.rb +0 -13
- data/lib/roby/planning/loops.rb +0 -309
- data/lib/roby/planning/model.rb +0 -1012
- data/lib/roby/planning/task.rb +0 -180
- data/lib/roby/query.rb +0 -655
- data/lib/roby/relations/conflicts.rb +0 -67
- data/lib/roby/relations/dependency.rb +0 -358
- data/lib/roby/relations/ensured.rb +0 -19
- data/lib/roby/relations/error_handling.rb +0 -22
- data/lib/roby/relations/events.rb +0 -7
- data/lib/roby/relations/executed_by.rb +0 -208
- data/lib/roby/relations/influence.rb +0 -10
- data/lib/roby/relations/planned_by.rb +0 -63
- data/lib/roby/state/information.rb +0 -55
- data/lib/roby/state/state.rb +0 -367
- data/lib/roby/task-operations.rb +0 -186
- data/lib/roby/task_index.rb +0 -80
- data/lib/roby/test/distributed.rb +0 -230
- data/lib/roby/test/tasks/simple_task.rb +0 -23
- data/lib/roby/transactions.rb +0 -507
- data/lib/roby/transactions/proxy.rb +0 -325
- data/plugins/fault_injection/History.txt +0 -4
- data/plugins/fault_injection/README.txt +0 -34
- data/plugins/fault_injection/Rakefile +0 -12
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +0 -52
- data/plugins/fault_injection/fault_injection.rb +0 -89
- data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
- data/plugins/subsystems/README.txt +0 -37
- data/plugins/subsystems/Rakefile +0 -13
- data/plugins/subsystems/app.rb +0 -182
- data/plugins/subsystems/test/app/README +0 -24
- data/plugins/subsystems/test/app/Rakefile +0 -8
- data/plugins/subsystems/test/app/config/app.yml +0 -71
- data/plugins/subsystems/test/app/config/init.rb +0 -12
- data/plugins/subsystems/test/app/config/roby.yml +0 -3
- data/plugins/subsystems/test/app/planners/main.rb +0 -20
- data/plugins/subsystems/test/app/scripts/distributed +0 -3
- data/plugins/subsystems/test/app/scripts/replay +0 -3
- data/plugins/subsystems/test/app/scripts/results +0 -3
- data/plugins/subsystems/test/app/scripts/run +0 -3
- data/plugins/subsystems/test/app/scripts/server +0 -3
- data/plugins/subsystems/test/app/scripts/shell +0 -3
- data/plugins/subsystems/test/app/scripts/test +0 -3
- data/plugins/subsystems/test/app/tasks/services.rb +0 -15
- data/plugins/subsystems/test/test_subsystems.rb +0 -78
- data/test/distributed/test_communication.rb +0 -195
- data/test/distributed/test_connection.rb +0 -284
- data/test/distributed/test_execution.rb +0 -378
- data/test/distributed/test_mixed_plan.rb +0 -341
- data/test/distributed/test_plan_notifications.rb +0 -238
- data/test/distributed/test_protocol.rb +0 -525
- data/test/distributed/test_query.rb +0 -106
- data/test/distributed/test_remote_plan.rb +0 -491
- data/test/distributed/test_transaction.rb +0 -466
- data/test/mockups/external_process +0 -28
- data/test/mockups/tasks.rb +0 -27
- data/test/planning/test_loops.rb +0 -432
- data/test/planning/test_model.rb +0 -427
- data/test/planning/test_task.rb +0 -126
- data/test/relations/test_conflicts.rb +0 -42
- data/test/relations/test_dependency.rb +0 -324
- data/test/relations/test_ensured.rb +0 -38
- data/test/relations/test_executed_by.rb +0 -224
- data/test/relations/test_planned_by.rb +0 -56
- data/test/suite_core.rb +0 -29
- data/test/suite_distributed.rb +0 -10
- data/test/suite_planning.rb +0 -4
- data/test/suite_relations.rb +0 -8
- data/test/tasks/test_external_process.rb +0 -126
- data/test/tasks/test_thread_task.rb +0 -70
- data/test/test_bgl.rb +0 -528
- data/test/test_event.rb +0 -969
- data/test/test_exceptions.rb +0 -591
- data/test/test_execution_engine.rb +0 -987
- data/test/test_gui.rb +0 -20
- data/test/test_interface.rb +0 -43
- data/test/test_log.rb +0 -125
- data/test/test_log_server.rb +0 -133
- data/test/test_plan.rb +0 -418
- data/test/test_query.rb +0 -424
- data/test/test_relations.rb +0 -260
- data/test/test_state.rb +0 -432
- data/test/test_support.rb +0 -16
- data/test/test_task.rb +0 -1181
- data/test/test_testcase.rb +0 -138
- data/test/test_transactions.rb +0 -610
- data/test/test_transactions_proxy.rb +0 -216
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
# Define Infinity
|
|
2
|
+
if !defined? Infinity
|
|
3
|
+
Infinity = 1.0/0
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
module Roby
|
|
7
|
+
class Plan
|
|
8
|
+
# An EventStructure::EventDeadlines instance that is used by the
|
|
9
|
+
# TemporalConstraints relation to maintain the set of event deadlines
|
|
10
|
+
attribute(:emission_deadlines) { EventStructure::EventDeadlines.new }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module EventStructure
|
|
14
|
+
# Class used to maintain the event deadlines
|
|
15
|
+
class EventDeadlines
|
|
16
|
+
attr_reader :deadlines
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@deadlines = Array.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Adds a deadline to the set
|
|
23
|
+
def add(deadline, event, generator)
|
|
24
|
+
deadlines << [deadline, event, generator]
|
|
25
|
+
@deadlines = deadlines.sort_by(&:first)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Remove the first deadline registered for +generator+
|
|
29
|
+
def remove_deadline_for(generator, time)
|
|
30
|
+
found = false
|
|
31
|
+
deadlines.delete_if do |deadline, _, gen|
|
|
32
|
+
if found
|
|
33
|
+
false
|
|
34
|
+
else
|
|
35
|
+
found = (deadline > time && generator == gen)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
found
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns the number of queued deadlines
|
|
42
|
+
def size
|
|
43
|
+
@deadlines.size
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns the set of deadlines that have been missed at
|
|
47
|
+
# +current_time+. These deadlines get removed from the set.
|
|
48
|
+
def missed_deadlines(current_time)
|
|
49
|
+
result = []
|
|
50
|
+
while !deadlines.empty? && deadlines.first[0] < current_time
|
|
51
|
+
result << deadlines.shift
|
|
52
|
+
end
|
|
53
|
+
result
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Exception class used when an event has missed its deadline
|
|
58
|
+
class MissedDeadlineError < LocalizedError
|
|
59
|
+
# The event from which we deduced the deadline
|
|
60
|
+
attr_reader :constraining_event
|
|
61
|
+
# The time before which the failed generator should have emitted
|
|
62
|
+
attr_reader :deadline
|
|
63
|
+
|
|
64
|
+
def initialize(generator, constraining_event, deadline)
|
|
65
|
+
super(generator)
|
|
66
|
+
@constraining_event = constraining_event
|
|
67
|
+
@deadline = deadline
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def pretty_print(pp)
|
|
71
|
+
pp.text "#{failed_generator} missed the deadline of #{deadline}"
|
|
72
|
+
pp.breakable
|
|
73
|
+
pp.text " required after the emission of #{constraining_event}"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Exception raised when an event gets emitted outside its specified
|
|
78
|
+
# temporal constraints
|
|
79
|
+
class TemporalConstraintViolation < LocalizedError
|
|
80
|
+
attr_reader :parent_generator
|
|
81
|
+
attr_reader :allowed_intervals
|
|
82
|
+
def initialize(event, parent_generator, allowed_intervals)
|
|
83
|
+
super(event)
|
|
84
|
+
@parent_generator = parent_generator
|
|
85
|
+
@allowed_intervals = allowed_intervals.dup
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def pretty_print(pp)
|
|
89
|
+
pp.text "Got "
|
|
90
|
+
failed_event.pretty_print(pp)
|
|
91
|
+
pp.text "It breaks the temporal constraint(s) #{allowed_intervals.map { |min, max| "[#{min}, #{max}]" }.join(" | ")} from"
|
|
92
|
+
pp.nest(2) do
|
|
93
|
+
pp.breakable
|
|
94
|
+
parent_generator.pretty_print(pp)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Exception raised when an event gets emitted outside its specified
|
|
100
|
+
# temporal constraints
|
|
101
|
+
class OccurenceConstraintViolation < LocalizedError
|
|
102
|
+
attr_reader :parent_generator
|
|
103
|
+
attr_reader :count
|
|
104
|
+
attr_reader :allowed_interval
|
|
105
|
+
attr_reader :since
|
|
106
|
+
|
|
107
|
+
def initialize(event, parent_generator, count, allowed_interval, since)
|
|
108
|
+
super(event)
|
|
109
|
+
@parent_generator = parent_generator
|
|
110
|
+
@count = count
|
|
111
|
+
@allowed_interval = allowed_interval
|
|
112
|
+
@since = since
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def pretty_print(pp)
|
|
116
|
+
pp.text "Got "
|
|
117
|
+
failed_event.pretty_print(pp)
|
|
118
|
+
pp.breakable
|
|
119
|
+
pp.text "This does not satisfy the occurance constraint [#{allowed_interval[0]}, #{allowed_interval[1]}] from"
|
|
120
|
+
pp.nest(2) do
|
|
121
|
+
pp.breakable
|
|
122
|
+
parent_generator.pretty_print(pp)
|
|
123
|
+
end
|
|
124
|
+
pp.breakable
|
|
125
|
+
pp.text "which has been emitted #{count} times"
|
|
126
|
+
if since
|
|
127
|
+
pp.text " since #{since}"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# A representation of a set of disjoint intervals, sorted in increasing
|
|
133
|
+
# order
|
|
134
|
+
class DisjointIntervalSet
|
|
135
|
+
# A list of intervals as [min, max]. The list is sorted in increasing order
|
|
136
|
+
attr_reader :intervals
|
|
137
|
+
|
|
138
|
+
def initialize
|
|
139
|
+
@intervals = Array.new
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Returns true if +value+ is included in one of the intervals
|
|
143
|
+
def include?(value)
|
|
144
|
+
candidate = intervals.
|
|
145
|
+
find { |min, max| max >= value }
|
|
146
|
+
candidate && (candidate[0] <= value)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Returns the lower and upper bound of the union of all intervals
|
|
150
|
+
def boundaries
|
|
151
|
+
[intervals.first[0], intervals.last[1]]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Adds a new interval to the set, merging it with existing intervals
|
|
155
|
+
# if needed
|
|
156
|
+
#
|
|
157
|
+
# Returns +self+
|
|
158
|
+
def add(min, max)
|
|
159
|
+
if intervals.empty?
|
|
160
|
+
intervals << [min, max]
|
|
161
|
+
return
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
new_list = Array.new
|
|
165
|
+
while interval = intervals.shift
|
|
166
|
+
if interval[1] < min
|
|
167
|
+
new_list << interval
|
|
168
|
+
elsif interval[0] > min
|
|
169
|
+
if interval[0] > max
|
|
170
|
+
new_list << [min, max] << interval
|
|
171
|
+
break
|
|
172
|
+
else
|
|
173
|
+
new_list << [min, [max, interval[1]].max]
|
|
174
|
+
end
|
|
175
|
+
break
|
|
176
|
+
else
|
|
177
|
+
new_list << [interval[0], [max, interval[1]].max]
|
|
178
|
+
break
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
if intervals.empty? && new_list.last[1] < min
|
|
183
|
+
new_list << [min, max]
|
|
184
|
+
|
|
185
|
+
elsif new_list.last[1] <= max
|
|
186
|
+
while interval = intervals.shift
|
|
187
|
+
last_interval = new_list.last
|
|
188
|
+
|
|
189
|
+
# It is guaranteed that interval[0] > last_interval[0].
|
|
190
|
+
# We therefore only need to check if interval[0] is
|
|
191
|
+
# included in last_interval
|
|
192
|
+
if interval[0] <= last_interval[1]
|
|
193
|
+
if last_interval[1] < interval[1]
|
|
194
|
+
last_interval[1] = interval[1]
|
|
195
|
+
break
|
|
196
|
+
end
|
|
197
|
+
else
|
|
198
|
+
new_list << interval
|
|
199
|
+
break
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# We now know that the last interval in new_list has an upper
|
|
205
|
+
# bound that comes from an already existing interval. We are
|
|
206
|
+
# therefore sure that there are no overlaps.
|
|
207
|
+
new_list.concat(intervals)
|
|
208
|
+
@intervals = new_list
|
|
209
|
+
self
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
class TemporalConstraintSet < DisjointIntervalSet
|
|
214
|
+
attr_reader :occurence_constraints
|
|
215
|
+
|
|
216
|
+
def initialize
|
|
217
|
+
super
|
|
218
|
+
|
|
219
|
+
@occurence_constraints = {
|
|
220
|
+
true => [0, Infinity],
|
|
221
|
+
false => [0, Infinity] }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def add_occurence_constraint(min, max, recurrent)
|
|
225
|
+
existing = occurence_constraints[!!recurrent]
|
|
226
|
+
if existing[0] < min
|
|
227
|
+
existing[0] = min
|
|
228
|
+
end
|
|
229
|
+
if existing[1] > max
|
|
230
|
+
existing[1] = max
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# This relation maintains a network of temporal constraints between
|
|
236
|
+
# events, that apply on the scheduling of these events
|
|
237
|
+
#
|
|
238
|
+
# If the a -> b edge exists in this graph, it specifies that
|
|
239
|
+
# \c b can be scheduled if and only if \c a can be scheduled *regardless
|
|
240
|
+
# of the existing temporal constraints that are due to \c b.
|
|
241
|
+
#
|
|
242
|
+
# As an example, let's set up a graph in which
|
|
243
|
+
# * a task ta will be started after a task tb has started *but*
|
|
244
|
+
# * all temporal constraints that apply on ta also apply on tb.
|
|
245
|
+
#
|
|
246
|
+
# The required edges are
|
|
247
|
+
#
|
|
248
|
+
# tb.success -> ta.start t=[0, Infinity], o=[1, Infinity] in TemporalConstraints
|
|
249
|
+
# ta.start -> tb.start in SchedulingConstraints
|
|
250
|
+
#
|
|
251
|
+
# The relation code takes care of maintaining the symmetric relationship
|
|
252
|
+
relation :SchedulingConstraints,
|
|
253
|
+
child_name: :forward_scheduling_constraint,
|
|
254
|
+
parent_name: :backward_scheduling_constraint,
|
|
255
|
+
dag: false,
|
|
256
|
+
noinfo: true
|
|
257
|
+
|
|
258
|
+
class SchedulingConstraints
|
|
259
|
+
# The graph of tasks related to each other by their events
|
|
260
|
+
attr_reader :task_graph
|
|
261
|
+
|
|
262
|
+
def initialize(*args)
|
|
263
|
+
super
|
|
264
|
+
@task_graph = Relations::BidirectionalDirectedAdjacencyGraph.new
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def add_edge(from, to, info)
|
|
268
|
+
if super
|
|
269
|
+
if from.respond_to?(:task) && to.respond_to?(:task)
|
|
270
|
+
add_edge_in_task_graph(from.task, to.task)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def add_edge_in_task_graph(from_task, to_task)
|
|
276
|
+
return if from_task == to_task
|
|
277
|
+
|
|
278
|
+
if task_graph.has_edge?(from_task, to_task)
|
|
279
|
+
count = task_graph.edge_info(from_task, to_task)
|
|
280
|
+
task_graph.set_edge_info(from_task, to_task, count + 1)
|
|
281
|
+
else
|
|
282
|
+
task_graph.add_edge(from_task, to_task, 1)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def remove_edge_in_task_graph(from_task, to_task)
|
|
287
|
+
return if from_task == to_task
|
|
288
|
+
|
|
289
|
+
count = task_graph.edge_info(from_task, to_task)
|
|
290
|
+
if count == 1
|
|
291
|
+
task_graph.remove_edge(from_task, to_task)
|
|
292
|
+
else
|
|
293
|
+
task_graph.set_edge_info(from_task, to_task, count - 1)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def merge(graph)
|
|
298
|
+
super
|
|
299
|
+
|
|
300
|
+
# There's really no easy way to handle the merge nicely. Rebuild
|
|
301
|
+
# the task graph
|
|
302
|
+
task_graph.clear
|
|
303
|
+
each_edge do |from, to|
|
|
304
|
+
if from.respond_to?(:task) && to.respond_to?(:task)
|
|
305
|
+
add_edge_in_task_graph(from.task, to.task)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def replace(graph)
|
|
311
|
+
super
|
|
312
|
+
task_graph.replace(graph.task_graph)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def remove_vertex(event)
|
|
316
|
+
if event.respond_to?(:task)
|
|
317
|
+
each_in_neighbour(event) do |from|
|
|
318
|
+
if from.respond_to?(:task)
|
|
319
|
+
remove_edge_in_task_graph(from.task, event.task)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
each_out_neighbour(event) do |to|
|
|
323
|
+
if to.respond_to?(:task)
|
|
324
|
+
remove_edge_in_task_graph(event.task, to.task)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
super
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def remove_edge(from, to)
|
|
332
|
+
super
|
|
333
|
+
if from.respond_to?(:task) && to.respond_to?(:task)
|
|
334
|
+
remove_edge_in_task_graph(from.task, to.task)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def related_tasks?(ta, tb)
|
|
339
|
+
task_graph.has_edge?(ta, tb)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def clear
|
|
343
|
+
super
|
|
344
|
+
task_graph.clear
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
module Extension
|
|
348
|
+
def schedule_as(event)
|
|
349
|
+
event.add_forward_scheduling_constraint(self)
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# True if this event is constrained by the TemporalConstraints
|
|
353
|
+
# relation in any way
|
|
354
|
+
def has_scheduling_constraints?
|
|
355
|
+
return true if has_temporal_constraints?
|
|
356
|
+
each_backward_scheduling_constraint do |parent|
|
|
357
|
+
return true
|
|
358
|
+
end
|
|
359
|
+
false
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Module that implements shortcuts on tasks to use the scheduling
|
|
365
|
+
# constraints
|
|
366
|
+
module TaskSchedulingConstraints
|
|
367
|
+
# Adds a constraint that ensures that the start event of +self+ is
|
|
368
|
+
# scheduled as the start event of +task+
|
|
369
|
+
def schedule_as(task)
|
|
370
|
+
start_event.schedule_as(task.start_event)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# This relation maintains a network of temporal constraints between
|
|
375
|
+
# events.
|
|
376
|
+
#
|
|
377
|
+
# A relation A => B [min, max] specifies that, once the event A is
|
|
378
|
+
# emitted, the event B should be emitted within a [min, max] amount of
|
|
379
|
+
# time. Obviously, it is guaranteed that min > 0 and max > min
|
|
380
|
+
#
|
|
381
|
+
# The relation code takes care of maintaining the symmetric relationship
|
|
382
|
+
relation :TemporalConstraints,
|
|
383
|
+
child_name: :forward_temporal_constraint,
|
|
384
|
+
parent_name: :backward_temporal_constraint,
|
|
385
|
+
dag: false
|
|
386
|
+
|
|
387
|
+
class TemporalConstraints
|
|
388
|
+
module EventFiredHook
|
|
389
|
+
# Overloaded to register deadlines that this event's emissions
|
|
390
|
+
# define
|
|
391
|
+
def fired(event)
|
|
392
|
+
super
|
|
393
|
+
|
|
394
|
+
# Verify that the event matches any running constraint
|
|
395
|
+
parent, intervals = find_failed_temporal_constraint(event.time)
|
|
396
|
+
if parent
|
|
397
|
+
plan.execution_engine.add_error TemporalConstraintViolation.new(event, parent, intervals.intervals)
|
|
398
|
+
end
|
|
399
|
+
parent, count, allowed_interval, since = find_failed_occurence_constraint(false)
|
|
400
|
+
if parent
|
|
401
|
+
plan.execution_engine.add_error OccurenceConstraintViolation.new(event, parent, count, allowed_interval, since)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
deadlines = plan.emission_deadlines
|
|
405
|
+
# Remove the deadline that this emission fullfills (if any)
|
|
406
|
+
deadlines.remove_deadline_for(self, event.time)
|
|
407
|
+
# Add new deadlines
|
|
408
|
+
each_forward_temporal_constraint do |target, disjoint_set|
|
|
409
|
+
next if disjoint_set.intervals.empty?
|
|
410
|
+
|
|
411
|
+
max_diff = disjoint_set.boundaries[1]
|
|
412
|
+
is_fullfilled = target.history.any? do |target_event|
|
|
413
|
+
diff = event.time - target_event.time
|
|
414
|
+
break if diff > max_diff
|
|
415
|
+
disjoint_set.include?(diff)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
if !is_fullfilled
|
|
419
|
+
deadlines.add(event.time + disjoint_set.boundaries[1], event, target)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
module Extension
|
|
426
|
+
# Shortcut to specify that +self+ should be emitted after
|
|
427
|
+
# +other_event+
|
|
428
|
+
def should_emit_after(other_event, options = nil)
|
|
429
|
+
if options
|
|
430
|
+
options = Kernel.validate_options options,
|
|
431
|
+
min_t: nil, max_t: nil, recurrent: false
|
|
432
|
+
recurrent = options[:recurrent]
|
|
433
|
+
end
|
|
434
|
+
other_event.add_occurence_constraint(self, 1, Infinity, recurrent)
|
|
435
|
+
if options && (options[:min_t] || options[:max_t])
|
|
436
|
+
other_event.add_temporal_constraint(self,
|
|
437
|
+
options[:min_t] || 0, options[:max_t] || Infinity)
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# Returns true if there is a constraint that specifies that self
|
|
442
|
+
# and generator are ordered in time
|
|
443
|
+
def should_emit_after?(generator)
|
|
444
|
+
graph = plan.event_relation_graph_for(TemporalConstraints)
|
|
445
|
+
graph.has_edge?(generator, self)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
# True if this event is constrained by the TemporalConstraints
|
|
449
|
+
# relation in any way
|
|
450
|
+
def has_temporal_constraints?
|
|
451
|
+
each_backward_temporal_constraint do |parent|
|
|
452
|
+
return true
|
|
453
|
+
end
|
|
454
|
+
false
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
# Returns a [parent, intervals] pair that represents a temporal
|
|
458
|
+
# constraint the given time fails to meet
|
|
459
|
+
def find_failed_temporal_constraint(time)
|
|
460
|
+
each_backward_temporal_constraint do |parent|
|
|
461
|
+
if block_given?
|
|
462
|
+
next if !yield(parent)
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
disjoint_set = parent[self, TemporalConstraints]
|
|
466
|
+
next if disjoint_set.intervals.empty?
|
|
467
|
+
|
|
468
|
+
if disjoint_set.boundaries[0] < 0
|
|
469
|
+
# It might be fullfilled in the future
|
|
470
|
+
next
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
max_diff = disjoint_set.boundaries[1]
|
|
474
|
+
parent.history.each do |parent_event|
|
|
475
|
+
diff = time - parent_event.time
|
|
476
|
+
if diff > max_diff || !disjoint_set.include?(diff)
|
|
477
|
+
return parent, disjoint_set
|
|
478
|
+
end
|
|
479
|
+
disjoint_set.include?(diff)
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
nil
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
# Returns true if this event meets its temporal constraints
|
|
486
|
+
def meets_temporal_constraints?(time, &block)
|
|
487
|
+
!find_failed_temporal_constraint(time, &block) &&
|
|
488
|
+
!find_failed_occurence_constraint(true, &block)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
# Creates a temporal constraint between +self+ and +other_event+.
|
|
492
|
+
# +min+ is the minimum time
|
|
493
|
+
def add_temporal_constraint(other_event, min, max)
|
|
494
|
+
if min > max
|
|
495
|
+
raise ArgumentError, "min should be lower than max (min == #{min} and max == #{max})"
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
if max < 0
|
|
499
|
+
return other_event.add_temporal_constraint(self, -max, -min)
|
|
500
|
+
elsif min < 0
|
|
501
|
+
set = TemporalConstraintSet.new
|
|
502
|
+
set.add(-max, -min)
|
|
503
|
+
other_event.add_forward_temporal_constraint(self, set)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
set = TemporalConstraintSet.new
|
|
507
|
+
set.add(min, max)
|
|
508
|
+
add_forward_temporal_constraint(other_event, set)
|
|
509
|
+
set
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
# Adds a constraint on the allowed emission of +other_event+ based
|
|
513
|
+
# on the existing emissions of +self+
|
|
514
|
+
#
|
|
515
|
+
# +min+ and +max+ specify the minimum (resp. maximum) of times
|
|
516
|
+
# +self+ should be emitted before +other_event+ has the right to be
|
|
517
|
+
# emitted.
|
|
518
|
+
#
|
|
519
|
+
# If +recurrent+ is true, then the min/max values are computed using
|
|
520
|
+
# the emissions of +self+ since the last emission of +other_event+.
|
|
521
|
+
# Otherwise, all emissions since the creation of +self+ are taken
|
|
522
|
+
# into account.
|
|
523
|
+
def add_occurence_constraint(other_event, min, max = Infinity, recurrent = false)
|
|
524
|
+
set = TemporalConstraintSet.new
|
|
525
|
+
set.add_occurence_constraint(min, max, recurrent)
|
|
526
|
+
add_forward_temporal_constraint(other_event, set)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def find_failed_occurence_constraint(next_event)
|
|
530
|
+
base_event = if next_event then last
|
|
531
|
+
else history[-2]
|
|
532
|
+
end
|
|
533
|
+
if base_event
|
|
534
|
+
base_time = base_event.time
|
|
535
|
+
end
|
|
536
|
+
each_backward_temporal_constraint do |parent|
|
|
537
|
+
if block_given?
|
|
538
|
+
next if !yield(parent)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
constraints = parent[self, TemporalConstraints]
|
|
542
|
+
counts = { false => parent.history.size }
|
|
543
|
+
if base_time
|
|
544
|
+
negative_count = parent.history.inject(0) do |count, ev|
|
|
545
|
+
break(count) if ev.time > base_time
|
|
546
|
+
count + 1
|
|
547
|
+
end
|
|
548
|
+
else
|
|
549
|
+
negative_count = 0
|
|
550
|
+
end
|
|
551
|
+
counts[true] = counts[false] - negative_count
|
|
552
|
+
counts.each do |recurrent, count|
|
|
553
|
+
min_count, max_count = constraints.occurence_constraints[recurrent]
|
|
554
|
+
if count < min_count || count > max_count
|
|
555
|
+
if recurrent && base_time
|
|
556
|
+
return [parent, parent.history.size, [min_count, max_count], base_time]
|
|
557
|
+
else
|
|
558
|
+
return [parent, parent.history.size, [min_count, max_count]]
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
nil
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
# Returns the DisjointIntervalSet that represent the merge of the
|
|
569
|
+
# deadlines represented by +opt1+ and +opt2+
|
|
570
|
+
def merge_info(parent, child, opt1, opt2)
|
|
571
|
+
result = TemporalConstraintSet.new
|
|
572
|
+
if opt1.intervals.size > opt2.intervals.size
|
|
573
|
+
result.intervals.concat(opt1.intervals)
|
|
574
|
+
for i in opt2.intervals
|
|
575
|
+
result.add(*i)
|
|
576
|
+
end
|
|
577
|
+
else
|
|
578
|
+
result.intervals.concat(opt2.intervals)
|
|
579
|
+
for i in opt1.intervals
|
|
580
|
+
result.add(*i)
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
result.occurence_constraints.merge!(opt1.occurence_constraints)
|
|
585
|
+
opt2.occurence_constraints.each do |recurrent, spec|
|
|
586
|
+
result.add_occurence_constraint(spec[0], spec[1], recurrent)
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
result
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
# Check the temporal constraint structure
|
|
593
|
+
#
|
|
594
|
+
# What it needs to do is check that events that *should* have been
|
|
595
|
+
# emitted had been. The emission of events outside of allowed intervals
|
|
596
|
+
# is already taken care of.
|
|
597
|
+
#
|
|
598
|
+
# Optimize by keeping the list of of maximum bounds at which an event
|
|
599
|
+
# should be emitted.
|
|
600
|
+
def check_structure(plan)
|
|
601
|
+
deadlines = plan.emission_deadlines
|
|
602
|
+
|
|
603
|
+
# Now look for the timeouts
|
|
604
|
+
errors = []
|
|
605
|
+
deadlines.missed_deadlines(Time.now).
|
|
606
|
+
each do |deadline, event, generator|
|
|
607
|
+
errors << MissedDeadlineError.new(generator, event, deadline)
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
errors
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
# Module defining shortcuts on tasks to use the temporal constraints
|
|
615
|
+
module TaskTemporalConstraints
|
|
616
|
+
# Ensures that this task is started after +task_or_event+ has
|
|
617
|
+
# finished (if it is a task) or +task_or_event+ is emitted (if it is
|
|
618
|
+
# an event)
|
|
619
|
+
def should_start_after(task_or_event)
|
|
620
|
+
case task_or_event
|
|
621
|
+
when Roby::Task
|
|
622
|
+
start_event.should_emit_after(task_or_event.stop_event)
|
|
623
|
+
when Roby::EventGenerator
|
|
624
|
+
start_event.should_emit_after(task_or_event)
|
|
625
|
+
else
|
|
626
|
+
raise ArgumentError, "expected a task or an event generator, got #{task_or_event} of class #{task_or_event.class}"
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
Roby::EventGenerator.class_eval do
|
|
631
|
+
prepend TemporalConstraints::EventFiredHook
|
|
632
|
+
end
|
|
633
|
+
Roby::Task.class_eval do
|
|
634
|
+
prepend TaskSchedulingConstraints
|
|
635
|
+
prepend TaskTemporalConstraints
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
|