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
data/bin/roby CHANGED
@@ -8,7 +8,7 @@ require 'fileutils'
8
8
  require 'yaml'
9
9
  require 'find'
10
10
 
11
- require 'roby/app'
11
+ require 'roby'
12
12
 
13
13
  MODES = %w{init robot}
14
14
  config = OpenStruct.new
@@ -75,13 +75,24 @@ when "stats"
75
75
  filename = if ARGV[0] == "--csv"
76
76
  do_csv = true
77
77
  ARGV[1]
78
- else
78
+ elsif ARGV[0] == "--help"
79
+ puts "roby-log stats [--csv]"
80
+ puts " displays statistics about the execution timings"
81
+ puts " if the --csv option is given, a table with all"
82
+ puts " the timings is output on stdout instead"
83
+ exit(0)
84
+ else
79
85
  ARGV[0]
80
86
  end
81
87
  io = Roby::Log.open(filename)
82
88
 
83
89
  cycle_count = io.index_data.size
84
- puts "#{cycle_count} cycles between #{io.range.first.to_hms} and #{io.range.last.to_hms}"
90
+ timespan = io.range
91
+ puts "#{cycle_count} cycles between #{timespan.first.to_hms} and #{timespan.last.to_hms}"
92
+ cpu_time = io.index_data.inject(0) { |old, info| old + info[:cpu_time] } / 1000
93
+ real_time = timespan.last - timespan.first
94
+ ratio = cpu_time / real_time
95
+ puts "Time: %.2fs CPU / %.2fs real (%i%% CPU use)" % [cpu_time, real_time, ratio * 100]
85
96
 
86
97
  if io.index_data.first.has_key?(:event_count)
87
98
  min, max = nil
@@ -116,13 +127,12 @@ when "replay"
116
127
  stream.open
117
128
  main.add_stream(stream)
118
129
  end
119
- else
120
- STDERR.puts parser
121
- exit(0)
122
130
  end
123
131
  else
124
132
  remaining.each do |file|
125
- if streams = Roby.app.data_streams_of([file])
133
+ if !File.exists?(file)
134
+ STDERR.puts "WARN: #{file} does not exist"
135
+ elsif streams = Roby.app.data_streams_of([file])
126
136
  streams.each do |s|
127
137
  s.open
128
138
  main.add_stream(s)
