Skip to content

Commit 8155112

Browse files
authored
Initial commit
0 parents  commit 8155112

File tree

9 files changed

+1650
-0
lines changed

9 files changed

+1650
-0
lines changed

LICENSE

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2019, Georgia Tech Research Corporation
2+
Atlanta, Georgia 30332-0415
3+
All Rights Reserved
4+
5+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6+
7+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8+
9+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10+
11+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12+
13+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
Multi-Robot RMPflow
2+
===================================================
3+
4+
This repository contains a python implementation of Multi-Robot RMPflow [[2]](https://arxiv.org/abs/1902.05177) and a 2D example for RMPflow [[1]](https://arxiv.org/abs/1811.07049).
5+
6+
## Prerequisites
7+
+ Python3
8+
+ Numpy
9+
+ Scipy
10+
+ Matplotlib
11+
+ [The Robotarium python simulator](https://github.com/robotarium/robotarium_python_simulator) (optional, only required for `formation_preservation.py` and `cyclic_pursuit_formation.py`)
12+
13+
14+
## To Run in simulation
15+
2D example in [1]:
16+
17+
`python3 rmp_example.py`
18+
19+
A simple multi-robot go-to-goal example (centralized version):
20+
21+
`python3 multi_agent_rmp_centralized.py`
22+
23+
24+
A simple multi-robot go-to-goal example (decentralized version):
25+
26+
`python3 multi_agent_rmp.py`
27+
28+
Formation preservation experiment in [2]: (the Robotarium python simulator required)
29+
30+
`python3 formation_preservation.py`
31+
32+
Cyclic pursuit experiment in [2]: (the Robotarium python simulator required)
33+
34+
`python3 cyclic_pursuit_formation.py`
35+
36+
## To Run on [the Robotarium](https://www.robotarium.gatech.edu/)
37+
38+
[The Robotarium](https://www.robotarium.gatech.edu/) is a remotely accessible swarm robotics testbed. The Robotarium gives users the chance to execute the same code they developed in simulation on real robots. A user can conveniently run an experiment on the Robotarium's robots remotely through the Robotarium's web interface. Please follow the instructions on [the Robotarium webpage](https://www.robotarium.gatech.edu/) to run the code on the real robots.
39+
40+
## References
41+
+ [1] [RMPflow: A Computational Graph for Automatic Motion Policy Generation](https://arxiv.org/abs/1811.07049)
42+
+ [2] [Multi-Objective Policy Generation for Multi-Robot Systems Using Riemannian Motion Policies](https://arxiv.org/abs/1902.05177)
43+
+ [3] [The Robotarium: A remotely accessible swarm robotics research testbed](https://ieeexplore.ieee.org/document/7989200)
44+
45+
46+
## Questions & Bug reporting
47+
48+
Please use Github issue tracker to report bugs. For other questions please contact [Anqi Li](mailto:anqi.li@gatech.edu).
49+
50+
## Citing
51+
52+
If you use the repository in an academic context, please cite following publications:
53+
54+
```
55+
@article{li2019multi,
56+
title={Multi-Objective Policy Generation for Multi-Robot Systems Using Riemannian Motion Policies},
57+
author={Li, Anqi and Mukadam, Mustafa and Egerstedt, Magnus and Boots, Byron},
58+
journal={arXiv preprint arXiv:1902.05177},
59+
year={2019}
60+
}
61+
62+
63+
@inproceedings{cheng2018rmpflow,
64+
title={{RMP}flow: A Computational Graph for Automatic Motion Policy Generation},
65+
author={Cheng, Ching-An and Mukadam, Mustafa and Issac, Jan and Birchfield, Stan and Fox, Dieter and Boots, Byron and Ratliff, Nathan},
66+
booktitle ={The 13th International Workshop on the Algorithmic Foundations of Robotics},
67+
url={arXiv preprint arXiv:1811.07049},
68+
year={2018}
69+
}
70+
```
71+
If you use the Robotarium, please cite following publication:
72+
```
73+
@inproceedings{pickem2017robotarium,
74+
title={The robotarium: A remotely accessible swarm robotics research testbed},
75+
author={Pickem, Daniel and Glotfelter, Paul and Wang, Li and Mote, Mark and Ames, Aaron and Feron, Eric and Egerstedt, Magnus},
76+
booktitle={2017 IEEE International Conference on Robotics and Automation (ICRA)},
77+
pages={1699--1706},
78+
year={2017},
79+
organization={IEEE}
80+
}
81+
```
82+
83+
## License
84+
85+
This repository is released under the BSD license, reproduced in the file LICENSE in this directory.

cyclic_pursuit_formation.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# Robotarium example: formation preservation and cyclic pursuit with two subteams
2+
# @author Anqi Li
3+
# @date April 8, 2019
4+
5+
import rps.robotarium as robotarium
6+
import rps.utilities.graph as graph
7+
import rps.utilities.transformations as transformations
8+
from rps.utilities.barrier_certificates import *
9+
from rps.utilities.misc import at_pose
10+
11+
import time
12+
13+
import numpy as np
14+
from numpy.linalg import norm
15+
16+
from rmp import RMPRoot, RMPNode
17+
from rmp_leaf import CollisionAvoidanceDecentralized, GoalAttractorUni, FormationDecentralized
18+
19+
from matplotlib import pyplot as plt
20+
21+
# Instantiate Robotarium object
22+
23+
# number of robots
24+
N = 5 + 3
25+
N_cyclic_pursuit = 5
26+
cyclic_pursuit_index = [i for i in range(N_cyclic_pursuit)]
27+
formation_control_index = [5, 6, 7]
28+
goal_2_goal_index = 5
29+
30+
# goal configurations
31+
theta = np.arange(N) * 2 * np.pi / N_cyclic_pursuit
32+
x_g = np.stack((np.cos(theta), np.sin(theta))).T * 0.8
33+
x_g[-3, :] = np.array([-0.8, -0.8])
34+
x_g[-2, :] = np.array([-0.8, -1.3])
35+
x_g[-1, :] = np.array([-1.3, -0.8])
36+
37+
38+
# initialize the robotarium
39+
rb = robotarium.Robotarium(number_of_agents=N, show_figure=True, save_data=False, update_time=0.1)
40+
41+
# the algorithm uses single-integrator dynamics, so we'll need these mappings.
42+
si_to_uni_dyn, uni_to_si_states = transformations.create_single_integrator_to_unicycle(projection_distance=0.04)
43+
44+
45+
# barrier certificate to avoid collisions. used for driving to the initial configs,
46+
# not used during the algorthim
47+
si_barrier_cert = create_single_integrator_barrier_certificate(N)
48+
49+
def at_position(states, poses, position_error=0.01):
50+
pes = norm(states[:2, :] - poses[:2, :], 2, axis=0)
51+
done = np.nonzero(pes <= position_error)
52+
return done
53+
54+
# --------------------------------------------------------------------------------------
55+
# build the RMPtree
56+
57+
r = RMPRoot('root')
58+
59+
robots = []
60+
61+
62+
def create_mappings(i):
63+
phi = lambda y, i=i: np.array([[y[2 * i, 0]], [y[2 * i + 1, 0]]])
64+
J = lambda y, i=i: np.concatenate((
65+
np.zeros((2, 2 * i)),
66+
np.eye(2),
67+
np.zeros((2, 2 * (N - i - 1)))), axis=1)
68+
J_dot = lambda y, y_dot: np.zeros((2, 2 * N))
69+
70+
return phi, J, J_dot
71+
72+
73+
for i in range(N):
74+
phi, J, J_dot = create_mappings(i)
75+
robot = RMPNode('robot_' + str(i), r, phi, J, J_dot)
76+
robots.append(robot)
77+
78+
79+
theta = 0.002
80+
Rot = np.array([[np.cos(theta), np.sin(theta)], [-np.sin(theta), np.cos(theta)]])
81+
82+
x_g = np.dot(x_g, Rot)
83+
84+
85+
weight_cp = 5
86+
cps = []
87+
for i in cyclic_pursuit_index:
88+
cp = GoalAttractorUni(
89+
'cp_robot_' + str(i),
90+
robots[i],
91+
y_g=x_g[i],
92+
w_u = 10,
93+
w_l = 0.01,
94+
sigma = 0.1,
95+
alpha = 1,
96+
gain = 1,
97+
eta = 1)
98+
cps.append(cp)
99+
100+
iacas = []
101+
for i in range(N):
102+
for j in range(N):
103+
if i == j:
104+
continue
105+
iaca = CollisionAvoidanceDecentralized(
106+
'ca_robot_' + str(i) + '_robot_' + str(j),
107+
robots[i],
108+
robots[j],
109+
R=0.18,
110+
eta=1)
111+
iacas.append(iaca)
112+
113+
114+
weight_fc = 10
115+
dd = 0.6
116+
fcs = []
117+
for i in formation_control_index:
118+
for j in formation_control_index:
119+
if i == j:
120+
continue
121+
fc = FormationDecentralized(
122+
'fc_robot_' + str(i) + '_robot_' + str(j),
123+
robots[i],
124+
robots[j],
125+
d=dd,
126+
w=weight_fc)
127+
fcs.append(fc)
128+
129+
130+
ga = GoalAttractorUni(
131+
'ga_robot_' + str(goal_2_goal_index),
132+
robots[goal_2_goal_index],
133+
np.array([1.3, 1.3]),
134+
w_u = 10,
135+
w_l = 1,
136+
sigma = 0.1,
137+
alpha = 10,
138+
gain = 1,
139+
eta = 2)
140+
141+
# ------------------------------------------------------
142+
# drive to the initial configurations
143+
144+
x_uni = rb.get_poses()
145+
si_velocities = np.zeros((2, N))
146+
rb.set_velocities(np.arange(N), si_to_uni_dyn(si_velocities, x_uni))
147+
rb.step()
148+
149+
150+
151+
for k in range(2000):
152+
x_uni = rb.get_poses()
153+
x_si = uni_to_si_states(x_uni)
154+
155+
if np.size(at_position(x_si, x_g.T)) == N:
156+
print('done!')
157+
break
158+
159+
si_velocities = (x_g.T - x_si)
160+
si_velocities = si_barrier_cert(si_velocities, x_si)
161+
rb.set_velocities(np.arange(N), si_to_uni_dyn(si_velocities, x_uni))
162+
rb.step()
163+
164+
165+
time.sleep(1)
166+
167+
# -----------------------------------------------
168+
# main simulation
169+
170+
dt = rb.time_step
171+
si_velocities = np.zeros((2, N))
172+
173+
magnitude_limit = 0.2
174+
for k in range(6000):
175+
176+
# Get the poses of the robots and convert to single-integrator poses
177+
x_uni = rb.get_poses()
178+
x_si = uni_to_si_states(x_uni)
179+
180+
x = x_si.T.flatten()
181+
x_dot = si_velocities.T.flatten()
182+
183+
r.set_root_state(x, x_dot)
184+
r.pushforward()
185+
x_g = np.dot(x_g, Rot)
186+
[cps[i].update_goal(x_g[i]) for i in range(N_cyclic_pursuit)]
187+
[leaf.update() for leaf in iacas]
188+
[leaf.update() for leaf in fcs]
189+
r.pullback()
190+
try:
191+
a = r.resolve()
192+
si_accelerations = a.reshape(-1, 2).T
193+
# simulate double-integrator dynamics
194+
si_velocities = si_velocities + si_accelerations * dt
195+
norms = norm(si_velocities, axis=0)
196+
idxs_to_normalize = (norms > magnitude_limit)
197+
si_velocities[:, idxs_to_normalize] *= magnitude_limit * (1 / norms[idxs_to_normalize])
198+
except:
199+
si_velocities = np.zeros((2, N))
200+
print(x_si)
201+
print('Warning: no sol found, emergency break')
202+
break
203+
204+
# Set the velocities of agents 1,...,N
205+
rb.set_velocities(np.arange(N), si_to_uni_dyn(si_velocities, x_uni))
206+
207+
# Iterate the simulation
208+
try:
209+
rb.step()
210+
except:
211+
rb.call_at_scripts_end()
212+
exit(0)
213+
214+
215+
216+
# Always call this function at the end of your script!!!!
217+
rb.call_at_scripts_end()

0 commit comments

Comments
 (0)