roby 0.7.3 → 0.8.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 (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
+