roby 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (236) hide show
  1. data/History.txt +7 -5
  2. data/Manifest.txt +91 -16
  3. data/README.txt +24 -24
  4. data/Rakefile +92 -64
  5. data/app/config/app.yml +42 -43
  6. data/app/config/init.rb +26 -0
  7. data/benchmark/alloc_misc.rb +123 -0
  8. data/benchmark/discovery_latency.rb +67 -0
  9. data/benchmark/garbage_collection.rb +48 -0
  10. data/benchmark/genom.rb +31 -0
  11. data/benchmark/transactions.rb +62 -0
  12. data/bin/roby +1 -1
  13. data/bin/roby-log +16 -6
  14. data/doc/guide/.gitignore +2 -0
  15. data/doc/guide/config.yaml +34 -0
  16. data/doc/guide/ext/init.rb +14 -0
  17. data/doc/guide/ext/previous_next.rb +40 -0
  18. data/doc/guide/ext/rdoc_links.rb +33 -0
  19. data/doc/guide/index.rdoc +16 -0
  20. data/doc/guide/overview.rdoc +62 -0
  21. data/doc/guide/plan_modifications.rdoc +67 -0
  22. data/doc/guide/src/abstraction/achieve_with.page +8 -0
  23. data/doc/guide/src/abstraction/forwarding.page +8 -0
  24. data/doc/guide/src/abstraction/hierarchy.page +19 -0
  25. data/doc/guide/src/abstraction/index.page +28 -0
  26. data/doc/guide/src/abstraction/task_models.page +13 -0
  27. data/doc/guide/src/basics.template +6 -0
  28. data/doc/guide/src/basics/app.page +139 -0
  29. data/doc/guide/src/basics/code_examples.page +33 -0
  30. data/doc/guide/src/basics/dry.page +69 -0
  31. data/doc/guide/src/basics/errors.page +443 -0
  32. data/doc/guide/src/basics/events.page +179 -0
  33. data/doc/guide/src/basics/hierarchy.page +275 -0
  34. data/doc/guide/src/basics/index.page +11 -0
  35. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  36. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  37. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  38. data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
  39. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  40. data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
  41. data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
  42. data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
  43. data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
  44. data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
  45. data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
  46. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  47. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  48. data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
  49. data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
  50. data/doc/guide/src/basics/plan_objects.page +71 -0
  51. data/doc/guide/src/basics/relations_display.page +203 -0
  52. data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
  53. data/doc/guide/src/basics/shell.page +102 -0
  54. data/doc/guide/src/basics/summary.page +32 -0
  55. data/doc/guide/src/basics/tasks.page +357 -0
  56. data/doc/guide/src/basics_shell_header.txt +16 -0
  57. data/doc/guide/src/cycle/cycle-overview.png +0 -0
  58. data/doc/guide/src/cycle/cycle-overview.svg +208 -0
  59. data/doc/guide/src/cycle/error_handling.page +168 -0
  60. data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
  61. data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
  62. data/doc/guide/src/cycle/garbage_collection.page +10 -0
  63. data/doc/guide/src/cycle/index.page +23 -0
  64. data/doc/guide/src/cycle/propagation.page +154 -0
  65. data/doc/guide/src/cycle/propagation_diamond.png +0 -0
  66. data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
  67. data/doc/guide/src/default.css +319 -0
  68. data/doc/guide/src/default.template +74 -0
  69. data/doc/guide/src/htmldoc.metainfo +20 -0
  70. data/doc/guide/src/htmldoc.virtual +18 -0
  71. data/doc/guide/src/images/bodybg.png +0 -0
  72. data/doc/guide/src/images/contbg.png +0 -0
  73. data/doc/guide/src/images/footerbg.png +0 -0
  74. data/doc/guide/src/images/gradient1.png +0 -0
  75. data/doc/guide/src/images/gradient2.png +0 -0
  76. data/doc/guide/src/index.page +7 -0
  77. data/doc/guide/src/introduction/index.page +29 -0
  78. data/doc/guide/src/introduction/install.page +133 -0
  79. data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
  80. data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
  81. data/doc/guide/src/plugins/fault_tolerance.page +44 -0
  82. data/doc/guide/src/plugins/index.page +11 -0
  83. data/doc/guide/src/plugins/subsystems.page +45 -0
  84. data/doc/guide/src/relations/dependency.page +89 -0
  85. data/doc/guide/src/relations/index.page +12 -0
  86. data/doc/misc/update_github +24 -0
  87. data/doc/tutorials/02-GoForward.rdoc +3 -3
  88. data/ext/graph/graph.cc +46 -0
  89. data/lib/roby.rb +57 -22
  90. data/lib/roby/app.rb +132 -112
  91. data/lib/roby/app/plugins/rake.rb +21 -0
  92. data/lib/roby/app/rake.rb +0 -7
  93. data/lib/roby/app/run.rb +1 -1
  94. data/lib/roby/app/scripts/distributed.rb +1 -2
  95. data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
  96. data/lib/roby/app/scripts/results.rb +2 -1
  97. data/lib/roby/app/scripts/run.rb +6 -2
  98. data/lib/roby/app/scripts/shell.rb +11 -11
  99. data/lib/roby/config.rb +1 -1
  100. data/lib/roby/decision_control.rb +62 -3
  101. data/lib/roby/distributed.rb +4 -0
  102. data/lib/roby/distributed/base.rb +8 -0
  103. data/lib/roby/distributed/communication.rb +12 -8
  104. data/lib/roby/distributed/connection_space.rb +61 -44
  105. data/lib/roby/distributed/distributed_object.rb +1 -1
  106. data/lib/roby/distributed/notifications.rb +22 -30
  107. data/lib/roby/distributed/peer.rb +13 -8
  108. data/lib/roby/distributed/proxy.rb +5 -5
  109. data/lib/roby/distributed/subscription.rb +4 -4
  110. data/lib/roby/distributed/transaction.rb +3 -3
  111. data/lib/roby/event.rb +176 -110
  112. data/lib/roby/exceptions.rb +12 -4
  113. data/lib/roby/execution_engine.rb +1604 -0
  114. data/lib/roby/external_process_task.rb +225 -0
  115. data/lib/roby/graph.rb +0 -6
  116. data/lib/roby/interface.rb +221 -137
  117. data/lib/roby/log/console.rb +5 -3
  118. data/lib/roby/log/data_stream.rb +94 -16
  119. data/lib/roby/log/dot.rb +8 -8
  120. data/lib/roby/log/event_stream.rb +13 -3
  121. data/lib/roby/log/file.rb +43 -18
  122. data/lib/roby/log/gui/basic_display_ui.rb +89 -0
  123. data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
  124. data/lib/roby/log/gui/data_displays.rb +4 -5
  125. data/lib/roby/log/gui/data_displays_ui.rb +146 -0
  126. data/lib/roby/log/gui/relations.rb +18 -18
  127. data/lib/roby/log/gui/relations_ui.rb +120 -0
  128. data/lib/roby/log/gui/relations_view_ui.rb +144 -0
  129. data/lib/roby/log/gui/replay.rb +41 -13
  130. data/lib/roby/log/gui/replay_controls.rb +3 -0
  131. data/lib/roby/log/gui/replay_controls.ui +133 -110
  132. data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
  133. data/lib/roby/log/hooks.rb +19 -18
  134. data/lib/roby/log/logger.rb +7 -6
  135. data/lib/roby/log/notifications.rb +4 -4
  136. data/lib/roby/log/plan_rebuilder.rb +20 -22
  137. data/lib/roby/log/relations.rb +44 -16
  138. data/lib/roby/log/server.rb +1 -4
  139. data/lib/roby/log/timings.rb +88 -19
  140. data/lib/roby/plan-object.rb +135 -11
  141. data/lib/roby/plan.rb +408 -224
  142. data/lib/roby/planning/loops.rb +32 -25
  143. data/lib/roby/planning/model.rb +157 -51
  144. data/lib/roby/planning/task.rb +47 -20
  145. data/lib/roby/query.rb +128 -92
  146. data/lib/roby/relations.rb +254 -136
  147. data/lib/roby/relations/conflicts.rb +6 -9
  148. data/lib/roby/relations/dependency.rb +358 -0
  149. data/lib/roby/relations/ensured.rb +0 -1
  150. data/lib/roby/relations/error_handling.rb +0 -1
  151. data/lib/roby/relations/events.rb +0 -2
  152. data/lib/roby/relations/executed_by.rb +26 -11
  153. data/lib/roby/relations/planned_by.rb +14 -14
  154. data/lib/roby/robot.rb +46 -0
  155. data/lib/roby/schedulers/basic.rb +34 -0
  156. data/lib/roby/standalone.rb +4 -0
  157. data/lib/roby/standard_errors.rb +21 -15
  158. data/lib/roby/state/events.rb +5 -4
  159. data/lib/roby/support.rb +107 -6
  160. data/lib/roby/task-operations.rb +23 -19
  161. data/lib/roby/task.rb +522 -148
  162. data/lib/roby/task_index.rb +80 -0
  163. data/lib/roby/test/common.rb +283 -44
  164. data/lib/roby/test/distributed.rb +53 -37
  165. data/lib/roby/test/testcase.rb +9 -204
  166. data/lib/roby/test/tools.rb +3 -3
  167. data/lib/roby/transactions.rb +154 -111
  168. data/lib/roby/transactions/proxy.rb +40 -7
  169. data/manifest.xml +20 -0
  170. data/plugins/fault_injection/README.txt +0 -3
  171. data/plugins/fault_injection/Rakefile +2 -8
  172. data/plugins/fault_injection/app.rb +1 -1
  173. data/plugins/fault_injection/fault_injection.rb +3 -3
  174. data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
  175. data/plugins/subsystems/README.txt +0 -3
  176. data/plugins/subsystems/Rakefile +2 -7
  177. data/plugins/subsystems/app.rb +27 -16
  178. data/plugins/subsystems/test/app/config/init.rb +3 -0
  179. data/plugins/subsystems/test/app/planners/main.rb +1 -1
  180. data/plugins/subsystems/test/app/tasks/services.rb +1 -1
  181. data/plugins/subsystems/test/test_subsystems.rb +23 -16
  182. data/test/distributed/test_communication.rb +32 -15
  183. data/test/distributed/test_connection.rb +28 -26
  184. data/test/distributed/test_execution.rb +59 -54
  185. data/test/distributed/test_mixed_plan.rb +34 -34
  186. data/test/distributed/test_plan_notifications.rb +26 -26
  187. data/test/distributed/test_protocol.rb +57 -48
  188. data/test/distributed/test_query.rb +11 -7
  189. data/test/distributed/test_remote_plan.rb +71 -71
  190. data/test/distributed/test_transaction.rb +50 -47
  191. data/test/mockups/external_process +28 -0
  192. data/test/planning/test_loops.rb +163 -119
  193. data/test/planning/test_model.rb +3 -3
  194. data/test/planning/test_task.rb +27 -7
  195. data/test/relations/test_conflicts.rb +3 -3
  196. data/test/relations/test_dependency.rb +324 -0
  197. data/test/relations/test_ensured.rb +2 -2
  198. data/test/relations/test_executed_by.rb +94 -19
  199. data/test/relations/test_planned_by.rb +11 -9
  200. data/test/suite_core.rb +6 -3
  201. data/test/suite_distributed.rb +1 -0
  202. data/test/suite_planning.rb +1 -0
  203. data/test/suite_relations.rb +2 -2
  204. data/test/tasks/test_external_process.rb +126 -0
  205. data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
  206. data/test/test_bgl.rb +21 -1
  207. data/test/test_event.rb +229 -155
  208. data/test/test_exceptions.rb +79 -80
  209. data/test/test_execution_engine.rb +987 -0
  210. data/test/test_gui.rb +1 -1
  211. data/test/test_interface.rb +11 -5
  212. data/test/test_log.rb +18 -7
  213. data/test/test_log_server.rb +1 -0
  214. data/test/test_plan.rb +229 -395
  215. data/test/test_query.rb +193 -35
  216. data/test/test_relations.rb +88 -8
  217. data/test/test_state.rb +55 -37
  218. data/test/test_support.rb +1 -1
  219. data/test/test_task.rb +371 -218
  220. data/test/test_testcase.rb +32 -16
  221. data/test/test_transactions.rb +211 -170
  222. data/test/test_transactions_proxy.rb +37 -19
  223. metadata +169 -71
  224. data/.gitignore +0 -29
  225. data/doc/styles/allison.css +0 -314
  226. data/doc/styles/allison.js +0 -316
  227. data/doc/styles/allison.rb +0 -276
  228. data/doc/styles/jamis.rb +0 -593
  229. data/lib/roby/control.rb +0 -746
  230. data/lib/roby/executives/simple.rb +0 -30
  231. data/lib/roby/propagation.rb +0 -562
  232. data/lib/roby/relations/hierarchy.rb +0 -239
  233. data/lib/roby/transactions/updates.rb +0 -139
  234. data/test/relations/test_hierarchy.rb +0 -158
  235. data/test/test_control.rb +0 -399
  236. data/test/test_propagation.rb +0 -210
