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.
- data/.gitignore +29 -0
- data/History.txt +4 -0
- data/License-fr.txt +519 -0
- data/License.txt +515 -0
- data/Manifest.txt +245 -0
- data/NOTES +4 -0
- data/README.txt +163 -0
- data/Rakefile +161 -0
- data/TODO.txt +146 -0
- data/app/README.txt +24 -0
- data/app/Rakefile +8 -0
- data/app/config/ROBOT.rb +5 -0
- data/app/config/app.yml +91 -0
- data/app/config/init.rb +7 -0
- data/app/config/roby.yml +3 -0
- data/app/controllers/.gitattributes +0 -0
- data/app/controllers/ROBOT.rb +2 -0
- data/app/data/.gitattributes +0 -0
- data/app/planners/ROBOT/main.rb +6 -0
- data/app/planners/main.rb +5 -0
- data/app/scripts/distributed +3 -0
- data/app/scripts/generate/bookmarks +3 -0
- data/app/scripts/replay +3 -0
- data/app/scripts/results +3 -0
- data/app/scripts/run +3 -0
- data/app/scripts/server +3 -0
- data/app/scripts/shell +3 -0
- data/app/scripts/test +3 -0
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby +210 -0
- data/bin/roby-log +168 -0
- data/bin/roby-shell +25 -0
- data/doc/images/event_generalization.png +0 -0
- data/doc/images/exception_propagation_1.png +0 -0
- data/doc/images/exception_propagation_2.png +0 -0
- data/doc/images/exception_propagation_3.png +0 -0
- data/doc/images/exception_propagation_4.png +0 -0
- data/doc/images/exception_propagation_5.png +0 -0
- data/doc/images/replay_handler_error.png +0 -0
- data/doc/images/replay_handler_error_0.png +0 -0
- data/doc/images/replay_handler_error_1.png +0 -0
- data/doc/images/roby_cycle_overview.png +0 -0
- data/doc/images/roby_replay_02.png +0 -0
- data/doc/images/roby_replay_03.png +0 -0
- data/doc/images/roby_replay_04.png +0 -0
- data/doc/images/roby_replay_event_representation.png +0 -0
- data/doc/images/roby_replay_first_state.png +0 -0
- data/doc/images/roby_replay_relations.png +0 -0
- data/doc/images/roby_replay_startup.png +0 -0
- data/doc/images/task_event_generalization.png +0 -0
- data/doc/papers.rdoc +11 -0
- data/doc/styles/allison.css +314 -0
- data/doc/styles/allison.js +316 -0
- data/doc/styles/allison.rb +276 -0
- data/doc/styles/jamis.rb +593 -0
- data/doc/tutorials/01-GettingStarted.rdoc +86 -0
- data/doc/tutorials/02-GoForward.rdoc +220 -0
- data/doc/tutorials/03-PlannedPath.rdoc +268 -0
- data/doc/tutorials/04-EventPropagation.rdoc +236 -0
- data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
- data/doc/tutorials/06-Overview.rdoc +40 -0
- data/doc/videos.rdoc +69 -0
- data/ext/droby/dump.cc +175 -0
- data/ext/droby/extconf.rb +3 -0
- data/ext/graph/algorithm.cc +746 -0
- data/ext/graph/extconf.rb +7 -0
- data/ext/graph/graph.cc +529 -0
- data/ext/graph/graph.hh +183 -0
- data/ext/graph/iterator_sequence.hh +102 -0
- data/ext/graph/undirected_dfs.hh +226 -0
- data/ext/graph/undirected_graph.hh +421 -0
- data/lib/roby.rb +41 -0
- data/lib/roby/app.rb +870 -0
- data/lib/roby/app/rake.rb +56 -0
- data/lib/roby/app/run.rb +14 -0
- data/lib/roby/app/scripts/distributed.rb +13 -0
- data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
- data/lib/roby/app/scripts/replay.rb +31 -0
- data/lib/roby/app/scripts/results.rb +15 -0
- data/lib/roby/app/scripts/run.rb +26 -0
- data/lib/roby/app/scripts/server.rb +18 -0
- data/lib/roby/app/scripts/shell.rb +88 -0
- data/lib/roby/app/scripts/test.rb +40 -0
- data/lib/roby/basic_object.rb +151 -0
- data/lib/roby/config.rb +5 -0
- data/lib/roby/control.rb +747 -0
- data/lib/roby/decision_control.rb +17 -0
- data/lib/roby/distributed.rb +32 -0
- data/lib/roby/distributed/base.rb +440 -0
- data/lib/roby/distributed/communication.rb +871 -0
- data/lib/roby/distributed/connection_space.rb +592 -0
- data/lib/roby/distributed/distributed_object.rb +206 -0
- data/lib/roby/distributed/drb.rb +62 -0
- data/lib/roby/distributed/notifications.rb +539 -0
- data/lib/roby/distributed/peer.rb +550 -0
- data/lib/roby/distributed/protocol.rb +529 -0
- data/lib/roby/distributed/proxy.rb +343 -0
- data/lib/roby/distributed/subscription.rb +311 -0
- data/lib/roby/distributed/transaction.rb +498 -0
- data/lib/roby/event.rb +897 -0
- data/lib/roby/exceptions.rb +234 -0
- data/lib/roby/executives/simple.rb +30 -0
- data/lib/roby/graph.rb +166 -0
- data/lib/roby/interface.rb +390 -0
- data/lib/roby/log.rb +3 -0
- data/lib/roby/log/chronicle.rb +303 -0
- data/lib/roby/log/console.rb +72 -0
- data/lib/roby/log/data_stream.rb +197 -0
- data/lib/roby/log/dot.rb +279 -0
- data/lib/roby/log/event_stream.rb +151 -0
- data/lib/roby/log/file.rb +340 -0
- data/lib/roby/log/gui/basic_display.ui +83 -0
- data/lib/roby/log/gui/chronicle.rb +26 -0
- data/lib/roby/log/gui/chronicle_view.rb +40 -0
- data/lib/roby/log/gui/chronicle_view.ui +70 -0
- data/lib/roby/log/gui/data_displays.rb +172 -0
- data/lib/roby/log/gui/data_displays.ui +155 -0
- data/lib/roby/log/gui/notifications.rb +26 -0
- data/lib/roby/log/gui/relations.rb +248 -0
- data/lib/roby/log/gui/relations.ui +123 -0
- data/lib/roby/log/gui/relations_view.rb +185 -0
- data/lib/roby/log/gui/relations_view.ui +149 -0
- data/lib/roby/log/gui/replay.rb +327 -0
- data/lib/roby/log/gui/replay_controls.rb +200 -0
- data/lib/roby/log/gui/replay_controls.ui +259 -0
- data/lib/roby/log/gui/runtime.rb +130 -0
- data/lib/roby/log/hooks.rb +185 -0
- data/lib/roby/log/logger.rb +202 -0
- data/lib/roby/log/notifications.rb +244 -0
- data/lib/roby/log/plan_rebuilder.rb +470 -0
- data/lib/roby/log/relations.rb +1056 -0
- data/lib/roby/log/server.rb +550 -0
- data/lib/roby/log/sqlite.rb +47 -0
- data/lib/roby/log/timings.rb +164 -0
- data/lib/roby/plan-object.rb +247 -0
- data/lib/roby/plan.rb +762 -0
- data/lib/roby/planning.rb +13 -0
- data/lib/roby/planning/loops.rb +302 -0
- data/lib/roby/planning/model.rb +906 -0
- data/lib/roby/planning/task.rb +151 -0
- data/lib/roby/propagation.rb +562 -0
- data/lib/roby/query.rb +619 -0
- data/lib/roby/relations.rb +583 -0
- data/lib/roby/relations/conflicts.rb +70 -0
- data/lib/roby/relations/ensured.rb +20 -0
- data/lib/roby/relations/error_handling.rb +23 -0
- data/lib/roby/relations/events.rb +9 -0
- data/lib/roby/relations/executed_by.rb +193 -0
- data/lib/roby/relations/hierarchy.rb +239 -0
- data/lib/roby/relations/influence.rb +10 -0
- data/lib/roby/relations/planned_by.rb +63 -0
- data/lib/roby/robot.rb +7 -0
- data/lib/roby/standard_errors.rb +218 -0
- data/lib/roby/state.rb +5 -0
- data/lib/roby/state/events.rb +221 -0
- data/lib/roby/state/information.rb +55 -0
- data/lib/roby/state/pos.rb +110 -0
- data/lib/roby/state/shapes.rb +32 -0
- data/lib/roby/state/state.rb +353 -0
- data/lib/roby/support.rb +92 -0
- data/lib/roby/task-operations.rb +182 -0
- data/lib/roby/task.rb +1618 -0
- data/lib/roby/test/common.rb +399 -0
- data/lib/roby/test/distributed.rb +214 -0
- data/lib/roby/test/tasks/empty_task.rb +9 -0
- data/lib/roby/test/tasks/goto.rb +36 -0
- data/lib/roby/test/tasks/simple_task.rb +23 -0
- data/lib/roby/test/testcase.rb +519 -0
- data/lib/roby/test/tools.rb +160 -0
- data/lib/roby/thread_task.rb +87 -0
- data/lib/roby/transactions.rb +462 -0
- data/lib/roby/transactions/proxy.rb +292 -0
- data/lib/roby/transactions/updates.rb +139 -0
- data/plugins/fault_injection/History.txt +4 -0
- data/plugins/fault_injection/README.txt +37 -0
- data/plugins/fault_injection/Rakefile +18 -0
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +52 -0
- data/plugins/fault_injection/fault_injection.rb +89 -0
- data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
- data/plugins/subsystems/README.txt +40 -0
- data/plugins/subsystems/Rakefile +18 -0
- data/plugins/subsystems/app.rb +171 -0
- data/plugins/subsystems/test/app/README +24 -0
- data/plugins/subsystems/test/app/Rakefile +8 -0
- data/plugins/subsystems/test/app/config/app.yml +71 -0
- data/plugins/subsystems/test/app/config/init.rb +9 -0
- data/plugins/subsystems/test/app/config/roby.yml +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +20 -0
- data/plugins/subsystems/test/app/scripts/distributed +3 -0
- data/plugins/subsystems/test/app/scripts/replay +3 -0
- data/plugins/subsystems/test/app/scripts/results +3 -0
- data/plugins/subsystems/test/app/scripts/run +3 -0
- data/plugins/subsystems/test/app/scripts/server +3 -0
- data/plugins/subsystems/test/app/scripts/shell +3 -0
- data/plugins/subsystems/test/app/scripts/test +3 -0
- data/plugins/subsystems/test/app/tasks/services.rb +15 -0
- data/plugins/subsystems/test/test_subsystems.rb +71 -0
- data/test/distributed/test_communication.rb +178 -0
- data/test/distributed/test_connection.rb +282 -0
- data/test/distributed/test_execution.rb +373 -0
- data/test/distributed/test_mixed_plan.rb +341 -0
- data/test/distributed/test_plan_notifications.rb +238 -0
- data/test/distributed/test_protocol.rb +516 -0
- data/test/distributed/test_query.rb +102 -0
- data/test/distributed/test_remote_plan.rb +491 -0
- data/test/distributed/test_transaction.rb +463 -0
- data/test/mockups/tasks.rb +27 -0
- data/test/planning/test_loops.rb +380 -0
- data/test/planning/test_model.rb +427 -0
- data/test/planning/test_task.rb +106 -0
- data/test/relations/test_conflicts.rb +42 -0
- data/test/relations/test_ensured.rb +38 -0
- data/test/relations/test_executed_by.rb +149 -0
- data/test/relations/test_hierarchy.rb +158 -0
- data/test/relations/test_planned_by.rb +54 -0
- data/test/suite_core.rb +24 -0
- data/test/suite_distributed.rb +9 -0
- data/test/suite_planning.rb +3 -0
- data/test/suite_relations.rb +8 -0
- data/test/test_bgl.rb +508 -0
- data/test/test_control.rb +399 -0
- data/test/test_event.rb +894 -0
- data/test/test_exceptions.rb +592 -0
- data/test/test_interface.rb +37 -0
- data/test/test_log.rb +114 -0
- data/test/test_log_server.rb +132 -0
- data/test/test_plan.rb +584 -0
- data/test/test_propagation.rb +210 -0
- data/test/test_query.rb +266 -0
- data/test/test_relations.rb +180 -0
- data/test/test_state.rb +414 -0
- data/test/test_support.rb +16 -0
- data/test/test_task.rb +938 -0
- data/test/test_testcase.rb +122 -0
- data/test/test_thread_task.rb +73 -0
- data/test/test_transactions.rb +569 -0
- data/test/test_transactions_proxy.rb +198 -0
- metadata +570 -0
data/lib/roby/log.rb
ADDED
|
@@ -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
|
+
|