29 |
30 | #### Task Manager
31 | To create a fully autonomous mission system, a task manager system has been implemented. The task manager is an independent software system that is able to recognize task assignments and monitor their progress. That is the process of computing a reward for each waypoint or attack task progress of the agents. When it is recognized that the reward is not increasing over a defined time window, the assigned task is getting aborted. The same applies to task execution that exceeds a certain time window. The time window for each assigned task is individually defined based on the task type, distance, and flying speed.
32 |
33 |
34 |
35 |
36 |
37 |
38 | #### Graphical User Interface
39 |
40 | The GUI was created to simplify the mission overview for the user during the competition. The GUI-System is fully integrated into the ROS Network System and is listening to the exchanged messages. Received information is displayed for the user in a Mission Window based on the PyQT framework.
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | ## Dependencies
49 |
50 | The software system us using external libraries which needs to be installed.
51 |
52 | Install Rospy for Pyton 3.6:
53 |
54 | sudo pip3 install -U rospkg
55 | sudo pip3 install roslibpy
56 | sudo apt-get install python3-yaml
57 | sudo pip3 install rospkg catkin_pkg
58 |
59 | Install PyQt, PyUic4 and PyRcc4:
60 |
61 | sudo apt-get install pyqt4-dev-tools qt4-designer
62 |
63 |
64 | **The software was tested under Linux Ubuntu Versions 16.04.6 LTS and 18.04.2 LTS*-**
65 |
66 | ### Usage
67 |
68 | This Software system is using ROS for that reason it needs to be integrated into a Robot Operating System Framework. If not already exist, a working ROS Workspace needs to be created. If that is the case, please go first to your workspace.
69 |
70 | # Go to your ROS Workspace Directory
71 | $ cd ~/your_ros_workspace
72 |
73 | The next step is to clone this github repository and use it as a new package:
74 |
75 | $ git clone https://github.com/JohannesAutenrieb/mission_planning.git ./src/mission_planning
76 |
77 | The system is built with:
78 |
79 | #Building all ROS packages
80 | $ catkin_make
81 |
82 | To have a functional Task Allocation system the system needs initial agent information to start. When the system is not embedded in the complete ROS environment, the publisher.py can be used to fake the swarm:
83 |
84 | # fakes a swarm environment with 5 agents and 2 moving targets
85 | $ rosrun mission_planning publisher.py
86 |
87 | The task allocation software is started with:
88 |
89 | $ rosrun mission_planning Main.py
90 |
91 | The task manager software is started with:
92 |
93 | $ rosrun mission_planning TaskManager.py
94 |
95 | When it is wanted to display the mission via the gui, the gui can started with:
96 |
97 | $ rosrun mission_planning GUI.py
98 |
99 |
100 | License
101 | -------
102 |
103 | Released under the 2-clause GPL GNU license, see `LICENSE`.
104 |
105 | Copyright (C) 2019, Johannes Autenrieb and Natalia Strawa
106 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " singlehtml to make a single large HTML file"
24 | @echo " pickle to make pickle files"
25 | @echo " json to make JSON files"
26 | @echo " htmlhelp to make HTML files and a HTML help project"
27 | @echo " qthelp to make HTML files and a qthelp project"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
32 | @echo " text to make text files"
33 | @echo " man to make manual pages"
34 | @echo " texinfo to make Texinfo files"
35 | @echo " info to make Texinfo files and run them through makeinfo"
36 | @echo " gettext to make PO message catalogs"
37 | @echo " changes to make an overview of all changed/added/deprecated items"
38 | @echo " linkcheck to check all external links for integrity"
39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 |
41 | clean:
42 | -rm -rf $(BUILDDIR)/*
43 |
44 | html:
45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 | @echo
47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48 |
49 | dirhtml:
50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51 | @echo
52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53 |
54 | singlehtml:
55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56 | @echo
57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58 |
59 | pickle:
60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61 | @echo
62 | @echo "Build finished; now you can process the pickle files."
63 |
64 | json:
65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66 | @echo
67 | @echo "Build finished; now you can process the JSON files."
68 |
69 | htmlhelp:
70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71 | @echo
72 | @echo "Build finished; now you can run HTML Help Workshop with the" \
73 | ".hhp project file in $(BUILDDIR)/htmlhelp."
74 |
75 | qthelp:
76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77 | @echo
78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sample.qhcp"
81 | @echo "To view the help file:"
82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sample.qhc"
83 |
84 | devhelp:
85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86 | @echo
87 | @echo "Build finished."
88 | @echo "To view the help file:"
89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/sample"
90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sample"
91 | @echo "# devhelp"
92 |
93 | epub:
94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95 | @echo
96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97 |
98 | latex:
99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100 | @echo
101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
103 | "(use \`make latexpdf' here to do that automatically)."
104 |
105 | latexpdf:
106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107 | @echo "Running LaTeX files through pdflatex..."
108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110 |
111 | text:
112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113 | @echo
114 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
115 |
116 | man:
117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118 | @echo
119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120 |
121 | texinfo:
122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123 | @echo
124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125 | @echo "Run \`make' in that directory to run these through makeinfo" \
126 | "(use \`make info' here to do that automatically)."
127 |
128 | info:
129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130 | @echo "Running Texinfo files through makeinfo..."
131 | make -C $(BUILDDIR)/texinfo info
132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133 |
134 | gettext:
135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136 | @echo
137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138 |
139 | changes:
140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141 | @echo
142 | @echo "The overview file is in $(BUILDDIR)/changes."
143 |
144 | linkcheck:
145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146 | @echo
147 | @echo "Link check complete; look for any errors in the above output " \
148 | "or in $(BUILDDIR)/linkcheck/output.txt."
149 |
150 | doctest:
151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152 | @echo "Testing of doctests in the sources finished, look at the " \
153 | "results in $(BUILDDIR)/doctest/output.txt."
154 |
--------------------------------------------------------------------------------
/scripts/GUI.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from PyQt4 import QtGui, QtCore # Import the PyQt4 module we'll need
3 | import sys # We need sys so that we can pass argv to QApplication
4 | import rospy
5 | import time
6 | import output # This file holds our MainWindow and all design related things
7 | # it also keeps events etc that we defined in Qt Designer
8 | from mission_planning.msg import TaskMessage, AgentInfo, SwarmInfo
9 |
10 | class ExampleApp(QtGui.QMainWindow, output.Ui_MissionOverview):
11 | def __init__(self, parent=None):
12 | # Explaining super is out of the scope of this article
13 | # So please google it if you're not familar with it
14 | # Simple reason why we use it here is that it allows us to
15 | # access variables, methods etc in the design.py file
16 | super(self.__class__, self).__init__()
17 | self.setupUi(self) # This is defined in design.py file automatically
18 | # It sets up layout and widgets that are defined
19 |
20 | self.taskText= str()
21 | self.taskList = []
22 |
23 | # Set total mission time in seconds
24 | self.startTime=time.time()
25 | self.missionTime=600
26 | self.endTime=self.startTime+self.missionTime
27 | #Static: Used for progress estimation
28 | self.totalMissionTime=1000
29 |
30 | def callbackFriend(self, msg):
31 |
32 | # Extract friends information from message
33 | dataFriend = msg.friendlies
34 |
35 | # Iter over list of messages
36 | for i in range(0, len(dataFriend)):
37 | # If agent is not on the list, append new agent object
38 | if(dataFriend[i].agentId==1):
39 | self.lineEdit_TID_A1.setText(str(dataFriend[i].agentTaskId))
40 | self.lineEdit_TS_A1.setText(str(dataFriend[i].agentTaskStatus))
41 | self.lineEdit_WS_A1.setText(str(dataFriend[i].agentWorkingStatus))
42 | self.lineEdit_Pos_A1.setText(str(dataFriend[i].agentPosition))
43 | #self.lineEdit_Vel_A1.setText(str(dataFriend[i].agentTaskStatus))
44 | self.lineEdit_Pay_A1.setText(str(dataFriend[i].agentPayload))
45 | self.lineEdit_Bat_A1.setText(str(dataFriend[i].agentBattery))
46 | #
47 | if(dataFriend[i].agentId==2):
48 | self.lineEdit_TID_A2.setText(str(dataFriend[i].agentTaskId))
49 | self.lineEdit_TS_A2.setText(str(dataFriend[i].agentTaskStatus))
50 | self.lineEdit_WS_A2.setText(str(dataFriend[i].agentWorkingStatus))
51 | self.lineEdit_Pos_A2.setText(str(dataFriend[i].agentPosition))
52 | #self.lineEdit_Vel_A1.setText(str(dataFriend[i].agentTaskStatus))
53 | self.lineEdit_Pay_A2.setText(str(dataFriend[i].agentPayload))
54 | self.lineEdit_Bat_A2.setText(str(dataFriend[i].agentBattery))
55 | #
56 | if(dataFriend[i].agentId==3):
57 | self.lineEdit_TID_A3.setText(str(dataFriend[i].agentTaskId))
58 | self.lineEdit_TS_A3.setText(str(dataFriend[i].agentTaskStatus))
59 | self.lineEdit_WS_A3.setText(str(dataFriend[i].agentWorkingStatus))
60 | self.lineEdit_Pos_A3.setText(str(dataFriend[i].agentPosition))
61 | #self.lineEdit_Vel_A1.setText(str(dataFriend[i].agentTaskStatus))
62 | self.lineEdit_Pay_A3.setText(str(dataFriend[i].agentPayload))
63 | self.lineEdit_Bat_A3.setText(str(dataFriend[i].agentBattery))
64 | #
65 | if(dataFriend[i].agentId==4):
66 | self.lineEdit_TID_A4.setText(str(dataFriend[i].agentTaskId))
67 | self.lineEdit_TS_A4.setText(str(dataFriend[i].agentTaskStatus))
68 | self.lineEdit_WS_A4.setText(str(dataFriend[i].agentWorkingStatus))
69 | self.lineEdit_Pos_A4.setText(str(dataFriend[i].agentPosition))
70 | #self.lineEdit_Vel_A1.setText(str(dataFriend[i].agentTaskStatus))
71 | self.lineEdit_Pay_A4.setText(str(dataFriend[i].agentPayload))
72 | self.lineEdit_Bat_A4.setText(str(dataFriend[i].agentBattery))
73 | #
74 |
75 | # Extract foos information from message
76 | dataFoo = msg.enemies
77 | self.testString=str()
78 | for i in range(0, len(dataFoo)):
79 | self.testEnemies="EnemyID: {} Position: {} Velocity: {} Confidence: {} \n \n".format(msg.enemies[i].agentId,msg.enemies[i].agentPosition,msg.enemies[i].agentVelocity,msg.enemies[i].confidence)
80 | self.testString=self.testString+self.testEnemies
81 | self.label_enemies.setText(self.testString)
82 | del self.testString
83 |
84 | #Timer
85 | self. currentTime= time.time()
86 | self.delta = int(self.endTime - self.currentTime)
87 | mins, secs = divmod(self.delta, 60)
88 | self.timeformat = '{:02d}:{:02d}'.format(mins, secs)
89 | #print(str(self.timeformat))
90 | self.lineEdit_time.setText(str(self.timeformat))
91 |
92 | self.string= "{0:.0%}".format((self.endTime - self.currentTime)/self.missionTime)
93 | self.label_progress.setText(self.string)
94 |
95 | # Callback for adding new tasks to current Database
96 | def callbackTaskMessages(self, msg):
97 |
98 | self.taskText=msg
99 | self.task="AgentID: {} TaskID: {} Waypoint: {} \n \n".format(msg.agentId,msg.taskId,msg.taskLocation)
100 | self.label_task_histo.setText(self.task)
101 |
102 |
103 | def updater(self):
104 |
105 | #update countdown timer
106 | mins, secs = divmod(self.missionTime, 60)
107 | self.timeformat = '{:02d}:{:02d}'.format(mins, secs)
108 | #print(str(self.timeformat))
109 | self.lineEdit_time.setText(str(self.timeformat))
110 | # Count one second down
111 | self.missionTime -= 1
112 |
113 |
114 | if __name__ == '__main__':
115 | # Setup System
116 | app = QtGui.QApplication(sys.argv)
117 | form = ExampleApp()
118 |
119 | # Init of ROS Listener Node
120 | rospy.init_node('MissionDisplayer', anonymous=True)
121 |
122 | # Init Listener for friend and foos
123 | rospy.Subscriber("SwarmInformation", SwarmInfo, form.callbackFriend)
124 |
125 | # Init Listener to Task Topic
126 | rospy.Subscriber('TaskAction', TaskMessage, form.callbackTaskMessages)
127 | #Execute the GUI
128 | form.show()
129 | app.exec_()
130 | # Timer for Time Measurement
131 | timer = QtCore.QTimer()
132 | timer.timeout.connect(form.updater)
133 | timer.setInterval(500)
134 | timer.start()
--------------------------------------------------------------------------------
/Include/python-statemachine/tests/test_multiple_destinations.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | import pytest
5 | import mock
6 |
7 | from statemachine import StateMachine, State, exceptions
8 |
9 |
10 | def test_transition_should_choose_final_state_on_multiple_possibilities(
11 | approval_machine, current_time):
12 | # given
13 | model = mock.MagicMock(
14 | state='requested',
15 | accepted_at=None,
16 | rejected_at=None,
17 | completed_at=None,
18 | )
19 | machine = approval_machine(model)
20 |
21 | model.is_ok.return_value = False
22 |
23 | # when
24 | assert machine.validate() == model
25 |
26 | # then
27 | assert model.rejected_at == current_time
28 | assert machine.is_rejected
29 |
30 | # given
31 | model.is_ok.return_value = True
32 |
33 | # when
34 | assert machine.retry() == model
35 |
36 | # then
37 | assert model.rejected_at is None
38 | assert machine.is_requested
39 |
40 | # when
41 | assert machine.validate() == model
42 |
43 | # then
44 | assert model.accepted_at == current_time
45 | assert machine.is_accepted
46 |
47 |
48 | def test_should_raise_error_if_not_define_callback_in_multiple_destinations():
49 | class ApprovalMachine(StateMachine):
50 | "A workflow"
51 | requested = State('Requested', initial=True)
52 | accepted = State('Accepted')
53 | rejected = State('Rejected')
54 |
55 | validate = requested.to(accepted, rejected)
56 |
57 | machine = ApprovalMachine()
58 |
59 | with pytest.raises(exceptions.MultipleStatesFound) as e:
60 | machine.validate()
61 |
62 | assert 'desired state' in e.message
63 |
64 |
65 | @pytest.mark.parametrize('return_value, expected_exception', [
66 | (None, exceptions.MultipleStatesFound),
67 | (1, exceptions.MultipleStatesFound),
68 | ((2, 3), exceptions.MultipleStatesFound),
69 | ((4, 5, 6), exceptions.MultipleStatesFound),
70 | (((7, 8), 9), exceptions.MultipleStatesFound),
71 | ('requested', exceptions.InvalidDestinationState),
72 | ])
73 | def test_should_raise_error_if_not_inform_state_in_multiple_destinations(
74 | return_value, expected_exception):
75 | class ApprovalMachine(StateMachine):
76 | "A workflow"
77 | requested = State('Requested', initial=True)
78 | accepted = State('Accepted')
79 | rejected = State('Rejected')
80 |
81 | @requested.to(accepted, rejected)
82 | def validate(self):
83 | "tries to get an attr (like a desired state), failsback to the `return_value` itself"
84 | return getattr(self, str(return_value), return_value)
85 |
86 | machine = ApprovalMachine()
87 |
88 | with pytest.raises(expected_exception) as e:
89 | machine.validate()
90 |
91 | assert 'desired state' in e.message
92 |
93 |
94 | @pytest.mark.parametrize('callback', ['single', 'multiple'])
95 | @pytest.mark.parametrize('with_return_value', [True, False], ids=['with_return', 'without_return'])
96 | @pytest.mark.parametrize('return_value', [None, 'spam'])
97 | def test_should_transition_to_the_state_returned_by_callback(
98 | callback, with_return_value, return_value):
99 | class ApprovalMachine(StateMachine):
100 | "A workflow"
101 | requested = State('Requested', initial=True)
102 | accepted = State('Accepted')
103 | rejected = State('Rejected')
104 |
105 | @requested.to(accepted)
106 | def transition_with_single_destination(self):
107 | if with_return_value:
108 | return return_value, self.accepted
109 | else:
110 | return self.accepted
111 |
112 | @requested.to(accepted, rejected)
113 | def transition_with_multiple_destination(self):
114 | if with_return_value:
115 | return return_value, self.accepted
116 | else:
117 | return self.accepted
118 |
119 | machine = ApprovalMachine()
120 |
121 | transition = 'transition_with_{}_destination'.format(callback)
122 |
123 | result = machine.run(transition)
124 | if with_return_value:
125 | assert result == return_value
126 | else:
127 | assert result is None
128 | assert machine.is_accepted
129 |
130 |
131 | def test_should_change_to_returned_state_on_multiple_destination_with_combined_transitions():
132 | class ApprovalMachine(StateMachine):
133 | "A workflow"
134 | requested = State('Requested', initial=True)
135 | accepted = State('Accepted')
136 | rejected = State('Rejected')
137 | completed = State('Completed')
138 |
139 | validate = requested.to(accepted, rejected) | accepted.to(completed)
140 | retry = rejected.to(requested)
141 |
142 | @validate
143 | def do_validate(self):
144 | if not self.is_accepted:
145 | if self.model.is_ok():
146 | return self.accepted
147 | else:
148 | return self.rejected
149 | else:
150 | return 'congrats!'
151 |
152 | # given
153 | model = mock.MagicMock(state='requested')
154 | machine = ApprovalMachine(model)
155 |
156 | model.is_ok.return_value = False
157 |
158 | # when
159 | assert machine.validate() is None
160 | # then
161 | assert machine.is_rejected
162 |
163 | # given
164 | assert machine.retry() is None
165 | assert machine.is_requested
166 | model.is_ok.return_value = True
167 |
168 | # when
169 | assert machine.validate() is None
170 | # then
171 | assert machine.is_accepted
172 |
173 | # when
174 | assert machine.validate() == 'congrats!'
175 | # then
176 | assert machine.is_completed
177 |
178 | with pytest.raises(exceptions.TransitionNotAllowed) as e:
179 | assert machine.validate()
180 | assert e.message == "Can't validate when in Completed."
181 |
182 |
183 | def test_transition_on_execute_should_be_called_with_run_syntax(approval_machine, current_time):
184 | # given
185 | model = mock.MagicMock(state='requested', accepted_at=None,)
186 | machine = approval_machine(model)
187 |
188 | model.is_ok.return_value = True
189 |
190 | # when
191 | assert machine.run('validate') == model
192 | # then
193 | assert model.accepted_at == current_time
194 | assert machine.is_accepted
195 |
196 |
197 | def test_multiple_transition_callbacks():
198 | class ApprovalMachine(StateMachine):
199 | "A workflow"
200 | requested = State('Requested', initial=True)
201 | accepted = State('Accepted')
202 |
203 | @requested.to(accepted)
204 | def validate(self):
205 | return self.accepted
206 |
207 | def on_validate(self):
208 | return self.accepted
209 |
210 | machine = ApprovalMachine()
211 |
212 | with pytest.raises(exceptions.MultipleTransitionCallbacksFound):
213 | machine.validate()
214 |
--------------------------------------------------------------------------------
/Include/python-statemachine/README.rst:
--------------------------------------------------------------------------------
1 | ====================
2 | Python State Machine
3 | ====================
4 |
5 |
6 | .. image:: https://img.shields.io/pypi/v/python-statemachine.svg
7 | :target: https://pypi.python.org/pypi/python-statemachine
8 |
9 | .. image:: https://travis-ci.org/fgmacedo/python-statemachine.svg?branch=master
10 | :target: https://travis-ci.org/fgmacedo/python-statemachine
11 | :alt: Build status
12 |
13 | .. image:: https://codecov.io/gh/fgmacedo/python-statemachine/branch/master/graph/badge.svg
14 | :target: https://codecov.io/gh/fgmacedo/python-statemachine
15 | :alt: Coverage report
16 |
17 | .. image:: https://readthedocs.org/projects/python-statemachine/badge/?version=latest
18 | :target: https://python-statemachine.readthedocs.io/en/latest/?badge=latest
19 | :alt: Documentation Status
20 |
21 | .. image:: https://pyup.io/repos/github/fgmacedo/python-statemachine/shield.svg
22 | :target: https://pyup.io/repos/github/fgmacedo/python-statemachine/
23 | :alt: Updates
24 |
25 | .. image:: https://badges.gitter.im/fgmacedo/python-statemachine.svg
26 | :alt: Join the chat at https://gitter.im/fgmacedo/python-statemachine
27 | :target: https://gitter.im/fgmacedo/python-statemachine
28 |
29 |
30 | Python `finite-state machines `_ made easy.
31 |
32 |
33 | * Free software: MIT license
34 | * Documentation: https://python-statemachine.readthedocs.io.
35 |
36 |
37 | Getting started
38 | ===============
39 |
40 | To install Python State Machine, run this command in your terminal:
41 |
42 | .. code-block:: console
43 |
44 | $ pip install python-statemachine
45 |
46 |
47 | Define your state machine:
48 |
49 | .. code-block:: python
50 |
51 | from statemachine import StateMachine, State
52 |
53 | class TrafficLightMachine(StateMachine):
54 | green = State('Green', initial=True)
55 | yellow = State('Yellow')
56 | red = State('Red')
57 |
58 | slowdown = green.to(yellow)
59 | stop = yellow.to(red)
60 | go = red.to(green)
61 |
62 |
63 | You can now create an instance:
64 |
65 | >>> traffic_light = TrafficLightMachine()
66 |
67 | And inspect about the current state:
68 |
69 | >>> traffic_light.current_state
70 | State('Green', identifier='green', value='green', initial=True)
71 | >>> traffic_light.current_state == TrafficLightMachine.green == traffic_light.green
72 | True
73 |
74 | For each state, there's a dinamically created property in the form ``is_``, that
75 | returns ``True`` if the current status matches the query:
76 |
77 | >>> traffic_light.is_green
78 | True
79 | >>> traffic_light.is_yellow
80 | False
81 | >>> traffic_light.is_red
82 | False
83 |
84 | Query about metadata:
85 |
86 | >>> [s.identifier for s in m.states]
87 | ['green', 'red', 'yellow']
88 | >>> [t.identifier for t in m.transitions]
89 | ['go', 'slowdown', 'stop']
90 |
91 | Call a transition:
92 |
93 | >>> traffic_light.slowdown()
94 |
95 | And check for the current status:
96 |
97 | >>> traffic_light.current_state
98 | State('Yellow', identifier='yellow', value='yellow', initial=False)
99 | >>> traffic_light.is_yellow
100 | True
101 |
102 | You can't run a transition from an invalid state:
103 |
104 | >>> traffic_light.is_yellow
105 | True
106 | >>> traffic_light.slowdown()
107 | Traceback (most recent call last):
108 | ...
109 | LookupError: Can't slowdown when in Yellow.
110 |
111 | You can also trigger events in an alternative way, calling the ``run()`` method:
112 |
113 | >>> traffic_light.is_yellow
114 | True
115 | >>> traffic_light.run('stop')
116 | >>> traffic_light.is_red
117 | True
118 |
119 | A state machine can be instantiated with an initial value:
120 |
121 | >>> machine = TrafficLightMachine(start_value='red')
122 | >>> traffic_light.is_red
123 | True
124 |
125 |
126 | Models
127 | ------
128 |
129 | If you need to persist the current state on another object, or you're using the
130 | state machine to control the flow of another object, you can pass this object
131 | to the ``StateMachine`` constructor:
132 |
133 | >>> class MyModel(object):
134 | ... def __init__(self, state):
135 | ... self.state = state
136 | ...
137 | >>> obj = MyModel(state='red')
138 | >>> traffic_light = TrafficLightMachine(obj)
139 | >>> traffic_light.is_red
140 | True
141 | >>> obj.state
142 | 'red'
143 | >>> obj.state = 'green'
144 | >>> traffic_light.is_green
145 | True
146 | >>> traffic_light.slowdown()
147 | >>> obj.state
148 | 'yellow'
149 | >>> traffic_light.is_yellow
150 | True
151 |
152 |
153 | Callbacks
154 | ---------
155 |
156 | Callbacks when running events:
157 |
158 | .. code-block:: python
159 |
160 | from statemachine import StateMachine, State
161 |
162 | class TrafficLightMachine(StateMachine):
163 | "A traffic light machine"
164 | green = State('Green', initial=True)
165 | yellow = State('Yellow')
166 | red = State('Red')
167 |
168 | slowdown = green.to(yellow)
169 | stop = yellow.to(red)
170 | go = red.to(green)
171 |
172 | def on_slowdown(self):
173 | print('Calma, lá!')
174 |
175 | def on_stop(self):
176 | print('Parou.')
177 |
178 | def on_go(self):
179 | print('Valendo!')
180 |
181 |
182 | >>> stm = TrafficLightMachine()
183 | >>> stm.slowdown()
184 | Calma, lá!
185 | >>> stm.stop()
186 | Parou.
187 | >>> stm.go()
188 | Valendo!
189 |
190 |
191 | Or when entering/exiting states:
192 |
193 | .. code-block:: python
194 |
195 | from statemachine import StateMachine, State
196 |
197 | class TrafficLightMachine(StateMachine):
198 | "A traffic light machine"
199 | green = State('Green', initial=True)
200 | yellow = State('Yellow')
201 | red = State('Red')
202 |
203 | cycle = green.to(yellow) | yellow.to(red) | red.to(green)
204 |
205 | def on_enter_green(self):
206 | print('Valendo!')
207 |
208 | def on_enter_yellow(self):
209 | print('Calma, lá!')
210 |
211 | def on_enter_red(self):
212 | print('Parou.')
213 |
214 | >>> stm = TrafficLightMachine()
215 | >>> stm.cycle()
216 | Calma, lá!
217 | >>> stm.cycle()
218 | Parou.
219 | >>> stm.cycle()
220 | Valendo!
221 |
222 | Mixins
223 | ------
224 |
225 | Your model can inherited from a custom mixin to auto-instantiate a state machine.
226 |
227 | .. code-block:: python
228 |
229 | class CampaignMachineWithKeys(StateMachine):
230 | "A workflow machine"
231 | draft = State('Draft', initial=True, value=1)
232 | producing = State('Being produced', value=2)
233 | closed = State('Closed', value=3)
234 |
235 | add_job = draft.to.itself() | producing.to.itself()
236 | produce = draft.to(producing)
237 | deliver = producing.to(closed)
238 |
239 |
240 | class MyModel(MachineMixin):
241 | state_machine_name = 'CampaignMachine'
242 |
243 | def __init__(self, **kwargs):
244 | for k, v in kwargs.items():
245 | setattr(self, k, v)
246 | super(MyModel, self).__init__()
247 |
248 | def __repr__(self):
249 | return "{}({!r})".format(type(self).__name__, self.__dict__)
250 |
251 |
252 | model = MyModel(state='draft')
253 | assert isinstance(model.statemachine, campaign_machine)
254 | assert model.state == 'draft'
255 | assert model.statemachine.current_state == model.statemachine.draft
256 |
--------------------------------------------------------------------------------
/Include/python-statemachine/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # User-friendly check for sphinx-build
11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13 | endif
14 |
15 | # Internal variables.
16 | PAPEROPT_a4 = -D latex_paper_size=a4
17 | PAPEROPT_letter = -D latex_paper_size=letter
18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
19 | # the i18n builder cannot share the environment and doctrees with the others
20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
21 |
22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
23 |
24 | help:
25 | @echo "Please use \`make ' where is one of"
26 | @echo " html to make standalone HTML files"
27 | @echo " dirhtml to make HTML files named index.html in directories"
28 | @echo " singlehtml to make a single large HTML file"
29 | @echo " pickle to make pickle files"
30 | @echo " json to make JSON files"
31 | @echo " htmlhelp to make HTML files and a HTML help project"
32 | @echo " qthelp to make HTML files and a qthelp project"
33 | @echo " devhelp to make HTML files and a Devhelp project"
34 | @echo " epub to make an epub"
35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38 | @echo " text to make text files"
39 | @echo " man to make manual pages"
40 | @echo " texinfo to make Texinfo files"
41 | @echo " info to make Texinfo files and run them through makeinfo"
42 | @echo " gettext to make PO message catalogs"
43 | @echo " changes to make an overview of all changed/added/deprecated items"
44 | @echo " xml to make Docutils-native XML files"
45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46 | @echo " linkcheck to check all external links for integrity"
47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48 |
49 | clean:
50 | rm -rf $(BUILDDIR)/*
51 |
52 | html:
53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54 | @echo
55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56 |
57 | dirhtml:
58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
59 | @echo
60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
61 |
62 | singlehtml:
63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
64 | @echo
65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
66 |
67 | pickle:
68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
69 | @echo
70 | @echo "Build finished; now you can process the pickle files."
71 |
72 | json:
73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
74 | @echo
75 | @echo "Build finished; now you can process the JSON files."
76 |
77 | htmlhelp:
78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
79 | @echo
80 | @echo "Build finished; now you can run HTML Help Workshop with the" \
81 | ".hhp project file in $(BUILDDIR)/htmlhelp."
82 |
83 | qthelp:
84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
85 | @echo
86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/statemachine.qhcp"
89 | @echo "To view the help file:"
90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/statemachine.qhc"
91 |
92 | devhelp:
93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
94 | @echo
95 | @echo "Build finished."
96 | @echo "To view the help file:"
97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/statemachine"
98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/statemachine"
99 | @echo "# devhelp"
100 |
101 | epub:
102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
103 | @echo
104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
105 |
106 | latex:
107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
108 | @echo
109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
111 | "(use \`make latexpdf' here to do that automatically)."
112 |
113 | latexpdf:
114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
115 | @echo "Running LaTeX files through pdflatex..."
116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
118 |
119 | latexpdfja:
120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121 | @echo "Running LaTeX files through platex and dvipdfmx..."
122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
124 |
125 | text:
126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
127 | @echo
128 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
129 |
130 | man:
131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
132 | @echo
133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
134 |
135 | texinfo:
136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
137 | @echo
138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
139 | @echo "Run \`make' in that directory to run these through makeinfo" \
140 | "(use \`make info' here to do that automatically)."
141 |
142 | info:
143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
144 | @echo "Running Texinfo files through makeinfo..."
145 | make -C $(BUILDDIR)/texinfo info
146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
147 |
148 | gettext:
149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
150 | @echo
151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
152 |
153 | changes:
154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
155 | @echo
156 | @echo "The overview file is in $(BUILDDIR)/changes."
157 |
158 | linkcheck:
159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
160 | @echo
161 | @echo "Link check complete; look for any errors in the above output " \
162 | "or in $(BUILDDIR)/linkcheck/output.txt."
163 |
164 | doctest:
165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
166 | @echo "Testing of doctests in the sources finished, look at the " \
167 | "results in $(BUILDDIR)/doctest/output.txt."
168 |
169 | xml:
170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
171 | @echo
172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
173 |
174 | pseudoxml:
175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
176 | @echo
177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
178 |
--------------------------------------------------------------------------------
/Include/python-statemachine/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Command file for Sphinx documentation
4 |
5 | if "%SPHINXBUILD%" == "" (
6 | set SPHINXBUILD=sphinx-build
7 | )
8 | set BUILDDIR=_build
9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
10 | set I18NSPHINXOPTS=%SPHINXOPTS% .
11 | if NOT "%PAPER%" == "" (
12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14 | )
15 |
16 | if "%1" == "" goto help
17 |
18 | if "%1" == "help" (
19 | :help
20 | echo.Please use `make ^` where ^ is one of
21 | echo. html to make standalone HTML files
22 | echo. dirhtml to make HTML files named index.html in directories
23 | echo. singlehtml to make a single large HTML file
24 | echo. pickle to make pickle files
25 | echo. json to make JSON files
26 | echo. htmlhelp to make HTML files and a HTML help project
27 | echo. qthelp to make HTML files and a qthelp project
28 | echo. devhelp to make HTML files and a Devhelp project
29 | echo. epub to make an epub
30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
31 | echo. text to make text files
32 | echo. man to make manual pages
33 | echo. texinfo to make Texinfo files
34 | echo. gettext to make PO message catalogs
35 | echo. changes to make an overview over all changed/added/deprecated items
36 | echo. xml to make Docutils-native XML files
37 | echo. pseudoxml to make pseudoxml-XML files for display purposes
38 | echo. linkcheck to check all external links for integrity
39 | echo. doctest to run all doctests embedded in the documentation if enabled
40 | goto end
41 | )
42 |
43 | if "%1" == "clean" (
44 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
45 | del /q /s %BUILDDIR%\*
46 | goto end
47 | )
48 |
49 |
50 | %SPHINXBUILD% 2> nul
51 | if errorlevel 9009 (
52 | echo.
53 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
54 | echo.installed, then set the SPHINXBUILD environment variable to point
55 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
56 | echo.may add the Sphinx directory to PATH.
57 | echo.
58 | echo.If you don't have Sphinx installed, grab it from
59 | echo.http://sphinx-doc.org/
60 | exit /b 1
61 | )
62 |
63 | if "%1" == "html" (
64 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
65 | if errorlevel 1 exit /b 1
66 | echo.
67 | echo.Build finished. The HTML pages are in %BUILDDIR%/html.
68 | goto end
69 | )
70 |
71 | if "%1" == "dirhtml" (
72 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
73 | if errorlevel 1 exit /b 1
74 | echo.
75 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
76 | goto end
77 | )
78 |
79 | if "%1" == "singlehtml" (
80 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
81 | if errorlevel 1 exit /b 1
82 | echo.
83 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
84 | goto end
85 | )
86 |
87 | if "%1" == "pickle" (
88 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
89 | if errorlevel 1 exit /b 1
90 | echo.
91 | echo.Build finished; now you can process the pickle files.
92 | goto end
93 | )
94 |
95 | if "%1" == "json" (
96 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
97 | if errorlevel 1 exit /b 1
98 | echo.
99 | echo.Build finished; now you can process the JSON files.
100 | goto end
101 | )
102 |
103 | if "%1" == "htmlhelp" (
104 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
105 | if errorlevel 1 exit /b 1
106 | echo.
107 | echo.Build finished; now you can run HTML Help Workshop with the ^
108 | .hhp project file in %BUILDDIR%/htmlhelp.
109 | goto end
110 | )
111 |
112 | if "%1" == "qthelp" (
113 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
114 | if errorlevel 1 exit /b 1
115 | echo.
116 | echo.Build finished; now you can run "qcollectiongenerator" with the ^
117 | .qhcp project file in %BUILDDIR%/qthelp, like this:
118 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\statemachine.qhcp
119 | echo.To view the help file:
120 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\statemachine.ghc
121 | goto end
122 | )
123 |
124 | if "%1" == "devhelp" (
125 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
126 | if errorlevel 1 exit /b 1
127 | echo.
128 | echo.Build finished.
129 | goto end
130 | )
131 |
132 | if "%1" == "epub" (
133 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
134 | if errorlevel 1 exit /b 1
135 | echo.
136 | echo.Build finished. The epub file is in %BUILDDIR%/epub.
137 | goto end
138 | )
139 |
140 | if "%1" == "latex" (
141 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
142 | if errorlevel 1 exit /b 1
143 | echo.
144 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
145 | goto end
146 | )
147 |
148 | if "%1" == "latexpdf" (
149 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
150 | cd %BUILDDIR%/latex
151 | make all-pdf
152 | cd %BUILDDIR%/..
153 | echo.
154 | echo.Build finished; the PDF files are in %BUILDDIR%/latex.
155 | goto end
156 | )
157 |
158 | if "%1" == "latexpdfja" (
159 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
160 | cd %BUILDDIR%/latex
161 | make all-pdf-ja
162 | cd %BUILDDIR%/..
163 | echo.
164 | echo.Build finished; the PDF files are in %BUILDDIR%/latex.
165 | goto end
166 | )
167 |
168 | if "%1" == "text" (
169 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
170 | if errorlevel 1 exit /b 1
171 | echo.
172 | echo.Build finished. The text files are in %BUILDDIR%/text.
173 | goto end
174 | )
175 |
176 | if "%1" == "man" (
177 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
178 | if errorlevel 1 exit /b 1
179 | echo.
180 | echo.Build finished. The manual pages are in %BUILDDIR%/man.
181 | goto end
182 | )
183 |
184 | if "%1" == "texinfo" (
185 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
186 | if errorlevel 1 exit /b 1
187 | echo.
188 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
189 | goto end
190 | )
191 |
192 | if "%1" == "gettext" (
193 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
194 | if errorlevel 1 exit /b 1
195 | echo.
196 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
197 | goto end
198 | )
199 |
200 | if "%1" == "changes" (
201 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
202 | if errorlevel 1 exit /b 1
203 | echo.
204 | echo.The overview file is in %BUILDDIR%/changes.
205 | goto end
206 | )
207 |
208 | if "%1" == "linkcheck" (
209 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
210 | if errorlevel 1 exit /b 1
211 | echo.
212 | echo.Link check complete; look for any errors in the above output ^
213 | or in %BUILDDIR%/linkcheck/output.txt.
214 | goto end
215 | )
216 |
217 | if "%1" == "doctest" (
218 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
219 | if errorlevel 1 exit /b 1
220 | echo.
221 | echo.Testing of doctests in the sources finished, look at the ^
222 | results in %BUILDDIR%/doctest/output.txt.
223 | goto end
224 | )
225 |
226 | if "%1" == "xml" (
227 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
228 | if errorlevel 1 exit /b 1
229 | echo.
230 | echo.Build finished. The XML files are in %BUILDDIR%/xml.
231 | goto end
232 | )
233 |
234 | if "%1" == "pseudoxml" (
235 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
236 | if errorlevel 1 exit /b 1
237 | echo.
238 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
239 | goto end
240 | )
241 |
242 | :end
243 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(mission_planning)
3 |
4 | ## Compile as C++11, supported in ROS Kinetic and newer
5 | # add_compile_options(-std=c++11)
6 |
7 | ## Find catkin macros and libraries
8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
9 | ## is used, also find other catkin packages
10 | find_package(catkin REQUIRED COMPONENTS
11 | rospy
12 | std_msgs
13 | message_generation
14 | )
15 |
16 | ## System dependencies are found with CMake's conventions
17 | # find_package(Boost REQUIRED COMPONENTS system)
18 |
19 | ## Uncomment this if the package has a setup.py. This macro ensures
20 | ## modules and global scripts declared therein get installed
21 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
22 | # catkin_python_setup()
23 |
24 | ################################################
25 | ## Declare ROS messages, services and actions ##
26 | ################################################
27 |
28 | ## To declare and build messages, services or actions from within this
29 | ## package, follow these steps:
30 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in
31 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
32 | ## * In the file package.xml:
33 | ## * add a build_depend tag for "message_generation"
34 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
35 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
36 | ## but can be declared for certainty nonetheless:
37 | ## * add a exec_depend tag for "message_runtime"
38 | ## * In this file (CMakeLists.txt):
39 | ## * add "message_generation" and every package in MSG_DEP_SET to
40 | ## find_package(catkin REQUIRED COMPONENTS ...)
41 | ## * add "message_runtime" and every package in MSG_DEP_SET to
42 | ## catkin_package(CATKIN_DEPENDS ...)
43 | ## * uncomment the add_*_files sections below as needed
44 | ## and list every .msg/.srv/.action file to be processed
45 | ## * uncomment the generate_messages entry below
46 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
47 |
48 | # Generate messages in the 'msg' folder
49 | add_message_files(
50 | FILES
51 | TaskMessage.msg
52 | AgentInfo.msg
53 | SwarmInformation.msg
54 | TargetInformation.msg
55 | TaskStatusMessage.msg
56 | RewardMessage.msg
57 | TaskStatusInformation.msg
58 | SystemStatusMessage.msg
59 | InitMessage.msg
60 | SwarmInfo.msg
61 | EnemyInfo.msg
62 | )
63 |
64 | ## Generate services in the 'srv' folder
65 | # add_service_files(
66 | # FILES
67 | # Service1.srv
68 | # Service2.srv
69 | # )
70 |
71 | ## Generate actions in the 'action' folder
72 | # add_action_files(
73 | # FILES
74 | # Action1.action
75 | # Action2.action
76 | # )
77 |
78 | # Generate added messages and services with any dependencies listed here
79 | generate_messages(
80 | DEPENDENCIES
81 | std_msgs
82 | )
83 |
84 | ################################################
85 | ## Declare ROS dynamic reconfigure parameters ##
86 | ################################################
87 |
88 | ## To declare and build dynamic reconfigure parameters within this
89 | ## package, follow these steps:
90 | ## * In the file package.xml:
91 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
92 | ## * In this file (CMakeLists.txt):
93 | ## * add "dynamic_reconfigure" to
94 | ## find_package(catkin REQUIRED COMPONENTS ...)
95 | ## * uncomment the "generate_dynamic_reconfigure_options" section below
96 | ## and list every .cfg file to be processed
97 |
98 | ## Generate dynamic reconfigure parameters in the 'cfg' folder
99 | # generate_dynamic_reconfigure_options(
100 | # cfg/DynReconf1.cfg
101 | # cfg/DynReconf2.cfg
102 | # )
103 |
104 | ###################################
105 | ## catkin specific configuration ##
106 | ###################################
107 | ## The catkin_package macro generates cmake config files for your package
108 | ## Declare things to be passed to dependent projects
109 | ## INCLUDE_DIRS: uncomment this if your package contains header files
110 | ## LIBRARIES: libraries you create in this project that dependent projects also need
111 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need
112 | ## DEPENDS: system dependencies of this project that dependent projects also need
113 | catkin_package(
114 | # INCLUDE_DIRS include
115 | # LIBRARIES mission_planning
116 | CATKIN_DEPENDS rospy std_msgs
117 | # DEPENDS system_lib
118 | )
119 |
120 | ###########
121 | ## Build ##
122 | ###########
123 |
124 | ## Specify additional locations of header files
125 | ## Your package locations should be listed before other locations
126 | include_directories(
127 | # include
128 | ${catkin_INCLUDE_DIRS}
129 | )
130 |
131 | ## Declare a C++ library
132 | # add_library(${PROJECT_NAME}
133 | # src/${PROJECT_NAME}/mission_planning.cpp
134 | # )
135 |
136 | ## Add cmake target dependencies of the library
137 | ## as an example, code may need to be generated before libraries
138 | ## either from message generation or dynamic reconfigure
139 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
140 |
141 | ## Declare a C++ executable
142 | ## With catkin_make all packages are built within a single CMake context
143 | ## The recommended prefix ensures that target names across packages don't collide
144 | # add_executable(${PROJECT_NAME}_node src/mission_planning_node.cpp)
145 |
146 | ## Rename C++ executable without prefix
147 | ## The above recommended prefix causes long target names, the following renames the
148 | ## target back to the shorter version for ease of user use
149 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
150 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
151 |
152 | ## Add cmake target dependencies of the executable
153 | ## same as for the library above
154 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
155 |
156 | ## Specify libraries to link a library or executable target against
157 | # target_link_libraries(${PROJECT_NAME}_node
158 | # ${catkin_LIBRARIES}
159 | # )
160 |
161 |
162 | #############
163 | ## Install ##
164 | #############
165 |
166 | # all install targets should use catkin DESTINATION variables
167 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
168 |
169 | ## Mark executable scripts (Python etc.) for installation
170 | ## in contrast to setup.py, you can choose the destination
171 | # install(PROGRAMS
172 | # scripts/my_python_script
173 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
174 | # )
175 |
176 | ## Mark executables and/or libraries for installation
177 | # install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
178 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
179 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
180 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
181 | # )
182 |
183 | ## Mark cpp header files for installation
184 | # install(DIRECTORY include/${PROJECT_NAME}/
185 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
186 | # FILES_MATCHING PATTERN "*.h"
187 | # PATTERN ".svn" EXCLUDE
188 | # )
189 |
190 | ## Mark other files for installation (e.g. launch and bag files, etc.)
191 | # install(FILES
192 | # # myfile1
193 | # # myfile2
194 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
195 | # )
196 |
197 | #############
198 | ## Testing ##
199 | #############
200 |
201 | ## Add gtest based cpp test target and link libraries
202 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_mission_planning.cpp)
203 | # if(TARGET ${PROJECT_NAME}-test)
204 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
205 | # endif()
206 |
207 | ## Add folders to be run by python nosetests
208 | # catkin_add_nosetests(test)
209 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # sample documentation build configuration file, created by
4 | # sphinx-quickstart on Mon Apr 16 21:22:43 2012.
5 | #
6 | # This file is execfile()d with the current directory set to its containing dir.
7 | #
8 | # Note that not all possible configuration values are present in this
9 | # autogenerated file.
10 | #
11 | # All configuration values have a default; values that are commented out
12 | # serve to show the default.
13 |
14 | import sys, os
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | #sys.path.insert(0, os.path.abspath('.'))
20 |
21 | # -- General configuration -----------------------------------------------------
22 |
23 | # If your documentation needs a minimal Sphinx version, state it here.
24 | #needs_sphinx = '1.0'
25 |
26 | # Add any Sphinx extension module names here, as strings. They can be extensions
27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28 | extensions = []
29 |
30 | # Add any paths that contain templates here, relative to this directory.
31 | templates_path = ['_templates']
32 |
33 | # The suffix of source filenames.
34 | source_suffix = '.rst'
35 |
36 | # The encoding of source files.
37 | #source_encoding = 'utf-8-sig'
38 |
39 | # The master toctree document.
40 | master_doc = 'index'
41 |
42 | # General information about the project.
43 | project = u'sample'
44 | copyright = u'2012, Kenneth Reitz'
45 |
46 | # The version info for the project you're documenting, acts as replacement for
47 | # |version| and |release|, also used in various other places throughout the
48 | # built documents.
49 | #
50 | # The short X.Y version.
51 | version = 'v0.0.1'
52 | # The full version, including alpha/beta/rc tags.
53 | release = 'v0.0.1'
54 |
55 | # The language for content autogenerated by Sphinx. Refer to documentation
56 | # for a list of supported languages.
57 | #language = None
58 |
59 | # There are two options for replacing |today|: either, you set today to some
60 | # non-false value, then it is used:
61 | #today = ''
62 | # Else, today_fmt is used as the format for a strftime call.
63 | #today_fmt = '%B %d, %Y'
64 |
65 | # List of patterns, relative to source directory, that match files and
66 | # directories to ignore when looking for source files.
67 | exclude_patterns = ['_build']
68 |
69 | # The reST default role (used for this markup: `text`) to use for all documents.
70 | #default_role = None
71 |
72 | # If true, '()' will be appended to :func: etc. cross-reference text.
73 | #add_function_parentheses = True
74 |
75 | # If true, the current module name will be prepended to all description
76 | # unit titles (such as .. function::).
77 | #add_module_names = True
78 |
79 | # If true, sectionauthor and moduleauthor directives will be shown in the
80 | # output. They are ignored by default.
81 | #show_authors = False
82 |
83 | # The name of the Pygments (syntax highlighting) style to use.
84 | pygments_style = 'sphinx'
85 |
86 | # A list of ignored prefixes for module index sorting.
87 | #modindex_common_prefix = []
88 |
89 |
90 | # -- Options for HTML output ---------------------------------------------------
91 |
92 | # The theme to use for HTML and HTML Help pages. See the documentation for
93 | # a list of builtin themes.
94 | html_theme = 'default'
95 |
96 | # Theme options are theme-specific and customize the look and feel of a theme
97 | # further. For a list of options available for each theme, see the
98 | # documentation.
99 | #html_theme_options = {}
100 |
101 | # Add any paths that contain custom themes here, relative to this directory.
102 | #html_theme_path = []
103 |
104 | # The name for this set of Sphinx documents. If None, it defaults to
105 | # " v documentation".
106 | #html_title = None
107 |
108 | # A shorter title for the navigation bar. Default is the same as html_title.
109 | #html_short_title = None
110 |
111 | # The name of an image file (relative to this directory) to place at the top
112 | # of the sidebar.
113 | #html_logo = None
114 |
115 | # The name of an image file (within the static path) to use as favicon of the
116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
117 | # pixels large.
118 | #html_favicon = None
119 |
120 | # Add any paths that contain custom static files (such as style sheets) here,
121 | # relative to this directory. They are copied after the builtin static files,
122 | # so a file named "default.css" will overwrite the builtin "default.css".
123 | html_static_path = ['_static']
124 |
125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126 | # using the given strftime format.
127 | #html_last_updated_fmt = '%b %d, %Y'
128 |
129 | # If true, SmartyPants will be used to convert quotes and dashes to
130 | # typographically correct entities.
131 | #html_use_smartypants = True
132 |
133 | # Custom sidebar templates, maps document names to template names.
134 | #html_sidebars = {}
135 |
136 | # Additional templates that should be rendered to pages, maps page names to
137 | # template names.
138 | #html_additional_pages = {}
139 |
140 | # If false, no module index is generated.
141 | #html_domain_indices = True
142 |
143 | # If false, no index is generated.
144 | #html_use_index = True
145 |
146 | # If true, the index is split into individual pages for each letter.
147 | #html_split_index = False
148 |
149 | # If true, links to the reST sources are added to the pages.
150 | #html_show_sourcelink = True
151 |
152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153 | #html_show_sphinx = True
154 |
155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156 | #html_show_copyright = True
157 |
158 | # If true, an OpenSearch description file will be output, and all pages will
159 | # contain a tag referring to it. The value of this option must be the
160 | # base URL from which the finished HTML is served.
161 | #html_use_opensearch = ''
162 |
163 | # This is the file name suffix for HTML files (e.g. ".xhtml").
164 | #html_file_suffix = None
165 |
166 | # Output file base name for HTML help builder.
167 | htmlhelp_basename = 'sampledoc'
168 |
169 |
170 | # -- Options for LaTeX output --------------------------------------------------
171 |
172 | latex_elements = {
173 | # The paper size ('letterpaper' or 'a4paper').
174 | #'papersize': 'letterpaper',
175 |
176 | # The font size ('10pt', '11pt' or '12pt').
177 | #'pointsize': '10pt',
178 |
179 | # Additional stuff for the LaTeX preamble.
180 | #'preamble': '',
181 | }
182 |
183 | # Grouping the document tree into LaTeX files. List of tuples
184 | # (source start file, target name, title, author, documentclass [howto/manual]).
185 | latex_documents = [
186 | ('index', 'sample.tex', u'sample Documentation',
187 | u'Kenneth Reitz', 'manual'),
188 | ]
189 |
190 | # The name of an image file (relative to this directory) to place at the top of
191 | # the title page.
192 | #latex_logo = None
193 |
194 | # For "manual" documents, if this is true, then toplevel headings are parts,
195 | # not chapters.
196 | #latex_use_parts = False
197 |
198 | # If true, show page references after internal links.
199 | #latex_show_pagerefs = False
200 |
201 | # If true, show URL addresses after external links.
202 | #latex_show_urls = False
203 |
204 | # Documents to append as an appendix to all manuals.
205 | #latex_appendices = []
206 |
207 | # If false, no module index is generated.
208 | #latex_domain_indices = True
209 |
210 |
211 | # -- Options for manual page output --------------------------------------------
212 |
213 | # One entry per manual page. List of tuples
214 | # (source start file, name, description, authors, manual section).
215 | man_pages = [
216 | ('index', 'sample', u'sample Documentation',
217 | [u'Kenneth Reitz'], 1)
218 | ]
219 |
220 | # If true, show URL addresses after external links.
221 | #man_show_urls = False
222 |
223 |
224 | # -- Options for Texinfo output ------------------------------------------------
225 |
226 | # Grouping the document tree into Texinfo files. List of tuples
227 | # (source start file, target name, title, author,
228 | # dir menu entry, description, category)
229 | texinfo_documents = [
230 | ('index', 'sample', u'sample Documentation',
231 | u'Kenneth Reitz', 'sample', 'One line description of project.',
232 | 'Miscellaneous'),
233 | ]
234 |
235 | # Documents to append as an appendix to all manuals.
236 | #texinfo_appendices = []
237 |
238 | # If false, no module index is generated.
239 | #texinfo_domain_indices = True
240 |
241 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
242 | #texinfo_show_urls = 'footnote'
243 |
--------------------------------------------------------------------------------
/scripts/StageThree.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | import os
4 |
5 | from StageThreeStateMachine import StageThreeStateMachine, StageThreeState
6 | from Task import Task,TaskType
7 | import time
8 |
9 |
10 | class MissionStageThree():
11 |
12 | def __init__(self):
13 | """
14 | ===========================================================
15 | Constructor to create initial relevant Objects and global
16 | Variables
17 | ===========================================================
18 | :Parameters: None
19 | :return: None
20 | ===========================================================
21 | """
22 |
23 | #State object to handle the states with initial state one
24 | self.obj = StageThreeState(state='hoverAtCurrentPosition')
25 | #state machine instance to handle the main state machine
26 | self.mission = StageThreeStateMachine(self.obj)
27 |
28 | # Entry Trigger
29 | self.EntryStartMotor = False
30 | self.EntryHover = False
31 | self.EntryGoToWaypoint = False
32 | self.EntryLandInAOI = False
33 | self.EntryWaitOnGround = False
34 | self.Entry = False
35 | self.Entry = False
36 | self.Entry = False
37 |
38 | self.StageDone = False
39 |
40 |
41 |
42 | def StageThree(self, agentsList, fooList, TaskList):
43 | """
44 | ===========================================================
45 | Stage Three Statemachine function which is executing the
46 | initial static mission steps
47 | ===========================================================
48 | :Parameters:
49 | - AgentsList:
50 | A list which contains a lits of Agents obejct.The Agents object
51 | represents a real entity and contains information about:
52 | AgentID
53 | AgentPosition
54 | AgentVelocity
55 | TaskStatus
56 | TaskID
57 | SystemWorkingStatus
58 |
59 |
60 |
61 | - FoosList:
62 | A list which contains a lits of target obejct.The foo object
63 | represents a real targets and contains information about:
64 | TargetID
65 | TargetPosition
66 | AgentVelocity
67 | AttackkStatus
68 | Confidence
69 |
70 | - TaskList:
71 | A list which contains a lits of task obejct.The task object
72 | object contains information of assigend tasks:
73 | AgentID
74 | TagetID
75 | TaskID
76 | TaskLocation/Waypoint
77 | TaskDeadLine
78 |
79 | :return: None
80 | ===========================================================
81 | """
82 |
83 | if self.obj.state == 'hoverAtCurrentPosition':
84 |
85 | # ======== Entry ========
86 | if not (self.EntryHover):
87 | # Hover State
88 | time.sleep(5)
89 | self.EntryHover = True
90 | return
91 |
92 | # ====Main Part ========
93 | print("S3: Agents hovering...")
94 | hoverTimeReached = True
95 | time.sleep(2)
96 |
97 | # ===== Exit ========
98 | if (hoverTimeReached):
99 | #execute statemachine transition with trigger
100 | self.mission.hoverTimeReached()
101 | #Set time new to restart the countdown
102 |
103 | elif self.obj.state == 'goToWaypoint':
104 |
105 | # ======== Entry ========
106 | if not (self.EntryGoToWaypoint):
107 |
108 | # Execute Payload Drop
109 | # Create Task Objects handle the tasks for each agent
110 | deadline = 120
111 | f = open(self.getRelativeFilePath("MissionPlan/Stage_3_Attack.txt"))
112 | line = f.readlines(0)
113 | print("S3: Setting waypoints")
114 | for i in range(0, len(agentsList)):
115 | waypoint = line[i].split(";")
116 | del waypoint[-1] # delete last element with new line command
117 | waypoint = [int(x) for x in waypoint]
118 | TaskList.append(Task(agentsList[i].agentId, 0, TaskType.WAYPOINT.value,waypoint,deadline))
119 | print "S3: Waypoint: {0} set for agent: {1}".format(waypoint, agentsList[i].agentId)
120 | self.EntryGoToWaypoint = True
121 | f.close()
122 | return
123 |
124 | # ====Main Part ========
125 | print("S3: Agents going to waypoint...")
126 | reachedAOI = self.allAgentsFinishedTask(agentsList)
127 | time.sleep(2)
128 |
129 | # ===== Exit ========
130 | if (reachedAOI):
131 | #execute statemachine transition with trigger
132 | self.mission.reachedAOI()
133 |
134 |
135 | elif self.obj.state == 'landInAOI':
136 |
137 | # ======== Entry ========
138 | if not (self.EntryLandInAOI):
139 | # Execute Payload Drop
140 | # Create Task Objects handle the tasks for each agent
141 | deadline = 180
142 | for i in range(0, len(agentsList)):
143 | TaskList.append(Task(agentsList[i].agentId, 0, TaskType.LAND.value,[1, 1, 1],deadline))
144 | print "S3: Land order send to agent: %d" % agentsList[i].agentId
145 | self.EntryLandInAOI = True
146 | return
147 |
148 | # ====Main Part ========
149 | touchedGround = self.allAgentsFinishedTask(agentsList)
150 | time.sleep(2)
151 |
152 | # ===== Exit ========
153 | if (touchedGround):
154 | #execute statemachine transition with trigger
155 | self.mission.touchedGround()
156 |
157 | elif self.obj.state == 'waitOnGround':
158 |
159 | # ======== Entry ========
160 | if not (self.EntryWaitOnGround):
161 | # Wait on Ground
162 | time.sleep(5)
163 | self.EntryWaitOnGround = True
164 | return
165 |
166 | # ====Main Part ========
167 | # System Turnsoff automaticly when landed therefore the flag just
168 | # set True
169 | timeToTurnOff = True
170 | time.sleep(2)
171 |
172 | # ===== Exit ========
173 | if (timeToTurnOff):
174 | print("End of the mission")
175 | self.StageDone = True
176 | return self.StageDone
177 |
178 |
179 | def getRelativeFilePath(self, relativePath):
180 | """
181 | ==============================================================
182 | Function to setup correct abolute path for rading the .txt file
183 | for predefined agent positions
184 | ===========================================================
185 | :Parameters:
186 | - relativePath: String which contains the relative path of
187 | file
188 |
189 | :return: absFilePath - absolute file path for further use
190 | ===========================================================
191 | """
192 |
193 | scriptDir = os.path.dirname(__file__)
194 | absFilePath = os.path.join(scriptDir, relativePath)
195 | return absFilePath
196 |
197 | def allAgentsFinishedTask(self,agentsList):
198 | """
199 | ==============================================================
200 | Function to recognize if all agents are free for new task in
201 | order to go further to next state of the statemachine
202 | ===========================================================
203 | :Parameters:
204 | - AgentsList:
205 | A list which contains a lits of Agents obejct.The Agents object
206 | represents a real entity and contains information about:
207 | AgentID
208 | AgentPosition
209 | AgentVelocity
210 | TaskStatus
211 | TaskID
212 | SystemWorkingStatus
213 |
214 | :return: True if all finished - False if still agents in work
215 | ===========================================================
216 | """
217 | for i in range(0, len(agentsList)):
218 | if(agentsList[i].taskStatus is True) and (agentsList[i].agentWorkingStatus is True):
219 | return False
220 | return True
221 |
--------------------------------------------------------------------------------
/Include/lap-master/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 | from pkg_resources import parse_version
5 | import shutil
6 | import subprocess
7 | import sys
8 | import traceback
9 |
10 | if sys.version_info[0] < 3:
11 | import __builtin__ as builtins
12 | else:
13 | import builtins
14 | builtins.__LAP_SETUP__ = True
15 |
16 | DISTNAME = 'lap'
17 | DESCRIPTION = 'Linear Assignment Problem solver (LAPJV/LAPMOD).'
18 | LONG_DESCRIPTION = """
19 | **lap** is a linear assignment problem solver using Jonker-Volgenant
20 | algorithm for dense (LAPJV) or sparse (LAPMOD) matrices.
21 | """
22 | MAINTAINER = 'Tomas Kazmar'
23 | MAINTAINER_EMAIL = 'tomash.kazmar@seznam.cz'
24 | URL = 'https://github.com/gatagat/lap'
25 | LICENSE = 'BSD (2-clause)'
26 | DOWNLOAD_URL = URL
27 |
28 | import lap
29 |
30 | VERSION = lap.__version__
31 |
32 | NUMPY_MIN_VERSION = '1.10.1'
33 |
34 | SETUPTOOLS_COMMANDS = set([
35 | 'develop', 'release', 'bdist_egg', 'bdist_rpm',
36 | 'bdist_wininst', 'install_egg_info', 'build_sphinx',
37 | 'egg_info', 'easy_install', 'upload', 'bdist_wheel',
38 | '--single-version-externally-managed',
39 | ])
40 | if SETUPTOOLS_COMMANDS.intersection(sys.argv):
41 | import setuptools
42 |
43 | extra_setuptools_args = dict(
44 | zip_safe=False, # the package can run out of an .egg file
45 | include_package_data=True,
46 | extras_require={
47 | 'alldeps': (
48 | 'numpy >= {0}'.format(NUMPY_MIN_VERSION),
49 | ),
50 | },
51 | )
52 | else:
53 | extra_setuptools_args = dict()
54 |
55 | from distutils.command.clean import clean as Clean
56 |
57 | class CleanCommand(Clean):
58 | description = "Remove build artifacts from the source tree"
59 |
60 | def run(self):
61 | Clean.run(self)
62 | if os.path.exists('build'):
63 | shutil.rmtree('build')
64 | # Remove c files if we are not within a sdist package
65 | cwd = os.path.abspath(os.path.dirname(__file__))
66 | remove_c_files = not os.path.exists(os.path.join(cwd, 'PKG-INFO'))
67 | if remove_c_files:
68 | if os.path.exists('lap/_lapjv.cpp'):
69 | os.unlink('lap/_lapjv.cpp')
70 | for dirpath, dirnames, filenames in os.walk('lap'):
71 | for filename in filenames:
72 | if any(filename.endswith(suffix) for suffix in
73 | (".so", ".pyd", ".dll", ".pyc")):
74 | os.unlink(os.path.join(dirpath, filename))
75 | for dirname in dirnames:
76 | if dirname == '__pycache__':
77 | shutil.rmtree(os.path.join(dirpath, dirname))
78 |
79 | cmdclass = {'clean': CleanCommand}
80 |
81 |
82 | from distutils.version import LooseVersion
83 |
84 | def cythonize(cython_file, gen_file):
85 | try:
86 | from Cython.Compiler.Version import version as cython_version
87 | if LooseVersion(cython_version) < LooseVersion('0.21'):
88 | raise ImportError('Installed cython is too old (0.21 required), '
89 | 'please "pip install -U cython".')
90 | except ImportError:
91 | raise ImportError('Building lapjv requires cython, '
92 | 'please "pip install cython".')
93 | pass
94 |
95 | flags = ['--fast-fail']
96 | if gen_file.endswith('.cpp'):
97 | flags += ['--cplus']
98 |
99 | try:
100 | try:
101 | rc = subprocess.call(['cython'] +
102 | flags + ["-o", gen_file, cython_file])
103 | if rc != 0:
104 | raise Exception('Cythonizing %s failed' % cython_file)
105 | except OSError:
106 | # There are ways of installing Cython that don't result in a cython
107 | # executable on the path, see scipy issue gh-2397.
108 | rc = subprocess.call([sys.executable, '-c',
109 | 'import sys; from Cython.Compiler.Main '
110 | 'import setuptools_main as main;'
111 | ' sys.exit(main())'] + flags +
112 | ["-o", gen_file, cython_file])
113 | if rc != 0:
114 | raise Exception('Cythonizing %s failed' % cython_file)
115 | except OSError:
116 | raise OSError('Cython needs to be installed')
117 |
118 |
119 | def get_numpy_status():
120 | """
121 | Returns a dictionary containing a boolean specifying whether NumPy
122 | is up-to-date, along with the version string (empty string if
123 | not installed).
124 | """
125 | numpy_status = {}
126 | try:
127 | import numpy
128 | numpy_version = numpy.__version__
129 | numpy_status['up_to_date'] = parse_version(
130 | numpy_version) >= parse_version(NUMPY_MIN_VERSION)
131 | numpy_status['version'] = numpy_version
132 | except ImportError:
133 | traceback.print_exc()
134 | numpy_status['up_to_date'] = False
135 | numpy_status['version'] = ""
136 | return numpy_status
137 |
138 |
139 | def get_wrapper_pyx():
140 | return os.path.join('lap', '_lapjv.pyx')
141 |
142 |
143 | def generate_cython():
144 | wrapper_pyx_file = get_wrapper_pyx()
145 | wrapper_c_file = os.path.splitext(wrapper_pyx_file)[0] + '.cpp'
146 | cythonize(wrapper_pyx_file, wrapper_c_file)
147 |
148 |
149 | def configuration(parent_package='', top_path=None):
150 | from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
151 |
152 | config = Configuration(None, parent_package, top_path)
153 |
154 | config.set_options(
155 | ignore_setup_xxx_py=True,
156 | assume_default_configuration=True,
157 | delegate_options_to_subpackages=True,
158 | quiet=True)
159 |
160 | config.add_data_dir('lap/tests')
161 |
162 | wrapper_pyx_file = get_wrapper_pyx()
163 | wrapper_c_file = os.path.splitext(wrapper_pyx_file)[0] + '.cpp'
164 | c_files = [
165 | os.path.join(os.path.dirname(wrapper_pyx_file), 'lapjv.cpp'),
166 | os.path.join(os.path.dirname(wrapper_pyx_file), 'lapmod.cpp')]
167 | config.add_extension('lap._lapjv', sources=[wrapper_c_file, c_files],
168 | include_dirs=[get_numpy_include_dirs(), 'lap'])
169 |
170 | return config
171 |
172 |
173 | def setup_package():
174 | metadata = dict(name=DISTNAME,
175 | maintainer=MAINTAINER,
176 | maintainer_email=MAINTAINER_EMAIL,
177 | description=DESCRIPTION,
178 | license=LICENSE,
179 | packages=['lap'],
180 | url=URL,
181 | version=VERSION,
182 | download_url=DOWNLOAD_URL,
183 | long_description=LONG_DESCRIPTION,
184 | classifiers=['Development Status :: 4 - Beta',
185 | 'Environment :: Console',
186 | 'Intended Audience :: Science/Research',
187 | 'Intended Audience :: Developers',
188 | 'Programming Language :: C',
189 | 'Programming Language :: Python',
190 | 'Programming Language :: Python :: 2',
191 | 'Programming Language :: Python :: 3',
192 | 'Programming Language :: Python :: 2.7',
193 | 'Programming Language :: Python :: 3.6',
194 | 'Programming Language :: Python :: 3.7',
195 | 'Operating System :: Microsoft :: Windows',
196 | 'Operating System :: POSIX',
197 | 'Operating System :: Unix',
198 | 'Operating System :: MacOS',
199 | ],
200 | cmdclass=cmdclass,
201 | **extra_setuptools_args)
202 |
203 | if len(sys.argv) == 1 or (
204 | len(sys.argv) >= 2 and ('--help' in sys.argv[1:] or
205 | sys.argv[1] in ('--help-commands',
206 | 'egg_info',
207 | '--version',
208 | 'clean'))):
209 | try:
210 | from setuptools import setup
211 | except ImportError:
212 | from distutils.core import setup
213 | else:
214 | numpy_status = get_numpy_status()
215 | if numpy_status['up_to_date'] is False:
216 | if numpy_status['version']:
217 | raise ImportError('Installed numpy is too old, '
218 | 'please "pip install -U numpy".')
219 | else:
220 | raise ImportError('lap requires numpy, '
221 | 'please "pip install numpy".')
222 |
223 | from numpy.distutils.core import setup
224 | metadata['configuration'] = configuration
225 |
226 | if len(sys.argv) >= 2 and sys.argv[1] not in 'config':
227 | print('Generating cython files')
228 | cwd = os.path.abspath(os.path.dirname(__file__))
229 | if not os.path.exists(os.path.join(cwd, 'PKG-INFO')):
230 | generate_cython()
231 |
232 | setup(**metadata)
233 |
234 |
235 | if __name__ == "__main__":
236 | setup_package()
237 |
--------------------------------------------------------------------------------