@@ -3,9 +3,12 @@
3
3
  # [Roby] core namespace for the Roby kernel
4
4
  # [Roby::Distributed] parts that are very specific to distributed plan management
5
5
  # [Roby::Planning] basic tools for plan generation
6
- # [Roby::Transactions] implementation of transactions
7
- # [Roby::EventStructure] event relations
8
- # [Roby::TaskStructure] task relations
6
+ # [Roby::Transactions] implementation of transactions. Transactions represent a
7
+ # change in the main plan, and can be distributed among different plan managers.
8
+ # [Roby::EventStructure] main namespace for event relations. The methods listed
9
+ # in the documentation of EventStructure are actually methods of Roby::EventGenerator
10
+ # [Roby::TaskStructure] main namespace for task relations. The methods listed in
11
+ # the documentation of TaskStructure are actually methods of Roby::Task
9
12
  module Roby
10
13
  class BasicObject; end
11
14
  class PlanObject < BasicObject; end
@@ -15,28 +18,60 @@ module Roby
15
18
  class Task < PlanObject; end
16
19
  end
17
20
 
18
- require 'roby/support'
19
- require 'roby/task'
20
- require 'roby/event'
21
- require 'roby/standard_errors'
21
+ require 'drb'
22
+ require 'utilrb/weakref'
23
+ require 'pp'
24
+ require 'thread'
25
+ require 'set'
26
+ require 'yaml'
27
+ require 'utilrb/value_set'
28
+ require 'utilrb/object/attribute'
29
+ require 'utilrb/module/ancestor_p'
30
+ require 'utilrb/kernel/options'
31
+ require 'utilrb/module/attr_enumerable'
32
+ require 'utilrb/module/attr_predicate'
33
+ require 'utilrb/module/inherited_enumerable'
34
+ require 'utilrb/module/include'
35
+ require 'utilrb/kernel/arity'
36
+ require 'utilrb/kernel/swap'
37
+ require 'utilrb/exception/full_message'
38
+ require 'utilrb/unbound_method/call'
22
39
 
