roby 0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +29 -0
- data/History.txt +4 -0
- data/License-fr.txt +519 -0
- data/License.txt +515 -0
- data/Manifest.txt +245 -0
- data/NOTES +4 -0
- data/README.txt +163 -0
- data/Rakefile +161 -0
- data/TODO.txt +146 -0
- data/app/README.txt +24 -0
- data/app/Rakefile +8 -0
- data/app/config/ROBOT.rb +5 -0
- data/app/config/app.yml +91 -0
- data/app/config/init.rb +7 -0
- data/app/config/roby.yml +3 -0
- data/app/controllers/.gitattributes +0 -0
- data/app/controllers/ROBOT.rb +2 -0
- data/app/data/.gitattributes +0 -0
- data/app/planners/ROBOT/main.rb +6 -0
- data/app/planners/main.rb +5 -0
- data/app/scripts/distributed +3 -0
- data/app/scripts/generate/bookmarks +3 -0
- data/app/scripts/replay +3 -0
- data/app/scripts/results +3 -0
- data/app/scripts/run +3 -0
- data/app/scripts/server +3 -0
- data/app/scripts/shell +3 -0
- data/app/scripts/test +3 -0
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby +210 -0
- data/bin/roby-log +168 -0
- data/bin/roby-shell +25 -0
- data/doc/images/event_generalization.png +0 -0
- data/doc/images/exception_propagation_1.png +0 -0
- data/doc/images/exception_propagation_2.png +0 -0
- data/doc/images/exception_propagation_3.png +0 -0
- data/doc/images/exception_propagation_4.png +0 -0
- data/doc/images/exception_propagation_5.png +0 -0
- data/doc/images/replay_handler_error.png +0 -0
- data/doc/images/replay_handler_error_0.png +0 -0
- data/doc/images/replay_handler_error_1.png +0 -0
- data/doc/images/roby_cycle_overview.png +0 -0
- data/doc/images/roby_replay_02.png +0 -0
- data/doc/images/roby_replay_03.png +0 -0
- data/doc/images/roby_replay_04.png +0 -0
- data/doc/images/roby_replay_event_representation.png +0 -0
- data/doc/images/roby_replay_first_state.png +0 -0
- data/doc/images/roby_replay_relations.png +0 -0
- data/doc/images/roby_replay_startup.png +0 -0
- data/doc/images/task_event_generalization.png +0 -0
- data/doc/papers.rdoc +11 -0
- data/doc/styles/allison.css +314 -0
- data/doc/styles/allison.js +316 -0
- data/doc/styles/allison.rb +276 -0
- data/doc/styles/jamis.rb +593 -0
- data/doc/tutorials/01-GettingStarted.rdoc +86 -0
- data/doc/tutorials/02-GoForward.rdoc +220 -0
- data/doc/tutorials/03-PlannedPath.rdoc +268 -0
- data/doc/tutorials/04-EventPropagation.rdoc +236 -0
- data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
- data/doc/tutorials/06-Overview.rdoc +40 -0
- data/doc/videos.rdoc +69 -0
- data/ext/droby/dump.cc +175 -0
- data/ext/droby/extconf.rb +3 -0
- data/ext/graph/algorithm.cc +746 -0
- data/ext/graph/extconf.rb +7 -0
- data/ext/graph/graph.cc +529 -0
- data/ext/graph/graph.hh +183 -0
- data/ext/graph/iterator_sequence.hh +102 -0
- data/ext/graph/undirected_dfs.hh +226 -0
- data/ext/graph/undirected_graph.hh +421 -0
- data/lib/roby.rb +41 -0
- data/lib/roby/app.rb +870 -0
- data/lib/roby/app/rake.rb +56 -0
- data/lib/roby/app/run.rb +14 -0
- data/lib/roby/app/scripts/distributed.rb +13 -0
- data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
- data/lib/roby/app/scripts/replay.rb +31 -0
- data/lib/roby/app/scripts/results.rb +15 -0
- data/lib/roby/app/scripts/run.rb +26 -0
- data/lib/roby/app/scripts/server.rb +18 -0
- data/lib/roby/app/scripts/shell.rb +88 -0
- data/lib/roby/app/scripts/test.rb +40 -0
- data/lib/roby/basic_object.rb +151 -0
- data/lib/roby/config.rb +5 -0
- data/lib/roby/control.rb +747 -0
- data/lib/roby/decision_control.rb +17 -0
- data/lib/roby/distributed.rb +32 -0
- data/lib/roby/distributed/base.rb +440 -0
- data/lib/roby/distributed/communication.rb +871 -0
- data/lib/roby/distributed/connection_space.rb +592 -0
- data/lib/roby/distributed/distributed_object.rb +206 -0
- data/lib/roby/distributed/drb.rb +62 -0
- data/lib/roby/distributed/notifications.rb +539 -0
- data/lib/roby/distributed/peer.rb +550 -0
- data/lib/roby/distributed/protocol.rb +529 -0
- data/lib/roby/distributed/proxy.rb +343 -0
- data/lib/roby/distributed/subscription.rb +311 -0
- data/lib/roby/distributed/transaction.rb +498 -0
- data/lib/roby/event.rb +897 -0
- data/lib/roby/exceptions.rb +234 -0
- data/lib/roby/executives/simple.rb +30 -0
- data/lib/roby/graph.rb +166 -0
- data/lib/roby/interface.rb +390 -0
- data/lib/roby/log.rb +3 -0
- data/lib/roby/log/chronicle.rb +303 -0
- data/lib/roby/log/console.rb +72 -0
- data/lib/roby/log/data_stream.rb +197 -0
- data/lib/roby/log/dot.rb +279 -0
- data/lib/roby/log/event_stream.rb +151 -0
- data/lib/roby/log/file.rb +340 -0
- data/lib/roby/log/gui/basic_display.ui +83 -0
- data/lib/roby/log/gui/chronicle.rb +26 -0
- data/lib/roby/log/gui/chronicle_view.rb +40 -0
- data/lib/roby/log/gui/chronicle_view.ui +70 -0
- data/lib/roby/log/gui/data_displays.rb +172 -0
- data/lib/roby/log/gui/data_displays.ui +155 -0
- data/lib/roby/log/gui/notifications.rb +26 -0
- data/lib/roby/log/gui/relations.rb +248 -0
- data/lib/roby/log/gui/relations.ui +123 -0
- data/lib/roby/log/gui/relations_view.rb +185 -0
- data/lib/roby/log/gui/relations_view.ui +149 -0
- data/lib/roby/log/gui/replay.rb +327 -0
- data/lib/roby/log/gui/replay_controls.rb +200 -0
- data/lib/roby/log/gui/replay_controls.ui +259 -0
- data/lib/roby/log/gui/runtime.rb +130 -0
- data/lib/roby/log/hooks.rb +185 -0
- data/lib/roby/log/logger.rb +202 -0
- data/lib/roby/log/notifications.rb +244 -0
- data/lib/roby/log/plan_rebuilder.rb +470 -0
- data/lib/roby/log/relations.rb +1056 -0
- data/lib/roby/log/server.rb +550 -0
- data/lib/roby/log/sqlite.rb +47 -0
- data/lib/roby/log/timings.rb +164 -0
- data/lib/roby/plan-object.rb +247 -0
- data/lib/roby/plan.rb +762 -0
- data/lib/roby/planning.rb +13 -0
- data/lib/roby/planning/loops.rb +302 -0
- data/lib/roby/planning/model.rb +906 -0
- data/lib/roby/planning/task.rb +151 -0
- data/lib/roby/propagation.rb +562 -0
- data/lib/roby/query.rb +619 -0
- data/lib/roby/relations.rb +583 -0
- data/lib/roby/relations/conflicts.rb +70 -0
- data/lib/roby/relations/ensured.rb +20 -0
- data/lib/roby/relations/error_handling.rb +23 -0
- data/lib/roby/relations/events.rb +9 -0
- data/lib/roby/relations/executed_by.rb +193 -0
- data/lib/roby/relations/hierarchy.rb +239 -0
- data/lib/roby/relations/influence.rb +10 -0
- data/lib/roby/relations/planned_by.rb +63 -0
- data/lib/roby/robot.rb +7 -0
- data/lib/roby/standard_errors.rb +218 -0
- data/lib/roby/state.rb +5 -0
- data/lib/roby/state/events.rb +221 -0
- data/lib/roby/state/information.rb +55 -0
- data/lib/roby/state/pos.rb +110 -0
- data/lib/roby/state/shapes.rb +32 -0
- data/lib/roby/state/state.rb +353 -0
- data/lib/roby/support.rb +92 -0
- data/lib/roby/task-operations.rb +182 -0
- data/lib/roby/task.rb +1618 -0
- data/lib/roby/test/common.rb +399 -0
- data/lib/roby/test/distributed.rb +214 -0
- data/lib/roby/test/tasks/empty_task.rb +9 -0
- data/lib/roby/test/tasks/goto.rb +36 -0
- data/lib/roby/test/tasks/simple_task.rb +23 -0
- data/lib/roby/test/testcase.rb +519 -0
- data/lib/roby/test/tools.rb +160 -0
- data/lib/roby/thread_task.rb +87 -0
- data/lib/roby/transactions.rb +462 -0
- data/lib/roby/transactions/proxy.rb +292 -0
- data/lib/roby/transactions/updates.rb +139 -0
- data/plugins/fault_injection/History.txt +4 -0
- data/plugins/fault_injection/README.txt +37 -0
- data/plugins/fault_injection/Rakefile +18 -0
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +52 -0
- data/plugins/fault_injection/fault_injection.rb +89 -0
- data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
- data/plugins/subsystems/README.txt +40 -0
- data/plugins/subsystems/Rakefile +18 -0
- data/plugins/subsystems/app.rb +171 -0
- data/plugins/subsystems/test/app/README +24 -0
- data/plugins/subsystems/test/app/Rakefile +8 -0
- data/plugins/subsystems/test/app/config/app.yml +71 -0
- data/plugins/subsystems/test/app/config/init.rb +9 -0
- data/plugins/subsystems/test/app/config/roby.yml +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +20 -0
- data/plugins/subsystems/test/app/scripts/distributed +3 -0
- data/plugins/subsystems/test/app/scripts/replay +3 -0
- data/plugins/subsystems/test/app/scripts/results +3 -0
- data/plugins/subsystems/test/app/scripts/run +3 -0
- data/plugins/subsystems/test/app/scripts/server +3 -0
- data/plugins/subsystems/test/app/scripts/shell +3 -0
- data/plugins/subsystems/test/app/scripts/test +3 -0
- data/plugins/subsystems/test/app/tasks/services.rb +15 -0
- data/plugins/subsystems/test/test_subsystems.rb +71 -0
- data/test/distributed/test_communication.rb +178 -0
- data/test/distributed/test_connection.rb +282 -0
- data/test/distributed/test_execution.rb +373 -0
- data/test/distributed/test_mixed_plan.rb +341 -0
- data/test/distributed/test_plan_notifications.rb +238 -0
- data/test/distributed/test_protocol.rb +516 -0
- data/test/distributed/test_query.rb +102 -0
- data/test/distributed/test_remote_plan.rb +491 -0
- data/test/distributed/test_transaction.rb +463 -0
- data/test/mockups/tasks.rb +27 -0
- data/test/planning/test_loops.rb +380 -0
- data/test/planning/test_model.rb +427 -0
- data/test/planning/test_task.rb +106 -0
- data/test/relations/test_conflicts.rb +42 -0
- data/test/relations/test_ensured.rb +38 -0
- data/test/relations/test_executed_by.rb +149 -0
- data/test/relations/test_hierarchy.rb +158 -0
- data/test/relations/test_planned_by.rb +54 -0
- data/test/suite_core.rb +24 -0
- data/test/suite_distributed.rb +9 -0
- data/test/suite_planning.rb +3 -0
- data/test/suite_relations.rb +8 -0
- data/test/test_bgl.rb +508 -0
- data/test/test_control.rb +399 -0
- data/test/test_event.rb +894 -0
- data/test/test_exceptions.rb +592 -0
- data/test/test_interface.rb +37 -0
- data/test/test_log.rb +114 -0
- data/test/test_log_server.rb +132 -0
- data/test/test_plan.rb +584 -0
- data/test/test_propagation.rb +210 -0
- data/test/test_query.rb +266 -0
- data/test/test_relations.rb +180 -0
- data/test/test_state.rb +414 -0
- data/test/test_support.rb +16 -0
- data/test/test_task.rb +938 -0
- data/test/test_testcase.rb +122 -0
- data/test/test_thread_task.rb +73 -0
- data/test/test_transactions.rb +569 -0
- data/test/test_transactions_proxy.rb +198 -0
- metadata +570 -0
data/TODO.txt
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
= TODO
|
2
|
+
|
3
|
+
== Refactoring
|
4
|
+
=== Small stuff
|
5
|
+
* remote_id => network_id
|
6
|
+
* incremental_dump? => dump_reference?
|
7
|
+
|
8
|
+
=== Big stuff
|
9
|
+
* fix the Roby singleton methods/Roby::Control/Roby::Propagation mess. Maybe move
|
10
|
+
all the execution-related stuff in a subclass of Plan, MainPlan. That would allow
|
11
|
+
per-MainPlan execution management and in the end having multiple executable
|
12
|
+
plan in the same plan manager (I'm thinking bi-simulation)
|
13
|
+
* have separate relation graphs in each Plan object. That would be possible
|
14
|
+
if we don't allow anymore to change any event or task relations if the task
|
15
|
+
is not included in a plan, which would greatly simply logging-related stuff
|
16
|
+
(for instance, rebuilding a representation of plans from logged data).
|
17
|
+
Moreover, we would not have tasks hanging around anymore because they have
|
18
|
+
never been removed from any plan.
|
19
|
+
* in dRoby, separate the implementation of the RX/TX and
|
20
|
+
connection/disconnection protocol, including the management of the TX queue
|
21
|
+
(callbacks, synchronous/asynchronous).
|
22
|
+
* have a thread-safe handling of transactions. This requires a few things:
|
23
|
+
- separate relation graphs: have one relation graph per plan object: see previous
|
24
|
+
point.
|
25
|
+
- stop using method forwarding, which is not the good way to do that.
|
26
|
+
Instead, do as for distributed: update the task status in the transaction
|
27
|
+
thread. Need to define a notion of "transaction thread" and how messages
|
28
|
+
can get propagated there, though.
|
29
|
+
|
30
|
+
== Core
|
31
|
+
* dynamic parameters. State prediction in both plan and transaction context:
|
32
|
+
allow to predict the effect of changing the value of dynamic parameters in
|
33
|
+
transaction context.
|
34
|
+
|
35
|
+
* when predicates like happened? are called in a propagation context, and
|
36
|
+
we don't know the result yet (happened? = false), register a continuation and
|
37
|
+
its dependency on the event. Include this continuation in the event set and
|
38
|
+
sort it accordingly.
|
39
|
+
|
40
|
+
* in #replace, use Hierarchy#fullfilled_events to check that
|
41
|
+
all needed events are provided. If some are missing, use define_event to try
|
42
|
+
to add a new one dynamically
|
43
|
+
|
44
|
+
* when replacing an event generator, what to do with its handlers ?
|
45
|
+
- either we discard them, because some handlers are used in a specific way
|
46
|
+
- either we apply them on the new task
|
47
|
+
- unfortunately there is no good answer... Both are useful and it is
|
48
|
+
difficult (if not impossible) to know what to do. Having no solution for
|
49
|
+
this problem reduces the usefulness of event handlers greatly.
|
50
|
+
|
51
|
+
* Need to tag relations with a name so that we can find what is what (kind of
|
52
|
+
'roles'). For instance, in PlanningLoop, we would tag the seeds (i.e. the
|
53
|
+
planned tasks) with a certain name which would allow to add any child without
|
54
|
+
the loop code noticing
|
55
|
+
|
56
|
+
* add a multiplicity parameter for hierarchy relations which tells
|
57
|
+
how many child task of a given kind are expected by the parent task. Add a
|
58
|
+
'realized_by' transition for that. For instance, in case of
|
59
|
+
Pom::Localization, we can tell that the task expects at least one
|
60
|
+
Pom::Estimator. If the last estimator breaks, we can repair the plan online
|
61
|
+
by adding a transition.
|
62
|
+
|
63
|
+
* we NEED plan merging: if we reuse a task which is already running, it should
|
64
|
+
be transparent for the new process: this new task tree will call start!, but
|
65
|
+
the task is running. Moreover, if it is synchronizing on the start event, it
|
66
|
+
should appear "as if" the event has been emitted
|
67
|
+
|
68
|
+
* Check the capability we have to put every application block in transaction
|
69
|
+
context. This would allow for instance to discard **all** plan modification
|
70
|
+
done by an exception handler (or plan command, event handler, you get my
|
71
|
+
drift) if an exception is raised. I think it would be a worthy feature [This
|
72
|
+
can't be done because of the transaction creation cost]
|
73
|
+
|
74
|
+
* Kill local tasks that are in force_gc even if they have parents, if their
|
75
|
+
parents are remote tasks
|
76
|
+
|
77
|
+
* rename Roby::TaskModelTag::argument into 'arguments' (beware of name clash
|
78
|
+
with the accessor)
|
79
|
+
|
80
|
+
* Fix transaction proxying. Better use the same kind of model than in dRoby:
|
81
|
+
create slightly modified tasks of the same model than the proxied event, do
|
82
|
+
not proxy task events
|
83
|
+
|
84
|
+
* Find a way to remove the "return unless proxying?" in top of proxy_code. It sucks
|
85
|
+
|
86
|
+
* fix handling of execution agents: we should re-spawn the execution agents
|
87
|
+
only if there is an execution agent model on the task model. We currently use
|
88
|
+
respawn on the execution agent instance. The problem lies in, for instance,
|
89
|
+
ConnectionTask which are respawned for all pending remote tasks.
|
90
|
+
ConnectionTask should never be created because of the exected_by relation.
|
91
|
+
|
92
|
+
== Planning
|
93
|
+
* fix memory leak regarding planning loops: for now, make_loop creates a new
|
94
|
+
planning method each time make_loop is called. The problem is that the
|
95
|
+
created method should actually be local to the planner object, not the
|
96
|
+
planner model (we are doing the latter right now).
|
97
|
+
|
98
|
+
== Distributed
|
99
|
+
* extension of communication to really have a multi-robot system. It is for now
|
100
|
+
too much peer-to-peer
|
101
|
+
- a pDB should always send the messages about objects it owns. For now, we
|
102
|
+
check two things: that the involved objects are owned and that the message
|
103
|
+
comes from the inside (we never forward a message coming from outside).
|
104
|
+
There is a synchronization problem here:
|
105
|
+
|
106
|
+
A sends a message M about a joint ab object to B
|
107
|
+
B does not send the message to C
|
108
|
+
but B can send other messages to C, including the /consequences/ of the M message
|
109
|
+
|
110
|
+
Result: C knows about the consequences of M, but not about M itself.
|
111
|
+
|
112
|
+
The solution is to mark all messages with an UID, and forward new messages
|
113
|
+
when we decode them (in PeerServer#demux)
|
114
|
+
- make sure unknown models are properly handled in 3-peers scenario. In
|
115
|
+
particular, the following situation should work
|
116
|
+
|
117
|
+
peer 1 and 2 know about a SpecificModel task model
|
118
|
+
peer 3 does not
|
119
|
+
|
120
|
+
If 1 sees tasks of 2 *through* the plan of 3, and if these tasks are of the
|
121
|
+
SpecificModel model, then they should be instances of the SpecificModel
|
122
|
+
class
|
123
|
+
|
124
|
+
* There is a race condition when removing objects: if a peer A is building a
|
125
|
+
transaction involving tasks from a peer B, and if the peer B removes the
|
126
|
+
tasks, then there is a race condition between the time B sends the
|
127
|
+
transaction and the time it processes the remove_object update from A. The
|
128
|
+
net effect is that when the transaction sibling is created, some tasks it
|
129
|
+
includes do not exist anymore. It is more general, since the same problem
|
130
|
+
exists when wrapping tasks in a transaction for instance.
|
131
|
+
|
132
|
+
I don't think we should really fix the race condition per se. We should in
|
133
|
+
general check if the object has not been removed when A processes updates
|
134
|
+
from B and have some ways to feedback B from A.
|
135
|
+
|
136
|
+
* Better handling of errors during transactions, better management of new
|
137
|
+
peers, ... DecisionControl should really be the central component handling
|
138
|
+
all that. Moreover, defining management policies for distributed transactions
|
139
|
+
should also be defined.
|
140
|
+
|
141
|
+
== UI
|
142
|
+
* log snapshot: build a set of logging messages which represent the current
|
143
|
+
state of the plan. Useful for display (it would allow to seek a lot faster)
|
144
|
+
and for runtime display of the plan state (send the snapshot on connection)
|
145
|
+
|
146
|
+
vim: tw=100
|
data/app/README.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
== Directories
|
2
|
+
A basic Roby application has the following directories:
|
3
|
+
config:: configuration files. config/init.rb is the main configuration file (loaded
|
4
|
+
by all robots). Robot-specific configuration is in config/ROBOTNAME.rb.
|
5
|
+
The main Roby configuration file is config/roby.yml. The default file
|
6
|
+
describes all available configuration options.
|
7
|
+
planners:: planner models. Global planners (shared by all robots) are in
|
8
|
+
planners/. Robot-specific planners are in planners/ROBOTNAME/
|
9
|
+
controllers:: robot controllers. These files are supposed to start the basic robot
|
10
|
+
services, to make the robot ready. A robot shall have a controllers/ROBOTNAME.rb
|
11
|
+
file which does that.
|
12
|
+
tasks:: task models
|
13
|
+
data:: where all data files are. See #find_data.
|
14
|
+
scripts:: various scripts needed to run and debug a Roby application
|
15
|
+
|
16
|
+
The basic directory structure, and the global files, are installed by <tt>roby init</tt>. Basic
|
17
|
+
robot files can be added by <tt>roby robot ROBOTNAME</tt>
|
18
|
+
|
19
|
+
== Genom/Pocosim integration
|
20
|
+
An application can use the Genom/Pocosim integration by calling <tt>roby init --module genom</tt>.
|
21
|
+
The following files and directories are added:
|
22
|
+
config/ROBOTNAME-genom.rb:: Genom-specific configuration for ROBOTNAME
|
23
|
+
tasks/genom/:: per-Genom module tasks
|
24
|
+
|
data/app/Rakefile
ADDED
data/app/config/ROBOT.rb
ADDED
data/app/config/app.yml
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Control configuration
|
2
|
+
control:
|
3
|
+
# Abort if a task/event exception is not caught
|
4
|
+
# abort_on_exception: false
|
5
|
+
# Abort if an application exception occurs
|
6
|
+
# abort_on_application_exception: false
|
7
|
+
|
8
|
+
# The executive. Set to 'none' to disable.
|
9
|
+
# The executive object determines, in the current plan, what are
|
10
|
+
# the tasks which must be started. The 'simple' executive starts
|
11
|
+
# all tasks that have no predecessors.
|
12
|
+
executive: simple
|
13
|
+
|
14
|
+
# The length of a cycle (in seconds)
|
15
|
+
# cycle: 0.1
|
16
|
+
|
17
|
+
# Logging configuration
|
18
|
+
log:
|
19
|
+
# Where log files go
|
20
|
+
# dir: log/
|
21
|
+
|
22
|
+
# Log system events (default: false)
|
23
|
+
# events: true
|
24
|
+
|
25
|
+
# Disables the log server (default: enabled)
|
26
|
+
# server: false
|
27
|
+
#
|
28
|
+
# ... or configure it
|
29
|
+
# server:
|
30
|
+
# # The port to listen on (for service discovery)
|
31
|
+
# port: 48933
|
32
|
+
# # The discovery period
|
33
|
+
# period: 10
|
34
|
+
|
35
|
+
# Logging levels. It is a hash of component_name: level (where level is one
|
36
|
+
# of DEBUG, INFO, WARN and FATAL). The output can be redirected in a file
|
37
|
+
# using level:filename, in which case 'filename' is relative to the log
|
38
|
+
# directory. Any occurence of 'ROBOT' in filename is replaced by the robot
|
39
|
+
# name
|
40
|
+
#
|
41
|
+
# levels:
|
42
|
+
# roby: INFO
|
43
|
+
# roby/planning: DEBUG
|
44
|
+
# roby/distributed: DEBUG:ROBOT-distributed.log
|
45
|
+
# genom: INFO
|
46
|
+
|
47
|
+
# dRoby neighbour discovery
|
48
|
+
discovery:
|
49
|
+
# The host:port at which we can connect to a discovery tuplespace
|
50
|
+
# (default: no discovery tuplespace)
|
51
|
+
# tuplespace: "localhost:29568"
|
52
|
+
# The port at which we do ring discovery (default: disabled)
|
53
|
+
# ring: 42865
|
54
|
+
|
55
|
+
# dRoby host configuration
|
56
|
+
droby:
|
57
|
+
# How many errors are allowed before disconnecting from a peer
|
58
|
+
# max_errors: 1
|
59
|
+
# The ring discovery period if we do ring discovery
|
60
|
+
# period: 0.5
|
61
|
+
# The hostname at the dRoby server must listen to. It is either
|
62
|
+
# 'host:port', or just ':port'
|
63
|
+
# host: ":48902"
|
64
|
+
|
65
|
+
# Genom configuration
|
66
|
+
genom:
|
67
|
+
# The memory size allocated for H2
|
68
|
+
# mem_size: 4000000
|
69
|
+
# If true, do not remove H2 devices when the application quit
|
70
|
+
# keep_h2: false
|
71
|
+
|
72
|
+
# Pocosim configuration
|
73
|
+
pocosim:
|
74
|
+
# The host of the GDHE display
|
75
|
+
# display: localhost
|
76
|
+
|
77
|
+
# An initialization script to display the scene on GDHE. The file is searched
|
78
|
+
# in the data/ director
|
79
|
+
# gdhe: lousa.gdhe
|
80
|
+
|
81
|
+
# The Gazebo world file for pocosim/gazebo simulations. The file is searched
|
82
|
+
# in the data/ directory
|
83
|
+
# gazebo: lousa.world
|
84
|
+
|
85
|
+
# Per-robot configuration. In these, you can override global options, or set
|
86
|
+
# new options.
|
87
|
+
# dala:
|
88
|
+
# droby:
|
89
|
+
# host: ":1287"
|
90
|
+
|
91
|
+
# vim: sw=2
|
data/app/config/init.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# This file is called to do application-global configuration. For configuration
|
2
|
+
# specific to a robot, edit config/NAME.rb, where NAME is the robot name.
|
3
|
+
#
|
4
|
+
# Enable some of the standard plugins
|
5
|
+
# Roby.app.using 'fault_injection'
|
6
|
+
# Roby.app.using 'subsystems'
|
7
|
+
|
data/app/config/roby.yml
ADDED
File without changes
|
File without changes
|
data/app/scripts/replay
ADDED
data/app/scripts/results
ADDED
data/app/scripts/run
ADDED
data/app/scripts/server
ADDED
data/app/scripts/shell
ADDED
data/app/scripts/test
ADDED
File without changes
|
File without changes
|
data/bin/roby
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
APP_DIR = Dir.pwd
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'ostruct'
|
7
|
+
require 'fileutils'
|
8
|
+
require 'yaml'
|
9
|
+
require 'find'
|
10
|
+
|
11
|
+
require 'roby/app'
|
12
|
+
|
13
|
+
MODES = %w{init robot}
|
14
|
+
config = OpenStruct.new
|
15
|
+
parser = OptionParser.new do |opt|
|
16
|
+
opt.banner = "Usage: roby mode [options]"
|
17
|
+
opt.on_tail('-h', '--help', 'this help message') do
|
18
|
+
if !config.mode
|
19
|
+
global_help(opt)
|
20
|
+
end
|
21
|
+
STDERR.puts opt
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def global_help(opt)
|
27
|
+
opt.separator ""
|
28
|
+
opt.separator " Available modes:"
|
29
|
+
opt.separator " init creates new roby application, or adds the files needed by plugins"
|
30
|
+
opt.separator " robot creates a new robot type in this application"
|
31
|
+
opt.separator ""
|
32
|
+
opt.separator " roby <mode> --help displays mode-specific help"
|
33
|
+
opt.separator ""
|
34
|
+
opt.separator " Global options"
|
35
|
+
end
|
36
|
+
|
37
|
+
def mode_init(opt, config)
|
38
|
+
config.enabled_plugins = []
|
39
|
+
|
40
|
+
opt.banner = "Usage: roby [global options] init [options]"
|
41
|
+
opt.separator ""
|
42
|
+
opt.separator " Creates an application template in the current directory, or"
|
43
|
+
opt.separator " installs the files needed by a specific plugin in an already"
|
44
|
+
opt.separator " existing application"
|
45
|
+
opt.separator ""
|
46
|
+
opt.separator " Available options"
|
47
|
+
known_plugins = Roby.app.available_plugins.map { |name, _, _| name }
|
48
|
+
opt.on('-p', '--plugin NAME,NAME', Array, "install the files needed by the given plugins. Known plugins are: #{known_plugins.join(", ")}") do |new_plugins|
|
49
|
+
new_plugins.each do |name|
|
50
|
+
if !known_plugins.include?(name)
|
51
|
+
STDERR.puts "unknown plugin #{name}. Known plugins are #{known_plugins}"
|
52
|
+
end
|
53
|
+
config.enabled_plugins << name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
opt.separator ""
|
58
|
+
opt.separator " Global options"
|
59
|
+
end
|
60
|
+
def mode_robot(opt, config)
|
61
|
+
opt.banner = "Usage: roby [global options] robot NAME"
|
62
|
+
opt.separator ""
|
63
|
+
opt.separator " Creates the template for a new robot type"
|
64
|
+
opt.separator ""
|
65
|
+
opt.separator " Global options"
|
66
|
+
end
|
67
|
+
|
68
|
+
remaining = []
|
69
|
+
parser.order(ARGV) do |arg|
|
70
|
+
if !config.mode
|
71
|
+
begin
|
72
|
+
send("mode_#{arg}", parser, config)
|
73
|
+
config.mode = arg
|
74
|
+
rescue NoMethodError
|
75
|
+
STDERR.puts "Invalid mode of operation '#{arg}'. Valid modes are: #{MODES.join(", ")}"
|
76
|
+
STDERR.puts parser
|
77
|
+
exit(1)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
remaining << arg
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
module Roby
|
85
|
+
class Installer
|
86
|
+
# The directory in which we are installing
|
87
|
+
attr_reader :app_dir
|
88
|
+
|
89
|
+
# The configuration hash saved in config/roby.yml
|
90
|
+
attr_reader :config
|
91
|
+
|
92
|
+
def config_path; File.join(app_dir, 'config', 'roby.yml') end
|
93
|
+
def installed_plugins; config['plugins'] || [] end
|
94
|
+
|
95
|
+
def check_plugins(plugins)
|
96
|
+
if name = plugins.find { |name| !Roby.app.defined_plugin?(name) }
|
97
|
+
known_plugins = Roby.app.available_plugins.map { |name, _| name }
|
98
|
+
raise ArgumentError, "unknown plugin #{name}. Available plugins are #{known_plugins.join(", ")}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def initialize(app_dir)
|
103
|
+
@app_dir = File.expand_path(app_dir)
|
104
|
+
|
105
|
+
# Read the application configuration from config/roby.yml if the file exists,
|
106
|
+
@config = if File.file?(config_path)
|
107
|
+
YAML.load_file(config_path)
|
108
|
+
else
|
109
|
+
Hash['plugins', []]
|
110
|
+
end
|
111
|
+
check_plugins(config['plugins'])
|
112
|
+
end
|
113
|
+
|
114
|
+
def save_config
|
115
|
+
File.open(config_path, 'w') do |io|
|
116
|
+
io << YAML.dump(config)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Install the template files for a core Roby application and the provided
|
121
|
+
# plugins
|
122
|
+
def install(plugins)
|
123
|
+
check_plugins(plugins)
|
124
|
+
install_dir(plugins) do |file|
|
125
|
+
next if file =~ /ROBOT/
|
126
|
+
file
|
127
|
+
end
|
128
|
+
|
129
|
+
config['plugins'] |= plugins
|
130
|
+
save_config
|
131
|
+
end
|
132
|
+
|
133
|
+
# Installs the template files for a new robot named +name+
|
134
|
+
def robot(name)
|
135
|
+
install_dir(installed_plugins) do |file|
|
136
|
+
next if file !~ /ROBOT/
|
137
|
+
file.gsub /ROBOT/, name
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Copies the template files into the application directory, without erasing
|
142
|
+
# already existing files. +plugins+ is the list of plugins we should copy
|
143
|
+
# files from
|
144
|
+
def install_dir(plugins = [], &filter)
|
145
|
+
Installer.copy_tree(File.join(Roby::ROBY_ROOT_DIR, 'app'), app_dir, &filter)
|
146
|
+
plugins.each do |enabled_name|
|
147
|
+
plugin_desc = Roby.app.available_plugins.find { |name, dir, _, _| enabled_name == name }
|
148
|
+
|
149
|
+
plugin_app_dir = File.join(plugin_desc[1], 'app')
|
150
|
+
next unless File.directory?(plugin_app_dir)
|
151
|
+
Installer.copy_tree(plugin_app_dir, app_dir, &filter)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Copy all files that are in +basedir+ into +destdir+. If a block is given,
|
156
|
+
# it is called with each file relative path. The block must then return the
|
157
|
+
# destination name, or nil if the file is to be skipped.
|
158
|
+
def self.copy_tree(basedir, destdir)
|
159
|
+
basedir = File.expand_path(basedir)
|
160
|
+
destdir = File.expand_path(destdir)
|
161
|
+
|
162
|
+
Find.find(basedir) do |file|
|
163
|
+
relative = file.gsub /#{Regexp.quote("#{basedir}")}\/?/, ''
|
164
|
+
relative = yield(relative) if block_given?
|
165
|
+
# The block can return nil if the file shouldn't be installed
|
166
|
+
next unless relative
|
167
|
+
|
168
|
+
destfile = File.join(destdir, relative)
|
169
|
+
if File.directory?(file)
|
170
|
+
if !File.exists?(destfile)
|
171
|
+
puts "creating #{relative}/"
|
172
|
+
Dir.mkdir destfile
|
173
|
+
elsif !File.directory?(destfile)
|
174
|
+
STDERR.puts "#{destfile} exists but it is not a directory"
|
175
|
+
exit(1)
|
176
|
+
end
|
177
|
+
else
|
178
|
+
if !File.exists?(destfile)
|
179
|
+
FileUtils.cp file, destfile
|
180
|
+
puts "creating #{relative}"
|
181
|
+
elsif !File.file?(destfile)
|
182
|
+
STDERR.puts "#{destfile} exists but it is not a file"
|
183
|
+
exit(1)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if !config.mode
|
192
|
+
global_help(parser)
|
193
|
+
STDERR.puts parser
|
194
|
+
exit
|
195
|
+
end
|
196
|
+
|
197
|
+
installer = Roby::Installer.new(APP_DIR)
|
198
|
+
if config.mode == 'init'
|
199
|
+
installer.install(config.enabled_plugins)
|
200
|
+
|
201
|
+
elsif config.mode == 'robot'
|
202
|
+
unless robotname = remaining.shift
|
203
|
+
STDERR.puts "No robot name given on command line"
|
204
|
+
STDERR.puts parser
|
205
|
+
exit(1)
|
206
|
+
end
|
207
|
+
|
208
|
+
installer.robot(robotname)
|
209
|
+
end
|
210
|
+
|