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
data/bin/roby
CHANGED
data/bin/roby-log
CHANGED
@@ -75,13 +75,24 @@ when "stats"
|
|
75
75
|
filename = if ARGV[0] == "--csv"
|
76
76
|
do_csv = true
|
77
77
|
ARGV[1]
|
78
|
-
|
78
|
+
elsif ARGV[0] == "--help"
|
79
|
+
puts "roby-log stats [--csv]"
|
80
|
+
puts " displays statistics about the execution timings"
|
81
|
+
puts " if the --csv option is given, a table with all"
|
82
|
+
puts " the timings is output on stdout instead"
|
83
|
+
exit(0)
|
84
|
+
else
|
79
85
|
ARGV[0]
|
80
86
|
end
|
81
87
|
io = Roby::Log.open(filename)
|
82
88
|
|
83
89
|
cycle_count = io.index_data.size
|
84
|
-
|
90
|
+
timespan = io.range
|
91
|
+
puts "#{cycle_count} cycles between #{timespan.first.to_hms} and #{timespan.last.to_hms}"
|
92
|
+
cpu_time = io.index_data.inject(0) { |old, info| old + info[:cpu_time] } / 1000
|
93
|
+
real_time = timespan.last - timespan.first
|
94
|
+
ratio = cpu_time / real_time
|
95
|
+
puts "Time: %.2fs CPU / %.2fs real (%i%% CPU use)" % [cpu_time, real_time, ratio * 100]
|
85
96
|
|
86
97
|
if io.index_data.first.has_key?(:event_count)
|
87
98
|
min, max = nil
|
@@ -116,13 +127,12 @@ when "replay"
|
|
116
127
|
stream.open
|
117
128
|
main.add_stream(stream)
|
118
129
|
end
|
119
|
-
else
|
120
|
-
STDERR.puts parser
|
121
|
-
exit(0)
|
122
130
|
end
|
123
131
|
else
|
124
132
|
remaining.each do |file|
|
125
|
-
|
133
|
+
if !File.exists?(file)
|
134
|
+
STDERR.puts "WARN: #{file} does not exist"
|
135
|
+
elsif streams = Roby.app.data_streams_of([file])
|
126
136
|
streams.each do |s|
|
127
137
|
s.open
|
128
138
|
main.add_stream(s)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This is the YAML configuration file for webgen used to set configuration options.
|
2
|
+
#
|
3
|
+
# The general syntax is:
|
4
|
+
#
|
5
|
+
# configuration.option.name: value
|
6
|
+
#
|
7
|
+
# For example, to set a different default language, you would do:
|
8
|
+
#
|
9
|
+
# website.lang: de
|
10
|
+
#
|
11
|
+
# Have a look at the documentation of the individual configuration options to see
|
12
|
+
# the allowed format of the values. Since this is a YAML file, you can easily set
|
13
|
+
# configuration options to strings, integers, dates, arrays, hashes and more.
|
14
|
+
#
|
15
|
+
# The available configuration options can be listed using the `webgen config`
|
16
|
+
# command, for example: `webgen config sourcehandler` will list all options starting
|
17
|
+
# with sourcehandler.
|
18
|
+
default_processing_pipeline:
|
19
|
+
Page: rdoc,tags,blocks
|
20
|
+
|
21
|
+
|
22
|
+
default_meta_info:
|
23
|
+
Webgen::SourceHandler::Page:
|
24
|
+
in_menu: true
|
25
|
+
|
26
|
+
tag.menu.nested: false
|
27
|
+
|
28
|
+
tag.breadcrumbtrail.omit_index_path: true
|
29
|
+
|
30
|
+
rdoclinks.base_url: /api
|
31
|
+
rdoclinks.base_module: Roby
|
32
|
+
|
33
|
+
tag.coderay.line_numbers: false
|
34
|
+
tag.coderay.lang: ruby
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# = webgen extensions directory
|
2
|
+
#
|
3
|
+
# All init.rb files anywhere under this directory get automatically loaded on a webgen run. This
|
4
|
+
# allows you to add your own extensions to webgen or to modify webgen's core!
|
5
|
+
#
|
6
|
+
# If you don't need this feature you can savely delete this file and the directory in which it is!
|
7
|
+
#
|
8
|
+
# The +config+ variable below can be used to access the Webgen::Configuration object for the current
|
9
|
+
# website.
|
10
|
+
config = Webgen::WebsiteAccess.website.config
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
|
13
|
+
require 'ext/rdoc_links'
|
14
|
+
require 'ext/previous_next'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'webgen/tag'
|
2
|
+
class PrevNextTag
|
3
|
+
include Webgen::Tag::Base
|
4
|
+
|
5
|
+
def call(tag, body, context)
|
6
|
+
node = context.content_node
|
7
|
+
while !node.is_file?
|
8
|
+
node = node.parent
|
9
|
+
end
|
10
|
+
|
11
|
+
siblings = node.parent.children.sort
|
12
|
+
siblings.delete_if { |n| !n.meta_info['in_menu'] }
|
13
|
+
prev, _ = siblings.
|
14
|
+
enum_for(:each_cons, 2).
|
15
|
+
find { |prev, this| this == node }
|
16
|
+
_, nxt = siblings.
|
17
|
+
enum_for(:each_cons, 2).
|
18
|
+
find { |this, nxt| this == node }
|
19
|
+
|
20
|
+
content = if tag == "next" && nxt
|
21
|
+
node.link_to(nxt)
|
22
|
+
elsif tag == "previous" && prev
|
23
|
+
node.link_to(prev)
|
24
|
+
end
|
25
|
+
|
26
|
+
if content
|
27
|
+
if !body.empty?
|
28
|
+
body.gsub '%', content
|
29
|
+
else
|
30
|
+
content
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
config = Webgen::WebsiteAccess.website.config
|
37
|
+
config['contentprocessor.tags.map']['previous'] = 'PrevNextTag'
|
38
|
+
config['contentprocessor.tags.map']['next'] = 'PrevNextTag'
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'webgen/tag'
|
2
|
+
class RdocLinks
|
3
|
+
include Webgen::Tag::Base
|
4
|
+
|
5
|
+
def call(tag, body, context)
|
6
|
+
name = param('rdoclinks.name')
|
7
|
+
if base_module = param('rdoclinks.base_module')
|
8
|
+
name = base_module + "::" + name
|
9
|
+
end
|
10
|
+
|
11
|
+
if name =~ /(?:\.|#)(\w+)$/
|
12
|
+
class_name = $`
|
13
|
+
method_name = $1
|
14
|
+
else
|
15
|
+
class_name = name
|
16
|
+
end
|
17
|
+
|
18
|
+
path = class_name.split('::')
|
19
|
+
path[-1] += ".html"
|
20
|
+
url = "#{param('rdoclinks.base_url')}/#{path.join("/")}"
|
21
|
+
|
22
|
+
"<a href=\"#{context.ref_node.route_to(url)}\">#{param('rdoclinks.name')}</a>"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
config = Webgen::WebsiteAccess.website.config
|
27
|
+
config.rdoclinks.name "", :mandatory => 'default'
|
28
|
+
config.rdoclinks.base_webgen "", :mandatory => false
|
29
|
+
config.rdoclinks.base_url "", :mandatory => false
|
30
|
+
config.rdoclinks.base_module nil, :mandatory => false
|
31
|
+
config.rdoclinks.full_name false, :mandatory => false
|
32
|
+
config['contentprocessor.tags.map']['rdoc_class'] = 'RdocLinks'
|
33
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= Roby's User's Guide
|
2
|
+
|
3
|
+
This guide is *definitely* a work in progress -- actually it is for now an
|
4
|
+
embryo of a user's guide, but things should improve ...
|
5
|
+
|
6
|
+
For people which want to extend Roby, see {this
|
7
|
+
guide}[link:files/doc/extending/index_rdoc.html]
|
8
|
+
|
9
|
+
== Table of Contents
|
10
|
+
|
11
|
+
* {Table of Contents}[link:files/doc/using/index_rdoc.html]
|
12
|
+
|
13
|
+
|
14
|
+
* {Overview}[link:files/doc/using/overview_rdoc.html]
|
15
|
+
* {Plan modifications}[link:files/doc/using/plan_modifications_rdoc.html]
|
16
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
= Overview
|
2
|
+
|
3
|
+
This page describes the various components that form a Roby application. It is
|
4
|
+
meant to be an "entry point" for people to understand what classes are there
|
5
|
+
for. This describes the software architecture of the upcoming v0.8.
|
6
|
+
|
7
|
+
== Life and death of a Roby Controller
|
8
|
+
|
9
|
+
One Roby::Application instance is created per Roby controller. This class sets
|
10
|
+
up the various central objects (Roby::Plan, Roby::ExecutionEngine and Roby::DecisionControl, see
|
11
|
+
below), starts the execution engine and loads the relevant configuration files.
|
12
|
+
|
13
|
+
A Roby controller offers a DRb main server which is a Roby::Interface instance.
|
14
|
+
The best way to interact through this channel is to use a Roby::RemoteInterface
|
15
|
+
instance, which handles some custom marshalling/demarshalling of data, offering
|
16
|
+
a transparent interface to the remote controller. The <tt>scripts/shell</tt>
|
17
|
+
default script sets this up properly.
|
18
|
+
|
19
|
+
A Roby controller will shut down in the following conditions:
|
20
|
+
* CTRL+C is hit in the controller's main terminal
|
21
|
+
* the 'exit' command is sent through the remote shell
|
22
|
+
* a framework exception is detected, meaning an exception which is not part of
|
23
|
+
the plan-based error recovery mechanism (everything but event commands, event
|
24
|
+
handlers and polling blocks).
|
25
|
+
|
26
|
+
== Plan execution
|
27
|
+
|
28
|
+
The plan representation and the plan execution is handled by three objects:
|
29
|
+
* a Roby::Plan object which manages the various tasks and events which describe the
|
30
|
+
system's plan.
|
31
|
+
* an Roby::ExecutionEngine object which manipulates that Roby::Plan object. It propagates
|
32
|
+
events according to a set of "initial event", a set of events that are
|
33
|
+
considered to be emitted. They can be generated by external communication (for
|
34
|
+
instance from external robotic control frameworks like GenoM or Orocos), or
|
35
|
+
internally by the scheduler object (see ExecutionEngine#scheduler). The engine
|
36
|
+
is also responsible for reaction to errors and for the garbage collection
|
37
|
+
mechanism, through which tasks that are useless for the system's goals are
|
38
|
+
automatically killed and removed.
|
39
|
+
* a Roby::DecisionControl object which handles runtime error resolution (i.e.
|
40
|
+
situations which require choosing between multiple course of action). For
|
41
|
+
instance, if a signal leads to a task conflict -- i.e. if the signal would
|
42
|
+
start a task which conflicts with another task -- the DecisionControl#conflict
|
43
|
+
method is called. The default policy is to postpone starting the new task
|
44
|
+
until all the conflicting tasks are stopped. Other policies could be to raise
|
45
|
+
an error for instance.
|
46
|
+
|
47
|
+
The three "main" instances of these objects -- i.e. the ones that are supposed
|
48
|
+
to interact directly with the underlying robotic system -- are available
|
49
|
+
through the Roby.plan, Roby.engine and Roby.control attributes. These
|
50
|
+
attributes are set up at application start by Roby::Application#run (see below).
|
51
|
+
This is for an easy access in the main controller, but the architecture allows
|
52
|
+
to run multiple plans in parallel by binding those three different objects
|
53
|
+
yourself.
|
54
|
+
|
55
|
+
== A note about multi-robot systems
|
56
|
+
|
57
|
+
Until now, the Roby plan manager is able to run <b>bi-robot</b> plans, i.e.
|
58
|
+
plans where only two robots are interacting with each other. Extending that to
|
59
|
+
multi-robot is definitely on the TODO list of the project, but unfortunately it
|
60
|
+
will wait until multi-robot is back at the the center of my research. If you are
|
61
|
+
interested in doing it, of course, feel free to contact me ;-)
|
62
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
= Plan representation and modifications to plans
|
2
|
+
|
3
|
+
Understanding the plan model, and how to modify it, is central to the use of
|
4
|
+
Roby. In effect, the plan *is* the information on which the controller bases
|
5
|
+
itself to control the robot ...
|
6
|
+
|
7
|
+
== Plan objects
|
8
|
+
In Roby, plans are made of tasks and events. See {my
|
9
|
+
papers}[link:files/doc/papers_rdoc.html] for an in-depth description of the
|
10
|
+
model.
|
11
|
+
|
12
|
+
On the one hand, Roby::EventGenerator instances represent the plan's _possible_
|
13
|
+
events. This is by contrast to the Roby::Event class, whose instances represent
|
14
|
+
the <em>actual events</em>. In other words, an Event instance represent an
|
15
|
+
event which has already been emitted while an EventGenerator instance
|
16
|
+
represents a source of events, therefore a kind of events that could possibly
|
17
|
+
be emitted.
|
18
|
+
|
19
|
+
On the other hand, instances of Roby::Task represent the activities of the
|
20
|
+
system. Special subclasses of Roby::EventGenerator and Roby::Event are used in
|
21
|
+
tasks, to represent some particular properties of task's events:
|
22
|
+
Roby::TaskEventGenerator and Roby::TaskEvent.
|
23
|
+
|
24
|
+
== Plan relations
|
25
|
+
Roby::EventGenerator instances can be linked to each other through the use of
|
26
|
+
<em>event relations</em>, as Roby::Task can be linked through the use of <em>task relations</em>.
|
27
|
+
Task and event relations are defined in the Roby::EventStructure and
|
28
|
+
Roby::TaskStructure relation spaces (Roby::RelationSpace instances), through the use of
|
29
|
+
Roby::RelationSpace#relation. Each relation object (for instance
|
30
|
+
Roby::EventStructure::Signal or Roby::TaskStructure::Hierarchy) is an instance
|
31
|
+
of the Roby::RelationGraph class.
|
32
|
+
|
33
|
+
In order to be managed in these relations, tasks and events
|
34
|
+
include the Roby::DirectedRelationSupport mixin to provide the basic
|
35
|
+
management tools needed by the RelationGraph instances. Moreover, all relation
|
36
|
+
types define specific methods which allow to more directly modify the relation
|
37
|
+
(like #add_signal, #each_parent or #parents in Hierarchy). See RelationSpace#relation
|
38
|
+
for details. Due to issues with Ruby's documentation system, those methods are
|
39
|
+
listed in
|
40
|
+
|
41
|
+
=== Plan modification
|
42
|
+
Modifying the plan therefore boils down to two things:
|
43
|
+
1. adding and removing tasks and events in the plan
|
44
|
+
2. adding and removing relations between objects of the same type (between tasks
|
45
|
+
or between events).
|
46
|
+
|
47
|
+
The first point is done by the following methods:
|
48
|
+
* Roby::Plan#discover: simply add tasks and events
|
49
|
+
* Roby::Plan#add_mission: adds special tasks, called missions. Missions are the
|
50
|
+
tasks the robot is supposed to execute. They are not subject to the plan's
|
51
|
+
garbage collection, and the tasks that are useful to them are not either.
|
52
|
+
|
53
|
+
|
54
|
+
To ease the plan management process, some synthetic
|
55
|
+
operations are defined on Roby::Plan:
|
56
|
+
* the _replacement_ operation: Roby::Plan#replace_task and
|
57
|
+
Roby::Plan#replace. #replace_task(a, b) will replace +a+ by +b+ in the plan.
|
58
|
+
It means that the operators will add to +b+ all the children and parents of +a+
|
59
|
+
in all relations, and do the same with +b+ and +a+'s events. Moreover, it will
|
60
|
+
remove them from +a+. #replace(a, b) will do the same, but constraining itself
|
61
|
+
to the _parents_ of +b+ and +b+'s events. It therefore replaces +a+ and its
|
62
|
+
generated subplan (i.e. +a+ and all children of +a+) by +b+ and its subplan.
|
63
|
+
* the _respawning_ operation: a given task is replaced by a new task of the same
|
64
|
+
kind and with the same parameters. This is used mainly to workaround a
|
65
|
+
"fragile" task which crashed spuriously.
|
66
|
+
|
67
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
title: Abstraction as task dependencies
|
3
|
+
sort_info: 200
|
4
|
+
--- name:content pipeline:tags,markdown,blocks
|
5
|
+
|
6
|
+
Dependency relations
|
7
|
+
--------------------
|
8
|
+
* Dependency is also a refinement relation
|
9
|
+
* the syntax and other concepts
|
10
|
+
- depends\_on :model
|
11
|
+
- fullfilled\_model
|
12
|
+
- fullfilled\_events
|
13
|
+
|
14
|
+
Plan modifications and model abstraction
|
15
|
+
----------------------------------------
|
16
|
+
|
17
|
+
* the replace operator
|
18
|
+
* semantics of the :returns flag in this context
|
19
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
title: Representing Abstraction
|
3
|
+
routed_title: Representing Abstraction
|
4
|
+
sort_info: 0
|
5
|
+
--- name:content pipeline:tags,markdown,blocks
|
6
|
+
Being able to abstract away the little details of execution is crucial. Indeed,
|
7
|
+
it allows to apply high-level reasoning algorithms, that are not able to take
|
8
|
+
into account too much details.
|
9
|
+
|
10
|
+
Roby offers a unique ability: to link in the same plan the high-level parts of
|
11
|
+
the plan and the low-level ones. What this section will present is how, using
|
12
|
+
Roby's plan model, one can represent the _mechanism_ of abstraction. In other
|
13
|
+
words, what are the details that are lost in the abstraction mechanism.
|
14
|
+
|
15
|
+
More specifically, we will see the following:
|
16
|
+
|
17
|
+
* the object-oriented nature of Roby's plan model: how task models are related
|
18
|
+
to each other, and the notion of abstract models.
|
19
|
+
* how the hierarchy relation uses this OO principles to not over-constrain the
|
20
|
+
plan. We will see that the hierarchy relation can be used to precisely
|
21
|
+
represent what is _needed_ and not only what _is_.
|
22
|
+
* how the execution flow of the low-level parts of the plan can be linked to the
|
23
|
+
higher-level execution flow by means of the _forwarding_ relation.
|
24
|
+
* how it is possible to cleanly (and easily) build event commands using tasks
|
25
|
+
|
26
|
+
To understand the content of this section, we will assume that you read and
|
27
|
+
understood the [basics](../basics/index.html).
|
28
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
---
|
2
|
+
title: Task Models
|
3
|
+
sort_info: 100
|
4
|
+
--- name:content pipeline:tags,markdown,blocks
|
5
|
+
|
6
|
+
* relationship between models
|
7
|
+
- semantics of subclasses
|
8
|
+
- rules of subclasses
|
9
|
+
- the TaskModelTag hack
|
10
|
+
* abstract models
|
11
|
+
- why is it useful => abstract actions that have to be chosen later on.
|
12
|
+
- syntax
|
13
|
+
- the :returns flag in planning models => example
|
@@ -0,0 +1,139 @@
|
|
1
|
+
---
|
2
|
+
title: A First Roby Application
|
3
|
+
sort_info: 300
|
4
|
+
--- pipeline:tags,markdown,blocks
|
5
|
+
|
6
|
+
This page will present another facet of Roby. What we saw until now is how,
|
7
|
+
in Roby, one can represent the task actions and build plans that describe the
|
8
|
+
task execution. What we will see here is how Roby tie the different models
|
9
|
+
together to offer an application environment.
|
10
|
+
|
11
|
+
{include_file: {filename: src/basics_shell_header.txt, escape_html: false}}
|
12
|
+
|
13
|
+
Creation
|
14
|
+
--------
|
15
|
+
|
16
|
+
Go into a *regular shell* (i.e. not the Ruby shell) and create a new directory.
|
17
|
+
That directory will become your first Roby application by running "roby init":
|
18
|
+
|
19
|
+
$ mkdir first_app
|
20
|
+
$ cd first_app
|
21
|
+
$ roby init
|
22
|
+
creating tasks/
|
23
|
+
creating tasks/.gitattributes
|
24
|
+
creating scripts/
|
25
|
+
creating scripts/test
|
26
|
+
creating scripts/shell
|
27
|
+
creating scripts/server
|
28
|
+
creating scripts/run
|
29
|
+
creating scripts/results
|
30
|
+
creating scripts/replay
|
31
|
+
creating scripts/generate/
|
32
|
+
creating scripts/generate/bookmarks
|
33
|
+
creating scripts/distributed
|
34
|
+
creating planners/
|
35
|
+
creating planners/main.rb
|
36
|
+
creating data/
|
37
|
+
creating data/.gitattributes
|
38
|
+
creating controllers/
|
39
|
+
creating controllers/.gitattributes
|
40
|
+
creating config/
|
41
|
+
creating config/roby.yml
|
42
|
+
creating config/init.rb
|
43
|
+
creating config/app.yml
|
44
|
+
creating Rakefile
|
45
|
+
creating README.txt
|
46
|
+
|
47
|
+
There's a lot of stuff created, but don't worry we'll learn what this is all
|
48
|
+
about later on. Right now, we're only interested in two small parts of it:
|
49
|
+
|
50
|
+
* the tasks/ directory, which is where task models (task classes) should be
|
51
|
+
defined
|
52
|
+
* the robot's controllers. These files contain the code that is run when the
|
53
|
+
application is started.
|
54
|
+
|
55
|
+
The goForward robot
|
56
|
+
-------------------
|
57
|
+
As an introduction, we will create a simulated robot controller which makes the
|
58
|
+
robot go forward at constant speed.
|
59
|
+
|
60
|
+
First, let's create the files specific to this robot
|
61
|
+
|
62
|
+
$ roby robot goForward
|
63
|
+
creating planners/goForward/
|
64
|
+
creating planners/goForward/main.rb
|
65
|
+
creating tasks/goForward/
|
66
|
+
creating tasks/goForward/.gitattributes
|
67
|
+
creating controllers/goForward.rb
|
68
|
+
creating config/goForward.rb
|
69
|
+
|
70
|
+
Let's define the task model. Edit tasks/go\_forward.rb and add
|
71
|
+
|
72
|
+
{coderay:: ruby}
|
73
|
+
class GoForward < Roby::Task
|
74
|
+
# The GoForward task needs the robot speed to be specified
|
75
|
+
arguments :speed
|
76
|
+
|
77
|
+
# Block called at every execution loop if the task is running. It simulates
|
78
|
+
# the robot moving at the specified speed.
|
79
|
+
poll do
|
80
|
+
State.pos.x += speed
|
81
|
+
end
|
82
|
+
|
83
|
+
# This task does not need any specific action to stop
|
84
|
+
terminates
|
85
|
+
end
|
86
|
+
{coderay}
|
87
|
+
|
88
|
+
In the controller file, controllers/goForward.rb, we add the code that
|
89
|
+
should run at startup:
|
90
|
+
|
91
|
+
{coderay:: ruby}
|
92
|
+
# Define the original value of x
|
93
|
+
State.pos.x = 0
|
94
|
+
|
95
|
+
# Will display the value of x every 1 second
|
96
|
+
Roby.every(1) do
|
97
|
+
puts State.pos.x
|
98
|
+
end
|
99
|
+
|
100
|
+
# Create the task and start moving !
|
101
|
+
Roby.plan.insert(go = GoForward.new(:speed => 0.1))
|
102
|
+
puts "Going forward at speed #{go.speed}"
|
103
|
+
go.start!
|
104
|
+
{coderay}
|
105
|
+
|
106
|
+
You can then start the robot controller with scripts/run and stop it with CTRL+C.
|
107
|
+
|
108
|
+
$ scripts/run goForward
|
109
|
+
335705:25:08.324 (goForward) loading controller file /home/doudou/dev/roby-tutorials/controllers/goForward.rb
|
110
|
+
Going forward at speed 0.1
|
111
|
+
335705:25:08.356 (goForward) done initialization
|
112
|
+
0
|
113
|
+
0.9
|
114
|
+
1.9
|
115
|
+
2.9
|
116
|
+
335705:25:16.449 (Roby) received interruption request
|
117
|
+
335705:25:16.524 (Roby) control quitting. Waiting for 1 tasks to finish (1 tasks still in plan)
|
118
|
+
|
119
|
+
Broken down explanation
|
120
|
+
-----------------------
|
121
|
+
* the Roby::State object holds all the configuration and state data that
|
122
|
+
represents the robot's state. In our case, we initialize the robot's position
|
123
|
+
in the controller file, and then update it when the robot moves.
|
124
|
+
|
125
|
+
* to understand the meaning of the __poll__ statement, you have to understand
|
126
|
+
the idea behind Roby's execution model. Roby relies on a _synchronous_
|
127
|
+
execution model, which is basically a two-steps loops (a more detailed
|
128
|
+
explanation will come later). This two-steps loops is basically:
|
129
|
+
1. gather all events that have occured since the last loop
|
130
|
+
2. propagate to those events through the signal and forward relations
|
131
|
+
|
132
|
+
In practice, this event loop runs with a fixed period which is by default
|
133
|
+
100ms. This period can be changed in the configuration file config/app.yml.
|
134
|
+
|
135
|
+
Now, what is the role of __poll__ here ? The block given to +poll+ is executed
|
136
|
+
at each execution cycle _while the task is running_. It can therefore be
|
137
|
+
used to _implement_ the actual task functionality (or to check the state of
|
138
|
+
external processes, ...)
|
139
|
+
|