23
- require 'roby/plan'
24
- require 'roby/query'
25
- require 'roby/control'
26
- require 'roby/decision_control'
40
+ require 'roby/config.rb'
41
+ require 'roby/support.rb'
42
+ require 'roby/basic_object.rb'
43
+ require 'roby/standard_errors.rb'
44
+ require 'roby/exceptions.rb'
45
+ require 'roby_bgl'
46
+ require 'roby/graph.rb'
47
+ require 'roby/relations.rb'
27
48
 
28
- require 'roby/propagation'
29
- require 'roby/relations/events'
30
- require 'roby/relations/hierarchy'
31
- require 'roby/relations/influence'
32
- require 'roby/relations/planned_by'
33
- require 'roby/relations/executed_by'
34
- require 'roby/relations/ensured'
49
+ require 'roby/plan-object.rb'
50
+ require 'roby/event.rb'
51
+ require 'roby/task.rb'
52
+ require 'roby/task-operations.rb'
35
53
 
36
- require 'roby/state'
37
- require 'roby/interface'
54
+ require 'roby/relations/conflicts.rb'
55
+ require 'roby/relations/ensured.rb'
56
+ require 'roby/relations/error_handling.rb'
57
+ require 'roby/relations/events.rb'
58
+ require 'roby/relations/executed_by.rb'
59
+ require 'roby/relations/dependency.rb'
60
+ require 'roby/relations/influence.rb'
61
+ require 'roby/relations/planned_by.rb'
38
62
 
