updated template for 2nd round of RoboLab Spring 2018
This commit is contained in:
commit
e6b628f41a
11 changed files with 629 additions and 0 deletions
29
src/communication.py
Normal file
29
src/communication.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Suggestion: Do not import the ev3dev.ev3 module in this file
|
||||
|
||||
|
||||
class Communication:
|
||||
"""
|
||||
Class to hold the MQTT client
|
||||
|
||||
Feel free to add functions, change the constructor and the example send_message() to satisfy your requirements and thereby solve the task according to the specifications
|
||||
"""
|
||||
|
||||
def __init__(self, mqtt_client):
|
||||
""" Initializes communication module, connect to server, subscribe, etc. """
|
||||
# THESE TWO VARIABLES MUST NOT BE CHANGED
|
||||
self.client = mqtt_client
|
||||
self.client.on_message = self.on_message
|
||||
|
||||
# ADD YOUR VARIABLES HERE
|
||||
|
||||
# THIS FUNCTIONS SIGNATURE MUST NOT BE CHANGED
|
||||
def on_message(self, client, data, message):
|
||||
""" Handles the callback if any message arrived """
|
||||
pass
|
||||
|
||||
# Example
|
||||
def send_message(self, topic, message):
|
||||
""" Sends given message to specified channel """
|
||||
pass
|
26
src/main.py
Normal file
26
src/main.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import ev3dev.ev3 as ev3
|
||||
import uuid
|
||||
import paho.mqtt.client as mqtt
|
||||
from planet import Direction, Planet
|
||||
from communication import Communication
|
||||
|
||||
client = None # DO NOT EDIT
|
||||
|
||||
|
||||
def run():
|
||||
# DO NOT EDIT
|
||||
global client
|
||||
client = mqtt.Client(client_id=str(uuid.uuid4()), # client_id has to be unique among ALL users
|
||||
clean_session=False,
|
||||
protocol=mqtt.MQTTv31)
|
||||
|
||||
# the execution of all code shall be started from within this function
|
||||
# ADD YOUR OWN IMPLEMENTATION HEREAFTER
|
||||
print("Hello World!")
|
||||
|
||||
|
||||
# DO NOT EDIT
|
||||
if __name__ == '__main__':
|
||||
run()
|
2
src/odometry.py
Normal file
2
src/odometry.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Suggestion: implement odometry as class that is not using the ev3dev.ev3 package
|
||||
# establish value exchange with main driving class via getters and setters
|
72
src/planet.py
Normal file
72
src/planet.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from enum import IntEnum, unique
|
||||
from typing import List, Optional, Tuple, Dict
|
||||
# IMPORTANT NOTE: DO NOT IMPORT THE ev3dev.ev3 MODULE IN THIS FILE
|
||||
|
||||
|
||||
@unique
|
||||
class Direction(IntEnum):
|
||||
""" Directions in degrees """
|
||||
NORTH = 0
|
||||
EAST = 90
|
||||
SOUTH = 180
|
||||
WEST = 270
|
||||
|
||||
|
||||
# simple alias, no magic here
|
||||
Weight = int
|
||||
"""
|
||||
Weight of a given path (received from the server)
|
||||
value: -1 if broken path
|
||||
>0 for all other paths
|
||||
never 0
|
||||
"""
|
||||
|
||||
|
||||
class Planet:
|
||||
"""
|
||||
Contains the representation of the map and provides certain functions to manipulate it according to the specifications
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
""" Initializes the data structure """
|
||||
self.target = None
|
||||
|
||||
def add_path(self, start: Tuple[Tuple[int, int], Direction], target: Tuple[Tuple[int, int], Direction], weight: int):
|
||||
"""
|
||||
Adds a bidirectional path defined between the start and end coordinates to the map and assigns the weight to it
|
||||
|
||||
example:
|
||||
add_path(((0, 3), Direction.NORTH), ((0, 3), Direction.WEST), 1)
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_paths(self) -> Dict[Tuple[int, int], Dict[Direction, Tuple[Tuple[int, int], Direction, Weight]]]:
|
||||
"""
|
||||
Returns all paths
|
||||
|
||||
example:
|
||||
get_paths() returns: {
|
||||
(0, 3): {
|
||||
Direction.NORTH: ((0, 3), Direction.WEST, 1),
|
||||
Direction.EAST: ((1, 3), Direction.WEST, 2)
|
||||
},
|
||||
(1, 3): {
|
||||
Direction.WEST: ((0, 3), Direction.EAST, 2),
|
||||
...
|
||||
},
|
||||
...
|
||||
}
|
||||
"""
|
||||
pass
|
||||
|
||||
def shortest_path(self, start: Tuple[int, int], target: Tuple[int, int]) -> Optional[List[Tuple[Tuple[int, int], Direction]]]:
|
||||
"""
|
||||
Returns a shortest path between two nodes
|
||||
|
||||
examples:
|
||||
shortest_path((0,0), (2,2)) returns: [((0, 0), Direction.EAST), ((1, 0), Direction.NORTH)]
|
||||
shortest_path((0,0), (1,2)) returns: None
|
||||
"""
|
||||
pass
|
85
src/planettest.py
Executable file
85
src/planettest.py
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
from planet import Direction, Planet
|
||||
|
||||
|
||||
class ExampleTestPlanet(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""
|
||||
Instantiates the planet data structure and fills it with paths
|
||||
|
||||
example planet:
|
||||
|
||||
+--+
|
||||
| |
|
||||
+-0,3------+
|
||||
| |
|
||||
0,2-----2,2 (target)
|
||||
| /
|
||||
+-0,1 /
|
||||
| | /
|
||||
+-0,0-1,0
|
||||
|
|
||||
(start)
|
||||
|
||||
"""
|
||||
|
||||
# set your data structure
|
||||
self.planet = Planet()
|
||||
|
||||
# add the paths
|
||||
self.planet.add_path(((0, 0), Direction.NORTH), ((0, 1), Direction.SOUTH), 1)
|
||||
self.planet.add_path(((0, 1), Direction.WEST), ((0, 0), Direction.WEST), 1)
|
||||
|
||||
def test_target_not_reachable_with_loop(self):
|
||||
# does the shortest path algorithm loop infinitely?
|
||||
# there is no shortest path
|
||||
self.assertIsNone(self.planet.shortest_path((0, 0), (1, 2)))
|
||||
|
||||
|
||||
class YourFirstTestPlanet(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""
|
||||
Instantiates the planet data structure and fills it with paths
|
||||
|
||||
MODEL YOUR TEST PLANET HERE (if you'd like):
|
||||
|
||||
"""
|
||||
# set your data structure
|
||||
self.planet = Planet()
|
||||
|
||||
# ADD YOUR PATHS HERE:
|
||||
# self.planet.add_path(...)
|
||||
|
||||
def test_integrity(self):
|
||||
# were all paths added correctly to the planet
|
||||
# check if add_path() works by using get_paths()
|
||||
self.fail('implement me!')
|
||||
|
||||
def test_empty_planet(self):
|
||||
self.fail('implement me!')
|
||||
|
||||
def test_target_not_reachable(self):
|
||||
self.fail('implement me!')
|
||||
|
||||
def test_shortest_path(self):
|
||||
# at least 2 possible paths
|
||||
self.fail('implement me!')
|
||||
|
||||
def test_same_length(self):
|
||||
# at least 2 possible paths with the same weight
|
||||
self.fail('implement me!')
|
||||
|
||||
def test_shortest_path_with_loop(self):
|
||||
# does the shortest path algorithm loop infinitely?
|
||||
# there is a shortest path
|
||||
self.fail('implement me!')
|
||||
|
||||
def test_target_not_reachable_with_loop(self):
|
||||
# there is no shortest path
|
||||
self.fail('implement me!')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Add table
Add a link
Reference in a new issue