@@ -0,0 +1,2 @@
1
+ out/
2
+ webgen.cache
@@ -0,0 +1,34 @@
1
+ # This is the YAML configuration file for webgen used to set configuration options.
2
+ #
3
+ # The general syntax is:
4
+ #
5
+ # configuration.option.name: value
6
+ #
7
+ # For example, to set a different default language, you would do:
8
+ #
9
+ # website.lang: de
10
+ #
11
+ # Have a look at the documentation of the individual configuration options to see
12
+ # the allowed format of the values. Since this is a YAML file, you can easily set
13
+ # configuration options to strings, integers, dates, arrays, hashes and more.
14
+ #
15
+ # The available configuration options can be listed using the `webgen config`
16
+ # command, for example: `webgen config sourcehandler` will list all options starting
17
+ # with sourcehandler.
18
+ default_processing_pipeline:
19
+ Page: rdoc,tags,blocks
20
+
21
+
22
+ default_meta_info:
23
+ Webgen::SourceHandler::Page:
24
+ in_menu: true
25
+
26
+ tag.menu.nested: false
27
+
28
+ tag.breadcrumbtrail.omit_index_path: true
29
+
30
+ rdoclinks.base_url: /api
31
+ rdoclinks.base_module: Roby
32
+
33
+ tag.coderay.line_numbers: false
34
+ tag.coderay.lang: ruby
@@ -0,0 +1,14 @@
1
+ # = webgen extensions directory
2
+ #
3
+ # All init.rb files anywhere under this directory get automatically loaded on a webgen run. This
4
+ # allows you to add your own extensions to webgen or to modify webgen's core!
5
+ #
6
+ # If you don't need this feature you can savely delete this file and the directory in which it is!
7
+ #
8
+ # The +config+ variable below can be used to access the Webgen::Configuration object for the current
9
+ # website.
10
+ config = Webgen::WebsiteAccess.website.config
11
+
12
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
13
+ require 'ext/rdoc_links'
14
+ require 'ext/previous_next'
@@ -0,0 +1,40 @@
1
+ require 'webgen/tag'
2
+ class PrevNextTag
3
+ include Webgen::Tag::Base
4
+
5
+ def call(tag, body, context)
6
+ node = context.content_node
7
+ while !node.is_file?
8
+ node = node.parent
9
+ end
10
+
11
+ siblings = node.parent.children.sort
12
+ siblings.delete_if { |n| !n.meta_info['in_menu'] }
13
+ prev, _ = siblings.
14
+ enum_for(:each_cons, 2).
15
+ find { |prev, this| this == node }
16
+ _, nxt = siblings.
17
+ enum_for(:each_cons, 2).
18
+ find { |this, nxt| this == node }
19
+
20
+ content = if tag == "next" && nxt
21
+ node.link_to(nxt)
22
+ elsif tag == "previous" && prev
23
+ node.link_to(prev)
24
+ end
25
+
26
+ if content
27
+ if !body.empty?
28
+ body.gsub '%', content
29
+ else
30
+ content
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ config = Webgen::WebsiteAccess.website.config
37
+ config['contentprocessor.tags.map']['previous'] = 'PrevNextTag'
38
+ config['contentprocessor.tags.map']['next'] = 'PrevNextTag'
39
+
40
+
@@ -0,0 +1,33 @@
1
+ require 'webgen/tag'
2
+ class RdocLinks
3
+ include Webgen::Tag::Base
4
+
5
+ def call(tag, body, context)
6
+ name = param('rdoclinks.name')
7
+ if base_module = param('rdoclinks.base_module')
8
+ name = base_module + "::" + name
9
+ end
10
+
11
+ if name =~ /(?:\.|#)(\w+)$/
12
+ class_name = $`
13
+ method_name = $1
14
+ else
15
+ class_name = name
16
+ end
17
+
18
+ path = class_name.split('::')
19
+ path[-1] += ".html"
20
+ url = "#{param('rdoclinks.base_url')}/#{path.join("/")}"
21
+
22
+ "<a href=\"#{context.ref_node.route_to(url)}\">#{param('rdoclinks.name')}</a>"
23
+ end
24
+ end
25
+
26
+ config = Webgen::WebsiteAccess.website.config
27
+ config.rdoclinks.name "", :mandatory => 'default'
28
+ config.rdoclinks.base_webgen "", :mandatory => false
29
+ config.rdoclinks.base_url "", :mandatory => false
30
+ config.rdoclinks.base_module nil, :mandatory => false
31
+ config.rdoclinks.full_name false, :mandatory => false
32
+ config['contentprocessor.tags.map']['rdoc_class'] = 'RdocLinks'
33
+
@@ -0,0 +1,16 @@
1
+ = Roby's User's Guide
2
+
3
+ This guide is *definitely* a work in progress -- actually it is for now an
4
+ embryo of a user's guide, but things should improve ...
5
+
6
+ For people which want to extend Roby, see {this
7
+ guide}[link:files/doc/extending/index_rdoc.html]
8
+
9
+ == Table of Contents
10
+
11
+ * {Table of Contents}[link:files/doc/using/index_rdoc.html]
12
+
13
+
14
+ * {Overview}[link:files/doc/using/overview_rdoc.html]
15
+ * {Plan modifications}[link:files/doc/using/plan_modifications_rdoc.html]
16
+
@@ -0,0 +1,62 @@
1
+ = Overview
2
+
3
+ This page describes the various components that form a Roby application. It is
4
+ meant to be an "entry point" for people to understand what classes are there
5
+ for. This describes the software architecture of the upcoming v0.8.
6
+
7
+ == Life and death of a Roby Controller
8
+
9
+ One Roby::Application instance is created per Roby controller. This class sets
10
+ up the various central objects (Roby::Plan, Roby::ExecutionEngine and Roby::DecisionControl, see
11
+ below), starts the execution engine and loads the relevant configuration files.
12
+
13
+ A Roby controller offers a DRb main server which is a Roby::Interface instance.
14
+ The best way to interact through this channel is to use a Roby::RemoteInterface
15
+ instance, which handles some custom marshalling/demarshalling of data, offering
16
+ a transparent interface to the remote controller. The <tt>scripts/shell</tt>
17
+ default script sets this up properly.
18
+
19
+ A Roby controller will shut down in the following conditions:
20
+ * CTRL+C is hit in the controller's main terminal
21
+ * the 'exit' command is sent through the remote shell
22
+ * a framework exception is detected, meaning an exception which is not part of
23
+ the plan-based error recovery mechanism (everything but event commands, event
24
+ handlers and polling blocks).
25
+
26
+ == Plan execution
27
+
28
+ The plan representation and the plan execution is handled by three objects:
29
+ * a Roby::Plan object which manages the various tasks and events which describe the
30
+ system's plan.
31
+ * an Roby::ExecutionEngine object which manipulates that Roby::Plan object. It propagates
32
+ events according to a set of "initial event", a set of events that are
33
+ considered to be emitted. They can be generated by external communication (for
34
+ instance from external robotic control frameworks like GenoM or Orocos), or
35
+ internally by the scheduler object (see ExecutionEngine#scheduler). The engine
36
+ is also responsible for reaction to errors and for the garbage collection
37
+ mechanism, through which tasks that are useless for the system's goals are
38
+ automatically killed and removed.
39
+ * a Roby::DecisionControl object which handles runtime error resolution (i.e.
40
+ situations which require choosing between multiple course of action). For
41
+ instance, if a signal leads to a task conflict -- i.e. if the signal would
42
+ start a task which conflicts with another task -- the DecisionControl#conflict
43
+ method is called. The default policy is to postpone starting the new task
44
+ until all the conflicting tasks are stopped. Other policies could be to raise
45
+ an error for instance.
46
+
47
+ The three "main" instances of these objects -- i.e. the ones that are supposed
48
+ to interact directly with the underlying robotic system -- are available
49
+ through the Roby.plan, Roby.engine and Roby.control attributes. These
50
+ attributes are set up at application start by Roby::Application#run (see below).
51
+ This is for an easy access in the main controller, but the architecture allows
52
+ to run multiple plans in parallel by binding those three different objects
53
+ yourself.
54
+
55
+ == A note about multi-robot systems
56
+
57
+ Until now, the Roby plan manager is able to run <b>bi-robot</b> plans, i.e.
58
+ plans where only two robots are interacting with each other. Extending that to
59
+ multi-robot is definitely on the TODO list of the project, but unfortunately it
60
+ will wait until multi-robot is back at the the center of my research. If you are
61
+ interested in doing it, of course, feel free to contact me ;-)
62
+
@@ -0,0 +1,67 @@
1
+ = Plan representation and modifications to plans
2
+
3
+ Understanding the plan model, and how to modify it, is central to the use of
4
+ Roby. In effect, the plan *is* the information on which the controller bases
5
+ itself to control the robot ...
6
+
7
+ == Plan objects
8
+ In Roby, plans are made of tasks and events. See {my
9
+ papers}[link:files/doc/papers_rdoc.html] for an in-depth description of the
10
+ model.
11
+
12
+ On the one hand, Roby::EventGenerator instances represent the plan's _possible_
13
+ events. This is by contrast to the Roby::Event class, whose instances represent
14
+ the <em>actual events</em>. In other words, an Event instance represent an
15
+ event which has already been emitted while an EventGenerator instance
16
+ represents a source of events, therefore a kind of events that could possibly
17
+ be emitted.
18
+
19
+ On the other hand, instances of Roby::Task represent the activities of the
20
+ system. Special subclasses of Roby::EventGenerator and Roby::Event are used in
21
+ tasks, to represent some particular properties of task's events:
22
+ Roby::TaskEventGenerator and Roby::TaskEvent.
23
+
24
+ == Plan relations
25
+ Roby::EventGenerator instances can be linked to each other through the use of
26
+ <em>event relations</em>, as Roby::Task can be linked through the use of <em>task relations</em>.
27
+ Task and event relations are defined in the Roby::EventStructure and
28
+ Roby::TaskStructure relation spaces (Roby::RelationSpace instances), through the use of
29
+ Roby::RelationSpace#relation. Each relation object (for instance
30
+ Roby::EventStructure::Signal or Roby::TaskStructure::Hierarchy) is an instance
31
+ of the Roby::RelationGraph class.
32
+
33
+ In order to be managed in these relations, tasks and events
34
+ include the Roby::DirectedRelationSupport mixin to provide the basic
35
+ management tools needed by the RelationGraph instances. Moreover, all relation
36
+ types define specific methods which allow to more directly modify the relation
37
+ (like #add_signal, #each_parent or #parents in Hierarchy). See RelationSpace#relation
38
+ for details. Due to issues with Ruby's documentation system, those methods are
39
+ listed in
40
+
41
+ === Plan modification
42
+ Modifying the plan therefore boils down to two things:
43
+ 1. adding and removing tasks and events in the plan
44
+ 2. adding and removing relations between objects of the same type (between tasks
45
+ or between events).
46
+
47
+ The first point is done by the following methods:
48
+ * Roby::Plan#discover: simply add tasks and events
49
+ * Roby::Plan#add_mission: adds special tasks, called missions. Missions are the
50
+ tasks the robot is supposed to execute. They are not subject to the plan's
51
+ garbage collection, and the tasks that are useful to them are not either.
52
+
53
+
54
+ To ease the plan management process, some synthetic
55
+ operations are defined on Roby::Plan:
56
+ * the _replacement_ operation: Roby::Plan#replace_task and
57
+ Roby::Plan#replace. #replace_task(a, b) will replace +a+ by +b+ in the plan.
58
+ It means that the operators will add to +b+ all the children and parents of +a+
59
+ in all relations, and do the same with +b+ and +a+'s events. Moreover, it will
60
+ remove them from +a+. #replace(a, b) will do the same, but constraining itself
61
+ to the _parents_ of +b+ and +b+'s events. It therefore replaces +a+ and its
62
+ generated subplan (i.e. +a+ and all children of +a+) by +b+ and its subplan.
63
+ * the _respawning_ operation: a given task is replaced by a new task of the same
64
+ kind and with the same parameters. This is used mainly to workaround a
65
+ "fragile" task which crashed spuriously.
66
+
67
+
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Achieving event commands with tasks
3
+ sort_info: 400
4
+ --- name:content pipeline:tags,markdown,blocks
5
+
6
+ * the achieve\_with operator
7
+ * semantics of it
8
+ * what happens when an error occurs ?
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: The forwarding relation
3
+ sort_info: 300
4
+ --- name:content pipeline:tags,markdown,blocks
5
+
6
+ * we already saw its usefulness inside tasks
7
+ * semantics of forwarding in-between tasks
8
+ * example: loops
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: Abstraction as task dependencies
3
+ sort_info: 200
4
+ --- name:content pipeline:tags,markdown,blocks
5
+
6
+ Dependency relations
7
+ --------------------
8
+ * Dependency is also a refinement relation
9
+ * the syntax and other concepts
10
+ - depends\_on :model
11
+ - fullfilled\_model
12
+ - fullfilled\_events
13
+
14
+ Plan modifications and model abstraction
15
+ ----------------------------------------
16
+
17
+ * the replace operator
18
+ * semantics of the :returns flag in this context
19
+
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Representing Abstraction
3
+ routed_title: Representing Abstraction
4
+ sort_info: 0
5
+ --- name:content pipeline:tags,markdown,blocks
6
+ Being able to abstract away the little details of execution is crucial. Indeed,
7
+ it allows to apply high-level reasoning algorithms, that are not able to take
8
+ into account too much details.
9
+
10
+ Roby offers a unique ability: to link in the same plan the high-level parts of
11
+ the plan and the low-level ones. What this section will present is how, using
12
+ Roby's plan model, one can represent the _mechanism_ of abstraction. In other
13
+ words, what are the details that are lost in the abstraction mechanism.
14
+
15
+ More specifically, we will see the following:
16
+
17
+ * the object-oriented nature of Roby's plan model: how task models are related
18
+ to each other, and the notion of abstract models.
19
+ * how the hierarchy relation uses this OO principles to not over-constrain the
20
+ plan. We will see that the hierarchy relation can be used to precisely
21
+ represent what is _needed_ and not only what _is_.
22
+ * how the execution flow of the low-level parts of the plan can be linked to the
23
+ higher-level execution flow by means of the _forwarding_ relation.
24
+ * how it is possible to cleanly (and easily) build event commands using tasks
25
+
26
+ To understand the content of this section, we will assume that you read and
27
+ understood the [basics](../basics/index.html).
28
+
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: Task Models
3
+ sort_info: 100
4
+ --- name:content pipeline:tags,markdown,blocks
5
+
6
+ * relationship between models
7
+ - semantics of subclasses
8
+ - rules of subclasses
9
+ - the TaskModelTag hack
10
+ * abstract models
11
+ - why is it useful => abstract actions that have to be chosen later on.
12
+ - syntax
13
+ - the :returns flag in planning models => example
@@ -0,0 +1,6 @@
1
+ ---
2
+ template: default.template
3
+ --- pipeline:tags,blocks
4
+ <webgen:block name="content" />
5
+
6
+ --- name:navbar
@@ -0,0 +1,139 @@
1
+ ---
2
+ title: A First Roby Application
3
+ sort_info: 300
4
+ --- pipeline:tags,markdown,blocks
5
+
6
+ This page will present another facet of Roby. What we saw until now is how,
7
+ in Roby, one can represent the task actions and build plans that describe the
8
+ task execution. What we will see here is how Roby tie the different models
9
+ together to offer an application environment.
10
+
11
+ {include_file: {filename: src/basics_shell_header.txt, escape_html: false}}
12
+
13
+ Creation
14
+ --------
15
+
16
+ Go into a *regular shell* (i.e. not the Ruby shell) and create a new directory.
17
+ That directory will become your first Roby application by running "roby init":
18
+
19
+ $ mkdir first_app
20
+ $ cd first_app
21
+ $ roby init
22
+ creating tasks/
23
+ creating tasks/.gitattributes
24
+ creating scripts/
25
+ creating scripts/test
26
+ creating scripts/shell
27
+ creating scripts/server
28
+ creating scripts/run
29
+ creating scripts/results
30
+ creating scripts/replay
31
+ creating scripts/generate/
32
+ creating scripts/generate/bookmarks
33
+ creating scripts/distributed
34
+ creating planners/
35
+ creating planners/main.rb
36
+ creating data/
37
+ creating data/.gitattributes
38
+ creating controllers/
39
+ creating controllers/.gitattributes
40
+ creating config/
41
+ creating config/roby.yml
42
+ creating config/init.rb
43
+ creating config/app.yml
44
+ creating Rakefile
45
+ creating README.txt
46
+
47
+ There's a lot of stuff created, but don't worry we'll learn what this is all
48
+ about later on. Right now, we're only interested in two small parts of it:
49
+
50
+ * the tasks/ directory, which is where task models (task classes) should be
51
+ defined
52
+ * the robot's controllers. These files contain the code that is run when the
53
+ application is started.
54
+
55
+ The goForward robot
56
+ -------------------
57
+ As an introduction, we will create a simulated robot controller which makes the
58
+ robot go forward at constant speed.
59
+
60
+ First, let's create the files specific to this robot
61
+
62
+ $ roby robot goForward
63
+ creating planners/goForward/
64
+ creating planners/goForward/main.rb
65
+ creating tasks/goForward/
66
+ creating tasks/goForward/.gitattributes
67
+ creating controllers/goForward.rb
68
+ creating config/goForward.rb
69
+
70
+ Let's define the task model. Edit tasks/go\_forward.rb and add
71
+
72
+ {coderay:: ruby}
73
+ class GoForward < Roby::Task
74
+ # The GoForward task needs the robot speed to be specified
75
+ arguments :speed
76
+
77
+ # Block called at every execution loop if the task is running. It simulates
78
+ # the robot moving at the specified speed.
79
+ poll do
80
+ State.pos.x += speed
81
+ end
82
+
83
+ # This task does not need any specific action to stop
84
+ terminates
85
+ end
86
+ {coderay}
87
+
88
+ In the controller file, controllers/goForward.rb, we add the code that
89
+ should run at startup:
90
+
91
+ {coderay:: ruby}
92
+ # Define the original value of x
93
+ State.pos.x = 0
94
+
95
+ # Will display the value of x every 1 second
96
+ Roby.every(1) do
97
+ puts State.pos.x
98
+ end
99
+
100
+ # Create the task and start moving !
101
+ Roby.plan.insert(go = GoForward.new(:speed => 0.1))
102
+ puts "Going forward at speed #{go.speed}"
103
+ go.start!
104
+ {coderay}
105
+
106
+ You can then start the robot controller with scripts/run and stop it with CTRL+C.
107
+
108
+ $ scripts/run goForward
109
+ 335705:25:08.324 (goForward) loading controller file /home/doudou/dev/roby-tutorials/controllers/goForward.rb
110
+ Going forward at speed 0.1
111
+ 335705:25:08.356 (goForward) done initialization
112
+ 0
113
+ 0.9
114
+ 1.9
115
+ 2.9
116
+ 335705:25:16.449 (Roby) received interruption request
117
+ 335705:25:16.524 (Roby) control quitting. Waiting for 1 tasks to finish (1 tasks still in plan)
118
+
119
+ Broken down explanation
120
+ -----------------------
121
+ * the Roby::State object holds all the configuration and state data that
122
+ represents the robot's state. In our case, we initialize the robot's position
123
+ in the controller file, and then update it when the robot moves.
124
+
125
+ * to understand the meaning of the __poll__ statement, you have to understand
126
+ the idea behind Roby's execution model. Roby relies on a _synchronous_
127
+ execution model, which is basically a two-steps loops (a more detailed
128
+ explanation will come later). This two-steps loops is basically:
129
+ 1. gather all events that have occured since the last loop
130
+ 2. propagate to those events through the signal and forward relations
131
+
132
+ In practice, this event loop runs with a fixed period which is by default
133
+ 100ms. This period can be changed in the configuration file config/app.yml.
134
+
135
+ Now, what is the role of __poll__ here ? The block given to +poll+ is executed
136
+ at each execution cycle _while the task is running_. It can therefore be
137
+ used to _implement_ the actual task functionality (or to check the state of
138
+ external processes, ...)
139
+