39
- require 'roby/distributed/protocol'
63
+ require 'roby/task_index.rb'
64
+ require 'roby/plan.rb'
65
+ require 'roby/transactions/proxy.rb'
66
+ require 'roby/transactions.rb'
67
+ require 'roby/query.rb'
40
68
 
41
- require 'roby/app'
69
+ require 'roby/distributed/base'
70
+ require 'roby/decision_control.rb'
71
+ require 'roby/execution_engine.rb'
72
+ require 'roby/app.rb'
73
+
74
+ require 'roby/robot.rb'
75
+ require 'roby/planning.rb'
76
+ require 'roby/state.rb'
42
77
 
@@ -1,16 +1,5 @@
1
- require 'roby'
2
- require 'roby/distributed'
3
- require 'roby/planning'
4
- require 'roby/log'
5
- require 'roby/log/event_stream'
6
-
7
- require 'roby/robot'
8
- require 'yaml'
9
-
1
+ require 'singleton'
10
2
  module Roby
11
- # Returns the only one Application object
12
- def self.app; Application.instance end
13
-
14
3
  # = Roby Applications
15
4
  #
16
5
  # There is one and only one Application object, which holds mainly the
@@ -56,6 +45,9 @@ module Roby
56
45
  # Roby::Test::TestCase for a description of Roby-specific tests.
