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.
Files changed (644) hide show
  1. checksums.yaml +7 -0
  2. data/.deep-cover.rb +3 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +24 -0
  5. data/.simplecov +10 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +15 -0
  9. data/README.md +11 -0
  10. data/Rakefile +47 -177
  11. data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
  12. data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
  13. data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
  14. data/benchmark/{genom.rb → attic/genom.rb} +0 -0
  15. data/benchmark/attic/transactions.rb +62 -0
  16. data/benchmark/plan_basic_operations.rb +28 -0
  17. data/benchmark/relations/graph.rb +63 -0
  18. data/benchmark/ruby/identity.rb +18 -0
  19. data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
  20. data/benchmark/ruby/yield_vs_block.rb +35 -0
  21. data/benchmark/run +5 -0
  22. data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
  23. data/benchmark/transactions.rb +99 -51
  24. data/bin/roby +38 -197
  25. data/bin/roby-display +14 -0
  26. data/bin/roby-log +3 -176
  27. data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
  28. data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
  29. data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
  30. data/doc/guide/{src → attic}/abstraction/index.page +1 -1
  31. data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
  32. data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
  33. data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
  34. data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
  35. data/doc/guide/attic/cycle/error_handling.page +98 -0
  36. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
  37. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
  38. data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
  39. data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
  40. data/doc/guide/{src → attic}/cycle/index.page +1 -1
  41. data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
  42. data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
  43. data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
  44. data/doc/guide/attic/plans/building_plans.page +89 -0
  45. data/doc/guide/attic/plans/code.page +192 -0
  46. data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
  47. data/doc/guide/attic/plans/index.page +7 -0
  48. data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
  49. data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
  50. data/doc/guide/attic/plans/querying_plans.page +5 -0
  51. data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
  52. data/doc/guide/config.yaml +7 -4
  53. data/doc/guide/ext/extended_menu.rb +29 -0
  54. data/doc/guide/ext/init.rb +6 -0
  55. data/doc/guide/ext/rdoc_links.rb +7 -6
  56. data/doc/guide/src/advanced_concepts/history.page +5 -0
  57. data/doc/guide/src/advanced_concepts/index.page +11 -0
  58. data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
  59. data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
  60. data/doc/guide/src/advanced_concepts/transactions.page +5 -0
  61. data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
  62. data/doc/guide/src/base.template +96 -0
  63. data/doc/guide/src/basics_shell_header.txt +5 -7
  64. data/doc/guide/src/building/action_coordination.page +96 -0
  65. data/doc/guide/src/building/actions.page +124 -0
  66. data/doc/guide/src/building/file_layout.page +71 -0
  67. data/doc/guide/src/building/index.page +50 -0
  68. data/doc/guide/src/building/patterns.page +86 -0
  69. data/doc/guide/src/building/patterns_forwarding.png +0 -0
  70. data/doc/guide/src/building/patterns_forwarding.svg +277 -0
  71. data/doc/guide/src/building/runtime.page +95 -0
  72. data/doc/guide/src/building/task_models.page +94 -0
  73. data/doc/guide/src/building/tasks.page +284 -0
  74. data/doc/guide/src/concepts/error_handling.page +100 -0
  75. data/doc/guide/src/concepts/exception_propagation.png +0 -0
  76. data/doc/guide/src/concepts/exception_propagation.svg +445 -0
  77. data/doc/guide/src/concepts/execution.page +85 -0
  78. data/doc/guide/src/concepts/execution.png +0 -0
  79. data/doc/guide/src/concepts/execution.svg +573 -0
  80. data/doc/guide/src/concepts/execution_cycle.png +0 -0
  81. data/doc/guide/src/concepts/garbage_collection.page +57 -0
  82. data/doc/guide/src/concepts/index.page +27 -0
  83. data/doc/guide/src/concepts/plans.page +101 -0
  84. data/doc/guide/src/concepts/policy.page +31 -0
  85. data/doc/guide/src/concepts/reactor.page +61 -0
  86. data/doc/guide/src/concepts/simple_plan_example.png +0 -0
  87. data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
  88. data/doc/guide/src/default.template +9 -74
  89. data/doc/guide/src/event_relations/forward.page +71 -0
  90. data/doc/guide/src/event_relations/index.page +12 -0
  91. data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
  92. data/doc/guide/src/event_relations/signal.page +55 -0
  93. data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
  94. data/doc/guide/src/htmldoc.metainfo +21 -8
  95. data/doc/guide/src/index.page +8 -3
  96. data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
  97. data/doc/guide/src/installation/publications.page +14 -0
  98. data/doc/guide/src/{introduction → installation}/videos.page +14 -7
  99. data/doc/guide/src/interacting/index.page +16 -0
  100. data/doc/guide/src/interacting/run.page +33 -0
  101. data/doc/guide/src/interacting/shell.page +95 -0
  102. data/doc/guide/src/plugins/creating_plugins.page +72 -0
  103. data/doc/guide/src/plugins/index.page +27 -5
  104. data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
  105. data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
  106. data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
  107. data/doc/guide/src/style_screen.css +687 -0
  108. data/doc/guide/src/task_relations/dependency.page +107 -0
  109. data/doc/guide/src/task_relations/executed_by.page +77 -0
  110. data/doc/guide/src/task_relations/index.page +12 -0
  111. data/doc/guide/src/task_relations/new_relations.page +119 -0
  112. data/doc/guide/src/task_relations/planned_by.page +46 -0
  113. data/doc/guide/src/tutorial/app.page +117 -0
  114. data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
  115. data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
  116. data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
  117. data/doc/guide/src/tutorial/events.page +195 -0
  118. data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
  119. data/doc/guide/src/tutorial/index.page +13 -0
  120. data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
  121. data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
  122. data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
  123. data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
  124. data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
  125. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
  126. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
  127. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
  128. data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
  129. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
  130. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
  131. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
  132. data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
  133. data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
  134. data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
  135. data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
  136. data/doc/guide/src/tutorial/relations_display.page +153 -0
  137. data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
  138. data/doc/guide/src/tutorial/shell.page +121 -0
  139. data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
  140. data/doc/guide/src/tutorial/tasks.page +374 -0
  141. data/lib/roby.rb +102 -47
  142. data/lib/roby/actions.rb +17 -0
  143. data/lib/roby/actions/action.rb +80 -0
  144. data/lib/roby/actions/interface.rb +45 -0
  145. data/lib/roby/actions/library.rb +23 -0
  146. data/lib/roby/actions/models/action.rb +224 -0
  147. data/lib/roby/actions/models/coordination_action.rb +58 -0
  148. data/lib/roby/actions/models/interface.rb +22 -0
  149. data/lib/roby/actions/models/interface_base.rb +294 -0
  150. data/lib/roby/actions/models/library.rb +12 -0
  151. data/lib/roby/actions/models/method_action.rb +90 -0
  152. data/lib/roby/actions/task.rb +114 -0
  153. data/lib/roby/and_generator.rb +125 -0
  154. data/lib/roby/app.rb +2795 -829
  155. data/lib/roby/app/autotest_console_reporter.rb +138 -0
  156. data/lib/roby/app/base.rb +21 -0
  157. data/lib/roby/app/cucumber.rb +2 -0
  158. data/lib/roby/app/cucumber/controller.rb +439 -0
  159. data/lib/roby/app/cucumber/helpers.rb +280 -0
  160. data/lib/roby/app/cucumber/world.rb +32 -0
  161. data/lib/roby/app/debug.rb +136 -0
  162. data/lib/roby/app/gen.rb +2 -0
  163. data/lib/roby/app/rake.rb +178 -38
  164. data/lib/roby/app/robot_config.rb +9 -0
  165. data/lib/roby/app/robot_names.rb +115 -0
  166. data/lib/roby/app/run.rb +3 -2
  167. data/lib/roby/app/scripts.rb +72 -0
  168. data/lib/roby/app/scripts/autotest.rb +173 -0
  169. data/lib/roby/app/scripts/display.rb +2 -0
  170. data/lib/roby/app/scripts/restart.rb +52 -0
  171. data/lib/roby/app/scripts/results.rb +17 -8
  172. data/lib/roby/app/scripts/run.rb +155 -24
  173. data/lib/roby/app/scripts/shell.rb +147 -62
  174. data/lib/roby/app/scripts/test.rb +107 -22
  175. data/lib/roby/app/test_reporter.rb +74 -0
  176. data/lib/roby/app/test_server.rb +159 -0
  177. data/lib/roby/app/vagrant.rb +47 -0
  178. data/lib/roby/backports.rb +16 -0
  179. data/lib/roby/cli/display.rb +190 -0
  180. data/lib/roby/cli/exceptions.rb +17 -0
  181. data/lib/roby/cli/gen/actions/class.rb +5 -0
  182. data/lib/roby/cli/gen/actions/test.rb +6 -0
  183. data/lib/roby/cli/gen/app/.yardopts +6 -0
  184. data/lib/roby/cli/gen/app/README.md +28 -0
  185. data/lib/roby/cli/gen/app/Rakefile +15 -0
  186. data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
  187. data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
  188. data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
  189. data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
  190. data/lib/roby/cli/gen/class/class.rb +6 -0
  191. data/lib/roby/cli/gen/class/test.rb +7 -0
  192. data/lib/roby/cli/gen/helpers.rb +203 -0
  193. data/lib/roby/cli/gen/module/module.rb +5 -0
  194. data/lib/roby/cli/gen/module/test.rb +6 -0
  195. data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
  196. data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
  197. data/lib/roby/cli/gen/task/class.rb +44 -0
  198. data/lib/roby/cli/gen/task/test.rb +6 -0
  199. data/lib/roby/cli/gen_main.rb +120 -0
  200. data/lib/roby/cli/log.rb +276 -0
  201. data/lib/roby/cli/log/flamegraph.html +499 -0
  202. data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
  203. data/lib/roby/cli/main.rb +153 -0
  204. data/lib/roby/coordination.rb +60 -0
  205. data/lib/roby/coordination/action_script.rb +25 -0
  206. data/lib/roby/coordination/action_state_machine.rb +125 -0
  207. data/lib/roby/coordination/actions.rb +106 -0
  208. data/lib/roby/coordination/base.rb +145 -0
  209. data/lib/roby/coordination/calculus.rb +40 -0
  210. data/lib/roby/coordination/child.rb +28 -0
  211. data/lib/roby/coordination/event.rb +29 -0
  212. data/lib/roby/coordination/fault_handler.rb +25 -0
  213. data/lib/roby/coordination/fault_handling_task.rb +13 -0
  214. data/lib/roby/coordination/fault_response_table.rb +110 -0
  215. data/lib/roby/coordination/models/action_script.rb +64 -0
  216. data/lib/roby/coordination/models/action_state_machine.rb +224 -0
  217. data/lib/roby/coordination/models/actions.rb +191 -0
  218. data/lib/roby/coordination/models/arguments.rb +55 -0
  219. data/lib/roby/coordination/models/base.rb +176 -0
  220. data/lib/roby/coordination/models/capture.rb +86 -0
  221. data/lib/roby/coordination/models/child.rb +35 -0
  222. data/lib/roby/coordination/models/event.rb +41 -0
  223. data/lib/roby/coordination/models/exceptions.rb +42 -0
  224. data/lib/roby/coordination/models/fault_handler.rb +219 -0
  225. data/lib/roby/coordination/models/fault_response_table.rb +77 -0
  226. data/lib/roby/coordination/models/root.rb +22 -0
  227. data/lib/roby/coordination/models/script.rb +283 -0
  228. data/lib/roby/coordination/models/task.rb +184 -0
  229. data/lib/roby/coordination/models/task_from_action.rb +50 -0
  230. data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
  231. data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
  232. data/lib/roby/coordination/models/task_from_variable.rb +27 -0
  233. data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
  234. data/lib/roby/coordination/models/variable.rb +32 -0
  235. data/lib/roby/coordination/script.rb +200 -0
  236. data/lib/roby/coordination/script_instruction.rb +12 -0
  237. data/lib/roby/coordination/task.rb +45 -0
  238. data/lib/roby/coordination/task_base.rb +69 -0
  239. data/lib/roby/coordination/task_script.rb +293 -0
  240. data/lib/roby/coordination/task_state_machine.rb +308 -0
  241. data/lib/roby/decision_control.rb +33 -21
  242. data/lib/roby/distributed_object.rb +76 -0
  243. data/lib/roby/droby.rb +17 -0
  244. data/lib/roby/droby/droby_id.rb +6 -0
  245. data/lib/roby/droby/enable.rb +153 -0
  246. data/lib/roby/droby/event_logger.rb +189 -0
  247. data/lib/roby/droby/event_logging.rb +57 -0
  248. data/lib/roby/droby/exceptions.rb +14 -0
  249. data/lib/roby/droby/identifiable.rb +22 -0
  250. data/lib/roby/droby/logfile.rb +141 -0
  251. data/lib/roby/droby/logfile/client.rb +176 -0
  252. data/lib/roby/droby/logfile/file_format.md +97 -0
  253. data/lib/roby/droby/logfile/index.rb +117 -0
  254. data/lib/roby/droby/logfile/reader.rb +139 -0
  255. data/lib/roby/droby/logfile/server.rb +199 -0
  256. data/lib/roby/droby/logfile/writer.rb +114 -0
  257. data/lib/roby/droby/marshal.rb +264 -0
  258. data/lib/roby/droby/marshallable.rb +12 -0
  259. data/lib/roby/droby/null_event_logger.rb +25 -0
  260. data/lib/roby/droby/object_manager.rb +205 -0
  261. data/lib/roby/droby/peer_id.rb +6 -0
  262. data/lib/roby/droby/plan_rebuilder.rb +373 -0
  263. data/lib/roby/droby/rebuilt_plan.rb +160 -0
  264. data/lib/roby/droby/remote_droby_id.rb +6 -0
  265. data/lib/roby/droby/timepoints.rb +205 -0
  266. data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
  267. data/lib/roby/droby/timepoints_ctf.rb +125 -0
  268. data/lib/roby/droby/v5.rb +14 -0
  269. data/lib/roby/droby/v5/builtin.rb +120 -0
  270. data/lib/roby/droby/v5/droby_class.rb +45 -0
  271. data/lib/roby/droby/v5/droby_constant.rb +81 -0
  272. data/lib/roby/droby/v5/droby_dump.rb +1026 -0
  273. data/lib/roby/droby/v5/droby_id.rb +44 -0
  274. data/lib/roby/droby/v5/droby_model.rb +82 -0
  275. data/lib/roby/droby/v5/peer_id.rb +10 -0
  276. data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
  277. data/lib/roby/event.rb +79 -957
  278. data/lib/roby/event_constraints.rb +835 -0
  279. data/lib/roby/event_generator.rb +1047 -0
  280. data/lib/roby/event_structure/causal_link.rb +6 -0
  281. data/lib/roby/event_structure/forwarding.rb +6 -0
  282. data/lib/roby/event_structure/precedence.rb +7 -0
  283. data/lib/roby/event_structure/signal.rb +8 -0
  284. data/lib/roby/event_structure/temporal_constraints.rb +640 -0
  285. data/lib/roby/exceptions.rb +446 -152
  286. data/lib/roby/executable_plan.rb +549 -0
  287. data/lib/roby/execution_engine.rb +1997 -950
  288. data/lib/roby/filter_generator.rb +26 -0
  289. data/lib/roby/gui/chronicle_view.rb +225 -0
  290. data/lib/roby/gui/chronicle_widget.rb +925 -0
  291. data/lib/roby/gui/dot_id.rb +11 -0
  292. data/lib/roby/gui/exception_view.rb +44 -0
  293. data/lib/roby/gui/log_display.rb +273 -0
  294. data/lib/roby/gui/model_views.rb +2 -0
  295. data/lib/roby/gui/model_views/action_interface.rb +53 -0
  296. data/lib/roby/gui/model_views/task.rb +47 -0
  297. data/lib/roby/gui/model_views/task.rhtml +41 -0
  298. data/lib/roby/gui/object_info_view.rb +89 -0
  299. data/lib/roby/gui/plan_dot_layout.rb +427 -0
  300. data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
  301. data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
  302. data/lib/roby/gui/relations_view.rb +278 -0
  303. data/lib/roby/gui/relations_view/relations.ui +139 -0
  304. data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
  305. data/lib/roby/gui/relations_view/relations_config.rb +292 -0
  306. data/lib/roby/gui/relations_view/relations_view.ui +53 -0
  307. data/lib/roby/gui/scheduler_view.css +24 -0
  308. data/lib/roby/gui/scheduler_view.rb +46 -0
  309. data/lib/roby/gui/scheduler_view.rhtml +53 -0
  310. data/lib/roby/gui/stepping.rb +93 -0
  311. data/lib/roby/gui/stepping.ui +181 -0
  312. data/lib/roby/gui/styles.rb +81 -0
  313. data/lib/roby/gui/task_display_configuration.rb +42 -0
  314. data/lib/roby/gui/task_state_at.rb +38 -0
  315. data/lib/roby/hooks.rb +26 -0
  316. data/lib/roby/interface.rb +136 -469
  317. data/lib/roby/interface/async.rb +20 -0
  318. data/lib/roby/interface/async/action_monitor.rb +188 -0
  319. data/lib/roby/interface/async/interface.rb +498 -0
  320. data/lib/roby/interface/async/job_monitor.rb +213 -0
  321. data/lib/roby/interface/async/log.rb +238 -0
  322. data/lib/roby/interface/async/new_job_listener.rb +79 -0
  323. data/lib/roby/interface/async/ui_connector.rb +183 -0
  324. data/lib/roby/interface/client.rb +553 -0
  325. data/lib/roby/interface/command.rb +24 -0
  326. data/lib/roby/interface/command_argument.rb +16 -0
  327. data/lib/roby/interface/command_library.rb +92 -0
  328. data/lib/roby/interface/droby_channel.rb +174 -0
  329. data/lib/roby/interface/exceptions.rb +22 -0
  330. data/lib/roby/interface/interface.rb +655 -0
  331. data/lib/roby/interface/job.rb +47 -0
  332. data/lib/roby/interface/rest.rb +10 -0
  333. data/lib/roby/interface/rest/api.rb +29 -0
  334. data/lib/roby/interface/rest/helpers.rb +24 -0
  335. data/lib/roby/interface/rest/server.rb +212 -0
  336. data/lib/roby/interface/server.rb +154 -0
  337. data/lib/roby/interface/shell_client.rb +468 -0
  338. data/lib/roby/interface/shell_subcommand.rb +24 -0
  339. data/lib/roby/interface/subcommand_client.rb +35 -0
  340. data/lib/roby/interface/tcp.rb +168 -0
  341. data/lib/roby/models/arguments.rb +112 -0
  342. data/lib/roby/models/plan_object.rb +83 -0
  343. data/lib/roby/models/task.rb +835 -0
  344. data/lib/roby/models/task_event.rb +62 -0
  345. data/lib/roby/models/task_service.rb +78 -0
  346. data/lib/roby/or_generator.rb +88 -0
  347. data/lib/roby/plan.rb +1751 -864
  348. data/lib/roby/plan_object.rb +611 -0
  349. data/lib/roby/plan_service.rb +200 -0
  350. data/lib/roby/promise.rb +332 -0
  351. data/lib/roby/queries.rb +23 -0
  352. data/lib/roby/queries/and_matcher.rb +32 -0
  353. data/lib/roby/queries/any.rb +27 -0
  354. data/lib/roby/queries/code_error_matcher.rb +58 -0
  355. data/lib/roby/queries/event_generator_matcher.rb +9 -0
  356. data/lib/roby/queries/execution_exception_matcher.rb +165 -0
  357. data/lib/roby/queries/index.rb +165 -0
  358. data/lib/roby/queries/localized_error_matcher.rb +149 -0
  359. data/lib/roby/queries/matcher_base.rb +107 -0
  360. data/lib/roby/queries/none.rb +27 -0
  361. data/lib/roby/queries/not_matcher.rb +30 -0
  362. data/lib/roby/queries/op_matcher.rb +8 -0
  363. data/lib/roby/queries/or_matcher.rb +30 -0
  364. data/lib/roby/queries/plan_object_matcher.rb +363 -0
  365. data/lib/roby/queries/query.rb +188 -0
  366. data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
  367. data/lib/roby/queries/task_matcher.rb +344 -0
  368. data/lib/roby/relations.rb +42 -678
  369. data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
  370. data/lib/roby/relations/directed_relation_support.rb +268 -0
  371. data/lib/roby/relations/event_relation_graph.rb +19 -0
  372. data/lib/roby/relations/fork_merge_visitor.rb +154 -0
  373. data/lib/roby/relations/graph.rb +533 -0
  374. data/lib/roby/relations/models/directed_relation_support.rb +11 -0
  375. data/lib/roby/relations/models/graph.rb +75 -0
  376. data/lib/roby/relations/models/task_relation_graph.rb +18 -0
  377. data/lib/roby/relations/space.rb +380 -0
  378. data/lib/roby/relations/task_relation_graph.rb +20 -0
  379. data/lib/roby/robot.rb +85 -38
  380. data/lib/roby/schedulers/basic.rb +155 -25
  381. data/lib/roby/schedulers/null.rb +20 -0
  382. data/lib/roby/schedulers/reporting.rb +31 -0
  383. data/lib/roby/schedulers/state.rb +129 -0
  384. data/lib/roby/schedulers/temporal.rb +91 -0
  385. data/lib/roby/singletons.rb +87 -0
  386. data/lib/roby/standalone.rb +4 -2
  387. data/lib/roby/standard_errors.rb +405 -82
  388. data/lib/roby/state.rb +6 -3
  389. data/lib/roby/state/conf_model.rb +5 -0
  390. data/lib/roby/state/events.rb +181 -95
  391. data/lib/roby/state/goal_model.rb +77 -0
  392. data/lib/roby/state/open_struct.rb +591 -0
  393. data/lib/roby/state/open_struct_model.rb +68 -0
  394. data/lib/roby/state/pos.rb +45 -45
  395. data/lib/roby/state/shapes.rb +11 -11
  396. data/lib/roby/state/state_model.rb +303 -0
  397. data/lib/roby/state/task.rb +43 -0
  398. data/lib/roby/support.rb +88 -148
  399. data/lib/roby/task.rb +1361 -1750
  400. data/lib/roby/task_arguments.rb +428 -0
  401. data/lib/roby/task_event.rb +127 -0
  402. data/lib/roby/task_event_generator.rb +337 -0
  403. data/lib/roby/task_service.rb +6 -0
  404. data/lib/roby/task_structure/conflicts.rb +104 -0
  405. data/lib/roby/task_structure/dependency.rb +932 -0
  406. data/lib/roby/task_structure/error_handling.rb +118 -0
  407. data/lib/roby/task_structure/executed_by.rb +234 -0
  408. data/lib/roby/task_structure/planned_by.rb +90 -0
  409. data/lib/roby/tasks/aggregator.rb +37 -0
  410. data/lib/roby/tasks/external_process.rb +275 -0
  411. data/lib/roby/tasks/group.rb +27 -0
  412. data/lib/roby/tasks/null.rb +19 -0
  413. data/lib/roby/tasks/parallel.rb +43 -0
  414. data/lib/roby/tasks/sequence.rb +88 -0
  415. data/lib/roby/tasks/simple.rb +21 -0
  416. data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
  417. data/lib/roby/tasks/timeout.rb +17 -0
  418. data/lib/roby/tasks/virtual.rb +55 -0
  419. data/lib/roby/template_plan.rb +7 -0
  420. data/lib/roby/test/aruba_minitest.rb +74 -0
  421. data/lib/roby/test/assertion.rb +16 -0
  422. data/lib/roby/test/assertions.rb +490 -0
  423. data/lib/roby/test/common.rb +368 -591
  424. data/lib/roby/test/dsl.rb +149 -0
  425. data/lib/roby/test/error.rb +18 -0
  426. data/lib/roby/test/event_reporter.rb +83 -0
  427. data/lib/roby/test/execution_expectations.rb +1134 -0
  428. data/lib/roby/test/expect_execution.rb +151 -0
  429. data/lib/roby/test/minitest_helpers.rb +166 -0
  430. data/lib/roby/test/roby_app_helpers.rb +200 -0
  431. data/lib/roby/test/run_planners.rb +155 -0
  432. data/lib/roby/test/self.rb +112 -0
  433. data/lib/roby/test/spec.rb +198 -0
  434. data/lib/roby/test/tasks/empty_task.rb +4 -4
  435. data/lib/roby/test/tasks/goto.rb +28 -27
  436. data/lib/roby/test/teardown_plans.rb +100 -0
  437. data/lib/roby/test/testcase.rb +239 -307
  438. data/lib/roby/test/tools.rb +159 -155
  439. data/lib/roby/test/validate_state_machine.rb +75 -0
  440. data/lib/roby/transaction.rb +1125 -0
  441. data/lib/roby/transaction/event_generator_proxy.rb +63 -0
  442. data/lib/roby/transaction/plan_object_proxy.rb +99 -0
  443. data/lib/roby/transaction/plan_service_proxy.rb +43 -0
  444. data/lib/roby/transaction/proxying.rb +120 -0
  445. data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
  446. data/lib/roby/transaction/task_proxy.rb +135 -0
  447. data/lib/roby/until_generator.rb +30 -0
  448. data/lib/roby/version.rb +5 -0
  449. data/lib/roby/yard.rb +169 -0
  450. data/lib/yard-roby.rb +1 -0
  451. data/manifest.xml +32 -6
  452. data/roby.gemspec +59 -0
  453. metadata +788 -587
  454. data/Manifest.txt +0 -321
  455. data/NOTES +0 -4
  456. data/README.txt +0 -166
  457. data/TODO.txt +0 -146
  458. data/app/README.txt +0 -24
  459. data/app/Rakefile +0 -8
  460. data/app/config/ROBOT.rb +0 -5
  461. data/app/config/init.rb +0 -33
  462. data/app/config/roby.yml +0 -3
  463. data/app/controllers/ROBOT.rb +0 -2
  464. data/app/planners/ROBOT/main.rb +0 -6
  465. data/app/planners/main.rb +0 -5
  466. data/app/scripts/distributed +0 -3
  467. data/app/scripts/generate/bookmarks +0 -3
  468. data/app/scripts/replay +0 -3
  469. data/app/scripts/results +0 -3
  470. data/app/scripts/run +0 -3
  471. data/app/scripts/server +0 -3
  472. data/app/scripts/shell +0 -3
  473. data/app/scripts/test +0 -3
  474. data/app/tasks/.gitattributes +0 -0
  475. data/app/tasks/ROBOT/.gitattributes +0 -0
  476. data/bin/roby-shell +0 -25
  477. data/doc/guide/src/basics/app.page +0 -139
  478. data/doc/guide/src/basics/index.page +0 -11
  479. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  480. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  481. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  482. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  483. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  484. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  485. data/doc/guide/src/basics/relations_display.page +0 -203
  486. data/doc/guide/src/basics/shell.page +0 -102
  487. data/doc/guide/src/default.css +0 -319
  488. data/doc/guide/src/introduction/index.page +0 -29
  489. data/doc/guide/src/introduction/publications.page +0 -14
  490. data/doc/guide/src/relations/dependency.page +0 -89
  491. data/doc/guide/src/relations/index.page +0 -12
  492. data/ext/droby/dump.cc +0 -175
  493. data/ext/droby/extconf.rb +0 -3
  494. data/ext/graph/algorithm.cc +0 -746
  495. data/ext/graph/extconf.rb +0 -7
  496. data/ext/graph/graph.cc +0 -575
  497. data/ext/graph/graph.hh +0 -183
  498. data/ext/graph/iterator_sequence.hh +0 -102
  499. data/ext/graph/undirected_dfs.hh +0 -226
  500. data/ext/graph/undirected_graph.hh +0 -421
  501. data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
  502. data/lib/roby/app/scripts/replay.rb +0 -31
  503. data/lib/roby/app/scripts/server.rb +0 -18
  504. data/lib/roby/basic_object.rb +0 -151
  505. data/lib/roby/config.rb +0 -14
  506. data/lib/roby/distributed.rb +0 -36
  507. data/lib/roby/distributed/base.rb +0 -448
  508. data/lib/roby/distributed/communication.rb +0 -875
  509. data/lib/roby/distributed/connection_space.rb +0 -616
  510. data/lib/roby/distributed/distributed_object.rb +0 -206
  511. data/lib/roby/distributed/drb.rb +0 -62
  512. data/lib/roby/distributed/notifications.rb +0 -531
  513. data/lib/roby/distributed/peer.rb +0 -555
  514. data/lib/roby/distributed/protocol.rb +0 -529
  515. data/lib/roby/distributed/proxy.rb +0 -343
  516. data/lib/roby/distributed/subscription.rb +0 -311
  517. data/lib/roby/distributed/transaction.rb +0 -498
  518. data/lib/roby/external_process_task.rb +0 -225
  519. data/lib/roby/graph.rb +0 -160
  520. data/lib/roby/log.rb +0 -3
  521. data/lib/roby/log/chronicle.rb +0 -303
  522. data/lib/roby/log/console.rb +0 -74
  523. data/lib/roby/log/data_stream.rb +0 -275
  524. data/lib/roby/log/dot.rb +0 -279
  525. data/lib/roby/log/event_stream.rb +0 -161
  526. data/lib/roby/log/file.rb +0 -396
  527. data/lib/roby/log/gui/basic_display.ui +0 -83
  528. data/lib/roby/log/gui/basic_display_ui.rb +0 -89
  529. data/lib/roby/log/gui/chronicle.rb +0 -26
  530. data/lib/roby/log/gui/chronicle_view.rb +0 -40
  531. data/lib/roby/log/gui/chronicle_view.ui +0 -70
  532. data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
  533. data/lib/roby/log/gui/data_displays.rb +0 -171
  534. data/lib/roby/log/gui/data_displays.ui +0 -155
  535. data/lib/roby/log/gui/data_displays_ui.rb +0 -146
  536. data/lib/roby/log/gui/notifications.rb +0 -26
  537. data/lib/roby/log/gui/relations.rb +0 -269
  538. data/lib/roby/log/gui/relations.ui +0 -123
  539. data/lib/roby/log/gui/relations_ui.rb +0 -120
  540. data/lib/roby/log/gui/relations_view.rb +0 -185
  541. data/lib/roby/log/gui/relations_view.ui +0 -149
  542. data/lib/roby/log/gui/relations_view_ui.rb +0 -144
  543. data/lib/roby/log/gui/replay.rb +0 -366
  544. data/lib/roby/log/gui/replay_controls.rb +0 -206
  545. data/lib/roby/log/gui/replay_controls.ui +0 -282
  546. data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
  547. data/lib/roby/log/gui/runtime.rb +0 -130
  548. data/lib/roby/log/hooks.rb +0 -186
  549. data/lib/roby/log/logger.rb +0 -203
  550. data/lib/roby/log/notifications.rb +0 -244
  551. data/lib/roby/log/plan_rebuilder.rb +0 -468
  552. data/lib/roby/log/relations.rb +0 -1084
  553. data/lib/roby/log/server.rb +0 -547
  554. data/lib/roby/log/sqlite.rb +0 -47
  555. data/lib/roby/log/timings.rb +0 -233
  556. data/lib/roby/plan-object.rb +0 -371
  557. data/lib/roby/planning.rb +0 -13
  558. data/lib/roby/planning/loops.rb +0 -309
  559. data/lib/roby/planning/model.rb +0 -1012
  560. data/lib/roby/planning/task.rb +0 -180
  561. data/lib/roby/query.rb +0 -655
  562. data/lib/roby/relations/conflicts.rb +0 -67
  563. data/lib/roby/relations/dependency.rb +0 -358
  564. data/lib/roby/relations/ensured.rb +0 -19
  565. data/lib/roby/relations/error_handling.rb +0 -22
  566. data/lib/roby/relations/events.rb +0 -7
  567. data/lib/roby/relations/executed_by.rb +0 -208
  568. data/lib/roby/relations/influence.rb +0 -10
  569. data/lib/roby/relations/planned_by.rb +0 -63
  570. data/lib/roby/state/information.rb +0 -55
  571. data/lib/roby/state/state.rb +0 -367
  572. data/lib/roby/task-operations.rb +0 -186
  573. data/lib/roby/task_index.rb +0 -80
  574. data/lib/roby/test/distributed.rb +0 -230
  575. data/lib/roby/test/tasks/simple_task.rb +0 -23
  576. data/lib/roby/transactions.rb +0 -507
  577. data/lib/roby/transactions/proxy.rb +0 -325
  578. data/plugins/fault_injection/History.txt +0 -4
  579. data/plugins/fault_injection/README.txt +0 -34
  580. data/plugins/fault_injection/Rakefile +0 -12
  581. data/plugins/fault_injection/TODO.txt +0 -0
  582. data/plugins/fault_injection/app.rb +0 -52
  583. data/plugins/fault_injection/fault_injection.rb +0 -89
  584. data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
  585. data/plugins/subsystems/README.txt +0 -37
  586. data/plugins/subsystems/Rakefile +0 -13
  587. data/plugins/subsystems/app.rb +0 -182
  588. data/plugins/subsystems/test/app/README +0 -24
  589. data/plugins/subsystems/test/app/Rakefile +0 -8
  590. data/plugins/subsystems/test/app/config/app.yml +0 -71
  591. data/plugins/subsystems/test/app/config/init.rb +0 -12
  592. data/plugins/subsystems/test/app/config/roby.yml +0 -3
  593. data/plugins/subsystems/test/app/planners/main.rb +0 -20
  594. data/plugins/subsystems/test/app/scripts/distributed +0 -3
  595. data/plugins/subsystems/test/app/scripts/replay +0 -3
  596. data/plugins/subsystems/test/app/scripts/results +0 -3
  597. data/plugins/subsystems/test/app/scripts/run +0 -3
  598. data/plugins/subsystems/test/app/scripts/server +0 -3
  599. data/plugins/subsystems/test/app/scripts/shell +0 -3
  600. data/plugins/subsystems/test/app/scripts/test +0 -3
  601. data/plugins/subsystems/test/app/tasks/services.rb +0 -15
  602. data/plugins/subsystems/test/test_subsystems.rb +0 -78
  603. data/test/distributed/test_communication.rb +0 -195
  604. data/test/distributed/test_connection.rb +0 -284
  605. data/test/distributed/test_execution.rb +0 -378
  606. data/test/distributed/test_mixed_plan.rb +0 -341
  607. data/test/distributed/test_plan_notifications.rb +0 -238
  608. data/test/distributed/test_protocol.rb +0 -525
  609. data/test/distributed/test_query.rb +0 -106
  610. data/test/distributed/test_remote_plan.rb +0 -491
  611. data/test/distributed/test_transaction.rb +0 -466
  612. data/test/mockups/external_process +0 -28
  613. data/test/mockups/tasks.rb +0 -27
  614. data/test/planning/test_loops.rb +0 -432
  615. data/test/planning/test_model.rb +0 -427
  616. data/test/planning/test_task.rb +0 -126
  617. data/test/relations/test_conflicts.rb +0 -42
  618. data/test/relations/test_dependency.rb +0 -324
  619. data/test/relations/test_ensured.rb +0 -38
  620. data/test/relations/test_executed_by.rb +0 -224
  621. data/test/relations/test_planned_by.rb +0 -56
  622. data/test/suite_core.rb +0 -29
  623. data/test/suite_distributed.rb +0 -10
  624. data/test/suite_planning.rb +0 -4
  625. data/test/suite_relations.rb +0 -8
  626. data/test/tasks/test_external_process.rb +0 -126
  627. data/test/tasks/test_thread_task.rb +0 -70
  628. data/test/test_bgl.rb +0 -528
  629. data/test/test_event.rb +0 -969
  630. data/test/test_exceptions.rb +0 -591
  631. data/test/test_execution_engine.rb +0 -987
  632. data/test/test_gui.rb +0 -20
  633. data/test/test_interface.rb +0 -43
  634. data/test/test_log.rb +0 -125
  635. data/test/test_log_server.rb +0 -133
  636. data/test/test_plan.rb +0 -418
  637. data/test/test_query.rb +0 -424
  638. data/test/test_relations.rb +0 -260
  639. data/test/test_state.rb +0 -432
  640. data/test/test_support.rb +0 -16
  641. data/test/test_task.rb +0 -1181
  642. data/test/test_testcase.rb +0 -138
  643. data/test/test_transactions.rb +0 -610
  644. data/test/test_transactions_proxy.rb +0 -216
@@ -0,0 +1,6 @@
1
+ module Roby
2
+ module EventStructure
3
+ relation :CausalLink, subsets: [Signal, Forwarding], noinfo: true
4
+ end
5
+ end
6
+
@@ -0,0 +1,6 @@
1
+ module Roby
2
+ module EventStructure
3
+ relation :Forwarding, noinfo: true
4
+ end
5
+ end
6
+
@@ -0,0 +1,7 @@
1
+ module Roby
2
+ module EventStructure
3
+ relation :Precedence, subsets: [CausalLink], noinfo: true
4
+ end
5
+ end
6
+
7
+
@@ -0,0 +1,8 @@
1
+ module Roby
2
+ module EventStructure
3
+ relation :Signal, noinfo: true
4
+ end
5
+ end
6
+
7
+
8
+
@@ -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
+