roby 0.7.2 → 0.7.3
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/History.txt +6 -0
- data/Manifest.txt +1 -0
- data/Rakefile +15 -6
- data/lib/roby/app/scripts/run.rb +1 -0
- data/lib/roby/app/scripts/shell.rb +14 -1
- data/lib/roby/config.rb +1 -1
- data/lib/roby/event.rb +32 -17
- data/lib/roby/log/file.rb +33 -2
- data/lib/roby/log/gui/relations.rb +29 -8
- data/lib/roby/log/gui/replay.rb +16 -5
- data/lib/roby/log/gui/replay_controls.rb +4 -1
- data/lib/roby/support.rb +1 -1
- data/lib/roby/task.rb +51 -16
- data/test/suite_core.rb +2 -0
- data/test/test_gui.rb +20 -0
- data/test/test_task.rb +90 -0
- metadata +58 -31
data/History.txt
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
=== 0.7.3
|
|
2
|
+
|
|
3
|
+
* fix needed update to run on latest activesupport
|
|
4
|
+
This is probably the last release of 0.7. The 'next' branch will become 0.8 as
|
|
5
|
+
soon as it is tested enough
|
|
6
|
+
|
|
1
7
|
=== 0.7.2
|
|
2
8
|
|
|
3
9
|
* fixed a memory leak regarding the event propagation histories. Until now,
|
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path('lib', File.dirname(__FILE__))
|
|
2
2
|
require 'enumerator'
|
|
3
|
-
require 'hoe'
|
|
4
3
|
require 'roby/config'
|
|
5
4
|
|
|
6
5
|
begin
|
|
@@ -11,11 +10,16 @@ begin
|
|
|
11
10
|
|
|
12
11
|
p.summary = 'A plan-based control framework for autonomous systems'
|
|
13
12
|
p.url = p.paragraphs_of('README.txt', 1).join("\n\n")
|
|
14
|
-
p.description = p.paragraphs_of('README.txt',
|
|
13
|
+
p.description = p.paragraphs_of('README.txt', 3..5).join("\n\n")
|
|
14
|
+
p.description +=
|
|
15
|
+
"\n\nSee the README.txt file at http://roby.rubyforge.org for more
|
|
16
|
+
informations, including links to tutorials and demonstration videos"
|
|
15
17
|
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
|
16
18
|
p.post_install_message = p.paragraphs_of('README.txt', 2).join("\n\n")
|
|
17
19
|
|
|
18
|
-
p.extra_deps << ['facets', '>= 2.0'] << 'activesupport' << ['utilrb', '>= 1.3.1']
|
|
20
|
+
p.extra_deps << ['facets', '>= 2.0'] << 'activesupport' << ['utilrb', '>= 1.3.1'] <<
|
|
21
|
+
['rake', '>= 0.8.3']
|
|
22
|
+
p.extra_dev_deps << 'flexmock'
|
|
19
23
|
if p.respond_to? :need_rdoc=
|
|
20
24
|
p.need_rdoc = false
|
|
21
25
|
end
|
|
@@ -42,8 +46,8 @@ begin
|
|
|
42
46
|
tasks.delete_if { |n, _| n =~ /dist:(re|clobber_|)docs/ }
|
|
43
47
|
end
|
|
44
48
|
end
|
|
45
|
-
rescue
|
|
46
|
-
puts "cannot
|
|
49
|
+
rescue
|
|
50
|
+
puts "cannot setup Hoe, distribution is disabled"
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
def build_extension(name, soname = name)
|
|
@@ -104,9 +108,14 @@ end
|
|
|
104
108
|
UIFILES = %w{relations.ui relations_view.ui data_displays.ui replay_controls.ui basic_display.ui chronicle_view.ui}
|
|
105
109
|
desc 'generate all Qt UI files using rbuic4'
|
|
106
110
|
task :uic do
|
|
111
|
+
rbuic = 'rbuic4'
|
|
112
|
+
if File.exists?('/usr/lib/kde4/bin/rbuic4')
|
|
113
|
+
rbuic = '/usr/lib/kde4/bin/rbuic4'
|
|
114
|
+
end
|
|
115
|
+
|
|
107
116
|
UIFILES.each do |file|
|
|
108
117
|
file = 'lib/roby/log/gui/' + file
|
|
109
|
-
if !system(
|
|
118
|
+
if !system(rbuic, '-o', file.gsub(/\.ui$/, '_ui.rb'), file)
|
|
110
119
|
STDERR.puts "Failed to generate #{file}"
|
|
111
120
|
end
|
|
112
121
|
end
|
data/lib/roby/app/scripts/run.rb
CHANGED
|
@@ -4,6 +4,8 @@ require 'roby/distributed'
|
|
|
4
4
|
require 'roby/distributed/protocol'
|
|
5
5
|
require 'optparse'
|
|
6
6
|
|
|
7
|
+
require 'pp'
|
|
8
|
+
|
|
7
9
|
remote_url = nil
|
|
8
10
|
opt = OptionParser.new do |opt|
|
|
9
11
|
opt.on('--host URL', String, "sets the host to connect to") do |url|
|
|
@@ -33,7 +35,18 @@ end
|
|
|
33
35
|
DRb.start_service
|
|
34
36
|
|
|
35
37
|
require 'irb'
|
|
36
|
-
IRB.setup(
|
|
38
|
+
IRB.setup(remote_url)
|
|
39
|
+
IRB.conf[:INSPECT_MODE] = false
|
|
40
|
+
IRB.conf[:IRB_NAME] = remote_url
|
|
41
|
+
IRB.conf[:PROMPT_MODE] = :ROBY
|
|
42
|
+
IRB.conf[:AUTO_INDENT] = true
|
|
43
|
+
IRB.conf[:PROMPT][:ROBY] = {
|
|
44
|
+
:PROMPT_I => "%N > ",
|
|
45
|
+
:PROMPT_N => "%N > ",
|
|
46
|
+
:PROMPT_S => "%N %l ",
|
|
47
|
+
:PROMPT_C => "%N * ",
|
|
48
|
+
:RETURN => "=> %s\n"
|
|
49
|
+
}
|
|
37
50
|
|
|
38
51
|
control = Roby::RemoteInterface.new(DRbObject.new_with_uri("druby://#{remote_url}"))
|
|
39
52
|
|
data/lib/roby/config.rb
CHANGED
|
@@ -8,7 +8,7 @@ try it on 1.9, checkout the 1.9 branch of the development repository on github
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
module Roby
|
|
11
|
-
VERSION = '0.7.
|
|
11
|
+
VERSION = '0.7.3'
|
|
12
12
|
ROBY_LIB_DIR = File.expand_path( File.join(File.dirname(__FILE__), '..') )
|
|
13
13
|
ROBY_ROOT_DIR = File.expand_path( File.join(ROBY_LIB_DIR, '..') )
|
|
14
14
|
end
|
data/lib/roby/event.rb
CHANGED
|
@@ -171,6 +171,7 @@ module Roby
|
|
|
171
171
|
end
|
|
172
172
|
super() if defined? super
|
|
173
173
|
@executable = true
|
|
174
|
+
|
|
174
175
|
end
|
|
175
176
|
|
|
176
177
|
def default_command(context)
|
|
@@ -183,12 +184,39 @@ module Roby
|
|
|
183
184
|
# True if this event is controlable
|
|
184
185
|
def controlable?; !!@command end
|
|
185
186
|
|
|
187
|
+
# Checks that the event can be called. Raises various exception
|
|
188
|
+
# when it is not the case.
|
|
189
|
+
def check_call_validity
|
|
190
|
+
if !self_owned?
|
|
191
|
+
raise OwnershipError, "not owner"
|
|
192
|
+
elsif !controlable?
|
|
193
|
+
raise EventNotControlable.new(self), "#call called on a non-controlable event"
|
|
194
|
+
elsif !executable?
|
|
195
|
+
raise EventNotExecutable.new(self), "#call called on #{self} which is non-executable event"
|
|
196
|
+
elsif !Roby.inside_control?
|
|
197
|
+
raise ThreadMismatch, "#call called while not in control thread"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Checks that the event can be emitted. Raises various exception
|
|
202
|
+
# when it is not the case.
|
|
203
|
+
def check_emission_validity
|
|
204
|
+
if !executable?
|
|
205
|
+
raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
|
|
206
|
+
elsif !self_owned?
|
|
207
|
+
raise OwnershipError, "cannot emit an event we don't own. #{self} is owned by #{owners}"
|
|
208
|
+
elsif !Roby.inside_control?
|
|
209
|
+
raise ThreadMismatch, "#emit called while not in control thread"
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
186
213
|
# Returns true if the command has been called and false otherwise
|
|
187
214
|
# The command won't be called if #postpone() is called within the
|
|
188
215
|
# #calling hook
|
|
189
216
|
#
|
|
190
217
|
# This is used by propagation code, and should never be called directly
|
|
191
218
|
def call_without_propagation(context) # :nodoc:
|
|
219
|
+
check_call_validity
|
|
192
220
|
if !controlable?
|
|
193
221
|
raise EventNotControlable.new(self), "#call called on a non-controlable event"
|
|
194
222
|
end
|
|
@@ -222,15 +250,7 @@ module Roby
|
|
|
222
250
|
# non-controlable and respond to the :call message. Controlability must
|
|
223
251
|
# be checked using #controlable?
|
|
224
252
|
def call(*context)
|
|
225
|
-
|
|
226
|
-
raise OwnershipError, "not owner"
|
|
227
|
-
elsif !controlable?
|
|
228
|
-
raise EventNotControlable.new(self), "#call called on a non-controlable event"
|
|
229
|
-
elsif !executable?
|
|
230
|
-
raise EventNotExecutable.new(self), "#call called on #{self} which is non-executable event"
|
|
231
|
-
elsif !Roby.inside_control?
|
|
232
|
-
raise ThreadMismatch, "#call called while not in control thread"
|
|
233
|
-
end
|
|
253
|
+
check_call_validity
|
|
234
254
|
|
|
235
255
|
context.compact!
|
|
236
256
|
if Propagation.gathering?
|
|
@@ -426,7 +446,7 @@ module Roby
|
|
|
426
446
|
begin
|
|
427
447
|
h.call(event)
|
|
428
448
|
rescue Exception => e
|
|
429
|
-
|
|
449
|
+
Propagation.add_error( EventHandlerError.new(e, event) )
|
|
430
450
|
end
|
|
431
451
|
end
|
|
432
452
|
end
|
|
@@ -460,6 +480,7 @@ module Roby
|
|
|
460
480
|
#
|
|
461
481
|
# This is used by event propagation. Do not call directly: use #call instead
|
|
462
482
|
def emit_without_propagation(context) # :nodoc:
|
|
483
|
+
check_emission_validity
|
|
463
484
|
if !executable?
|
|
464
485
|
raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
|
|
465
486
|
end
|
|
@@ -482,13 +503,7 @@ module Roby
|
|
|
482
503
|
|
|
483
504
|
# Emit the event with +context+ as the event context
|
|
484
505
|
def emit(*context)
|
|
485
|
-
|
|
486
|
-
raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
|
|
487
|
-
elsif !self_owned?
|
|
488
|
-
raise OwnershipError, "cannot emit an event we don't own. #{self} is owned by #{owners}"
|
|
489
|
-
elsif !Roby.inside_control?
|
|
490
|
-
raise ThreadMismatch, "#emit called while not in control thread"
|
|
491
|
-
end
|
|
506
|
+
check_emission_validity
|
|
492
507
|
|
|
493
508
|
context.compact!
|
|
494
509
|
if Propagation.gathering?
|
data/lib/roby/log/file.rb
CHANGED
|
@@ -43,8 +43,17 @@ module Roby::Log
|
|
|
43
43
|
super(@event_io)
|
|
44
44
|
|
|
45
45
|
@index_data = Array.new
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
begin
|
|
47
|
+
rewind
|
|
48
|
+
rescue ArgumentError, EOFError
|
|
49
|
+
rebuild_index
|
|
50
|
+
rewind
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if !valid_index?
|
|
54
|
+
rebuild_index
|
|
55
|
+
rewind
|
|
56
|
+
end
|
|
48
57
|
end
|
|
49
58
|
|
|
50
59
|
# Reads as much index data as possible
|
|
@@ -65,6 +74,28 @@ module Roby::Log
|
|
|
65
74
|
return if index_data.empty?
|
|
66
75
|
end
|
|
67
76
|
|
|
77
|
+
def valid_index?
|
|
78
|
+
100.times do |i|
|
|
79
|
+
break if i * 10 >= index_data.size
|
|
80
|
+
index = index_data[i * 10]
|
|
81
|
+
|
|
82
|
+
event_io.seek(index[:pos])
|
|
83
|
+
cycle = begin
|
|
84
|
+
Marshal.load(event_io)
|
|
85
|
+
rescue EOFError
|
|
86
|
+
return false
|
|
87
|
+
rescue ArgumentError
|
|
88
|
+
return false
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if cycle[-4] != :cycle_end ||
|
|
92
|
+
cycle[-1].first != index
|
|
93
|
+
return false
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
true
|
|
97
|
+
end
|
|
98
|
+
|
|
68
99
|
def rewind
|
|
69
100
|
@event_io.rewind
|
|
70
101
|
Marshal.load(@event_io)
|
|
@@ -18,7 +18,7 @@ module Ui
|
|
|
18
18
|
CATEGORIES = ['Task structure']
|
|
19
19
|
|
|
20
20
|
def event_root_index; createIndex(TASK_ROOT_INDEX, 0, -1) end
|
|
21
|
-
def task_root_index;
|
|
21
|
+
def task_root_index; createIndex(EVENT_ROOT_INDEX, 0, -1) end
|
|
22
22
|
|
|
23
23
|
attr_reader :relations
|
|
24
24
|
attr_reader :display
|
|
@@ -31,10 +31,30 @@ module Ui
|
|
|
31
31
|
@relations = []
|
|
32
32
|
|
|
33
33
|
relations[TASK_ROOT_INDEX] = Roby::TaskStructure.enum_for(:each_relation).to_a
|
|
34
|
+
|
|
35
|
+
RelationConfigModel.detect_qtruby_behaviour(createIndex(0, 0, 0))
|
|
34
36
|
end
|
|
35
37
|
|
|
38
|
+
QTRUBY_INDEX_USING_POINTERS = 1
|
|
39
|
+
QTRUBY_INDEX_USING_OBJECTIDS = 2
|
|
40
|
+
def self.detect_qtruby_behaviour(idx)
|
|
41
|
+
if idx.internalPointer == 0
|
|
42
|
+
@@qtruby_behaviour = QTRUBY_INDEX_USING_POINTERS
|
|
43
|
+
elsif idx.internalId == 1
|
|
44
|
+
@@qtruby_behaviour = QTRUBY_INDEX_USING_OBJECTIDS
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.category_from_index(idx)
|
|
49
|
+
if @@qtruby_behaviour == QTRUBY_INDEX_USING_POINTERS
|
|
50
|
+
idx.internalPointer
|
|
51
|
+
else
|
|
52
|
+
idx.internalId >> 1
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
36
56
|
def index(row, column, parent)
|
|
37
|
-
if parent.valid? && parent
|
|
57
|
+
if parent.valid? && RelationConfigModel.category_from_index(parent) == -1
|
|
38
58
|
createIndex(row, column, parent.row)
|
|
39
59
|
elsif row < relations.size
|
|
40
60
|
createIndex(row, column, -1)
|
|
@@ -42,13 +62,14 @@ module Ui
|
|
|
42
62
|
Qt::ModelIndex.new
|
|
43
63
|
end
|
|
44
64
|
end
|
|
65
|
+
|
|
45
66
|
def parent(index)
|
|
46
|
-
category = index
|
|
67
|
+
category = RelationConfigModel.category_from_index(index)
|
|
47
68
|
if !index.valid? || category == -1 then Qt::ModelIndex.new
|
|
48
69
|
else createIndex(category, 0, -1) end
|
|
49
70
|
end
|
|
50
71
|
def columnCount(parent); 2 end
|
|
51
|
-
def hasChildren(parent); !parent.valid? || parent
|
|
72
|
+
def hasChildren(parent); !parent.valid? || RelationConfigModel.category_from_index(parent) == -1 end
|
|
52
73
|
def rowCount(parent)
|
|
53
74
|
if !parent.valid? then relations.size
|
|
54
75
|
else relations[parent.row].size end
|
|
@@ -62,7 +83,7 @@ module Ui
|
|
|
62
83
|
def data(index, role)
|
|
63
84
|
return Qt::Variant.new unless index.valid?
|
|
64
85
|
|
|
65
|
-
category = index
|
|
86
|
+
category = RelationConfigModel.category_from_index(index)
|
|
66
87
|
value = if category == -1
|
|
67
88
|
if index.column == COL_NAME && role == Qt::DisplayRole
|
|
68
89
|
CATEGORIES[index.row]
|
|
@@ -86,7 +107,7 @@ module Ui
|
|
|
86
107
|
end
|
|
87
108
|
end
|
|
88
109
|
def setData(index, value, role)
|
|
89
|
-
category = index
|
|
110
|
+
category = RelationConfigModel.category_from_index(index)
|
|
90
111
|
relation = relations[category][index.row]
|
|
91
112
|
if role == Qt::CheckStateRole
|
|
92
113
|
case value.to_i
|
|
@@ -104,7 +125,7 @@ module Ui
|
|
|
104
125
|
emit dataChanged(index, index)
|
|
105
126
|
end
|
|
106
127
|
def flags(index)
|
|
107
|
-
if !index.valid? || index
|
|
128
|
+
if !index.valid? || RelationConfigModel.category_from_index(index) == -1 then Qt::ItemIsEnabled
|
|
108
129
|
else
|
|
109
130
|
flags = Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable
|
|
110
131
|
if index.column == 1
|
|
@@ -124,7 +145,7 @@ module Ui
|
|
|
124
145
|
nil
|
|
125
146
|
end
|
|
126
147
|
def paint(painter, option, index)
|
|
127
|
-
if index.column == 1 && index
|
|
148
|
+
if index.column == 1 && RelationConfigModel.category_from_index(index) >= 0
|
|
128
149
|
color = index.model.data(index, Qt::DisplayRole).to_string
|
|
129
150
|
rect = option.rect
|
|
130
151
|
rect.adjust(1, 1, -1, -1)
|
data/lib/roby/log/gui/replay.rb
CHANGED
|
@@ -2,6 +2,7 @@ require 'Qt4'
|
|
|
2
2
|
require 'roby/app'
|
|
3
3
|
require 'optparse'
|
|
4
4
|
|
|
5
|
+
require 'roby/log/event_stream'
|
|
5
6
|
require 'roby/log/gui/replay_controls'
|
|
6
7
|
require 'roby/log/gui/data_displays'
|
|
7
8
|
|
|
@@ -135,9 +136,14 @@ class Replay < Qt::MainWindow
|
|
|
135
136
|
@first_sample = @time = min
|
|
136
137
|
@last_sample = max
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
if min
|
|
140
|
+
ui_controls.progress.minimum = min.to_i
|
|
141
|
+
ui_controls.progress.maximum = max.to_i
|
|
142
|
+
ui_controls.update_bookmarks_menu
|
|
143
|
+
else
|
|
144
|
+
ui_controls.progress.minimum = 0
|
|
145
|
+
ui_controls.progress.maximum = 1
|
|
146
|
+
end
|
|
141
147
|
else
|
|
142
148
|
play_until time, integrate
|
|
143
149
|
end
|
|
@@ -146,8 +152,13 @@ class Replay < Qt::MainWindow
|
|
|
146
152
|
end
|
|
147
153
|
|
|
148
154
|
def update_time_display
|
|
149
|
-
|
|
150
|
-
|
|
155
|
+
if first_sample
|
|
156
|
+
ui_controls.time_lcd.display(((self.time - first_sample) * 1000.0).round / 1000.0)
|
|
157
|
+
ui_controls.progress.value = self.time.to_i
|
|
158
|
+
else
|
|
159
|
+
ui_controls.time_lcd.display(0)
|
|
160
|
+
ui_controls.progress.value = 0
|
|
161
|
+
end
|
|
151
162
|
end
|
|
152
163
|
|
|
153
164
|
attr_reader :time
|
|
@@ -182,9 +182,12 @@ class Ui::ReplayControls
|
|
|
182
182
|
retry
|
|
183
183
|
end
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
if !replay.first_sample
|
|
186
186
|
replay.seek(nil)
|
|
187
187
|
end
|
|
188
|
+
if !replay.first_sample # no samples at all !
|
|
189
|
+
return
|
|
190
|
+
end
|
|
188
191
|
|
|
189
192
|
user_time = if !op
|
|
190
193
|
replay.first_sample + (user_time - Time.at(0))
|
data/lib/roby/support.rb
CHANGED
data/lib/roby/task.rb
CHANGED
|
@@ -248,6 +248,41 @@ module Roby
|
|
|
248
248
|
super(obj)
|
|
249
249
|
end
|
|
250
250
|
end
|
|
251
|
+
|
|
252
|
+
# Checks that the event can be called. Raises various exception
|
|
253
|
+
# when it is not the case.
|
|
254
|
+
def check_call_validity
|
|
255
|
+
super
|
|
256
|
+
rescue EventNotExecutable => e
|
|
257
|
+
refine_exception(e)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Checks that the event can be emitted. Raises various exception
|
|
261
|
+
# when it is not the case.
|
|
262
|
+
def check_emission_validity
|
|
263
|
+
super
|
|
264
|
+
rescue EventNotExecutable => e
|
|
265
|
+
refine_exception(e)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def refine_exception (e)
|
|
270
|
+
if task.partially_instanciated?
|
|
271
|
+
raise EventNotExecutable.new(self), "#{name}! called on #{task} which is partially instanciated\n" +
|
|
272
|
+
"The following arguments were not set: \n" +
|
|
273
|
+
task.list_unset_arguments.map {|n| "\t#{n}"}.join("\n")+"\n"
|
|
274
|
+
#
|
|
275
|
+
elsif !plan
|
|
276
|
+
raise EventNotExecutable.new(self), "#{name}! called on #{task} but the task is in no plan"
|
|
277
|
+
elsif !plan.executable?
|
|
278
|
+
raise EventNotExecutable.new(self), "#{name}! called on #{task} but the plan is not executable"
|
|
279
|
+
elsif task.abstract?
|
|
280
|
+
raise EventNotExecutable.new(self), "#{name}! called on #{task} but the task is abstract"
|
|
281
|
+
else
|
|
282
|
+
raise EventNotExecutable.new(self), "#{name}! called on #{task} which is not executable: #{e.message}"
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
251
286
|
end
|
|
252
287
|
|
|
253
288
|
class TaskArguments < Hash
|
|
@@ -473,10 +508,23 @@ module Roby
|
|
|
473
508
|
@model = self.class
|
|
474
509
|
|
|
475
510
|
yield(self) if block_given?
|
|
476
|
-
|
|
477
511
|
initialize_events
|
|
478
512
|
end
|
|
479
513
|
|
|
514
|
+
|
|
515
|
+
# Lists all arguments, that are set to be needed via the :argument
|
|
516
|
+
# syntax but are not set.
|
|
517
|
+
# This is needed for debugging purposes.
|
|
518
|
+
def list_unset_arguments
|
|
519
|
+
ret = Array.new
|
|
520
|
+
model.arguments.each { |name|
|
|
521
|
+
if !arguments.has_key?(name) then
|
|
522
|
+
ret << name
|
|
523
|
+
end }
|
|
524
|
+
ret
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
|
|
480
528
|
# Helper methods which creates all the necessary TaskEventGenerator
|
|
481
529
|
# objects and stores them in the #bound_events map
|
|
482
530
|
def initialize_events # :nodoc:
|
|
@@ -672,7 +720,7 @@ module Roby
|
|
|
672
720
|
def executable?; !abstract? && !partially_instanciated? && super end
|
|
673
721
|
# Returns true if this task's stop event is controlable
|
|
674
722
|
def interruptible?; event(:stop).controlable? end
|
|
675
|
-
# Set the executable flag. executable cannot be set to +false+
|
|
723
|
+
# Set the executable flag. executable cannot be set to +false+ if the
|
|
676
724
|
# task is running, and cannot be set to true on a finished task.
|
|
677
725
|
def executable=(flag)
|
|
678
726
|
return if flag == @executable
|
|
@@ -1119,22 +1167,8 @@ module Roby
|
|
|
1119
1167
|
|
|
1120
1168
|
# define an instance method which calls the event command
|
|
1121
1169
|
define_method("#{ev_s}!") do |*context|
|
|
1122
|
-
begin
|
|
1123
1170
|
generator = event(ev)
|
|
1124
1171
|
generator.call(*context)
|
|
1125
|
-
rescue EventNotExecutable => e
|
|
1126
|
-
if partially_instanciated?
|
|
1127
|
-
raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} which is partially instanciated"
|
|
1128
|
-
elsif !plan
|
|
1129
|
-
raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} but the task is in no plan"
|
|
1130
|
-
elsif !plan.executable?
|
|
1131
|
-
raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} but the plan is not executable"
|
|
1132
|
-
elsif abstract?
|
|
1133
|
-
raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} but the task is abstract"
|
|
1134
|
-
else
|
|
1135
|
-
raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} which is not executable: #{e.message}"
|
|
1136
|
-
end
|
|
1137
|
-
end
|
|
1138
1172
|
end
|
|
1139
1173
|
end
|
|
1140
1174
|
|
|
@@ -1611,6 +1645,7 @@ module Roby
|
|
|
1611
1645
|
unless defined? TaskStructure
|
|
1612
1646
|
TaskStructure = RelationSpace(Task)
|
|
1613
1647
|
end
|
|
1648
|
+
|
|
1614
1649
|
end
|
|
1615
1650
|
|
|
1616
1651
|
require 'roby/task-operations'
|
data/test/suite_core.rb
CHANGED
data/test/test_gui.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
|
|
2
|
+
require 'roby/test/common'
|
|
3
|
+
require 'roby/test/tasks/simple_task'
|
|
4
|
+
require 'roby/test/tasks/empty_task'
|
|
5
|
+
|
|
6
|
+
require 'roby/log/gui/relations'
|
|
7
|
+
|
|
8
|
+
class TC_Task < Test::Unit::TestCase
|
|
9
|
+
include Roby::Test
|
|
10
|
+
|
|
11
|
+
def test_index_handling
|
|
12
|
+
model = Ui::RelationConfigModel.new(nil)
|
|
13
|
+
[-1, 0, 222].each do |id|
|
|
14
|
+
idx = model.createIndex(0, 0, id)
|
|
15
|
+
assert_equal(id, Ui::RelationConfigModel.category_from_index(idx))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
data/test/test_task.rb
CHANGED
|
@@ -560,6 +560,17 @@ class TC_Task < Test::Unit::TestCase
|
|
|
560
560
|
assert_equal(task.event(:failed).last, task.terminal_event)
|
|
561
561
|
end
|
|
562
562
|
|
|
563
|
+
def assert_exception_message(klass, msg)
|
|
564
|
+
yield
|
|
565
|
+
flunk 'no exception raised'
|
|
566
|
+
rescue klass => e
|
|
567
|
+
unless msg === e.message
|
|
568
|
+
flunk "exception message '#{e.message}' does not match the expected pattern"
|
|
569
|
+
end
|
|
570
|
+
rescue Exception => e
|
|
571
|
+
flunk "expected an exception of class #{klass} but got #{e.full_message}"
|
|
572
|
+
end
|
|
573
|
+
|
|
563
574
|
def test_executable
|
|
564
575
|
model = Class.new(SimpleTask) do
|
|
565
576
|
event(:inter, :command => true)
|
|
@@ -570,6 +581,8 @@ class TC_Task < Test::Unit::TestCase
|
|
|
570
581
|
assert_raises(EventNotExecutable) { task.start! }
|
|
571
582
|
assert_raises(EventNotExecutable) { task.event(:start).call }
|
|
572
583
|
|
|
584
|
+
|
|
585
|
+
|
|
573
586
|
plan.discover(task)
|
|
574
587
|
assert(task.executable?)
|
|
575
588
|
assert_nothing_raised { task.event(:start).call(nil) }
|
|
@@ -593,6 +606,83 @@ class TC_Task < Test::Unit::TestCase
|
|
|
593
606
|
task.executable = nil
|
|
594
607
|
assert(task.executable?)
|
|
595
608
|
end
|
|
609
|
+
|
|
610
|
+
class ParameterizedTask < Roby::Task
|
|
611
|
+
arguments :arg
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
class AbstractTask < Roby::Task
|
|
615
|
+
abstract
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
class NotExecutablePlan < Roby::Plan
|
|
619
|
+
def executable?
|
|
620
|
+
false
|
|
621
|
+
end
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def exception_propagator(task, relation)
|
|
625
|
+
first_task = SimpleTask.new
|
|
626
|
+
second_task = task
|
|
627
|
+
first_task.send(relation, :start, second_task, :start)
|
|
628
|
+
first_task.start!
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
def check_direct_start(substring, check_signaling)
|
|
632
|
+
error = yield
|
|
633
|
+
assert_exception_message(EventNotExecutable, substring) { error.start! }
|
|
634
|
+
error = yield
|
|
635
|
+
assert_exception_message(EventNotExecutable, substring) {error.event(:start).call(nil)}
|
|
636
|
+
error = yield
|
|
637
|
+
assert_exception_message(EventNotExecutable, substring) {error.event(:start).emit(nil)}
|
|
638
|
+
|
|
639
|
+
if check_signaling then
|
|
640
|
+
error = yield
|
|
641
|
+
assert_exception_message(EventNotExecutable, substring) do
|
|
642
|
+
exception_propagator(error, :on)
|
|
643
|
+
end
|
|
644
|
+
error = yield
|
|
645
|
+
assert_exception_message(EventNotExecutable, substring) do
|
|
646
|
+
exception_propagator(error, :forward)
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def test_exception_refinement
|
|
652
|
+
# test for partially instanciation
|
|
653
|
+
check_direct_start(/partially instanciated/,true) do
|
|
654
|
+
plan.discover(task = ParameterizedTask.new)
|
|
655
|
+
task
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
#test for a task that is in no plan
|
|
659
|
+
check_direct_start(/no plan/,false) do
|
|
660
|
+
SimpleTask.new
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
#test for an abstract task
|
|
664
|
+
check_direct_start(/abstract/,true) do
|
|
665
|
+
plan.discover(task = AbstractTask.new)
|
|
666
|
+
task
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
#test for a not executable plan
|
|
670
|
+
erroneous_plan = NotExecutablePlan.new
|
|
671
|
+
check_direct_start(/plan is not executable/,false) do
|
|
672
|
+
erroneous_plan.discover(task = SimpleTask.new)
|
|
673
|
+
task
|
|
674
|
+
end
|
|
675
|
+
erroneous_plan.garbage_collect
|
|
676
|
+
|
|
677
|
+
#test for a not executable task
|
|
678
|
+
check_direct_start(/is not executable/,true) do
|
|
679
|
+
plan.discover(task = SimpleTask.new)
|
|
680
|
+
task.executable = false
|
|
681
|
+
task
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
|
|
596
686
|
|
|
597
687
|
def test_task_success_failure
|
|
598
688
|
FlexMock.use do |mock|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: roby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sylvain Joyeux
|
|
@@ -9,11 +9,12 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date:
|
|
12
|
+
date: 2009-03-01 00:00:00 +01:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: facets
|
|
17
|
+
type: :runtime
|
|
17
18
|
version_requirement:
|
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
|
19
20
|
requirements:
|
|
@@ -23,6 +24,7 @@ dependencies:
|
|
|
23
24
|
version:
|
|
24
25
|
- !ruby/object:Gem::Dependency
|
|
25
26
|
name: activesupport
|
|
27
|
+
type: :runtime
|
|
26
28
|
version_requirement:
|
|
27
29
|
version_requirements: !ruby/object:Gem::Requirement
|
|
28
30
|
requirements:
|
|
@@ -32,6 +34,7 @@ dependencies:
|
|
|
32
34
|
version:
|
|
33
35
|
- !ruby/object:Gem::Dependency
|
|
34
36
|
name: utilrb
|
|
37
|
+
type: :runtime
|
|
35
38
|
version_requirement:
|
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
40
|
requirements:
|
|
@@ -39,14 +42,35 @@ dependencies:
|
|
|
39
42
|
- !ruby/object:Gem::Version
|
|
40
43
|
version: 1.3.1
|
|
41
44
|
version:
|
|
45
|
+
- !ruby/object:Gem::Dependency
|
|
46
|
+
name: rake
|
|
47
|
+
type: :runtime
|
|
48
|
+
version_requirement:
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.8.3
|
|
54
|
+
version:
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: flexmock
|
|
57
|
+
type: :development
|
|
58
|
+
version_requirement:
|
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: "0"
|
|
64
|
+
version:
|
|
42
65
|
- !ruby/object:Gem::Dependency
|
|
43
66
|
name: hoe
|
|
67
|
+
type: :development
|
|
44
68
|
version_requirement:
|
|
45
69
|
version_requirements: !ruby/object:Gem::Requirement
|
|
46
70
|
requirements:
|
|
47
71
|
- - ">="
|
|
48
72
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: 1.
|
|
73
|
+
version: 1.9.0
|
|
50
74
|
version:
|
|
51
75
|
description: A plan-based control framework for autonomous systems
|
|
52
76
|
email:
|
|
@@ -230,6 +254,7 @@ extra_rdoc_files:
|
|
|
230
254
|
- test/test_control.rb
|
|
231
255
|
- test/test_event.rb
|
|
232
256
|
- test/test_exceptions.rb
|
|
257
|
+
- test/test_gui.rb
|
|
233
258
|
- test/test_interface.rb
|
|
234
259
|
- test/test_log.rb
|
|
235
260
|
- test/test_log_server.rb
|
|
@@ -476,6 +501,7 @@ files:
|
|
|
476
501
|
- test/test_control.rb
|
|
477
502
|
- test/test_event.rb
|
|
478
503
|
- test/test_exceptions.rb
|
|
504
|
+
- test/test_gui.rb
|
|
479
505
|
- test/test_interface.rb
|
|
480
506
|
- test/test_log.rb
|
|
481
507
|
- test/test_log_server.rb
|
|
@@ -528,43 +554,44 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
528
554
|
requirements: []
|
|
529
555
|
|
|
530
556
|
rubyforge_project: roby
|
|
531
|
-
rubygems_version: 1.
|
|
557
|
+
rubygems_version: 1.2.0
|
|
532
558
|
signing_key:
|
|
533
559
|
specification_version: 2
|
|
534
560
|
summary: A plan-based control framework for autonomous systems
|
|
535
561
|
test_files:
|
|
536
|
-
- test/
|
|
537
|
-
- test/
|
|
538
|
-
- test/
|
|
562
|
+
- test/distributed/test_communication.rb
|
|
563
|
+
- test/distributed/test_connection.rb
|
|
564
|
+
- test/distributed/test_execution.rb
|
|
565
|
+
- test/distributed/test_mixed_plan.rb
|
|
566
|
+
- test/distributed/test_plan_notifications.rb
|
|
567
|
+
- test/distributed/test_protocol.rb
|
|
568
|
+
- test/distributed/test_query.rb
|
|
569
|
+
- test/distributed/test_remote_plan.rb
|
|
570
|
+
- test/distributed/test_transaction.rb
|
|
571
|
+
- test/planning/test_loops.rb
|
|
572
|
+
- test/planning/test_model.rb
|
|
573
|
+
- test/planning/test_task.rb
|
|
539
574
|
- test/relations/test_conflicts.rb
|
|
540
575
|
- test/relations/test_ensured.rb
|
|
576
|
+
- test/relations/test_executed_by.rb
|
|
577
|
+
- test/relations/test_hierarchy.rb
|
|
578
|
+
- test/relations/test_planned_by.rb
|
|
579
|
+
- test/test_bgl.rb
|
|
580
|
+
- test/test_control.rb
|
|
581
|
+
- test/test_event.rb
|
|
541
582
|
- test/test_exceptions.rb
|
|
542
|
-
- test/
|
|
543
|
-
- test/planning/test_loops.rb
|
|
544
|
-
- test/planning/test_task.rb
|
|
545
|
-
- test/planning/test_model.rb
|
|
546
|
-
- test/test_transactions.rb
|
|
547
|
-
- test/test_support.rb
|
|
548
|
-
- test/test_relations.rb
|
|
583
|
+
- test/test_gui.rb
|
|
549
584
|
- test/test_interface.rb
|
|
585
|
+
- test/test_log.rb
|
|
550
586
|
- test/test_log_server.rb
|
|
551
|
-
- test/test_event.rb
|
|
552
|
-
- test/test_bgl.rb
|
|
553
587
|
- test/test_plan.rb
|
|
554
|
-
- test/test_thread_task.rb
|
|
555
|
-
- test/distributed/test_query.rb
|
|
556
|
-
- test/distributed/test_communication.rb
|
|
557
|
-
- test/distributed/test_transaction.rb
|
|
558
|
-
- test/distributed/test_remote_plan.rb
|
|
559
|
-
- test/distributed/test_plan_notifications.rb
|
|
560
|
-
- test/distributed/test_mixed_plan.rb
|
|
561
|
-
- test/distributed/test_connection.rb
|
|
562
|
-
- test/distributed/test_execution.rb
|
|
563
|
-
- test/distributed/test_protocol.rb
|
|
564
|
-
- test/test_task.rb
|
|
565
|
-
- test/test_control.rb
|
|
566
|
-
- test/test_transactions_proxy.rb
|
|
567
|
-
- test/test_testcase.rb
|
|
568
588
|
- test/test_propagation.rb
|
|
589
|
+
- test/test_query.rb
|
|
590
|
+
- test/test_relations.rb
|
|
569
591
|
- test/test_state.rb
|
|
570
|
-
- test/
|
|
592
|
+
- test/test_support.rb
|
|
593
|
+
- test/test_task.rb
|
|
594
|
+
- test/test_testcase.rb
|
|
595
|
+
- test/test_thread_task.rb
|
|
596
|
+
- test/test_transactions.rb
|
|
597
|
+
- test/test_transactions_proxy.rb
|