57
46
  class Application
58
47
  include Singleton
48
+
49
+ # A set of planners declared in this application
50
+ attr_reader :planners
59
51
 
60
52
  # The plain option hash saved in config/app.yml
61
53
  attr_reader :options
@@ -70,6 +62,9 @@ module Roby
70
62
  # dir:: the log directory. Uses APP_DIR/log if not set
71
63
  # filter_backtraces:: true if the framework code should be removed from the error backtraces
72
64
  attr_reader :log
65
+
66
+ # ExecutionEngine setup
67
+ attr_reader :engine
73
68
 
74
69
  # A [name, dir, file, module] array of available plugins, where 'name'
75
70
  # is the plugin name, 'dir' the directory in which it is installed,
@@ -88,12 +83,10 @@ module Roby
88
83
  # detected
89
84
  attr_reader :droby
90
85
 
91
- # Configuration of the control loop
92
- # abort_on_exception:: if the control loop should abort if an uncaught task or event exception is received. Defaults
93
- # to false
94
- # abort_on_application_exception:: if the control should abort if an uncaught application exception (not originating
95
- # from a task or event) is caught. Defaults to true.
96
- attr_reader :control
86
+ # If true, abort if an unhandled exception is found
87
+ attr_predicate :abort_on_exception, true
88
+ # If true, abort if an application exception is found
89
+ attr_predicate :abort_on_application_exception, true
97
90
 
98
91
  # An array of directories in which to search for plugins
99
92
  attr_reader :plugin_dirs
@@ -117,13 +110,13 @@ module Roby
117
110
  @log = Hash['events' => 'stats', 'levels' => Hash.new, 'filter_backtraces' => true]
118
111
  @discovery = Hash.new
119
112
  @droby = Hash['period' => 0.5, 'max_errors' => 1]
120
- @control = Hash[ 'abort_on_exception' => false,
121
- 'abort_on_application_exception' => true ]
113
+ @engine = Hash.new
122
114
 
123
115
  @automatic_testing = true
124
116
  @testing_keep_logs = false
125
117
 
126
118
  @plugin_dirs = []
119
+ @planners = []
127
120
  end
128
121
 
129
122
  # Adds +dir+ in the list of directories searched for plugins
@@ -207,7 +200,7 @@ module Roby
207
200
 
208
201
  @options = options
209
202
 
210
- load_option_hashes(options, %w{log control discovery droby})
203
+ load_option_hashes(options, %w{log engine discovery droby})
211
204
  call_plugins(:load, self, options)
212
205
  end
213
206
 
@@ -349,7 +342,7 @@ module Roby
349
342
 
350
343
  # Set up log levels
351
344
  log['levels'].each do |name, value|
352
- name = name.camelize
345
+ name = name.camelcase(true)
353
346
  if value =~ /^(\w+):(.+)$/
354
347
  level, file = $1, $2
355
348
  level = Logger.const_get(level)
@@ -367,19 +360,18 @@ module Roby
367
360
  new_logger.level = level
368
361
  new_logger.formatter = Roby.logger.formatter
369
362
 
370
- if (mod = name.constantize rescue nil)
371
- if robot_name
372
- new_logger.progname = "#{name} #{robot_name}"
373
- else
374
- new_logger.progname = name
375
- end
376
- mod.logger = new_logger
377
- end
363
+ mod = Kernel.constant(name)
364
+ if robot_name
365
+ new_logger.progname = "#{name} #{robot_name}"
366
+ else
367
+ new_logger.progname = name
368
+ end
369
+ mod.logger = new_logger
378
370
  end
379
371
  end
