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