Skip to content

Commit 0e2ca66

Browse files
committed
add tests for mobile robot planning
1 parent e034509 commit 0e2ca66

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

tests/test_mobile_planner.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
from collections import namedtuple
2+
from math import pi
3+
import numpy.testing as nt
4+
import numpy as np
5+
import unittest
6+
import spatialmath.base as sm
7+
8+
from roboticstoolbox.mobile import *
9+
10+
11+
class TestPlanners(unittest.TestCase):
12+
13+
def test_occgrid(self):
14+
g = np.zeros((100, 120))
15+
g[20:30, 50:80] = 1
16+
17+
og = BinaryOccupancyGrid(g, name='my grid')
18+
19+
self.assertEqual(og.shape, g.shape)
20+
21+
s = str(og)
22+
self.assertIsInstance(s, str)
23+
self.assertEqual(s, "BinaryOccupancyGrid[my grid]: 120 x 100, cell size=1, x = [0.0, 119.0], y = [0.0, 99.0], 2.5% occupied")
24+
25+
self.assertEqual(og.xmin, 0)
26+
self.assertEqual(og.xmax, 119)
27+
self.assertEqual(og.ymin, 0)
28+
self.assertEqual(og.ymax, 99)
29+
30+
self.assertTrue(og.isoccupied((50, 20)))
31+
self.assertTrue(og.isoccupied((60, 25)))
32+
self.assertTrue(og.isoccupied((200, 200)))
33+
self.assertFalse(og.isoccupied((0, 0)))
34+
self.assertFalse(og.isoccupied((80, 30)))
35+
36+
og.plot(block=False)
37+
38+
og2 = og.copy()
39+
40+
self.assertEqual(og2.xmin, 0)
41+
self.assertEqual(og2.xmax, 119)
42+
self.assertEqual(og2.ymin, 0)
43+
self.assertEqual(og2.ymax, 99)
44+
45+
self.assertTrue(og2.isoccupied((50, 20)))
46+
self.assertTrue(og2.isoccupied((60, 25)))
47+
self.assertTrue(og2.isoccupied((200, 200)))
48+
self.assertFalse(og2.isoccupied((0, 0)))
49+
self.assertFalse(og2.isoccupied((80, 30)))
50+
self.assertFalse(og2.isoccupied((45, 20)))
51+
52+
og2.inflate(5)
53+
54+
self.assertTrue(og2.isoccupied((50, 20)))
55+
self.assertTrue(og2.isoccupied((60, 25)))
56+
self.assertTrue(og2.isoccupied((200, 200)))
57+
self.assertFalse(og2.isoccupied((0, 0)))
58+
self.assertTrue(og2.isoccupied((80, 30)))
59+
self.assertTrue(og2.isoccupied((45, 20)))
60+
61+
self.assertEqual(str(og2), "BinaryOccupancyGrid[my grid]: 120 x 100, cell size=1, x = [0.0, 119.0], y = [0.0, 99.0], 6.3% occupied")
62+
63+
# check no change to original
64+
self.assertFalse(og.isoccupied((80, 30)))
65+
66+
og = BinaryOccupancyGrid(g, cellsize=0.1, origin=(2,4), name='foo')
67+
68+
self.assertEqual(og.xmin, 2)
69+
self.assertEqual(og.xmax, 13.9)
70+
self.assertEqual(og.ymin, 4)
71+
self.assertEqual(og.ymax, 13.9)
72+
self.assertTrue(og.isoccupied((8.5, 6.5)))
73+
self.assertTrue(og.isoccupied((500, 500)))
74+
self.assertFalse(og.isoccupied((3, 5)))
75+
76+
og.inflate(0.5)
77+
self.assertEqual(str(og), "BinaryOccupancyGrid[foo]: 120 x 100, cell size=0.1, x = [2.0, 13.9], y = [4.0, 13.9], 6.3% occupied")
78+
79+
def test_bug2(self):
80+
pass
81+
82+
def test_dubins(self):
83+
84+
start = (0, 0, pi/2)
85+
goal = (1, 0, pi/2)
86+
87+
dubins = DubinsPlanner(curvature=1.0)
88+
path, status = dubins.query(start, goal)
89+
90+
self.assertIsInstance(path, np.ndarray)
91+
self.assertEqual(path.shape, (74,3))
92+
self.assertEqual(status.__class__.__name__, "DubinsStatus")
93+
self.assertTrue(hasattr(status, 'segments'))
94+
self.assertTrue(hasattr(status, 'length'))
95+
96+
def test_reedsshepp(self):
97+
98+
start = (0, 0, pi/2)
99+
goal = (1, 0, pi/2)
100+
101+
rs = ReedsSheppPlanner(curvature=1.0)
102+
path, status = rs.query(start, goal)
103+
104+
self.assertIsInstance(path, np.ndarray)
105+
self.assertEqual(path.shape, (66,3))
106+
self.assertEqual(status.__class__.__name__, "ReedsSheppStatus")
107+
self.assertTrue(hasattr(status, 'segments'))
108+
self.assertTrue(hasattr(status, 'length'))
109+
self.assertTrue(hasattr(status, 'direction'))
110+
111+
# def test_bug2(self):
112+
113+
# vars = loadmat("data/map1.mat")
114+
# map = vars['map']
115+
116+
# bug = Bug2Planner(map)
117+
# # bug.plan()
118+
# path = bug.query([20, 10], [50, 35])
119+
120+
# # valid path
121+
# self.assertTrue(path is not None)
122+
123+
# # valid Nx2 array
124+
# self.assertIsInstance(path, np.ndarray)
125+
# self.assertEqual(path.shape[1], 2)
126+
127+
# # includes start and goal
128+
# self.assertTrue(all(path[0,:] == [20,10]))
129+
# self.assertTrue(all(path[-1,:] == [50,35]))
130+
131+
# # path doesn't include obstacles
132+
# for p in path:
133+
# self.assertFalse(bug.is_occupied(p))
134+
135+
# # there are no gaps
136+
# for k in range(len(path)-1):
137+
# d = np.linalg.norm(path[k] - path[k+1])
138+
# self.assertTrue(d < 1.5)
139+
140+
# bug.plot()
141+
# bug.plot(path=path)
142+
143+
# def test_dxform(self):
144+
145+
# vars = loadmat("data/map1.mat")
146+
# map = vars['map']
147+
148+
# dx = DXform(map)
149+
# dx.plan([50, 35])
150+
# path = dx.query([20, 10])
151+
152+
# # valid path
153+
# self.assertTrue(path is not None)
154+
155+
# # valid Nx2 array
156+
# self.assertIsInstance(path, np.ndarray)
157+
# self.assertEqual(path.shape[1], 2)
158+
159+
# # includes start and goal
160+
# self.assertTrue(all(path[0,:] == [20,10]))
161+
# self.assertTrue(all(path[-1,:] == [50,35]))
162+
163+
# # path doesn't include obstacles
164+
# for p in path:
165+
# self.assertFalse(dx.is_occupied(p))
166+
167+
# # there are no gaps
168+
# for k in range(len(path)-1):
169+
# d = np.linalg.norm(path[k] - path[k+1])
170+
# self.assertTrue(d < 1.5)
171+
172+
# dx.plot()
173+
# dx.plot(path=path)
174+
if __name__ == '__main__': # pragma nocover
175+
unittest.main()
176+
# pytest.main(['tests/test_SerialLink.py'])

0 commit comments

Comments
 (0)