380
372
 
381
373
  def setup_dirs
382
- Dir.mkdir(log_dir) unless File.exists?(log_dir)
374
+ FileUtils.mkdir_p(log_dir) unless File.exists?(log_dir)
383
375
  if File.directory?(libdir = File.join(APP_DIR, 'lib'))
384
376
  if !$LOAD_PATH.include?(libdir)
385
377
  $LOAD_PATH.unshift File.join(APP_DIR, 'lib')
@@ -397,22 +389,17 @@ module Roby
397
389
  def require_models
398
390
  # Require all common task models and the task models specific to
399
391
  # this robot
400
- require_dir(File.join(APP_DIR, 'tasks'))
401
- require_robotdir(File.join(APP_DIR, 'tasks', 'ROBOT'))
392
+ list_dir('tasks') { |p| require(p) }
393
+ list_robotdir('tasks', 'ROBOT') { |p| require(p) }
402
394
 
403
395
  # Load robot-specific configuration
404
- planner_dir = File.join(APP_DIR, 'planners')
405
- models_search = [planner_dir]
396
+ models_search = ['planners']
406
397
  if robot_name
407
- load_robotfile(File.join(APP_DIR, 'config', "ROBOT.rb"))
408
-
409
- models_search << File.join(planner_dir, robot_name) << File.join(planner_dir, robot_type)
410
- if !require_robotfile(File.join(APP_DIR, 'planners', 'ROBOT', 'main.rb'))
411
- require File.join(APP_DIR, "planners", "main")
412
- end
413
- else
414
- require File.join(APP_DIR, "planners", "main")
415
- end
398
+ models_search << File.join('planners', robot_name) << File.join('planners', robot_type)
399
+ file = robotfile('planners', 'ROBOT', 'main.rb')
400
+ end
401
+ file ||= File.join("planners", "main")
402
+ require file if File.file?(file)
416
403
 
417
404
  # Load the other planners
418
405
  models_search.each do |base_dir|
@@ -423,10 +410,19 @@ module Roby
423
410
  end
424
411
  end
425
412
  end
413
+
414
+ # Set up the loaded plugins
415
+ call_plugins(:require_models, self)
426
416
  end
427
417
 
428
418
  def setup
419
+ if !Roby.plan
420
+ Roby.instance_variable_set :@plan, Plan.new
421
+ end
422
+
429
423
  reset
424
+ require 'roby/planning'
425
+ require 'roby/interface'
430
426
 
431
427
  $LOAD_PATH.unshift(APP_DIR) unless $LOAD_PATH.include?(APP_DIR)
432
428
 
@@ -448,14 +444,21 @@ module Roby
448
444
  Object.const_set(:State, Roby::State)
449
445
  end
450
446
 
447
+ # Set up the loaded plugins
448
+ call_plugins(:setup, self)
449
+
451
450
  require_models
452
451
 
452
+ if file = robotfile(APP_DIR, 'config', "ROBOT.rb")
453
+ load file
454
+ end
455
+
456
+
453
457
  # MainPlanner is always included in the planner list
454
- Roby.control.planners << MainPlanner
458
+ if defined? MainPlanner
459
+ self.planners << MainPlanner
460
+ end
455
461
 
456
- # Set up the loaded plugins
457
- call_plugins(:setup, self)
458
-
459
462
  # If we are in test mode, import the test extensions from plugins
460
463
  if testing?
461
464
  require 'roby/test/testcase'
@@ -468,6 +471,8 @@ module Roby
468
471
  end
469
472
 
470
473
  def run(&block)
474
+ setup_global_singletons
475
+
471
476
  # Set up dRoby, setting an Interface object as front server, for shell access
472
477
  host = droby['host'] || ""
473
478
  if host !~ /:\d+$/
@@ -476,9 +481,9 @@ module Roby
476
481
 
477
482
  if single? || !robot_name
478
483
  host =~ /:(\d+)$/
479
- DRb.start_service "druby://:#{$1 || '0'}", Interface.new(Roby.control)
484
+ DRb.start_service "druby://:#{$1 || '0'}", Interface.new(Roby.engine)
480
485
  else
