-
Notifications
You must be signed in to change notification settings - Fork 0
/
robtools.py
117 lines (90 loc) · 2.81 KB
/
robtools.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import sys
import itertools
from typing import Any, NamedTuple
from collections import namedtuple
from enum import Enum
class IRSensorData(NamedTuple):
center: float
left: float
right: float
back: float
class Point(NamedTuple):
x: float
y: float
class Orientation(Enum):
E = -90
N = 0
W = 90
S = 180
class RobotStates(Enum):
MOVING = 0
MAPPING = 1
FINISHED = 2
class Ground():
def __init__(self, NBeacons):
init_enum_pair = [('normal', -1), ('home', 0)]
for beacon in range(1, NBeacons):
beacon_string = 'beacon'+ str(beacon)
init_enum_pair.append((beacon_string, beacon))
self.GroundStatus = Enum('GroundStatus', init_enum_pair)
class GroundSensorData(NamedTuple):
status: Any
def SetGroundSensorData(status, ground_enum):
return GroundSensorData(ground_enum(status))
class PIDController():
def __init__(self, Kp):
self.u = 0
self.e = 0
self.max_u = 0.5
self.Kp = Kp
Ti = sys.float_info.max
Td = 0.0
h = 0.050
self.delta = 0.05
self.K0 = Kp * (1+h/Ti+Td/h)
self.K1 = -Kp * (1+2*Td/h)
self.K2 = Kp*Td/h
self.e_m1 = 0
self.e_m2 = 0
self.u_m1 = 0
def control_action(self, set_point, feedback):
self.e = set_point - feedback
self.u = self.u_m1 + self.K0*self.e + self.K1*self.e_m1 + self.K2*self.e_m2
self.e_m2 = self.e_m1
self.e_m1 = self.e
self.e_m1 = self.u
if self.u_m1>self.max_u:
self.u_m1 = self.max_u
if self.u_m1<-self.max_u:
self.u_m1 = -self.max_u
return self.u
# Based on Gist by RobertSudwarts
def degree_to_cardinal(d):
dirs = ["N", "W", "S", "E"]
ix = round(d/(360. / len(dirs)))
return dirs[ix % len(dirs)]
def round_up_to_even(f):
if f >= 0:
return int(f) if ((abs(int(f)) % 2) == 0) else abs(int(f)) + 1
if f < 0:
return int(f) if ((abs(int(f)) % 2) == 0) else int(f) - 1
# From itertools documentation
def pairwise(iterable):
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
def path_to_moves(path):
if len(path) <= 2:
return None
node_pairs = pairwise(path)
move_list = []
for node in node_pairs:
if node[1][1] > node[0][1]:
move_list.append((Point(node[1][1], node[1][0]), Orientation.N))
elif node[1][1] < node[0][1]:
move_list.append((Point(node[1][1], node[1][0]), Orientation.S))
elif node[1][0] > node[0][0]:
move_list.append((Point(node[1][1], node[1][0]), Orientation.E))
elif node[1][0] < node[0][0]:
move_list.append((Point(node[1][1], node[1][0]), Orientation.W))
return move_list