roby 0.7

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 (240) hide show
  1. data/.gitignore +29 -0
  2. data/History.txt +4 -0
  3. data/License-fr.txt +519 -0
  4. data/License.txt +515 -0
  5. data/Manifest.txt +245 -0
  6. data/NOTES +4 -0
  7. data/README.txt +163 -0
  8. data/Rakefile +161 -0
  9. data/TODO.txt +146 -0
  10. data/app/README.txt +24 -0
  11. data/app/Rakefile +8 -0
  12. data/app/config/ROBOT.rb +5 -0
  13. data/app/config/app.yml +91 -0
  14. data/app/config/init.rb +7 -0
  15. data/app/config/roby.yml +3 -0
  16. data/app/controllers/.gitattributes +0 -0
  17. data/app/controllers/ROBOT.rb +2 -0
  18. data/app/data/.gitattributes +0 -0
  19. data/app/planners/ROBOT/main.rb +6 -0
  20. data/app/planners/main.rb +5 -0
  21. data/app/scripts/distributed +3 -0
  22. data/app/scripts/generate/bookmarks +3 -0
  23. data/app/scripts/replay +3 -0
  24. data/app/scripts/results +3 -0
  25. data/app/scripts/run +3 -0
  26. data/app/scripts/server +3 -0
  27. data/app/scripts/shell +3 -0
  28. data/app/scripts/test +3 -0
  29. data/app/tasks/.gitattributes +0 -0
  30. data/app/tasks/ROBOT/.gitattributes +0 -0
  31. data/bin/roby +210 -0
  32. data/bin/roby-log +168 -0
  33. data/bin/roby-shell +25 -0
  34. data/doc/images/event_generalization.png +0 -0
  35. data/doc/images/exception_propagation_1.png +0 -0
  36. data/doc/images/exception_propagation_2.png +0 -0
  37. data/doc/images/exception_propagation_3.png +0 -0
  38. data/doc/images/exception_propagation_4.png +0 -0
  39. data/doc/images/exception_propagation_5.png +0 -0
  40. data/doc/images/replay_handler_error.png +0 -0
  41. data/doc/images/replay_handler_error_0.png +0 -0
  42. data/doc/images/replay_handler_error_1.png +0 -0
  43. data/doc/images/roby_cycle_overview.png +0 -0
  44. data/doc/images/roby_replay_02.png +0 -0
  45. data/doc/images/roby_replay_03.png +0 -0
  46. data/doc/images/roby_replay_04.png +0 -0
  47. data/doc/images/roby_replay_event_representation.png +0 -0
  48. data/doc/images/roby_replay_first_state.png +0 -0
  49. data/doc/images/roby_replay_relations.png +0 -0
  50. data/doc/images/roby_replay_startup.png +0 -0
  51. data/doc/images/task_event_generalization.png +0 -0
  52. data/doc/papers.rdoc +11 -0
  53. data/doc/styles/allison.css +314 -0
  54. data/doc/styles/allison.js +316 -0
  55. data/doc/styles/allison.rb +276 -0
  56. data/doc/styles/jamis.rb +593 -0
  57. data/doc/tutorials/01-GettingStarted.rdoc +86 -0
  58. data/doc/tutorials/02-GoForward.rdoc +220 -0
  59. data/doc/tutorials/03-PlannedPath.rdoc +268 -0
  60. data/doc/tutorials/04-EventPropagation.rdoc +236 -0
  61. data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
  62. data/doc/tutorials/06-Overview.rdoc +40 -0
  63. data/doc/videos.rdoc +69 -0
  64. data/ext/droby/dump.cc +175 -0
  65. data/ext/droby/extconf.rb +3 -0
  66. data/ext/graph/algorithm.cc +746 -0
  67. data/ext/graph/extconf.rb +7 -0
  68. data/ext/graph/graph.cc +529 -0
  69. data/ext/graph/graph.hh +183 -0
  70. data/ext/graph/iterator_sequence.hh +102 -0
  71. data/ext/graph/undirected_dfs.hh +226 -0
  72. data/ext/graph/undirected_graph.hh +421 -0
  73. data/lib/roby.rb +41 -0
  74. data/lib/roby/app.rb +870 -0
  75. data/lib/roby/app/rake.rb +56 -0
  76. data/lib/roby/app/run.rb +14 -0
  77. data/lib/roby/app/scripts/distributed.rb +13 -0
  78. data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
  79. data/lib/roby/app/scripts/replay.rb +31 -0
  80. data/lib/roby/app/scripts/results.rb +15 -0
  81. data/lib/roby/app/scripts/run.rb +26 -0
  82. data/lib/roby/app/scripts/server.rb +18 -0
  83. data/lib/roby/app/scripts/shell.rb +88 -0
  84. data/lib/roby/app/scripts/test.rb +40 -0
  85. data/lib/roby/basic_object.rb +151 -0
  86. data/lib/roby/config.rb +5 -0
  87. data/lib/roby/control.rb +747 -0
  88. data/lib/roby/decision_control.rb +17 -0
  89. data/lib/roby/distributed.rb +32 -0
  90. data/lib/roby/distributed/base.rb +440 -0
  91. data/lib/roby/distributed/communication.rb +871 -0
  92. data/lib/roby/distributed/connection_space.rb +592 -0
  93. data/lib/roby/distributed/distributed_object.rb +206 -0
  94. data/lib/roby/distributed/drb.rb +62 -0
  95. data/lib/roby/distributed/notifications.rb +539 -0
  96. data/lib/roby/distributed/peer.rb +550 -0
  97. data/lib/roby/distributed/protocol.rb +529 -0
  98. data/lib/roby/distributed/proxy.rb +343 -0
  99. data/lib/roby/distributed/subscription.rb +311 -0
  100. data/lib/roby/distributed/transaction.rb +498 -0
  101. data/lib/roby/event.rb +897 -0
  102. data/lib/roby/exceptions.rb +234 -0
  103. data/lib/roby/executives/simple.rb +30 -0
  104. data/lib/roby/graph.rb +166 -0
  105. data/lib/roby/interface.rb +390 -0
  106. data/lib/roby/log.rb +3 -0
  107. data/lib/roby/log/chronicle.rb +303 -0
  108. data/lib/roby/log/console.rb +72 -0
  109. data/lib/roby/log/data_stream.rb +197 -0
  110. data/lib/roby/log/dot.rb +279 -0
  111. data/lib/roby/log/event_stream.rb +151 -0
  112. data/lib/roby/log/file.rb +340 -0
  113. data/lib/roby/log/gui/basic_display.ui +83 -0
  114. data/lib/roby/log/gui/chronicle.rb +26 -0
  115. data/lib/roby/log/gui/chronicle_view.rb +40 -0
  116. data/lib/roby/log/gui/chronicle_view.ui +70 -0
  117. data/lib/roby/log/gui/data_displays.rb +172 -0
  118. data/lib/roby/log/gui/data_displays.ui +155 -0
  119. data/lib/roby/log/gui/notifications.rb +26 -0
  120. data/lib/roby/log/gui/relations.rb +248 -0
  121. data/lib/roby/log/gui/relations.ui +123 -0
  122. data/lib/roby/log/gui/relations_view.rb +185 -0
  123. data/lib/roby/log/gui/relations_view.ui +149 -0
  124. data/lib/roby/log/gui/replay.rb +327 -0
  125. data/lib/roby/log/gui/replay_controls.rb +200 -0
  126. data/lib/roby/log/gui/replay_controls.ui +259 -0
  127. data/lib/roby/log/gui/runtime.rb +130 -0
  128. data/lib/roby/log/hooks.rb +185 -0
  129. data/lib/roby/log/logger.rb +202 -0
  130. data/lib/roby/log/notifications.rb +244 -0
  131. data/lib/roby/log/plan_rebuilder.rb +470 -0
  132. data/lib/roby/log/relations.rb +1056 -0
  133. data/lib/roby/log/server.rb +550 -0
  134. data/lib/roby/log/sqlite.rb +47 -0
  135. data/lib/roby/log/timings.rb +164 -0
  136. data/lib/roby/plan-object.rb +247 -0
  137. data/lib/roby/plan.rb +762 -0
  138. data/lib/roby/planning.rb +13 -0
  139. data/lib/roby/planning/loops.rb +302 -0
  140. data/lib/roby/planning/model.rb +906 -0
  141. data/lib/roby/planning/task.rb +151 -0
  142. data/lib/roby/propagation.rb +562 -0
  143. data/lib/roby/query.rb +619 -0
  144. data/lib/roby/relations.rb +583 -0
  145. data/lib/roby/relations/conflicts.rb +70 -0
  146. data/lib/roby/relations/ensured.rb +20 -0
  147. data/lib/roby/relations/error_handling.rb +23 -0
  148. data/lib/roby/relations/events.rb +9 -0
  149. data/lib/roby/relations/executed_by.rb +193 -0
  150. data/lib/roby/relations/hierarchy.rb +239 -0
  151. data/lib/roby/relations/influence.rb +10 -0
  152. data/lib/roby/relations/planned_by.rb +63 -0
  153. data/lib/roby/robot.rb +7 -0
  154. data/lib/roby/standard_errors.rb +218 -0
  155. data/lib/roby/state.rb +5 -0
  156. data/lib/roby/state/events.rb +221 -0
  157. data/lib/roby/state/information.rb +55 -0
  158. data/lib/roby/state/pos.rb +110 -0
  159. data/lib/roby/state/shapes.rb +32 -0
  160. data/lib/roby/state/state.rb +353 -0
  161. data/lib/roby/support.rb +92 -0
  162. data/lib/roby/task-operations.rb +182 -0
  163. data/lib/roby/task.rb +1618 -0
  164. data/lib/roby/test/common.rb +399 -0
  165. data/lib/roby/test/distributed.rb +214 -0
  166. data/lib/roby/test/tasks/empty_task.rb +9 -0
  167. data/lib/roby/test/tasks/goto.rb +36 -0
  168. data/lib/roby/test/tasks/simple_task.rb +23 -0
  169. data/lib/roby/test/testcase.rb +519 -0
  170. data/lib/roby/test/tools.rb +160 -0
  171. data/lib/roby/thread_task.rb +87 -0
  172. data/lib/roby/transactions.rb +462 -0
  173. data/lib/roby/transactions/proxy.rb +292 -0
  174. data/lib/roby/transactions/updates.rb +139 -0
  175. data/plugins/fault_injection/History.txt +4 -0
  176. data/plugins/fault_injection/README.txt +37 -0
  177. data/plugins/fault_injection/Rakefile +18 -0
  178. data/plugins/fault_injection/TODO.txt +0 -0
  179. data/plugins/fault_injection/app.rb +52 -0
  180. data/plugins/fault_injection/fault_injection.rb +89 -0
  181. data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
  182. data/plugins/subsystems/README.txt +40 -0
  183. data/plugins/subsystems/Rakefile +18 -0
  184. data/plugins/subsystems/app.rb +171 -0
  185. data/plugins/subsystems/test/app/README +24 -0
  186. data/plugins/subsystems/test/app/Rakefile +8 -0
  187. data/plugins/subsystems/test/app/config/app.yml +71 -0
  188. data/plugins/subsystems/test/app/config/init.rb +9 -0
  189. data/plugins/subsystems/test/app/config/roby.yml +3 -0
  190. data/plugins/subsystems/test/app/planners/main.rb +20 -0
  191. data/plugins/subsystems/test/app/scripts/distributed +3 -0
  192. data/plugins/subsystems/test/app/scripts/replay +3 -0
  193. data/plugins/subsystems/test/app/scripts/results +3 -0
  194. data/plugins/subsystems/test/app/scripts/run +3 -0
  195. data/plugins/subsystems/test/app/scripts/server +3 -0
  196. data/plugins/subsystems/test/app/scripts/shell +3 -0
  197. data/plugins/subsystems/test/app/scripts/test +3 -0
  198. data/plugins/subsystems/test/app/tasks/services.rb +15 -0
  199. data/plugins/subsystems/test/test_subsystems.rb +71 -0
  200. data/test/distributed/test_communication.rb +178 -0
  201. data/test/distributed/test_connection.rb +282 -0
  202. data/test/distributed/test_execution.rb +373 -0
  203. data/test/distributed/test_mixed_plan.rb +341 -0
  204. data/test/distributed/test_plan_notifications.rb +238 -0
  205. data/test/distributed/test_protocol.rb +516 -0
  206. data/test/distributed/test_query.rb +102 -0
  207. data/test/distributed/test_remote_plan.rb +491 -0
  208. data/test/distributed/test_transaction.rb +463 -0
  209. data/test/mockups/tasks.rb +27 -0
  210. data/test/planning/test_loops.rb +380 -0
  211. data/test/planning/test_model.rb +427 -0
  212. data/test/planning/test_task.rb +106 -0
  213. data/test/relations/test_conflicts.rb +42 -0
  214. data/test/relations/test_ensured.rb +38 -0
  215. data/test/relations/test_executed_by.rb +149 -0
  216. data/test/relations/test_hierarchy.rb +158 -0
  217. data/test/relations/test_planned_by.rb +54 -0
  218. data/test/suite_core.rb +24 -0
  219. data/test/suite_distributed.rb +9 -0
  220. data/test/suite_planning.rb +3 -0
  221. data/test/suite_relations.rb +8 -0
  222. data/test/test_bgl.rb +508 -0
  223. data/test/test_control.rb +399 -0
  224. data/test/test_event.rb +894 -0
  225. data/test/test_exceptions.rb +592 -0
  226. data/test/test_interface.rb +37 -0
  227. data/test/test_log.rb +114 -0
  228. data/test/test_log_server.rb +132 -0
  229. data/test/test_plan.rb +584 -0
  230. data/test/test_propagation.rb +210 -0
  231. data/test/test_query.rb +266 -0
  232. data/test/test_relations.rb +180 -0
  233. data/test/test_state.rb +414 -0
  234. data/test/test_support.rb +16 -0
  235. data/test/test_task.rb +938 -0
  236. data/test/test_testcase.rb +122 -0
  237. data/test/test_thread_task.rb +73 -0
  238. data/test/test_transactions.rb +569 -0
  239. data/test/test_transactions_proxy.rb +198 -0
  240. metadata +570 -0