481
- DRb.start_service "druby://#{host}", Interface.new(Roby.control)
486
+ DRb.start_service "druby://#{host}", Interface.new(Roby.engine)
482
487
  droby_config = { :ring_discovery => !!discovery['ring'],
483
488
  :name => robot_name,
484
489
  :plan => Roby.plan,
@@ -492,7 +497,7 @@ module Roby
492
497
  if discovery['ring']
493
498
  Roby::Distributed.publish discovery['ring']
494
499
  end
495
- Roby::Control.every(discovery['period'] || 0.5) do
500
+ Roby.every(discovery['period'] || 0.5) do
496
501
  Roby::Distributed.state.start_neighbour_discovery
497
502
  end
498
503
  end
@@ -500,27 +505,18 @@ module Roby
500
505
  @robot_name ||= 'common'
501
506
  @robot_type ||= 'common'
502
507
 
503
- control_config = self.control
504
- control = Roby.control
505
- options = { :detach => true, :cycle => control_config['cycle'] || 0.1 }
508
+ engine_config = self.engine
509
+ engine = Roby.engine
510
+ options = { :cycle => engine_config['cycle'] || 0.1 }
506
511
 
507
- # Add an executive if one is defined
508
- if control_config['executive']
509
- self.executive = control_config['executive']
510
- end
511
-
512
512
  if log['events']
513
513
  require 'roby/log/file'
514
514
  logfile = File.join(log_dir, robot_name)
515
- logger = Roby::Log::FileLogger.new(logfile)
515
+ logger = Roby::Log::FileLogger.new(logfile, :plugins => plugins.map { |n, _| n })
516
516
  logger.stats_mode = log['events'] == 'stats'
517
517
  Roby::Log.add_logger logger
518
518
  end
519
- control.abort_on_exception =
520
- control_config['abort_on_exception']
521
- control.abort_on_application_exception =
522
- control_config['abort_on_application_exception']
523
- control.run options
519
+ engine.run options
524
520
 
525
521
  plugins = self.plugins.map { |_, mod| mod if mod.respond_to?(:run) }.compact
526
522
  run_plugins(plugins, &block)
@@ -533,11 +529,11 @@ module Roby
533
529
  end
534
530
  end
535
531
  def run_plugins(mods, &block)
536
- control = Roby.control
532
+ engine = Roby.engine
537
533
 
538
534
  if mods.empty?
539
535
  yield
540
- control.join
536
+ engine.join
541
537
  else
542
538
  mod = mods.shift
543
539
  mod.run(self) do
@@ -546,30 +542,15 @@ module Roby
546
542
  end
547
543
 
548
544
  rescue Exception => e
549
- if Roby.control.running?
550
- control.quit
551
- control.join
545
+ if Roby.engine.running?
546
+ engine.quit
547
+ engine.join
552
548
  raise e, e.message, e.backtrace
553
549
  else
554
550
  raise
555
551
  end
556
552
  end
557
553
 
558
- attr_reader :executive
559
-
560
- def executive=(name)
561
- if executive
562
- Control.event_processing.delete(executive.method(:initial_events))
563
- @executive = nil
564
- end
565
- return unless name
566
-
567
- full_name = "roby/executives/#{name}"
568
- require full_name
569
- @executive = full_name.camelize.constantize.new
570
- Control.event_processing << executive.method(:initial_events)
571
- end
572
-
573
554
  def stop; call_plugins(:stop, self) end
574
555
 
575
556
  DISCOVERY_TEMPLATE = [:droby, nil, nil]
@@ -583,7 +564,7 @@ module Roby
583
564
  Thread.abort_on_exception = true
584
565
 
585
566
  if !File.exists?(log_dir)
586
- Dir.mkdir(log_dir)
567
+ FileUtils.mkdir_p(log_dir)
587
568
  end
588
569
 
589
570
  unless single? || !discovery['tuplespace']
@@ -678,52 +659,49 @@ module Roby
678
659
  call_plugins(:stop_server, self)
679
660
  end
680
661
 
681
- # Require all files in +dirname+
682
- def require_dir(dirname)
662
+ def list_dir(*path)
663
+ if !block_given?
664
+ return enum_for(:list_dir, *path)
665
+ end
666
+
667
+ dirname = File.join(*path)
683
668
  Dir.new(dirname).each do |file|
684
669
  file = File.join(dirname, file)
685
- file = file.gsub(/^#{Regexp.quote(APP_DIR)}\//, '')
686
- require file if file =~ /\.rb$/ && File.file?(file)
670
+ if file =~ /\.rb$/ && File.file?(file)
671
+ file = file.gsub(/^#{Regexp.quote(APP_DIR)}\//, '')
672
+ yield(file)
673
+ end
687
674
  end
688
- end
675
+ end
689
676
 
690
677
  # Require all files in the directories matching +pattern+. If +pattern+
691
678
  # contains the word ROBOT, it is replaced by -- in order -- the robot
692
679
  # name and then the robot type
693
- def require_robotdir(pattern)
680
+ def list_robotdir(*path, &block)
681
+ if !block_given?
682
+ return enum_for(:list_robotdir, *path)
683
+ end
684
+
694
685
  return unless robot_name && robot_type
695
686
 
696
- [robot_name, robot_type].each do |name|
687
+ pattern = File.expand_path(File.join(*path), APP_DIR)
688
+ [robot_name, robot_type].uniq.each do |name|
697
689
  dirname = pattern.gsub(/ROBOT/, name)
698
- require_dir(dirname) if File.directory?(dirname)
690
+ list_dir(dirname, &block) if File.directory?(dirname)
699
691
  end
700
692
  end
701
693
 
702
- # Loads the first file found matching +pattern+
703
- #
704
- # See #require_robotfile
705
- def load_robotfile(pattern)
706
- require_robotfile(pattern, :load)
707
- end
708
-
709
- # Requires or loads (according to the value of +method+) the first file
710
- # found matching +pattern+. +pattern+ can contain the word ROBOT, in
711
- # which case the file is first checked against the robot name and then
712
- # against the robot type
713
- def require_robotfile(pattern, method = :require)
694
+ def robotfile(*path) # :nodoc
714
695
  return unless robot_name && robot_type
715
696
 
697
+ pattern = File.join(*path)
716
698
  robot_config = pattern.gsub(/ROBOT/, robot_name)
717
699
  if File.file?(robot_config)
718
- Kernel.send(method, robot_config)
719
- true
700
+ robot_config
720
701
  else
721
702
  robot_config = pattern.gsub(/ROBOT/, robot_type)
722
703
  if File.file?(robot_config)
723
- Kernel.send(method, robot_config)
724
- true
725
- else
726
- false
704
+ robot_config
727
705
  end
728
706
  end
729
707
  end
@@ -738,6 +716,34 @@ module Roby
738
716
  def single?; @single || discovery.empty? end
739
717
  def single; @single = true end
740
718
 
719
+ def setup_global_singletons
720
+ if !Roby.plan
721
+ Roby.instance_variable_set :@plan, Plan.new
722
+ end
723
+
724
+ if !Roby.engine && Roby.plan.engine
725
+ # This checks coherence with Roby.control, and sets it
726
+ # accordingly
727
+ Roby.engine = Roby.plan.engine
728
+ elsif !Roby.control
729
+ Roby.control = DecisionControl.new
730
+ end
731
+
732
+ if !Roby.engine
733
+ Roby.engine = ExecutionEngine.new(Roby.plan, Roby.control)
734
+ end
735
+
736
+ if Roby.control != Roby.engine.control
737
+ raise "inconsistency between Roby.control and Roby.engine.control"
738
+ elsif Roby.engine != Roby.plan.engine
739
+ raise "inconsistency between Roby.engine and Roby.plan.engine"
740
+ end
741
+
742
+ if !Roby.engine.scheduler && Roby.scheduler
743
+ Roby.engine.scheduler = Roby.scheduler
744
+ end
745
+ end
746
+
741
747
  # Guesses the type of +filename+ if it is a source suitable for
742
748
  # data display in this application
743
749
  def data_streams_of(filenames)
@@ -857,6 +863,20 @@ module Roby
857
863
  end
858
864
  end
859
865
 
866
+ @app = Application.instance
867
+ class << self
868
+ # The one and only Application object
869
+ attr_reader :app
870
+
871
+ # The scheduler object to be used during execution. See
872
+ # ExecutionEngine#scheduler.
873
+ #
874
+ # This is only used during the configuration of the application, and
875
+ # not afterwards. It is also possible to set per-engine through
876
+ # ExecutionEngine#scheduler=
877
+ attr_accessor :scheduler
878
+ end
879
+
860
880
  # Load the plugins 'main' files
861
881
  Roby.app.plugin_dir File.join(ROBY_ROOT_DIR, 'plugins')
862
882
  if plugin_path = ENV['ROBY_PLUGIN_PATH']