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,139 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>RelationsConfig</class>
4
+ <widget class="QWidget" name="RelationsConfig">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>428</width>
10
+ <height>668</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>RelationsConfig</string>
15
+ </property>
16
+ <layout class="QVBoxLayout" name="verticalLayout">
17
+ <item>
18
+ <widget class="QGroupBox" name="taskLabelsGroup">
19
+ <property name="title">
20
+ <string>Task Labels</string>
21
+ </property>
22
+ <layout class="QGridLayout" name="gridLayout">
23
+ <item row="0" column="0">
24
+ <widget class="QCheckBox" name="showOwnership">
25
+ <property name="text">
26
+ <string>Show ownership</string>
27
+ </property>
28
+ <property name="checked">
29
+ <bool>true</bool>
30
+ </property>
31
+ </widget>
32
+ </item>
33
+ <item row="1" column="0">
34
+ <widget class="QLabel" name="lblRemovedPrefixes">
35
+ <property name="text">
36
+ <string>Remove the following prefixes (comma-separated)</string>
37
+ </property>
38
+ <property name="wordWrap">
39
+ <bool>true</bool>
40
+ </property>
41
+ </widget>
42
+ </item>
43
+ <item row="2" column="0">
44
+ <widget class="QLineEdit" name="removedPrefixes">
45
+ <property name="text">
46
+ <string>Roby::</string>
47
+ </property>
48
+ </widget>
49
+ </item>
50
+ </layout>
51
+ </widget>
52
+ </item>
53
+ <item>
54
+ <widget class="QGroupBox" name="displayOptionsGroup">
55
+ <property name="title">
56
+ <string>Display Options</string>
57
+ </property>
58
+ <layout class="QGridLayout" name="gridLayout_2">
59
+ <item row="0" column="0" colspan="2">
60
+ <widget class="QRadioButton" name="displayExplicit">
61
+ <property name="text">
62
+ <string>Explicit hide/show management</string>
63
+ </property>
64
+ <property name="checked">
65
+ <bool>true</bool>
66
+ </property>
67
+ </widget>
68
+ </item>
69
+ <item row="1" column="0" colspan="2">
70
+ <widget class="QRadioButton" name="displayEmitters">
71
+ <property name="text">
72
+ <string>Only show tasks that emit events</string>
73
+ </property>
74
+ </widget>
75
+ </item>
76
+ <item row="2" column="0" colspan="2">
77
+ <widget class="QRadioButton" name="displayEmittersAndParents">
78
+ <property name="text">
79
+ <string>Only show tasks that emit events and their parents</string>
80
+ </property>
81
+ </widget>
82
+ </item>
83
+ <item row="3" column="0" colspan="2">
84
+ <widget class="QLabel" name="lblHiddenLabels">
85
+ <property name="text">
86
+ <string>Hide tasks whose label matches (comma-separated)</string>
87
+ </property>
88
+ <property name="wordWrap">
89
+ <bool>true</bool>
90
+ </property>
91
+ </widget>
92
+ </item>
93
+ <item row="4" column="0" colspan="2">
94
+ <widget class="QLineEdit" name="hiddenLabels"/>
95
+ </item>
96
+ <item row="5" column="0" colspan="2">
97
+ <widget class="QCheckBox" name="showFinalized">
98
+ <property name="text">
99
+ <string>Show finalized objects</string>
100
+ </property>
101
+ <property name="checked">
102
+ <bool>true</bool>
103
+ </property>
104
+ </widget>
105
+ </item>
106
+ <item row="6" column="0">
107
+ <widget class="QLabel" name="lblLayoutMethod">
108
+ <property name="sizePolicy">
109
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
110
+ <horstretch>0</horstretch>
111
+ <verstretch>0</verstretch>
112
+ </sizepolicy>
113
+ </property>
114
+ <property name="text">
115
+ <string>Layout method</string>
116
+ </property>
117
+ </widget>
118
+ </item>
119
+ <item row="6" column="1">
120
+ <widget class="QComboBox" name="layoutMethod">
121
+ <property name="sizePolicy">
122
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
123
+ <horstretch>0</horstretch>
124
+ <verstretch>0</verstretch>
125
+ </sizepolicy>
126
+ </property>
127
+ </widget>
128
+ </item>
129
+ </layout>
130
+ </widget>
131
+ </item>
132
+ <item>
133
+ <widget class="QTreeView" name="relations"/>
134
+ </item>
135
+ </layout>
136
+ </widget>
137
+ <resources/>
138
+ <connections/>
139
+ </ui>
@@ -0,0 +1,1088 @@
1
+ require 'roby/gui/qt4_toMSecsSinceEpoch'
2
+ require 'utilrb/module/attr_predicate'
3
+ require 'roby/gui/task_display_configuration'
4
+ require 'roby/gui/plan_dot_layout'
5
+ require 'roby/gui/styles'
6
+ require 'roby/gui/task_state_at'
7
+
8
+ module Roby
9
+ module GUI
10
+ module RelationsCanvasPlanObject
11
+ def display_parent; end
12
+ def display_create(display); end
13
+ def display_events; Set.new end
14
+ def display_name(display); remote_name end
15
+ def display(display, graphics_item)
16
+ end
17
+ end
18
+
19
+ module RelationsCanvasEventGenerator
20
+ include RelationsCanvasPlanObject
21
+
22
+ def self.style(object, flags)
23
+ flags |= (object.controlable? ? EVENT_CONTROLABLE : EVENT_CONTINGENT)
24
+
25
+ if (flags & EVENT_CALLED) == EVENT_CALLED
26
+ if (flags & EVENT_CONTROLABLE) != EVENT_CONTROLABLE
27
+ STDERR.puts "WARN: inconsistency in replayed logs. Found event call on #{object} #{object.object_id} which is marked as contingent (#{object.controlable?}"
28
+ end
29
+ flags |= EVENT_CONTROLABLE
30
+ end
31
+
32
+ if !styles.has_key?(flags)
33
+ raise ArgumentError, "event #{object} has flags #{flags}, which has no defined style (controlable=#{object.controlable?})"
34
+ end
35
+
36
+ styles[flags]
37
+ end
38
+
39
+ def self.styles
40
+ return EVENT_STYLES
41
+ end
42
+
43
+ def self.priorities
44
+ @@priorities ||= Hash.new
45
+ end
46
+
47
+ def display_create(display)
48
+ scene = display.scene
49
+ circle = scene.add_ellipse(-EVENT_CIRCLE_RADIUS, -EVENT_CIRCLE_RADIUS, EVENT_CIRCLE_RADIUS * 2, EVENT_CIRCLE_RADIUS * 2)
50
+ text = scene.add_text(display_name(display))
51
+ circle.singleton_class.class_eval { attr_accessor :text }
52
+ circle.z_value = EVENT_LAYER
53
+
54
+ text.parent_item = circle
55
+ text_width = text.bounding_rect.width
56
+ text.set_pos(-text_width / 2, 0)
57
+ circle.text = text
58
+ circle
59
+ end
60
+
61
+ def display_time_start(circle, pos); circle.translate(pos) end
62
+ def display_time_end(circle, pos); end
63
+
64
+ def display_name(display)
65
+ name = if model.ancestors[0].name != 'Roby::EventGenerator'
66
+ [display.filter_prefixes(model.ancestors[0].name.dup)]
67
+ else
68
+ []
69
+ end
70
+
71
+ if display.show_ownership
72
+ owners = self.owners.dup
73
+ owners.delete_if { |o| o.remote_name == "log_replay" }
74
+ if !owners.empty?
75
+ name << "[#{owners.map(&:name).join(", ")}]"
76
+ end
77
+ end
78
+ name.join("\n")
79
+ end
80
+
81
+ def display(display, graphics_item)
82
+ graphics_item.text.plain_text = display_name(display).to_s
83
+ end
84
+ end
85
+
86
+ module RelationsCanvasTaskEventGenerator
87
+ include RelationsCanvasEventGenerator
88
+ def display_parent; task end
89
+ def display_name(display); symbol.to_s end
90
+ def display(display, graphics_item)
91
+ end
92
+ end
93
+
94
+ module RelationsCanvasTask
95
+ # NOTE: we must NOT include ReplayTask here, as ReplayTask overloads
96
+ # some methods from Task and it would break this overloading
97
+ include RelationsCanvasPlanObject
98
+ def layout_events(display)
99
+ graphics_item = display[self]
100
+
101
+ width, height = 0, 0
102
+ events = self.each_event.map do |e|
103
+ next unless display.displayed?(e)
104
+ next unless circle = display[e]
105
+ br = (circle.bounding_rect | circle.children_bounding_rect)
106
+ [e, circle, br]
107
+ end
108
+ events.compact!
109
+ events = events.sort_by { |ev, _| RelationsCanvasEventGenerator.priorities[ev] }
110
+
111
+ events.each do |_, circle, br|
112
+ w, h = br.width, br.height
113
+ height = h if h > height
114
+ width += w
115
+ end
116
+ width += TASK_EVENT_SPACING * (events.size + 1)
117
+ height += TASK_EVENT_SPACING
118
+
119
+ x = -width / 2 + TASK_EVENT_SPACING
120
+ events.each do |e, circle, br|
121
+ w = br.width
122
+ circle.set_pos(x + w / 2, -br.height / 2 + EVENT_CIRCLE_RADIUS + TASK_EVENT_SPACING)
123
+ x += w + TASK_EVENT_SPACING
124
+ end
125
+
126
+ width = DEFAULT_TASK_WIDTH unless width > DEFAULT_TASK_WIDTH
127
+ height = DEFAULT_TASK_HEIGHT unless height > DEFAULT_TASK_HEIGHT
128
+
129
+ if @width != width || @height != height
130
+ @width, @height = width, height
131
+ coords = Qt::RectF.new( -(width / 2), -(height / 2), width, height )
132
+ graphics_item.rect = coords
133
+ end
134
+
135
+ text = graphics_item.text
136
+ text.set_pos(- text.bounding_rect.width / 2, height / 2 + TASK_EVENT_SPACING)
137
+ end
138
+
139
+ def display_create(display)
140
+ scene = display.scene
141
+ rect = scene.add_rect Qt::RectF.new(0, 0, 0, 0)
142
+ text = scene.add_text display_name(display)
143
+ rect.brush = Qt::Brush.new(TASK_BRUSH_COLORS[:pending])
144
+ rect.pen = Qt::Pen.new(TASK_PEN_COLORS[:pending])
145
+ @displayed_state = :pending
146
+ text.parent_item = rect
147
+ rect.singleton_class.class_eval { attr_accessor :text }
148
+ rect.text = text
149
+ rect.z_value = TASK_LAYER
150
+
151
+ @width, @height = nil
152
+
153
+ rect.set_data(0, Qt::Variant.new(self.object_id.to_s))
154
+ rect
155
+ end
156
+
157
+ def display_time_start(rect, pos); rect.left = pos end
158
+ def display_time_end(rect, pos); rect.right = pos end
159
+
160
+ attr_accessor :last_event
161
+
162
+ def display_name(display)
163
+ ancestor_with_name = model.ancestors.find { |m| m.name }
164
+ if ancestor_with_name
165
+ name = display.filter_prefixes(ancestor_with_name.name)
166
+ else
167
+ name = "<anonymous>"
168
+ end
169
+ if display.show_ownership
170
+ owners = self.owners.dup
171
+ owners.delete_if { |o| o.remote_name == "log_replay" }
172
+ if !owners.empty?
173
+ name << "\n[#{owners.map(&:name).join(", ")}]"
174
+ end
175
+ end
176
+ name
177
+ end
178
+
179
+ attr_reader :displayed_state
180
+ def update_graphics(display, graphics_item)
181
+ new_state = GUI.task_state_at(self, display.current_time)
182
+ finalized = (finalization_time && finalization_time <= display.current_time)
183
+ if displayed_state != [new_state, finalized]
184
+ if finalized
185
+ pen = Qt::Pen.new(TASK_PEN_COLORS[:finalized])
186
+ pen.width = 4
187
+ graphics_item.pen = pen
188
+ else
189
+ graphics_item.pen = Qt::Pen.new(TASK_PEN_COLORS[new_state])
190
+ end
191
+ graphics_item.brush = Qt::Brush.new(TASK_BRUSH_COLORS[new_state])
192
+ @displayed_state = [new_state, finalized]
193
+ end
194
+
195
+ graphics_item.text.plain_text = display_name(display).to_s
196
+ end
197
+
198
+ def display(display, graphics_item)
199
+ update_graphics(display, graphics_item)
200
+ super
201
+ end
202
+
203
+ # Generates a SVG representation of a given task model, using the
204
+ # task as proxy for the model
205
+ #
206
+ # @param [Roby::Task] task the Roby task
207
+ # @option options [String] :path a file path to which the SVG should
208
+ # be saved
209
+ # @option options [Float] :scale_x (PlanDotLayout::DOT_TO_QT_SCALE_FACTOR_X)
210
+ # @option options [Float] :scale_y (PlanDotLayout::DOT_TO_QT_SCALE_FACTOR_Y)
211
+ #
212
+ # @return [String,nil] if the file path is not set, the SVG content.
213
+ # Otherwise, nil.
214
+ def self.to_svg(task, options = Hash.new)
215
+ options = Kernel.validate_options options,
216
+ path: nil,
217
+ scale_x: PlanDotLayout::DOT_TO_QT_SCALE_FACTOR_X,
218
+ scale_y: PlanDotLayout::DOT_TO_QT_SCALE_FACTOR_Y
219
+
220
+ task.extend RelationsCanvasTask
221
+ plan = task.plan
222
+
223
+ display = RelationsCanvas.new([plan])
224
+ display.display_plan_bounding_boxes = false
225
+ display.layout_options.merge!(options.slice(:scale_x, :scale_y))
226
+ task.each_event do |ev|
227
+ if ev.controlable?
228
+ plan.called_generators << ev
229
+ end
230
+ plan.emitted_events << ev.new([], 0)
231
+ end
232
+ task.model.all_forwardings.each do |source_name, targets|
233
+ source = task.event(source_name)
234
+ targets.each do |target_name|
235
+ plan.propagated_events << [true, [source.new([], 0)], task.event(target_name)]
236
+ end
237
+ end
238
+ task.model.all_signals.each do |source_name, targets|
239
+ source = task.event(source_name)
240
+ targets.each do |target_name|
241
+ plan.propagated_events << [false, [source.new([], 0)], task.event(target_name)]
242
+ end
243
+ end
244
+ display.update
245
+ scene = display.scene
246
+
247
+ svg = Qt::SvgGenerator.new
248
+ if path = options[:path]
249
+ svg.file_name = path
250
+ else
251
+ buffer = svg.output_device = Qt::Buffer.new
252
+ end
253
+ svg.size = Qt::Size.new(Integer(scene.width), Integer(scene.height))
254
+ painter = Qt::Painter.new
255
+ painter.begin(svg)
256
+ scene.render(painter)
257
+ painter.end
258
+ if !path
259
+ buffer.data
260
+ end
261
+ end
262
+ end
263
+
264
+ module RelationsCanvasTaskProxy
265
+ include RelationsCanvasTask
266
+
267
+ attr_writer :real_object
268
+ def flags; real_object.flags end
269
+
270
+ def display_parent; end
271
+ def display_name(display); real_object.display_name(display) end
272
+ def display_create(display)
273
+ scene = display.scene
274
+ item = super
275
+
276
+ brush = item.brush
277
+ brush.style = Qt::BDiagPattern
278
+ item.brush = brush
279
+ item
280
+ end
281
+ def display(display, graphics_item)
282
+ graphics_item.text.plain_text = display_name(display).to_s
283
+ layout_events(display)
284
+ end
285
+ end
286
+
287
+ module RelationsCanvasPlan
288
+ PLAN_STROKE_WIDTH = 5
289
+ # The plan depth, i.e. its distance from the root plan
290
+ attr_reader :depth
291
+ # The max depth of the plan tree in this branch
292
+ attr_reader :max_depth
293
+
294
+ def display_create(display)
295
+ scene = display.scene
296
+ pen = Qt::Pen.new
297
+ pen.width = PLAN_STROKE_WIDTH
298
+ pen.style = Qt::SolidLine
299
+ pen.cap_style = Qt::SquareCap
300
+ pen.join_style = Qt::RoundJoin
301
+ scene.add_rect Qt::RectF.new(0, 0, 0, 0), pen
302
+ end
303
+ def display_parent
304
+ if respond_to?(:plan) then plan
305
+ end
306
+ end
307
+ def display(display, item)
308
+ end
309
+ def display_name(display)
310
+ ""
311
+ end
312
+ end
313
+
314
+ Roby::PlanObject.include RelationsCanvasPlanObject
315
+ Roby::EventGenerator.include RelationsCanvasEventGenerator
316
+ Roby::TaskEventGenerator.include RelationsCanvasTaskEventGenerator
317
+ Roby::Task.include RelationsCanvasTask
318
+ Roby::Transaction::TaskProxy.include RelationsCanvasTaskProxy
319
+ Roby::Plan.include RelationsCanvasPlan
320
+
321
+ class Qt::GraphicsScene
322
+ attr_reader :default_arrow_pen
323
+ attr_reader :default_arrow_brush
324
+ def add_arrow(size, pen = nil, brush = nil)
325
+ @default_arrow_pen ||= Qt::Pen.new(ARROW_COLOR)
326
+ @default_arrow_brush ||= Qt::Brush.new(ARROW_COLOR)
327
+
328
+ @arrow_points ||= (1..4).map { Qt::PointF.new(0, 0) }
329
+ @arrow_points[1].x = -size
330
+ @arrow_points[1].y = size / 2
331
+ @arrow_points[2].x = -size
332
+ @arrow_points[2].y = -size / 2
333
+ polygon = Qt::PolygonF.new(@arrow_points)
334
+ @arrow_line ||= Qt::LineF.new(-1, 0, 0, 0)
335
+
336
+ ending = add_polygon polygon, (pen || default_arrow_pen), (brush || default_arrow_brush)
337
+ line = add_line @arrow_line
338
+
339
+ @arrow_id ||= 0
340
+ id = (@arrow_id += 1)
341
+ line.setData(0, Qt::Variant.new(id.to_s))
342
+ ending.setData(0, Qt::Variant.new(id.to_s))
343
+
344
+ line.parent_item = ending
345
+ ending.singleton_class.class_eval do
346
+ attr_accessor :line
347
+
348
+ def pen=(pen)
349
+ super
350
+ line.pen = pen
351
+ end
352
+ end
353
+ ending.line = line
354
+ ending
355
+ end
356
+ end
357
+
358
+ def self.intersect_rect(w, h, from, to)
359
+ to_x, to_y = *to
360
+ from_x, from_y = *from
361
+
362
+ # We only use half dimensions since 'to' is supposed to be be the
363
+ # center of the rectangle we are intersecting
364
+ w /= 2
365
+ h /= 2
366
+
367
+ dx = (to_x - from_x)
368
+ dy = (to_y - from_y)
369
+ delta_x = dx / dy * h
370
+ if dy != 0 && delta_x.abs < w
371
+ if dy > 0
372
+ [to_x - delta_x, to_y - h]
373
+ else
374
+ [to_x + delta_x, to_y + h]
375
+ end
376
+ elsif dx != 0
377
+ delta_y = dy / dx * w
378
+ if dx > 0
379
+ [to_x - w, to_y - delta_y]
380
+ else
381
+ [to_x + w, to_y + delta_y]
382
+ end
383
+ else
384
+ [0, 0]
385
+ end
386
+ end
387
+
388
+ def self.correct_line(from, to, rect)
389
+ intersect_rect(rect.width, rect.height, from, to)
390
+ end
391
+
392
+ def self.arrow_set(arrow, start_object, end_object)
393
+ start_br = start_object.scene_bounding_rect
394
+ end_br = end_object.scene_bounding_rect
395
+ start_point = start_br.center
396
+ end_point = end_br.center
397
+
398
+ #from = intersect_rect(start_br.width, start_br.height, end_point, start_point)
399
+ from = [start_point.x, start_point.y]
400
+ to = intersect_rect(end_br.width, end_br.height, from, [end_point.x, end_point.y])
401
+
402
+ dy = to[1] - from[1]
403
+ dx = to[0] - from[0]
404
+ alpha = Math.atan2(dy, dx)
405
+ length = Math.sqrt(dx ** 2 + dy ** 2)
406
+
407
+ #arrow.line.set_line from[0], from[1], to[0], to[1]
408
+ arrow.resetMatrix
409
+ arrow.line.set_line(-length, 0, 0, 0)
410
+ arrow.translate to[0], to[1]
411
+ arrow.rotate(alpha * 180 / Math::PI)
412
+ arrow
413
+ end
414
+
415
+ class RelationsCanvas < Qt::Object
416
+ # Common configuration options for displays that represent tasks
417
+ include TaskDisplayConfiguration
418
+
419
+ # The Qt::GraphicsScene we are manipulating
420
+ attr_reader :scene
421
+
422
+ # The set of plans that should be displayed
423
+ attr_reader :plans
424
+
425
+ # A [object, object, relation] => GraphicsItem mapping of arrows
426
+ attr_reader :arrows
427
+
428
+ # A [object, object, relation] => GraphicsItem mapping of arrows
429
+ attr_reader :last_arrows
430
+
431
+ attr_reader :free_arrows
432
+
433
+ # A DRbObject => GraphicsItem mapping
434
+ attr_reader :graphics
435
+
436
+ # The set of objects that are to be shown at the last update
437
+ attr_reader :visible_objects
438
+
439
+ # The set of objects that are selected for display in the :explicit
440
+ # display mode
441
+ attr_reader :selected_objects
442
+
443
+ # A set of events that are shown during only two calls of #update
444
+ attr_reader :flashing_objects
445
+
446
+ # A pool of arrows items used to display the event signalling
447
+ attr_reader :signal_arrows
448
+
449
+ # True if the finalized tasks should not be displayed
450
+ attr_accessor :hide_finalized
451
+
452
+ # @return [Boolean] true if the plan's bounding boxes should be
453
+ # displayed or not (true)
454
+ attr_predicate :display_plan_bounding_boxes?, true
455
+
456
+ # @return [Hash] set of options that should be passed to
457
+ # Graphviz#layout
458
+ attr_reader :layout_options
459
+
460
+ def initialize(plans)
461
+ @scene = Qt::GraphicsScene.new
462
+ super()
463
+
464
+ @plans = plans.dup
465
+ @display_plan_bounding_boxes = false
466
+
467
+ @display_policy = :explicit
468
+ @graphics = Hash.new
469
+ @selected_objects = Set.new
470
+ @visible_objects = Set.new
471
+ @flashing_objects = Hash.new
472
+ @arrows = Hash.new
473
+ @free_arrows = Array.new
474
+ @enabled_relations = Set.new
475
+ @layout_relations = Set.new
476
+ @relation_colors = Hash.new
477
+ @relation_pens = Hash.new(Qt::Pen.new(Qt::Color.new(ARROW_COLOR)))
478
+ @relation_brushes = Hash.new(Qt::Brush.new(Qt::Color.new(ARROW_COLOR)))
479
+ @current_color = 0
480
+
481
+ @signal_arrows = []
482
+ @hide_finalized = true
483
+ @layout_options = Hash.new
484
+
485
+ default_colors = {
486
+ Roby::TaskStructure::Dependency => 'grey',
487
+ Roby::TaskStructure::PlannedBy => '#32ba21',
488
+ Roby::TaskStructure::ExecutionAgent => '#5d95cf',
489
+ Roby::TaskStructure::ErrorHandling => '#ff2727'
490
+ }
491
+ default_colors.each do |rel, color|
492
+ update_relation_color(rel, color)
493
+ end
494
+
495
+ relation_pens[Roby::EventStructure::Signal] = Qt::Pen.new(Qt::Color.new('black'))
496
+ relation_brushes[Roby::EventStructure::Signal] = Qt::Brush.new(Qt::Color.new('black'))
497
+ relation_pens[Roby::EventStructure::Forwarding] = Qt::Pen.new(Qt::Color.new('black'))
498
+ relation_pens[Roby::EventStructure::Forwarding].style = Qt::DotLine
499
+ relation_brushes[Roby::EventStructure::Forwarding] = Qt::Brush.new(Qt::Color.new('black'))
500
+ relation_brushes[Roby::EventStructure::Forwarding].style = Qt::DotLine
501
+
502
+
503
+ enable_relation(Roby::TaskStructure::Dependency)
504
+ enable_relation(Roby::TaskStructure::ExecutionAgent)
505
+ enable_relation(Roby::TaskStructure::PlannedBy)
506
+ end
507
+
508
+ def save_options
509
+ options = Hash.new
510
+ options['enabled_relations'] = @enabled_relations.map(&:name)
511
+ options['show_ownership'] = show_ownership
512
+ options['hide_finalized'] = hide_finalized
513
+ options['removed_prefixes'] = removed_prefixes.dup
514
+ options['hidden_labels'] = hidden_labels.dup
515
+ options['display_policy'] = display_policy
516
+ options
517
+ end
518
+
519
+ def apply_options(options)
520
+ if enabled_relations = options['enabled_relations']
521
+ enabled_relations.each do |name|
522
+ rel = constant(name)
523
+ enable_relation(rel)
524
+ end
525
+ end
526
+ apply_simple_option('show_ownership', options)
527
+ apply_simple_option('removed_prefixes', options)
528
+ apply_simple_option('hide_finalized', options)
529
+ apply_simple_option('removed_prefixes', options)
530
+ apply_simple_option('hidden_labels', options)
531
+ apply_simple_option('display_policy', options)
532
+ end
533
+
534
+ def apply_simple_option(option_name, options)
535
+ if options.has_key?(option_name)
536
+ self.send("#{option_name}=", options[option_name])
537
+ end
538
+ end
539
+
540
+ def object_of(item)
541
+ id = item.data(0).to_string
542
+ return if !id
543
+ id = Integer(id)
544
+
545
+ obj, _ = graphics.find do |obj, obj_item|
546
+ obj.object_id == id
547
+ end
548
+ obj
549
+ end
550
+
551
+ def relation_of(item)
552
+ id = item.data(0).to_string
553
+ arrows.each do |(from, to, rel), arrow|
554
+ if arrow.data(0).to_string == id
555
+ return from, to, rel
556
+ end
557
+ end
558
+ nil
559
+ end
560
+
561
+ def [](item); graphics[item] end
562
+
563
+ # Returns a canvas object that represents this relation
564
+ def task_relation(from, to, rel, info)
565
+ arrow(from, to, rel, info, TASK_LAYER)
566
+ end
567
+ # Returns a canvas object that represents this relation
568
+ def event_relation(form, to, rel, info)
569
+ arrow(from, to, rel, info, EVENT_LAYER)
570
+ end
571
+
572
+ # Creates or reuses an arrow object to represent the given relation
573
+ def arrow(from, to, rel, info, base_layer)
574
+ id = [from, to, rel]
575
+ if !(item = arrows[id])
576
+ if item = last_arrows.delete(id)
577
+ arrows[id] = item
578
+ else
579
+ item = arrows[id] = (free_arrows.pop || scene.add_arrow(ARROW_SIZE))
580
+ item.z_value = base_layer - 1
581
+ item.pen = item.line.pen = relation_pens[rel]
582
+ item.brush = relation_brushes[rel]
583
+ end
584
+ end
585
+
586
+ GUI.arrow_set item, self[from], self[to]
587
+ end
588
+
589
+ # Centers the view on the set of object found which matches
590
+ # +regex+. If +regex+ is nil, ask one to the user
591
+ def find(regex = nil)
592
+ unless regex
593
+ regex = Qt::InputDialog.get_text main, 'Find objects in relation view', 'Object name'
594
+ return unless regex && !regex.empty?
595
+ end
596
+ regex = /#{regex.to_str}/i if regex.respond_to?(:to_str)
597
+
598
+ # Get the tasks and events matching the string
599
+ objects = []
600
+ for p in plans
601
+ objects.concat p.tasks.
602
+ find_all { |object| displayed?(object) && regex === object.display_name(self) }
603
+ objects.concat p.free_events.
604
+ find_all { |object| displayed?(object) && regex === object.display_name(self) }
605
+ end
606
+
607
+ return if objects.empty?
608
+
609
+ # Find the graphics items
610
+ bb = objects.inject(Qt::RectF.new) do |bb, object|
611
+ if item = self[object]
612
+ item.selected = true
613
+ bb | item.scene_bounding_rect | item.map_to_scene(item.children_bounding_rect).bounding_rect
614
+ else
615
+ bb
616
+ end
617
+ end
618
+ bb.adjust(-FIND_MARGIN, -FIND_MARGIN, FIND_MARGIN, FIND_MARGIN)
619
+ ui.graphics.fit_in_view bb, Qt::KeepAspectRatio
620
+ scale = ui.graphics.matrix.m11
621
+ if scale > 1
622
+ ui.graphics.resetMatrix
623
+ ui.graphics.scale 1, 1
624
+ end
625
+ end
626
+ slots 'find()'
627
+
628
+ attr_accessor :keep_signals
629
+
630
+ COLORS = %w{'black' #800000 #008000 #000080 #C05800 #6633FF #CDBE70 #CD8162 #A2B5CD}
631
+ attr_reader :current_color
632
+ # returns the next color in COLORS, cycles if at the end of the array
633
+ def allocate_color
634
+ @current_color = (current_color + 1) % COLORS.size
635
+ COLORS[current_color]
636
+ end
637
+
638
+ # True if this relation should be displayed
639
+ def relation_enabled?(relation); @enabled_relations.include?(relation) end
640
+ # True if this relation should be used for layout
641
+ #
642
+ # See also #relation_enabled?, #layout_relation, #ignore_relation
643
+ def layout_relation?(relation); relation_enabled?(relation) || @layout_relations.include?(relation) end
644
+
645
+ # Display this relation
646
+ def enable_relation(relation)
647
+ return if relation_enabled?(relation)
648
+ @enabled_relations << relation
649
+ arrows.each do |(_, _, rel), arrow|
650
+ if rel == relation
651
+ arrow.visible = true
652
+ end
653
+ end
654
+ end
655
+
656
+ # The set of relations that should be displayed
657
+ attr_reader :enabled_relations
658
+
659
+ # Use this relation for layout but not for display
660
+ #
661
+ # See also #ignore_relation
662
+ def layout_relation(relation)
663
+ disable_relation(relation)
664
+ @layout_relations << relation
665
+ end
666
+
667
+ # Don't use this relation at all
668
+ def ignore_relation(relation)
669
+ disable_relation(relation)
670
+ @layout_relations.delete(relation)
671
+ end
672
+
673
+ def disable_relation(relation)
674
+ return unless relation_enabled?(relation)
675
+ @enabled_relations.delete(relation)
676
+ arrows.each do |(_, _, rel), arrow|
677
+ if rel == relation
678
+ arrow.visible = false
679
+ end
680
+ end
681
+ end
682
+
683
+ attr_reader :relation_colors
684
+ attr_reader :relation_pens
685
+ attr_reader :relation_brushes
686
+ def relation_color(relation)
687
+ if !relation_colors.has_key?(relation)
688
+ update_relation_color(relation, allocate_color)
689
+ end
690
+ relation_colors[relation]
691
+ end
692
+ def update_relation_color(relation, color)
693
+ relation_colors[relation] = color
694
+ color = Qt::Color.new(color)
695
+ pen = relation_pens[relation] = Qt::Pen.new(color)
696
+ brush = relation_brushes[relation] = Qt::Brush.new(color)
697
+ arrows.each do |(_, _, rel), arrow|
698
+ if rel == relation
699
+ arrow.pen = arrow.line.pen = pen
700
+ arrow.brush = brush
701
+ end
702
+ end
703
+ end
704
+
705
+ def layout_method=(new_method)
706
+ return if new_method == @layout_method
707
+
708
+ @layout_method = nil
709
+ @layout_options = nil
710
+ if new_method
711
+ new_method =~ /^(\w+)(?: \[(.*)\])?$/
712
+ @layout_method = $1
713
+ if $2
714
+ @layout_options = $2.split(",").inject(Hash.new) do |h, v|
715
+ k, v = v.split("=")
716
+ h[k] = v
717
+ h
718
+ end
719
+ end
720
+ end
721
+ display
722
+ end
723
+ def layout_options
724
+ return @layout_options if @layout_options
725
+ { rankdir: 'TB' }
726
+ end
727
+ def layout_method
728
+ return @layout_method if @layout_method
729
+ "dot"
730
+ end
731
+
732
+ DISPLAY_POLICIES = [:explicit, :emitters, :emitters_and_parents]
733
+ attr_reader :display_policy
734
+ def display_policy=(policy)
735
+ if !DISPLAY_POLICIES.include?(policy)
736
+ raise ArgumentError, "got #{policy.inspect} as a display policy, accepted values are #{DISPLAY_POLICIES.map(&:inspect).join(", ")}"
737
+ end
738
+ @display_policy = policy
739
+ end
740
+
741
+ def displayed?(object)
742
+ if (parent = object.display_parent) && !displayed?(parent)
743
+ return false
744
+ end
745
+ return visible_objects.include?(object)
746
+ end
747
+
748
+ def create_or_get_item(object, initial_selection)
749
+ if !(item = graphics[object])
750
+ item = graphics[object] = object.display_create(self)
751
+ if item
752
+ if object.display_parent
753
+ item.parent_item = self[object.display_parent]
754
+ end
755
+
756
+ yield(item) if block_given?
757
+
758
+ if initial_selection
759
+ selected_objects << object
760
+ end
761
+ end
762
+ end
763
+ item
764
+ end
765
+
766
+ # Add +object+ to the list of objects temporarily displayed. If a
767
+ # block is given, the object is removed when the block returns
768
+ # false. Otherwise, it is removed at the next display update
769
+ #
770
+ # If this method is called more than once for the same object, the
771
+ # object is removed when *all* blocks have returned false at least
772
+ # once
773
+ def add_flashing_object(object, &block)
774
+ if block
775
+ flashing_objects[object] ||= []
776
+ flashing_objects[object] << block
777
+ else
778
+ flashing_objects[object] ||= nil
779
+ end
780
+ if object.display_parent
781
+ add_flashing_object(object.display_parent, &block)
782
+ end
783
+
784
+ create_or_get_item(object, false)
785
+ end
786
+
787
+ # Removes the objects added with #add_flashing_object when they
788
+ # should be removed
789
+ def clear_flashing_objects
790
+ removed_objects = []
791
+ flashing_objects.delete_if do |object, blocks|
792
+ blocks.delete_if { |block| !block.call }
793
+ if !blocks.empty?
794
+ next
795
+ end
796
+ removed_objects << object
797
+ end
798
+
799
+ removed_objects.each do |object|
800
+ if item = graphics[object]
801
+ item.visible = displayed?(object)
802
+ end
803
+ end
804
+ end
805
+
806
+ # Sets the style on +arrow+ according to the event propagation type
807
+ # provided in +flag+
808
+ #
809
+ # +arrow+ is the graphics item representing the relation and +flag+
810
+ # is one of the PROPAG_ constant
811
+ def propagation_style(arrow, flag)
812
+ unless defined? @@propagation_styles
813
+ @@propagation_styles = Hash.new
814
+ @@propagation_styles[true] =
815
+ [Qt::Brush.new(Qt::Color.new('black')), Qt::Pen.new, (forward_pen = Qt::Pen.new)]
816
+ forward_pen.style = Qt::DotLine
817
+ @@propagation_styles[false] =
818
+ [Qt::Brush.new(Qt::Color.new('black')), Qt::Pen.new, Qt::Pen.new]
819
+ end
820
+ arrow.brush, arrow.pen, arrow.line.pen = @@propagation_styles[flag]
821
+ end
822
+
823
+ def update_visible_objects
824
+ @visible_objects = Set.new
825
+
826
+ # NOTE: we unconditionally add events that are propagated, as
827
+ # #displayed?(obj) will filter out the ones whose task is hidden
828
+ plans.each do |p|
829
+ if display_plan_bounding_boxes?
830
+ visible_objects << p
831
+ end
832
+ p.emitted_events.each do |event|
833
+ visible_objects << event.generator
834
+ end
835
+ p.propagated_events.each do |_, sources, to, _|
836
+ sources.each do |src|
837
+ visible_objects << src.generator
838
+ end
839
+ visible_objects << to
840
+ end
841
+ end
842
+
843
+ if display_policy == :explicit
844
+ visible_objects.merge(selected_objects)
845
+
846
+ elsif display_policy == :emitters || display_policy == :emitters_and_parents
847
+ # Make sure that the event's tasks are added to
848
+ # visible_objects as well
849
+ visible_objects.dup.each do |obj|
850
+ if parent = obj.display_parent
851
+ visible_objects << parent
852
+ end
853
+ end
854
+ end
855
+
856
+ if display_policy == :emitters_and_parents
857
+ while true
858
+ new_visible_objects = Set.new
859
+ visible_objects.group_by(&:plan).each do |plan, plan_objects|
860
+ graphs = plan.each_task_relation_graph.find_all(&:root_relation?).map(&:reverse)
861
+ new_visible_objects.merge(plan.compute_useful_tasks(plan_objects.to_set, graphs: graphs))
862
+ new_visible_objects.subtract(plan_objects.to_set)
863
+ end
864
+ break if new_visible_objects.empty?
865
+ visible_objects.merge(new_visible_objects)
866
+ end
867
+ visible_objects.dup.each do |obj|
868
+ if obj.kind_of?(Roby::Task)
869
+ obj.each_relation do |rel|
870
+ visible_objects.merge(obj.child_objects(rel))
871
+ end
872
+ end
873
+ end
874
+ end
875
+
876
+ if hide_finalized
877
+ plans.each do |plan|
878
+ all_finalized = plan.finalized_tasks | plan.finalized_events
879
+ @visible_objects = visible_objects - all_finalized
880
+ end
881
+ end
882
+ visible_objects.delete_if do |obj|
883
+ filtered_out_label?(obj.display_name(self))
884
+ end
885
+ end
886
+
887
+ def make_graphics_visible(object)
888
+ object = create_or_get_item(object, false)
889
+ object.visible = true
890
+ object
891
+ end
892
+
893
+ attr_reader :current_time
894
+
895
+ # Update the display with new data that has come from the data
896
+ # stream.
897
+ #
898
+ # It would be too complex at this stage to know if the plan has been
899
+ # updated, so the method always returns true
900
+ def update(time = nil)
901
+ # Allow time to be a Qt::DateTime object, so that we can make it
902
+ # a slot
903
+ if time.kind_of?(Qt::DateTime)
904
+ time = Time.at(Float(time.toMSecsSinceEpoch) / 1000)
905
+ end
906
+ enabled_relations << Roby::EventStructure::Signal << Roby::EventStructure::Forwarding
907
+
908
+ if time
909
+ @current_time = time
910
+ end
911
+
912
+ @last_arrows, @arrows = arrows, Hash.new
913
+ @free_arrows ||= Array.new
914
+
915
+ update_prefixes_removal
916
+ clear_flashing_objects
917
+
918
+ # The sets of tasks and events know to the data stream
919
+ all_tasks = plans.inject(Set.new) do |all_tasks, plan|
920
+ all_tasks.merge plan.tasks
921
+ all_tasks.merge plan.finalized_tasks
922
+ end
923
+ all_events = plans.inject(Set.new) do |all_events, plan|
924
+ all_events.merge plan.free_events
925
+ all_events.merge plan.finalized_events
926
+ end
927
+ all_task_events = all_tasks.inject(Set.new) do |all_task_events, task|
928
+ all_task_events.merge(task.bound_events.values)
929
+ end
930
+
931
+ # Remove the items for objects that don't exist anymore
932
+ (graphics.keys.to_set - all_tasks - all_events - all_task_events).each do |obj|
933
+ selected_objects.delete(obj)
934
+ remove_graphics(graphics.delete(obj))
935
+ clear_arrows(obj)
936
+ end
937
+
938
+ # Create graphics items for all objects that may get displayed
939
+ # on the canvas
940
+ all_tasks.each do |object|
941
+ create_or_get_item(object, true)
942
+ object.each_event do |ev|
943
+ create_or_get_item(ev, false)
944
+ end
945
+ end
946
+ all_events.each { |ev| create_or_get_item(ev, true) }
947
+ plans.each { |p| create_or_get_item(p, display_plan_bounding_boxes?) }
948
+
949
+ update_visible_objects
950
+
951
+ graphics.each do |object, item|
952
+ item.visible = displayed?(object)
953
+ end
954
+
955
+ RelationsCanvasEventGenerator.priorities.clear
956
+ event_priority = 0
957
+ plans.each do |p|
958
+ flags = Hash.new(0)
959
+
960
+ p.called_generators.each_with_index do |generator, priority|
961
+ flags[generator] |= EVENT_CALLED
962
+ end
963
+ base_priority = p.called_generators.size
964
+
965
+ p.emitted_events.each_with_index do |event, priority|
966
+ generator = event.generator
967
+ flags[generator] |= EVENT_EMITTED
968
+ end
969
+
970
+ p.failed_emissions.each do |generator, reason|
971
+ flags[generator] = FAILED_EMISSION
972
+ end
973
+
974
+ flags.each_with_index do |(generator, generator_flags), priority|
975
+ RelationsCanvasEventGenerator.priorities[generator] = priority
976
+ if displayed?(generator)
977
+ item = graphics[generator]
978
+ item.brush, item.pen = RelationsCanvasEventGenerator.style(
979
+ generator, generator_flags)
980
+ end
981
+ end
982
+ end
983
+
984
+ plans.each do |p|
985
+ p.propagated_events.each do |_, sources, to, _|
986
+ sources.each do |from|
987
+ RelationsCanvasEventGenerator.priorities[from] ||= (event_priority += 1)
988
+ RelationsCanvasEventGenerator.priorities[to] ||= (event_priority += 1)
989
+ end
990
+ end
991
+ end
992
+
993
+ [all_tasks, all_events, plans].each do |object_set|
994
+ object_set.each do |object|
995
+ graphics = self.graphics[object]
996
+ if graphics.visible?
997
+ object.display(self, graphics)
998
+ end
999
+ end
1000
+ end
1001
+
1002
+ # Update arrow visibility
1003
+ arrows.each do |(from, to, rel), item|
1004
+ next if !@enabled_relations.include?(rel)
1005
+ item.visible = (displayed?(from) && displayed?(to))
1006
+ end
1007
+
1008
+ # Layout the graph
1009
+ layouts = plans.find_all { |p| p.root_plan? }.
1010
+ map do |p|
1011
+ dot = PlanDotLayout.new
1012
+ begin
1013
+ dot.layout(self, p, layout_options)
1014
+ dot
1015
+ rescue Exception => e
1016
+ puts "Failed to lay out the plan: #{e}"
1017
+ end
1018
+ end.compact
1019
+ layouts.each { |dot| dot.apply }
1020
+
1021
+ # Display the signals
1022
+ signal_arrow_idx = -1
1023
+ plans.each do |p|
1024
+ p.propagated_events.each_with_index do |(flag, sources, to), signal_arrow_idx|
1025
+ relation =
1026
+ if flag
1027
+ Roby::EventStructure::Forwarding
1028
+ else
1029
+ Roby::EventStructure::Signal
1030
+ end
1031
+
1032
+ sources.each do |source_event|
1033
+ arrow = arrow(source_event.generator, to, relation, nil, EVENT_PROPAGATION_LAYER)
1034
+ propagation_style(arrow, flag)
1035
+ end
1036
+ end
1037
+ end
1038
+ arrows.each do |_, item|
1039
+ item.visible = true
1040
+ end
1041
+ @free_arrows = last_arrows.values
1042
+ free_arrows.each do |item|
1043
+ item.visible = false
1044
+ end
1045
+ last_arrows.clear
1046
+
1047
+ true
1048
+ #rescue Exception => e
1049
+ # message = "<html>#{e.message.gsub('<', '&lt;').gsub('>', '&gt;')}<ul><li>#{e.backtrace.join("</li><li>")}</li></ul></html>"
1050
+ # Qt::MessageBox.critical nil, "Display failure", message
1051
+ end
1052
+
1053
+ def remove_graphics(item, scene = nil)
1054
+ return unless item
1055
+ scene ||= item.scene
1056
+ scene.remove_item(item) if scene
1057
+ end
1058
+
1059
+ def clear_arrows(object)
1060
+ arrows.delete_if do |(from, to, _), arrow|
1061
+ if from == object || to == object
1062
+ remove_graphics(arrow)
1063
+ true
1064
+ end
1065
+ end
1066
+ end
1067
+
1068
+ def clear
1069
+ arrows.dup.each_value(&method(:remove_graphics))
1070
+ graphics.dup.each_value(&method(:remove_graphics))
1071
+ arrows.clear
1072
+ free_arrows.clear
1073
+ last_arrows.clear
1074
+ graphics.clear
1075
+
1076
+ signal_arrows.each do |arrow|
1077
+ arrow.visible = false
1078
+ end
1079
+
1080
+ selected_objects.clear
1081
+ visible_objects.clear
1082
+ flashing_objects.clear
1083
+ scene.update(scene.scene_rect)
1084
+ end
1085
+ end
1086
+ end
1087
+ end
1088
+