data/lib/roby/log.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'roby'
2
+ require 'roby/distributed'
3
+ require 'roby/log/logger'
@@ -0,0 +1,303 @@
1
+ require 'roby/log/data_stream'
2
+ require 'roby/log/relations'
3
+ require 'roby/log/gui/chronicle_view'
4
+
5
+ module Roby
6
+ module Log
7
+ class ChronicleDisplay < Qt::Object
8
+
9
+ # y:: the Y of this line in the graphics scene
10
+ # item:: the main item, either a free event or a task
11
+ # graphic_items:: the array of graphic items
12
+ # graphics_group:: a Qt::GraphicsGroup object holding all graphic objects for this line
13
+ Line = Struct.new :y, :item, :graphic_items, :graphic_group, :start_time
14
+ class Line
15
+ def add(graphic_item, time)
16
+ class << graphic_item; attr_accessor :time end
17
+ graphic_item.time = time
18
+ graphic_group.add_to_group graphic_item
19
+
20
+ if graphic_items.empty?
21
+ self.start_time = time
22
+ end
23
+ graphic_items << graphic_item
24
+ end
25
+ end
26
+
27
+ include DataDisplay
28
+ decoder PlanRebuilder
29
+
30
+ include TaskDisplaySupport
31
+
32
+ attr_reader :scene
33
+ attr_reader :ui
34
+
35
+ attr_reader :signalled_events
36
+ attr_reader :execution_events
37
+ attr_reader :graphic_stack
38
+ attr_reader :graphic_objects
39
+ attr_reader :last_event_graphics
40
+ attr_reader :time_scale
41
+
42
+ attr_predicate :display_follows_execution?, true
43
+ attr_predicate :display_follows_new_tasks?, true
44
+
45
+ def initialize
46
+ @scene = Qt::GraphicsScene.new
47
+ super()
48
+
49
+ @main = Qt::MainWindow.new
50
+ main.resize 500, 500
51
+ @ui = Ui::ChronicleView.new
52
+ ui.setupUi(self, main)
53
+ ui.graphics.scene = @scene
54
+
55
+ @signalled_events = []
56
+ @execution_events = []
57
+ @graphic_stack = []
58
+ @graphic_objects = Hash.new
59
+ @last_event_graphics = Hash.new
60
+ self.show_ownership = false
61
+
62
+ connect(ui.graphics.horizontalScrollBar, SIGNAL('valueChanged(int)'), self, SLOT('hscroll()'))
63
+ connect(ui.graphics.verticalScrollBar, SIGNAL('valueChanged(int)'), self, SLOT('vscroll()'))
64
+
65
+ @time_scale = 100.0
66
+ end
67
+
68
+ def time_scale=(new_value)
69
+ @time_scale = new_value
70
+
71
+ # For now, we don't relayout event labels
72
+ graphic_stack.each do |line_info|
73
+ base_x = time_to_display(line_info.start_time)
74
+
75
+ line_info.graphic_items.each do |g|
76
+ g.set_pos(time_to_display(g.time), g.pos.y)
77
+ end
78
+ end
79
+
80
+ # call update to update the task width
81
+ update
82
+ end
83
+
84
+ def vscroll(user = true)
85
+ if user
86
+ scrollbar = ui.graphics.verticalScrollBar
87
+ @display_follows_new_tasks = (scrollbar.maximum == scrollbar.value)
88
+ end
89
+ end
90
+ slots 'vscroll()'
91
+
92
+ def hscroll(user = true)
93
+ left_side = ui.graphics.mapToScene(0, 0).x
94
+
95
+ if user
96
+ scrollbar = ui.graphics.horizontalScrollBar
97
+ @display_follows_execution = (scrollbar.maximum == scrollbar.value)
98
+ end
99
+
100
+ graphic_stack.each do |line|
101
+ item = line.item
102
+ next unless item.kind_of?(Roby::Task::DRoby)
103
+
104
+ graphics = graphic_objects[item]
105
+ dx = graphics.pos.x - left_side
106
+ if dx <= 0
107
+ graphics.text.set_pos(-dx, graphics.text.pos.y)
108
+ else
109
+ graphics.text.set_pos(0, graphics.text.pos.y)
110
+ end
111
+ end
112
+ end
113
+ slots 'hscroll()'
114
+
115
+ def time_to_display(time)
116
+ (time - decoder.start_time) * time_scale
117
+ end
118
+
119
+ def create_line(item)
120
+ group = scene.create_item_group([])
121
+ graphic_stack << (new_line = Line.new(0, item, [], group))
122
+ new_line
123
+ end
124
+
125
+ def create_or_get_task(item, time)
126
+ unless g = graphic_objects[item]
127
+ pos_x = time_to_display(time)
128
+
129
+ g = graphic_objects[item] = item.display_create(self)
130
+ g.rect = Qt::RectF.new(0, 0, 0, Log::DEFAULT_TASK_HEIGHT)
131
+ g.move_by pos_x, 0
132
+ line = create_line(item)
133
+ line.add g, time
134
+ end
135
+ g
136
+ end
137
+
138
+ def line_of(object)
139
+ graphic_stack.each_with_index do |line, i|
140
+ return i if line.item == object
141
+ end
142
+ nil
143
+ end
144
+
145
+ def stream=(stream)
146
+ super
147
+
148
+ # Initialize the set of running tasks
149
+ update_prefixes_removal
150
+ decoder.tasks.each_key do |task|
151
+ if task.current_state == :started
152
+ create_or_get_task(task, decoder.time)
153
+ end
154
+ end
155
+ end
156
+
157
+
158
+ def append_event(task, event)
159
+ index = line_of(task)
160
+ create_or_get_item(event, index)
161
+ end
162
+
163
+ def update
164
+ update_prefixes_removal
165
+
166
+ execution_events.each do |flags, time, event|
167
+ graphics = event.display_create(self)
168
+ graphics.move_by time_to_display(time), 0
169
+ y_offset = Log::EVENT_CIRCLE_RADIUS + Log::TASK_EVENT_SPACING
170
+
171
+ if event.respond_to?(:task)
172
+ task_graphics = create_or_get_task(event.task, time)
173
+ line = line_of(event.task)
174
+
175
+ # Check that the event labels to not collide. If it is
176
+ # the case, move the current label at the bottom of the
177
+ # last label found
178
+ line_info = graphic_stack[line]
179
+ if line_info.graphic_items.size > 1
180
+ last_event = line_info.graphic_items[-1]
181
+ last_br = last_event.text.scene_bounding_rect
182
+ current_br = graphics.text.scene_bounding_rect
183
+ if last_br.right > current_br.left
184
+ if event.task.last_event[1] == event
185
+ last_event.text.hide
186
+ else
187
+ graphics.text.set_pos(0, last_br.bottom - last_event.scene_pos.y)
188
+ end
189
+ end
190
+ end
191
+
192
+ # Move the right edge of the task to reflect that it is
193
+ # still running. Then, make sure the rectangle can
194
+ # contain the event graphics
195
+ expected_height = graphics.text.bounding_rect.bottom + y_offset
196
+ if expected_height > task_graphics.rect.height
197
+ task_graphics.set_rect(0, 0, time_to_display(time) - time_to_display(line_info.start_time), expected_height)
198
+ task_graphics.text.set_pos(task_graphics.text.pos.x, expected_height)
199
+ end
200
+ event.task.last_event = [time, event]
201
+
202
+ elsif !(line = line_of(event))
203
+ group = create_line(event)
204
+ line = (graphic_stack.size - 1)
205
+ end
206
+
207
+ line_info = graphic_stack[line]
208
+ graphics.move_by 0, line_info.y + y_offset
209
+
210
+ # Try to handle too-near events gracefully
211
+ #old_flag, old_graphics = last_event_graphics[event]
212
+ #if old_flag
213
+ # flag = 2 if old_flag == 0 && flag == 1
214
+ # if old_graphics.text.bounding_rect.right > graphics.text.bounding_rect.left
215
+ # old_graphics.text.hide
216
+ # end
217
+ #end
218
+ #last_event_graphics[event] = [flag, graphics]
219
+
220
+ graphics.brush, graphics.pen = EventGeneratorDisplay.style(event, flags)
221
+ if flags & EVENT_EMITTED == 1
222
+ graphics.z_layer += 1
223
+ end
224
+ line_info.add graphics, time
225
+ end
226
+
227
+ removed_objects = (graphic_objects.keys - decoder.tasks.keys - decoder.events.keys)
228
+ removed_objects.each do |obj|
229
+ if line = line_of(obj)
230
+ graphic_objects.delete(obj)
231
+ scene.remove_item graphic_stack[line].graphic_group
232
+ graphic_stack.delete_at(line)
233
+ end
234
+ end
235
+
236
+ decoder.tasks.each_key do |task|
237
+ next unless task_graphics = graphic_objects[task]
238
+ line_info = graphic_stack[line_of(task)]
239
+
240
+ old_state = task.displayed_state
241
+ task.update_graphics(self, task_graphics)
242
+
243
+ state = task.current_state
244
+ rect = task_graphics.rect
245
+
246
+ last_time = if state == :success || state == :finished
247
+ task.last_event[0]
248
+ else decoder.time
249
+ end
250
+ task_graphics.set_rect(0, 0, time_to_display(last_time) - time_to_display(line_info.start_time), rect.height)
251
+ end
252
+
253
+ if display_follows_execution?
254
+ scrollbar = ui.graphics.horizontalScrollBar
255
+ scrollbar.value = scrollbar.maximum
256
+ hscroll(false)
257
+ end
258
+
259
+ if display_follows_new_tasks?
260
+ scrollbar = ui.graphics.verticalScrollBar
261
+ scrollbar.value = scrollbar.maximum
262
+ end
263
+
264
+ # layout lines
265
+ y = 0
266
+ graphic_stack.each do |line|
267
+ offset = y - line.y
268
+ if offset != 0
269
+ line.y = y
270
+ line.graphic_group.move_by 0, offset
271
+ end
272
+
273
+ br = line.graphic_group.bounding_rect | line.graphic_group.children_bounding_rect
274
+ y += br.bottom + Log::TASK_EVENT_SPACING
275
+ end
276
+
277
+ execution_events.clear
278
+ signalled_events.clear
279
+ end
280
+
281
+ def local_task(obj); decoder.local_task(obj) end
282
+ def local_event(obj); decoder.local_event(obj) end
283
+ def local_plan(obj); decoder.local_plan(obj) end
284
+ def local_object(obj); decoder.local_object(obj) end
285
+
286
+ def generator_called(time, generator, context)
287
+ execution_events << [EVENT_CALLED, time, local_event(generator)]
288
+ end
289
+ def generator_fired(time, generator, event_id, event_time, event_context)
290
+ generator = local_event(generator)
291
+ execution_events << [EVENT_EMITTED, event_time, generator]
292
+ end
293
+ def generator_signalling(time, flag, from, to, event_id, event_time, event_context)
294
+ signalled_events << [flag, local_event(from), local_event(to), event_id]
295
+ end
296
+ def generator_forwarding(time, flag, from, to, event_id, event_time, event_context)
297
+ signalled_events << [flag, local_event(from), local_event(to), event_id]
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+
@@ -0,0 +1,72 @@
1
+ require 'utilrb/time/to_hms'
2
+ require 'roby/log/logger'
3
+
4
+ module Roby::Log
5
+ # A logger object which dumps events in a human-readable form to an IO object.
6
+ class ConsoleLogger
7
+ def splat?; false end
8
+ def self.filter_names(name)
9
+ name.gsub(/Roby::(?:Genom::)?/, '')
10
+ end
11
+ # Name of an event generator source
12
+ def self.gen_source(gen)
13
+ if gen.respond_to?(:task) then gen.task.name
14
+ else 'toplevel'
15
+ end
16
+ end
17
+ # Human readable name for event generators
18
+ def self.gen_name(gen)
19
+ if gen.respond_to?(:symbol) then "[#{gen.symbol}]"
20
+ else gen.name
21
+ end
22
+ end
23
+
24
+ attr_reader :io, :columns
25
+ def initialize(io)
26
+ @io = io
27
+ @columns = Hash.new { |h, k| h[k] = Array.new }
28
+ end
29
+
30
+ def arg_to_s(arg)
31
+ case arg
32
+ when Time then Time.at(arg - @reftime).to_hms
33
+ when Array then arg.map(&method(:arg_to_s)).to_s
34
+ when Hash then arg.map { |k, v| [arg_to_s(k), arg_to_s(v)].join(" => ") }.to_s
35
+ else arg.to_s
36
+ end
37
+ end
38
+
39
+
40
+ def display(m, time, *args) # :nodoc:
41
+ @reftime ||= time
42
+
43
+ args.map! { |a| arg_to_s(a) }
44
+ args.map!(&ConsoleLogger.method(:filter_names))
45
+ args.unshift(m).
46
+ unshift(Time.at(time - @reftime).to_hms)
47
+
48
+ columns = self.columns[m]
49
+ args.each_with_index do |str, i|
50
+ str = str.to_s
51
+ if !columns[i] || (str.length > columns[i])
52
+ columns[i] = str.length
53
+ end
54
+ end
55
+
56
+ args.each_with_index do |arg, i|
57
+ w = columns[i]
58
+ io << ("%-#{w}s " % arg)
59
+ end
60
+ io << "\n"
61
+ rescue
62
+ STDERR.puts "#{time} #{m} #{args}"
63
+ raise
64
+ end
65
+ private :display
66
+
67
+ Roby::Log.each_hook do |klass, m|
68
+ define_method(m) { |args| display(m, *args) }
69
+ end
70
+ end
71
+ end
72
+
@@ -0,0 +1,197 @@
1
+ require 'roby/log'
2
+ module Roby::Log
3
+ # == Displaying log data
4
+ #
5
+ # Data display is done in three objects:
6
+ # * a DataStream object which is the data source itself. It gives
7
+ # information about available samples, time of samples and extracts raw
8
+ # data. An example of data stream is the EventStream object which reads
9
+ # Roby's event logs, returning one cycle worth of data at a time.
10
+ # * a DataDecoder object which takes the raw data returned by a DataStream
11
+ # object and turns it into a more usable representation. For instance, the PlanBuilder
12
+ # decoder takes an event stream from an EventStream object and rebuilds a plan-like
13
+ # structure from it.
14
+ # * a display which takes its information from the decoder. The RelationDisplay displays
15
+ # the information included in the PlanRebuilder decoder and displays it as a graph.
16
+ class DataStream
17
+ # The stream ID, which has to be unique on a single Roby core
18
+ attr_reader :id
19
+ # The stream name. A [name, type] has to be globally unique
20
+ attr_reader :name
21
+ # The stream type, as a string.
22
+ attr_reader :type
23
+
24
+ def self.open(basename)
25
+ stream = new(basename)
26
+ stream.open
27
+
28
+ if block_given?
29
+ begin
30
+ yield(stream)
31
+ ensure
32
+ stream.logfile.close
33
+ end
34
+ else
35
+ stream
36
+ end
37
+ end
38
+
39
+
40
+ def initialize(name, type)
41
+ @id = object_id
42
+ @name = name
43
+ @type = type
44
+ @range = [nil, nil]
45
+
46
+ @decoders = []
47
+ end
48
+
49
+ def to_s; "#{name} [#{type}]" end
50
+ def open; end
51
+ def close; end
52
+
53
+ def has_sample?; false end
54
+ attr_predicate :reinit, true
55
+ def reinit?; end
56
+ def reinit!
57
+ @range = [nil, nil]
58
+ @reinit = false
59
+
60
+ clear
61
+ end
62
+ def read_all; end
63
+
64
+ def read_and_decode
65
+ self.class.decode(read)
66
+ end
67
+
68
+ # The [min, max] range of available samples. Initially
69
+ # [nil, nil]
70
+ attr_reader :range
71
+
72
+ # The set of decoders attached to this stream
73
+ attr_reader :decoders
74
+
75
+ def clear
76
+ decoders.each { |dec| dec.clear }
77
+ end
78
+
79
+ # True if there is at least one display attached to this data stream
80
+ def displayed?
81
+ decoders.any? do |dec|
82
+ !dec.displays.empty?
83
+ end
84
+ end
85
+
86
+ # Reuse or creates a decoder of the given class for this data
87
+ # stream
88
+ def decoder(klass)
89
+ if dec = decoders.find { |d| d.kind_of?(klass) }
90
+ dec
91
+ else
92
+ decoders << (dec = klass.new(name))
93
+ dec.stream = self
94
+ added_decoder(dec)
95
+ dec
96
+ end
97
+ end
98
+
99
+ def added_decoder(dec)
100
+ super if defined? super
101
+ end
102
+
103
+ # Do a read - decode - feed cycle
104
+ def advance
105
+ data = decode(read)
106
+ decoders.each do |dec|
107
+ dec.process(data)
108
+ end
109
+ end
110
+
111
+ def init(data)
112
+ self.class.init(data)
113
+ end
114
+ def decode(data)
115
+ self.class.decode(data)
116
+ end
117
+
118
+ def clear_integrated
119
+ decoders.each do |decoder|
120
+ decoder.clear_integrated
121
+ end
122
+ end
123
+
124
+ # Update the displays
125
+ def display
126
+ decoders.each do |decoder|
127
+ decoder.display
128
+ end
129
+ end
130
+
131
+ def ==(other)
132
+ other.kind_of?(DataStream) &&
133
+ name == other.name &&
134
+ type == other.type
135
+ end
136
+ def eql?(other); self == other end
137
+ def hash; [name, type].hash end
138
+ end
139
+
140
+ class DataDecoder
141
+ # The set of displays attached to this decoder
142
+ attr_reader :displays
143
+ attr_reader :name
144
+ attr_accessor :stream
145
+
146
+ def initialize(name)
147
+ @name = name
148
+ @displays = []
149
+ end
150
+
151
+ def clear
152
+ displays.each { |d| d.clear }
153
+ end
154
+
155
+ def clear_integrated
156
+ displays.each do |display|
157
+ display.clear_integrated if display.respond_to?(:clear_integrated)
158
+ end
159
+ end
160
+
161
+ # Update the display to the current state of the decoder
162
+ def display
163
+ displays.each do |display|
164
+ display.update
165
+ end
166
+ end
167
+ end
168
+
169
+ module DataDisplay
170
+ module ClassExtension
171
+ def decoder(new_type = nil)
172
+ if new_type
173
+ @decoder_class = new_type
174
+ else
175
+ @decoder_class
176
+ end
177
+ end
178
+ end
179
+
180
+ attr_reader :decoder
181
+ attr_reader :main
182
+ attr_accessor :config_ui
183
+ def splat?; true end
184
+
185
+ def stream=(data_stream)
186
+ if decoder
187
+ clear
188
+ end
189
+
190
+ @decoder = data_stream.decoder(self.class.decoder)
191
+ decoder.displays << self
192
+ end
193
+
194
+ def clear; end
195
+ end
196
+ end
197
+