roby 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -5
- data/Manifest.txt +91 -16
- data/README.txt +24 -24
- data/Rakefile +92 -64
- data/app/config/app.yml +42 -43
- data/app/config/init.rb +26 -0
- data/benchmark/alloc_misc.rb +123 -0
- data/benchmark/discovery_latency.rb +67 -0
- data/benchmark/garbage_collection.rb +48 -0
- data/benchmark/genom.rb +31 -0
- data/benchmark/transactions.rb +62 -0
- data/bin/roby +1 -1
- data/bin/roby-log +16 -6
- data/doc/guide/.gitignore +2 -0
- data/doc/guide/config.yaml +34 -0
- data/doc/guide/ext/init.rb +14 -0
- data/doc/guide/ext/previous_next.rb +40 -0
- data/doc/guide/ext/rdoc_links.rb +33 -0
- data/doc/guide/index.rdoc +16 -0
- data/doc/guide/overview.rdoc +62 -0
- data/doc/guide/plan_modifications.rdoc +67 -0
- data/doc/guide/src/abstraction/achieve_with.page +8 -0
- data/doc/guide/src/abstraction/forwarding.page +8 -0
- data/doc/guide/src/abstraction/hierarchy.page +19 -0
- data/doc/guide/src/abstraction/index.page +28 -0
- data/doc/guide/src/abstraction/task_models.page +13 -0
- data/doc/guide/src/basics.template +6 -0
- data/doc/guide/src/basics/app.page +139 -0
- data/doc/guide/src/basics/code_examples.page +33 -0
- data/doc/guide/src/basics/dry.page +69 -0
- data/doc/guide/src/basics/errors.page +443 -0
- data/doc/guide/src/basics/events.page +179 -0
- data/doc/guide/src/basics/hierarchy.page +275 -0
- data/doc/guide/src/basics/index.page +11 -0
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/basics/plan_objects.page +71 -0
- data/doc/guide/src/basics/relations_display.page +203 -0
- data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
- data/doc/guide/src/basics/shell.page +102 -0
- data/doc/guide/src/basics/summary.page +32 -0
- data/doc/guide/src/basics/tasks.page +357 -0
- data/doc/guide/src/basics_shell_header.txt +16 -0
- data/doc/guide/src/cycle/cycle-overview.png +0 -0
- data/doc/guide/src/cycle/cycle-overview.svg +208 -0
- data/doc/guide/src/cycle/error_handling.page +168 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
- data/doc/guide/src/cycle/garbage_collection.page +10 -0
- data/doc/guide/src/cycle/index.page +23 -0
- data/doc/guide/src/cycle/propagation.page +154 -0
- data/doc/guide/src/cycle/propagation_diamond.png +0 -0
- data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
- data/doc/guide/src/default.css +319 -0
- data/doc/guide/src/default.template +74 -0
- data/doc/guide/src/htmldoc.metainfo +20 -0
- data/doc/guide/src/htmldoc.virtual +18 -0
- data/doc/guide/src/images/bodybg.png +0 -0
- data/doc/guide/src/images/contbg.png +0 -0
- data/doc/guide/src/images/footerbg.png +0 -0
- data/doc/guide/src/images/gradient1.png +0 -0
- data/doc/guide/src/images/gradient2.png +0 -0
- data/doc/guide/src/index.page +7 -0
- data/doc/guide/src/introduction/index.page +29 -0
- data/doc/guide/src/introduction/install.page +133 -0
- data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
- data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
- data/doc/guide/src/plugins/fault_tolerance.page +44 -0
- data/doc/guide/src/plugins/index.page +11 -0
- data/doc/guide/src/plugins/subsystems.page +45 -0
- data/doc/guide/src/relations/dependency.page +89 -0
- data/doc/guide/src/relations/index.page +12 -0
- data/doc/misc/update_github +24 -0
- data/doc/tutorials/02-GoForward.rdoc +3 -3
- data/ext/graph/graph.cc +46 -0
- data/lib/roby.rb +57 -22
- data/lib/roby/app.rb +132 -112
- data/lib/roby/app/plugins/rake.rb +21 -0
- data/lib/roby/app/rake.rb +0 -7
- data/lib/roby/app/run.rb +1 -1
- data/lib/roby/app/scripts/distributed.rb +1 -2
- data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
- data/lib/roby/app/scripts/results.rb +2 -1
- data/lib/roby/app/scripts/run.rb +6 -2
- data/lib/roby/app/scripts/shell.rb +11 -11
- data/lib/roby/config.rb +1 -1
- data/lib/roby/decision_control.rb +62 -3
- data/lib/roby/distributed.rb +4 -0
- data/lib/roby/distributed/base.rb +8 -0
- data/lib/roby/distributed/communication.rb +12 -8
- data/lib/roby/distributed/connection_space.rb +61 -44
- data/lib/roby/distributed/distributed_object.rb +1 -1
- data/lib/roby/distributed/notifications.rb +22 -30
- data/lib/roby/distributed/peer.rb +13 -8
- data/lib/roby/distributed/proxy.rb +5 -5
- data/lib/roby/distributed/subscription.rb +4 -4
- data/lib/roby/distributed/transaction.rb +3 -3
- data/lib/roby/event.rb +176 -110
- data/lib/roby/exceptions.rb +12 -4
- data/lib/roby/execution_engine.rb +1604 -0
- data/lib/roby/external_process_task.rb +225 -0
- data/lib/roby/graph.rb +0 -6
- data/lib/roby/interface.rb +221 -137
- data/lib/roby/log/console.rb +5 -3
- data/lib/roby/log/data_stream.rb +94 -16
- data/lib/roby/log/dot.rb +8 -8
- data/lib/roby/log/event_stream.rb +13 -3
- data/lib/roby/log/file.rb +43 -18
- data/lib/roby/log/gui/basic_display_ui.rb +89 -0
- data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
- data/lib/roby/log/gui/data_displays.rb +4 -5
- data/lib/roby/log/gui/data_displays_ui.rb +146 -0
- data/lib/roby/log/gui/relations.rb +18 -18
- data/lib/roby/log/gui/relations_ui.rb +120 -0
- data/lib/roby/log/gui/relations_view_ui.rb +144 -0
- data/lib/roby/log/gui/replay.rb +41 -13
- data/lib/roby/log/gui/replay_controls.rb +3 -0
- data/lib/roby/log/gui/replay_controls.ui +133 -110
- data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
- data/lib/roby/log/hooks.rb +19 -18
- data/lib/roby/log/logger.rb +7 -6
- data/lib/roby/log/notifications.rb +4 -4
- data/lib/roby/log/plan_rebuilder.rb +20 -22
- data/lib/roby/log/relations.rb +44 -16
- data/lib/roby/log/server.rb +1 -4
- data/lib/roby/log/timings.rb +88 -19
- data/lib/roby/plan-object.rb +135 -11
- data/lib/roby/plan.rb +408 -224
- data/lib/roby/planning/loops.rb +32 -25
- data/lib/roby/planning/model.rb +157 -51
- data/lib/roby/planning/task.rb +47 -20
- data/lib/roby/query.rb +128 -92
- data/lib/roby/relations.rb +254 -136
- data/lib/roby/relations/conflicts.rb +6 -9
- data/lib/roby/relations/dependency.rb +358 -0
- data/lib/roby/relations/ensured.rb +0 -1
- data/lib/roby/relations/error_handling.rb +0 -1
- data/lib/roby/relations/events.rb +0 -2
- data/lib/roby/relations/executed_by.rb +26 -11
- data/lib/roby/relations/planned_by.rb +14 -14
- data/lib/roby/robot.rb +46 -0
- data/lib/roby/schedulers/basic.rb +34 -0
- data/lib/roby/standalone.rb +4 -0
- data/lib/roby/standard_errors.rb +21 -15
- data/lib/roby/state/events.rb +5 -4
- data/lib/roby/support.rb +107 -6
- data/lib/roby/task-operations.rb +23 -19
- data/lib/roby/task.rb +522 -148
- data/lib/roby/task_index.rb +80 -0
- data/lib/roby/test/common.rb +283 -44
- data/lib/roby/test/distributed.rb +53 -37
- data/lib/roby/test/testcase.rb +9 -204
- data/lib/roby/test/tools.rb +3 -3
- data/lib/roby/transactions.rb +154 -111
- data/lib/roby/transactions/proxy.rb +40 -7
- data/manifest.xml +20 -0
- data/plugins/fault_injection/README.txt +0 -3
- data/plugins/fault_injection/Rakefile +2 -8
- data/plugins/fault_injection/app.rb +1 -1
- data/plugins/fault_injection/fault_injection.rb +3 -3
- data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
- data/plugins/subsystems/README.txt +0 -3
- data/plugins/subsystems/Rakefile +2 -7
- data/plugins/subsystems/app.rb +27 -16
- data/plugins/subsystems/test/app/config/init.rb +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +1 -1
- data/plugins/subsystems/test/app/tasks/services.rb +1 -1
- data/plugins/subsystems/test/test_subsystems.rb +23 -16
- data/test/distributed/test_communication.rb +32 -15
- data/test/distributed/test_connection.rb +28 -26
- data/test/distributed/test_execution.rb +59 -54
- data/test/distributed/test_mixed_plan.rb +34 -34
- data/test/distributed/test_plan_notifications.rb +26 -26
- data/test/distributed/test_protocol.rb +57 -48
- data/test/distributed/test_query.rb +11 -7
- data/test/distributed/test_remote_plan.rb +71 -71
- data/test/distributed/test_transaction.rb +50 -47
- data/test/mockups/external_process +28 -0
- data/test/planning/test_loops.rb +163 -119
- data/test/planning/test_model.rb +3 -3
- data/test/planning/test_task.rb +27 -7
- data/test/relations/test_conflicts.rb +3 -3
- data/test/relations/test_dependency.rb +324 -0
- data/test/relations/test_ensured.rb +2 -2
- data/test/relations/test_executed_by.rb +94 -19
- data/test/relations/test_planned_by.rb +11 -9
- data/test/suite_core.rb +6 -3
- data/test/suite_distributed.rb +1 -0
- data/test/suite_planning.rb +1 -0
- data/test/suite_relations.rb +2 -2
- data/test/tasks/test_external_process.rb +126 -0
- data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
- data/test/test_bgl.rb +21 -1
- data/test/test_event.rb +229 -155
- data/test/test_exceptions.rb +79 -80
- data/test/test_execution_engine.rb +987 -0
- data/test/test_gui.rb +1 -1
- data/test/test_interface.rb +11 -5
- data/test/test_log.rb +18 -7
- data/test/test_log_server.rb +1 -0
- data/test/test_plan.rb +229 -395
- data/test/test_query.rb +193 -35
- data/test/test_relations.rb +88 -8
- data/test/test_state.rb +55 -37
- data/test/test_support.rb +1 -1
- data/test/test_task.rb +371 -218
- data/test/test_testcase.rb +32 -16
- data/test/test_transactions.rb +211 -170
- data/test/test_transactions_proxy.rb +37 -19
- metadata +169 -71
- data/.gitignore +0 -29
- data/doc/styles/allison.css +0 -314
- data/doc/styles/allison.js +0 -316
- data/doc/styles/allison.rb +0 -276
- data/doc/styles/jamis.rb +0 -593
- data/lib/roby/control.rb +0 -746
- data/lib/roby/executives/simple.rb +0 -30
- data/lib/roby/propagation.rb +0 -562
- data/lib/roby/relations/hierarchy.rb +0 -239
- data/lib/roby/transactions/updates.rb +0 -139
- data/test/relations/test_hierarchy.rb +0 -158
- data/test/test_control.rb +0 -399
- data/test/test_propagation.rb +0 -210
@@ -0,0 +1,357 @@
|
|
1
|
+
---
|
2
|
+
title: Tasks
|
3
|
+
sort_info: 200
|
4
|
+
--- pipeline:tags,markdown,blocks
|
5
|
+
{include_file: {filename: src/basics_shell_header.txt, escape_html: false}}
|
6
|
+
|
7
|
+
Definition of Tasks
|
8
|
+
-------------------
|
9
|
+
|
10
|
+
Unlike with event objects, which are usually created and parametrized on-the-fly, tasks are mostly first _defined_ and then _used_. To define a task, one creates a subclass of Roby::Task. In our examples, we'll take "the mother of all tasks in robotic systems": the MoveTo task.
|
11
|
+
|
12
|
+
{coderay:: ruby}
|
13
|
+
class MoveTo < Roby::Task
|
14
|
+
...
|
15
|
+
end
|
16
|
+
{coderay}
|
17
|
+
|
18
|
+
Then, to use it, one would do:
|
19
|
+
{coderay:: ruby}
|
20
|
+
plan.add(task = MoveTo.new)
|
21
|
+
{coderay}
|
22
|
+
|
23
|
+
As for events, the task must be included in a plan to be usable, which is done
|
24
|
+
by calling plan.add(). Don't forget that !
|
25
|
+
|
26
|
+
Parametrization
|
27
|
+
---------------
|
28
|
+
|
29
|
+
Obviously, a plain MoveTo task is nothing if the system does not know *where* to go to ... That is called parametrization and has to be declared in the task definition, using Task.argument
|
30
|
+
{coderay:: ruby}
|
31
|
+
>> class MoveTo < Roby::Task
|
32
|
+
?> argument :x
|
33
|
+
?> argument :y
|
34
|
+
>> end
|
35
|
+
{coderay}
|
36
|
+
|
37
|
+
Then, the arguments are provided at instanciation through an argument hash:
|
38
|
+
|
39
|
+
{coderay:: ruby}
|
40
|
+
>> task = MoveTo.new :x => 10, :y => 20
|
41
|
+
>> task.x
|
42
|
+
=> 10
|
43
|
+
>> task.y
|
44
|
+
=> 20
|
45
|
+
{coderay}
|
46
|
+
|
47
|
+
A task instance (i.e. the result of TaskClass.new) will *not* be usable unless
|
48
|
+
you initialize all its arguments. Such a task is called _partially
|
49
|
+
instanciated_:
|
50
|
+
|
51
|
+
{coderay:: ruby}
|
52
|
+
>> task = MoveTo.new
|
53
|
+
>> task.partially_instanciated?
|
54
|
+
=> true
|
55
|
+
>> task = MoveTo.new(:x => 10, :y => 10)
|
56
|
+
>> task.partially_instanciated?
|
57
|
+
=> false
|
58
|
+
{coderay}
|
59
|
+
|
60
|
+
Of course, it is possible to set default arguments by defining a #initialize
|
61
|
+
method (like with all Ruby classes)
|
62
|
+
{coderay:: ruby}
|
63
|
+
>> class MoveTo
|
64
|
+
?> argument :max_speed
|
65
|
+
?> def initialize(arguments)
|
66
|
+
?> arguments[:max_speed] ||= 1
|
67
|
+
?> super(arguments)
|
68
|
+
?> end
|
69
|
+
?> end
|
70
|
+
>> task = MoveTo.new(:x => 10, :y => 20)
|
71
|
+
>> task.max_speed
|
72
|
+
=> 1
|
73
|
+
>> task.partially_instanciated?
|
74
|
+
=> false
|
75
|
+
{coderay}
|
76
|
+
|
77
|
+
Task control and monitoring: defining events
|
78
|
+
--------------------------------------------
|
79
|
+
|
80
|
+
In Roby, tasks are a __collection of events__. Now that you know the basics
|
81
|
+
about events, the purpose of those events should be clear:
|
82
|
+
|
83
|
+
* the controllable events allow to change the process' behaviour (the obvious
|
84
|
+
one being "start" which allows to start the task)
|
85
|
+
* both contingent and controllable events allow to monitor the task's execution.
|
86
|
+
|
87
|
+
The basic task already defines four events:
|
88
|
+
* the *start* event
|
89
|
+
* the *stop* event
|
90
|
+
* the *success* event
|
91
|
+
* and finally the *failed* event
|
92
|
+
|
93
|
+
In the class definition, events are defined using Task#event. To define a
|
94
|
+
controllable event, simply associate a block. First, copy/paste the following code in a
|
95
|
+
my\_task.rb file.
|
96
|
+
|
97
|
+
{coderay:: ruby}
|
98
|
+
class MyTask < Roby::Task
|
99
|
+
event :start do
|
100
|
+
puts "start event called"
|
101
|
+
emit :start
|
102
|
+
end
|
103
|
+
event :controlable do
|
104
|
+
puts "controlable event called"
|
105
|
+
emit :controlable
|
106
|
+
end
|
107
|
+
event :contingent
|
108
|
+
|
109
|
+
on(:start) { puts "start event emitted" }
|
110
|
+
on(:controlable) { puts "controlable event emitted" }
|
111
|
+
on(:contingent) { puts "contingent event emitted" }
|
112
|
+
on(:failed) { puts "failed event emitted" }
|
113
|
+
on(:stop) { puts "stop event emitted" }
|
114
|
+
|
115
|
+
event :finished, :terminal => true
|
116
|
+
on(:finished) { puts "finished event emitted" }
|
117
|
+
end
|
118
|
+
{coderay}
|
119
|
+
|
120
|
+
Finally, an event can be *terminal*: its emission means the end of the task's
|
121
|
+
execution. __failed__ and __success__ are examples of terminal events. To declare a
|
122
|
+
terminal event, one does as for the "finished" event above.
|
123
|
+
|
124
|
+
Now, read that code into the ruby shell with
|
125
|
+
{coderay:: ruby}
|
126
|
+
>> source "my_task.rb"
|
127
|
+
{coderay}
|
128
|
+
|
129
|
+
Using task events
|
130
|
+
-----------------
|
131
|
+
The {rdoc_class: EventGenerator} class that defines the task event can be
|
132
|
+
accessed with Task#event. Then, you can manipulate them as for normal events:
|
133
|
+
{coderay:: ruby}
|
134
|
+
>> plan.add(task = MyTask.new)
|
135
|
+
>> ev = task.event(:start)
|
136
|
+
>> ev.call
|
137
|
+
start event called
|
138
|
+
start event emitted
|
139
|
+
>> task.running?
|
140
|
+
=> true
|
141
|
+
>> ev = task.event(:contingent)
|
142
|
+
>> ev.controlable?
|
143
|
+
=> false
|
144
|
+
>> ev.emit
|
145
|
+
contingent event emitted
|
146
|
+
{coderay}
|
147
|
+
|
148
|
+
Instead of calling #on, #signal, #emit and #call on the event object, one can use
|
149
|
+
shortcuts that are defined on {rdoc_class: Task}:
|
150
|
+
{coderay:: ruby}
|
151
|
+
# Same as task.event(:contingent).on { ... }
|
152
|
+
>> task.on(:contingent) { puts "contingent event emitted" }
|
153
|
+
# Same as task.event(:contingent).emit
|
154
|
+
>> task.emit(:contingent)
|
155
|
+
# There's two handlers now, so we should have two lines displayed
|
156
|
+
contingent event emitted
|
157
|
+
contingent event emitted
|
158
|
+
# Same as task.event(:controlable).call
|
159
|
+
>> task.controlable!
|
160
|
+
controlable event called
|
161
|
+
controlable event emitted
|
162
|
+
# Same as task.event(:contingent).signals task.event(:controlable)
|
163
|
+
>> task.signals(:contingent, task, :controlable)
|
164
|
+
>> task.emit :contingent
|
165
|
+
contingent event emitted
|
166
|
+
contingent event emitted
|
167
|
+
controlable event called
|
168
|
+
controlable event emitted
|
169
|
+
>> task.emit :finished
|
170
|
+
finished event emitted
|
171
|
+
stop event emitted
|
172
|
+
>> task.running?
|
173
|
+
=> false
|
174
|
+
{coderay}
|
175
|
+
|
176
|
+
Event classification: using the *forward* relation
|
177
|
+
--------------------------------------------------
|
178
|
+
As we in the above examples, it is possible to have terminal events, which are events
|
179
|
+
that end the task. Obviously, the "stop" event should be emitted when they are
|
180
|
+
emitted ("stop" represents the task end, does not it ?).
|
181
|
+
|
182
|
+
In a more generic way, these terminal events are likely to be either special
|
183
|
+
cases of the task success or of the task failure. Then, we actually need a way
|
184
|
+
to *classify* events: to say "success is a special case of stop, or
|
185
|
+
"wheel\_blocked is a special case of failed, which is a special case of
|
186
|
+
stop".
|
187
|
+
|
188
|
+
To represent this specific event relationship, Roby provides a *forward*
|
189
|
+
relation between events, which can be added as follows:
|
190
|
+
{coderay:: ruby}
|
191
|
+
>> class MyTask < Roby::Task
|
192
|
+
?> event :wheel_blocked
|
193
|
+
?> on(:wheel_blocked) { puts "wheel_blocked emitted" }
|
194
|
+
?> end
|
195
|
+
>> plan.add(task = MyTask.new)
|
196
|
+
>> task.start!
|
197
|
+
start event called
|
198
|
+
start event emitted
|
199
|
+
>> blocked = task.event(:wheel_blocked)
|
200
|
+
>> failed = task.event(:failed)
|
201
|
+
>> blocked.forward_to failed
|
202
|
+
>> task.emit :wheel_blocked
|
203
|
+
wheel_blocked emitted
|
204
|
+
stop event emitted
|
205
|
+
{coderay}
|
206
|
+
|
207
|
+
In practice, a _forward_ relation between two events a and b says "b should be
|
208
|
+
emitted when a is". Or "b is a superset of the situations that a represents".
|
209
|
+
|
210
|
+
This relation is also available on "plain" events (i.e. EventGenerator.new).
|
211
|
+
|
212
|
+
Task model and event relations
|
213
|
+
------------------------------
|
214
|
+
Until now, we only saw how to add relations between events of task instances.
|
215
|
+
Sometime (especially with forwarding relations), some relations should be
|
216
|
+
defined on _all_ the task instances of a given task class. To do that, use the
|
217
|
+
class methods <tt>signal</tt> and <tt>forward</tt> defined on {rdoc_class:
|
218
|
+
Task}:
|
219
|
+
|
220
|
+
{coderay:: ruby}
|
221
|
+
>> class MyTask < Roby::Task
|
222
|
+
?> signal :start => :controlable
|
223
|
+
?> forward :wheel_blocked => :failed
|
224
|
+
?> end
|
225
|
+
>> plan.add(task = MyTask.new)
|
226
|
+
>> task.start!
|
227
|
+
start event called
|
228
|
+
start event emitted
|
229
|
+
controlable event called
|
230
|
+
controlable event emitted
|
231
|
+
>> task.emit :wheel_blocked
|
232
|
+
wheel_blocked emitted
|
233
|
+
failed event emitted
|
234
|
+
stop event emitted
|
235
|
+
{coderay}
|
236
|
+
|
237
|
+
Tasks that terminates
|
238
|
+
---------------------
|
239
|
+
A very important characteristic of tasks is their ability to be _interrupted_
|
240
|
+
(or lack of). What is meant by that is that Roby should be able to stop some
|
241
|
+
(actually, most) tasks. In Roby, that ability is represented by giving a command
|
242
|
+
to the 'stop' event.
|
243
|
+
|
244
|
+
For most of the tasks, there is actually no need to perform specific actions.
|
245
|
+
Simply having Roby mark the task as 'stopped' is enough. For those tasks, using
|
246
|
+
the 'terminates' statement is enough:
|
247
|
+
|
248
|
+
{coderay:: ruby}
|
249
|
+
>> class MyTask
|
250
|
+
?> terminates
|
251
|
+
?> end
|
252
|
+
>> plan.add(task = MyTask.new)
|
253
|
+
>> task.start!
|
254
|
+
start event called
|
255
|
+
start event emitted
|
256
|
+
controlable event called
|
257
|
+
controlable event emitted
|
258
|
+
>> task.stop!
|
259
|
+
failed event emitted
|
260
|
+
stop event emitted
|
261
|
+
{coderay}
|
262
|
+
|
263
|
+
As you can see, 'terminates' is equivalent to
|
264
|
+
{coderay:: ruby}
|
265
|
+
>> class MyTask
|
266
|
+
?> event(:failed) { emit :failed }
|
267
|
+
?> event(:stop) { failed! }
|
268
|
+
?> end
|
269
|
+
{coderay}
|
270
|
+
|
271
|
+
Common errors when manipulating tasks
|
272
|
+
-------------------------------------
|
273
|
+
|
274
|
+
As for the event, a common error is to forget to include the task in a plan
|
275
|
+
before calling events on it:
|
276
|
+
|
277
|
+
{coderay:: ruby}
|
278
|
+
>> task = MyTask.new
|
279
|
+
>> task.start!
|
280
|
+
Roby::EventNotExecutable: start! called on MyTask{}:0x7f336c455af0[] but the task is in no plan
|
281
|
+
{coderay}
|
282
|
+
|
283
|
+
Another related error is to emit/call events other than "start" while the task is not yet running ...
|
284
|
+
|
285
|
+
{coderay:: ruby}
|
286
|
+
>> plan.add(task = MyTask.new)
|
287
|
+
>> task.controllable!
|
288
|
+
Roby::CommandFailed: controlable!() called by [] but the task has never been started
|
289
|
+
from (irb):30
|
290
|
+
>> task.emit :contingent
|
291
|
+
Roby::EmissionFailed: emit(contingent, []) called by [] but the task has never been started
|
292
|
+
from (irb):31
|
293
|
+
{coderay}
|
294
|
+
|
295
|
+
... or when it has stopped
|
296
|
+
|
297
|
+
{coderay:: ruby}
|
298
|
+
>> task.start!
|
299
|
+
>> task.stop!
|
300
|
+
>> task.controlable!
|
301
|
+
Roby::CommandFailed: controlable!() called by [] but the task has finished. Task has been terminated by [MyTask{}:0x7ff179064358[]/failed@7 [344917:00:42.215]:
|
302
|
+
from (irb):32
|
303
|
+
>> task.emit :contingent
|
304
|
+
Roby::EmissionFailed: emit(contingent, []) called by [] but the task has finished. Task has been terminated by [MyTask{}:0x7ff179064358[]/failed@7 [344917:00:42.215]: ].
|
305
|
+
from (irb):33
|
306
|
+
{coderay}
|
307
|
+
|
308
|
+
<div markdown="1" class="info">
|
309
|
+
In these messages, the notation
|
310
|
+
|
311
|
+
MyTask{}:0x7ff179064358[]
|
312
|
+
|
313
|
+
represents a task, the notation
|
314
|
+
|
315
|
+
MyTask{}:0x7ff179064358[]/failed
|
316
|
+
|
317
|
+
represents the event "failed" of the same task and finally
|
318
|
+
|
319
|
+
MyTask{}:0x7ff179064358[]/failed@7 [344917:00:42.215]
|
320
|
+
|
321
|
+
is an emitted event that has been generated by the "failed" event of the given
|
322
|
+
task. The time on the right is the time of emission, and the "@x" notation is
|
323
|
+
the propagation cycle (usually, you don't care about this but it is VERY useful
|
324
|
+
for debugging Roby itself).
|
325
|
+
</div>
|
326
|
+
|
327
|
+
Of course, as we saw at the beginning of this page, a task must be fully
|
328
|
+
instanciated to be started:
|
329
|
+
|
330
|
+
{coderay:: ruby}
|
331
|
+
>> class Bla < Roby::Task
|
332
|
+
>> argument :foo
|
333
|
+
>> end
|
334
|
+
>> plan.add(task = Bla.new)
|
335
|
+
>> task.start!
|
336
|
+
Roby::EventNotExecutable: start! called on Bar{}:0x7ff17901c1e8[] which is partially instanciated
|
337
|
+
The following arguments were not set:
|
338
|
+
foo
|
339
|
+
{coderay}
|
340
|
+
|
341
|
+
Summary
|
342
|
+
-------
|
343
|
+
|
344
|
+
What do we do know ?
|
345
|
+
|
346
|
+
* we know how the robot's situation is represented: through the *emission
|
347
|
+
of events*
|
348
|
+
* we know how the robot is controlled: through the call of *controlable
|
349
|
+
events*
|
350
|
+
* we know how to sort events in tasks, in order to represent the different
|
351
|
+
processes that run on the robot.
|
352
|
+
|
353
|
+
One important question is still left open: how all of this can be made into a
|
354
|
+
whole that allows to control a robot ? Right now, we only have an overview of
|
355
|
+
the basics of Roby plan. What follows will show what a *Roby application* is
|
356
|
+
made of.
|
357
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Code examples
|
2
|
+
-------------
|
3
|
+
This page includes code samples that you can try out in Ruby or Unix shells. See
|
4
|
+
[this page](code_examples.html) for explanations on the notation.
|
5
|
+
{.warning}
|
6
|
+
|
7
|
+
Moreover, to run the examples on this page, you must first set up your ruby
|
8
|
+
shell:
|
9
|
+
|
10
|
+
$ irb
|
11
|
+
{coderay:: ruby}
|
12
|
+
>> require 'roby/standalone'
|
13
|
+
>> include Roby
|
14
|
+
>> plan = Roby.plan
|
15
|
+
{coderay}
|
16
|
+
|
Binary file
|
@@ -0,0 +1,208 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
3
|
+
<svg
|
4
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
5
|
+
xmlns:cc="http://web.resource.org/cc/"
|
6
|
+
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
7
|
+
xmlns:svg="http://www.w3.org/2000/svg"
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
9
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
10
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
11
|
+
width="744.09448819"
|
12
|
+
height="1052.3622047"
|
13
|
+
id="svg2"
|
14
|
+
sodipodi:version="0.32"
|
15
|
+
inkscape:version="0.45.1"
|
16
|
+
sodipodi:docbase="/home/doudou/laas/documents/production/thesis/figures/supervision"
|
17
|
+
sodipodi:docname="cycle-overview.svg"
|
18
|
+
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
19
|
+
<defs
|
20
|
+
id="defs4">
|
21
|
+
<marker
|
22
|
+
inkscape:stockid="Arrow1Lend"
|
23
|
+
orient="auto"
|
24
|
+
refY="0.0"
|
25
|
+
refX="0.0"
|
26
|
+
id="Arrow1Lend"
|
27
|
+
style="overflow:visible;">
|
28
|
+
<path
|
29
|
+
id="path3265"
|
30
|
+
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
31
|
+
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
|
32
|
+
transform="scale(0.8) rotate(180) translate(12.5,0)" />
|
33
|
+
</marker>
|
34
|
+
</defs>
|
35
|
+
<sodipodi:namedview
|
36
|
+
id="base"
|
37
|
+
pagecolor="#ffffff"
|
38
|
+
bordercolor="#666666"
|
39
|
+
borderopacity="1.0"
|
40
|
+
gridtolerance="10000"
|
41
|
+
guidetolerance="10"
|
42
|
+
objecttolerance="10"
|
43
|
+
inkscape:pageopacity="0.0"
|
44
|
+
inkscape:pageshadow="2"
|
45
|
+
inkscape:zoom="0.49497475"
|
46
|
+
inkscape:cx="818.39952"
|
47
|
+
inkscape:cy="483.78467"
|
48
|
+
inkscape:document-units="px"
|
49
|
+
inkscape:current-layer="layer1"
|
50
|
+
inkscape:window-width="1016"
|
51
|
+
inkscape:window-height="710"
|
52
|
+
inkscape:window-x="0"
|
53
|
+
inkscape:window-y="0" />
|
54
|
+
<metadata
|
55
|
+
id="metadata7">
|
56
|
+
<rdf:RDF>
|
57
|
+
<cc:Work
|
58
|
+
rdf:about="">
|
59
|
+
<dc:format>image/svg+xml</dc:format>
|
60
|
+
<dc:type
|
61
|
+
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
62
|
+
</cc:Work>
|
63
|
+
</rdf:RDF>
|
64
|
+
</metadata>
|
65
|
+
<g
|
66
|
+
inkscape:label="Layer 1"
|
67
|
+
inkscape:groupmode="layer"
|
68
|
+
id="layer1">
|
69
|
+
<g
|
70
|
+
id="g3241"
|
71
|
+
transform="translate(96.232983,-246.65343)">
|
72
|
+
<path
|
73
|
+
transform="matrix(0.516129,0,0,0.516129,82.148213,214.40589)"
|
74
|
+
d="M 324.25896 525.56763 A 78.286819 78.286819 0 1 1 167.68532,525.56763 A 78.286819 78.286819 0 1 1 324.25896 525.56763 z"
|
75
|
+
sodipodi:ry="78.286819"
|
76
|
+
sodipodi:rx="78.286819"
|
77
|
+
sodipodi:cy="525.56763"
|
78
|
+
sodipodi:cx="245.97214"
|
79
|
+
id="path3185"
|
80
|
+
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.63598328;fill-rule:evenodd;stroke:#000000;stroke-width:2.71250033;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
81
|
+
sodipodi:type="arc" />
|
82
|
+
<text
|
83
|
+
sodipodi:linespacing="125%"
|
84
|
+
id="text3187"
|
85
|
+
y="482.02158"
|
86
|
+
x="209.04053"
|
87
|
+
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
88
|
+
xml:space="preserve"><tspan
|
89
|
+
y="482.02158"
|
90
|
+
x="209.04053"
|
91
|
+
id="tspan3189"
|
92
|
+
sodipodi:role="line">1. Event</tspan><tspan
|
93
|
+
id="tspan3191"
|
94
|
+
y="494.52158"
|
95
|
+
x="209.04053"
|
96
|
+
sodipodi:role="line">Propagation</tspan></text>
|
97
|
+
</g>
|
98
|
+
<g
|
99
|
+
id="g3247"
|
100
|
+
transform="translate(90.900118,-242.41612)">
|
101
|
+
<path
|
102
|
+
transform="matrix(0.516129,0,0,0.516129,210.51882,259.86277)"
|
103
|
+
d="M 324.25896 525.56763 A 78.286819 78.286819 0 1 1 167.68532,525.56763 A 78.286819 78.286819 0 1 1 324.25896 525.56763 z"
|
104
|
+
sodipodi:ry="78.286819"
|
105
|
+
sodipodi:rx="78.286819"
|
106
|
+
sodipodi:cy="525.56763"
|
107
|
+
sodipodi:cx="245.97214"
|
108
|
+
id="path3193"
|
109
|
+
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.63598328;fill-rule:evenodd;stroke:#000000;stroke-width:2.71250033;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
110
|
+
sodipodi:type="arc" />
|
111
|
+
<text
|
112
|
+
sodipodi:linespacing="125%"
|
113
|
+
id="text3195"
|
114
|
+
y="527.47845"
|
115
|
+
x="337.41113"
|
116
|
+
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
117
|
+
xml:space="preserve"><tspan
|
118
|
+
id="tspan3199"
|
119
|
+
y="527.47845"
|
120
|
+
x="337.41113"
|
121
|
+
sodipodi:role="line">2. Error</tspan><tspan
|
122
|
+
id="tspan3203"
|
123
|
+
y="539.97845"
|
124
|
+
x="337.41113"
|
125
|
+
sodipodi:role="line">Handling</tspan></text>
|
126
|
+
</g>
|
127
|
+
<g
|
128
|
+
id="g3253"
|
129
|
+
transform="translate(97.432971,-240.67052)">
|
130
|
+
<path
|
131
|
+
transform="matrix(0.516129,0,0,0.516129,99.320817,339.66483)"
|
132
|
+
d="M 324.25896 525.56763 A 78.286819 78.286819 0 1 1 167.68532,525.56763 A 78.286819 78.286819 0 1 1 324.25896 525.56763 z"
|
133
|
+
sodipodi:ry="78.286819"
|
134
|
+
sodipodi:rx="78.286819"
|
135
|
+
sodipodi:cy="525.56763"
|
136
|
+
sodipodi:cx="245.97214"
|
137
|
+
id="path3205"
|
138
|
+
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.63598328;fill-rule:evenodd;stroke:#000000;stroke-width:2.71250033;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
139
|
+
sodipodi:type="arc" />
|
140
|
+
<text
|
141
|
+
sodipodi:linespacing="125%"
|
142
|
+
id="text3207"
|
143
|
+
y="607.28052"
|
144
|
+
x="226.21313"
|
145
|
+
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
146
|
+
xml:space="preserve"><tspan
|
147
|
+
id="tspan3211"
|
148
|
+
y="607.28052"
|
149
|
+
x="226.21313"
|
150
|
+
sodipodi:role="line">3. Garbage</tspan><tspan
|
151
|
+
id="tspan3215"
|
152
|
+
y="619.78052"
|
153
|
+
x="226.21313"
|
154
|
+
sodipodi:role="line">Collection</tspan></text>
|
155
|
+
</g>
|
156
|
+
<path
|
157
|
+
style="opacity:1;color:#000000;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
158
|
+
d="M 341.12139,257.78591 L 387.27981,274.13091"
|
159
|
+
id="path3235"
|
160
|
+
inkscape:connector-type="polyline" />
|
161
|
+
<path
|
162
|
+
style="opacity:1;color:#000000;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
163
|
+
d="M 396.23341,313.66319 L 353.30654,347.3016"
|
164
|
+
id="path3237"
|
165
|
+
inkscape:connector-type="polyline" />
|
166
|
+
<path
|
167
|
+
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;marker-end:url(#Arrow1Lend);stroke-opacity:1"
|
168
|
+
d="M 311.55238,327.38282 L 305.65081,284.33607"
|
169
|
+
id="path3239"
|
170
|
+
inkscape:connector-type="polyline" />
|
171
|
+
<flowRoot
|
172
|
+
xml:space="preserve"
|
173
|
+
id="flowRoot2185"
|
174
|
+
style="text-align:justify;text-anchor:start"
|
175
|
+
transform="translate(9.0913726,-136.3706)"><flowRegion
|
176
|
+
id="flowRegion2187"><rect
|
177
|
+
id="rect2189"
|
178
|
+
width="183.84776"
|
179
|
+
height="61.619305"
|
180
|
+
x="56.568542"
|
181
|
+
y="346.26556"
|
182
|
+
style="text-align:justify;text-anchor:start" /></flowRegion><flowPara
|
183
|
+
id="flowPara2195">determine what events should be emitted and/or called, and propagate the events in the event relation graphs.</flowPara></flowRoot> <flowRoot
|
184
|
+
xml:space="preserve"
|
185
|
+
id="flowRoot2201"
|
186
|
+
transform="translate(38.056586,-153.1509)"
|
187
|
+
style="text-align:end;text-anchor:end"><flowRegion
|
188
|
+
id="flowRegion2203"><rect
|
189
|
+
id="rect2205"
|
190
|
+
width="192.20023"
|
191
|
+
height="60.052284"
|
192
|
+
x="389.91888"
|
193
|
+
y="363.43814"
|
194
|
+
style="text-align:end;text-anchor:end" /></flowRegion><flowPara
|
195
|
+
id="flowPara2209">detect errors as violation of the constraints defined by the relation graphs, and try to recover from them.</flowPara></flowRoot> <flowRoot
|
196
|
+
xml:space="preserve"
|
197
|
+
id="flowRoot2213"
|
198
|
+
style="text-align:justify;text-anchor:start"
|
199
|
+
transform="translate(-114.08627,-193.1509)"><flowRegion
|
200
|
+
id="flowRegion2215"><rect
|
201
|
+
id="rect2217"
|
202
|
+
width="272.14285"
|
203
|
+
height="47.142876"
|
204
|
+
x="318.57144"
|
205
|
+
y="606.64789"
|
206
|
+
style="text-align:justify;text-anchor:start" /></flowRegion><flowPara
|
207
|
+
id="flowPara2223">kill and remove the tasks that are either not useful for the completion of the robot goals, or for which errors have not been recovered.</flowPara></flowRoot> </g>
|
208
|
+
</svg>
|