from __future__ import print_function
import pygame
import sys, os, getopt, math
import numpy as np
import pickle
swarm_size = 30
manual_mode = False
try:
opts, args = getopt.getopt(sys.argv[1:], 'n:', ['manual'])
except getopt.GetoptError as err:
print(str(err))
sys.exit()
for opt,arg in opts:
if opt == '-n':
swarm_size = int(arg)
elif opt == '--manual':
manual_mode = True
power_exponent = 1.3
pixels_per_length = 50
def cal_world_side_coef():
desired_screen_size = 600
desired_world_size = float(desired_screen_size) / pixels_per_length
return desired_world_size / pow(30, 1/power_exponent)
world_side_coef = cal_world_side_coef()
world_side_length = world_side_coef * pow(swarm_size, 1/power_exponent)
world_size = (world_side_length, world_side_length)
screen_side_length = int(pixels_per_length * world_side_length)
screen_size = (screen_side_length, screen_side_length)
comm_range = 0.65
desired_space_ratio = 0.8
desired_space = comm_range * desired_space_ratio
perp_thres = math.pi/18
devia_angle = math.pi/9
curve_folder = "curve-data"
shape_catalog = ["ARM", "CWRU", "DIRL", "KID", "MAD", "squarehelix"]
shape_quantity = len(shape_catalog)
shape_decision = -1
force_shape_set = range(shape_quantity)
robot_poses = np.random.rand(swarm_size, 2) * world_side_length
dist_table = np.zeros((swarm_size, swarm_size))
conn_table = np.zeros((swarm_size, swarm_size))
conn_lists = [[] for i in range(swarm_size)]
def dist_conn_update():
global dist_table
global conn_table
global conn_lists
conn_lists = [[] for i in range(swarm_size)]
for i in range(swarm_size):
for j in range(i+1, swarm_size):
dist_temp = np.linalg.norm(robot_poses[i] - robot_poses[j])
dist_table[i,j] = dist_temp
dist_table[j,i] = dist_temp
if dist_temp > comm_range:
conn_table[i,j] = 0
conn_table[j,i] = 0
else:
conn_table[i,j] = 1
conn_table[j,i] = 1
conn_lists[i].append(j)
conn_lists[j].append(i)
dist_conn_update()
disp_poses = []
def disp_poses_update():
global disp_poses
poses_temp = robot_poses / world_side_length
poses_temp[:,1] = 1.0 - poses_temp[:,1]
poses_temp = poses_temp * screen_side_length
disp_poses = poses_temp.astype(int)
disp_poses_update()
seed_percentage = 0.1
seed_quantity = min(max(int(swarm_size*seed_percentage), 1), swarm_size)
robot_seeds = [False for i in range(swarm_size)]
seed_list_temp = np.arange(swarm_size)
np.random.shuffle(seed_list_temp)
for i in seed_list_temp[:seed_quantity]:
robot_seeds[i] = True
color_white = (255,255,255)
color_black = (0,0,0)
color_grey = (128,128,128)
color_red = (255,0,0)
distinct_color_set = ((230,25,75), (60,180,75), (255,225,25), (0,130,200), (245,130,48),
(145,30,180), (70,240,240), (240,50,230), (210,245,60), (250,190,190),
(0,128,128), (230,190,255), (170,110,40), (128,0,0),
(170,255,195), (128,128,0), (0,0,128))
color_quantity = 17
robot_size = 5
robot_empty_width = 2
conn_width = 2
robot_size_consensus = 7
conn_width_thin_consensus = 2
conn_width_thick_consensus = 4
pygame.init()
font = pygame.font.SysFont("Cabin", 12)
icon = pygame.image.load("icon_geometry_art.jpg")
pygame.display.set_icon(icon)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("Demo 3")
screen.fill(color_white)
for i in range(swarm_size):
pygame.draw.circle(screen, color_black, disp_poses[i], robot_size,
robot_empty_width)
pygame.display.update()
raw_input("<Press Enter to continue>")
def S1_robot_grouping(robot_list, robot_group_ids, groups):
groups_temp = {}
for i in robot_list:
group_id_temp = robot_group_ids[i]
if group_id_temp not in groups_temp.keys():
groups_temp[group_id_temp] = [i]
else:
groups_temp[group_id_temp].append(i)
group_id_max = -1
if len(groups_temp.keys()) > 1:
group_id_max = groups_temp.keys()[0]
size_max = len(groups[group_id_max][0])
for group_id_temp in groups_temp.keys()[1:]:
size_temp = len(groups[group_id_temp][0])
if size_temp > size_max:
group_id_max = group_id_temp
size_max = size_temp
else:
group_id_max = groups_temp.keys()[0]
return groups_temp, group_id_max
def S1_closest_robot(robot_host, robot_neighbors):
robot_closest = robot_neighbors[0]
dist_closest = dist_table[robot_host,robot_closest]
for i in robot_neighbors[1:]:
dist_temp = dist_table[robot_host,i]
if dist_temp < dist_closest:
robot_closest = i
dist_closest = dist_temp
return robot_closest
def robot_boundary_check(robot_pos, robot_ori):
new_ori = robot_ori
if robot_pos[0] >= world_side_length:
if math.cos(new_ori) > 0:
new_ori = reset_radian(2*(math.pi/2) - new_ori)
if new_ori > 0:
if (math.pi - new_ori) < perp_thres:
new_ori = new_ori - devia_angle
else:
if (new_ori + math.pi) < perp_thres:
new_ori = new_ori + devia_angle
elif robot_pos[0] <= 0:
if math.cos(new_ori) < 0:
new_ori = reset_radian(2*(math.pi/2) - new_ori)
if new_ori > 0:
if new_ori < perp_thres:
new_ori = new_ori + devia_angle
else:
if (-new_ori) < perp_thres:
new_ori = new_ori - devia_angle
if robot_pos[1] >= world_side_length:
if math.sin(new_ori) > 0:
new_ori = reset_radian(2*(0) - new_ori)
if new_ori > -math.pi/2:
if (new_ori + math.pi/2) < perp_thres:
new_ori = new_ori + devia_angle
else:
if (-math.pi/2 - new_ori) < perp_thres:
new_ori = new_ori - devia_angle
elif robot_pos[1] <= 0:
if math.sin(new_ori) < 0:
new_ori = reset_radian(2*(0) - new_ori)
if new_ori > math.pi/2:
if (new_ori - math.pi/2) < perp_thres:
new_ori = new_ori + devia_angle
else:
if (math.pi/2 - new_ori) < perp_thres:
new_ori = new_ori - devia_angle
return new_ori
def reset_radian(radian):
while radian >= math.pi:
radian = radian - 2*math.pi
while radian < -math.pi:
radian = radian + 2*math.pi
return radian
print("##### simulation 1: line formation #####")
robot_states = np.array([-1 for i in range(swarm_size)])
n1_life_lower = 2
n1_life_upper = 6
robot_n1_lives = np.random.uniform(n1_life_lower, n1_life_upper, swarm_size)
robot_oris = np.random.rand(swarm_size) * 2 * math.pi - math.pi
robot_key_neighbors = [[] for i in range(swarm_size)]
groups = {}
life_incre = 5
group_id_upper = swarm_size
robot_group_ids = np.array([-1 for i in range(swarm_size)])
step_moving_dist = 0.05
destination_error = 0.08
space_good_thres = desired_space * 0.9
sim_haulted = False
time_last = pygame.time.get_ticks()
time_now = time_last
frame_period = 50
sim_freq_control = True
iter_count = 0
line_formed = False
ending_period = 5.0
print("swarm robots are forming a straight line ...")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("program exit in simulation 1")
sys.exit()
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
sim_haulted = not sim_haulted
if sim_haulted: continue
if sim_freq_control:
time_now = pygame.time.get_ticks()
if (time_now - time_last) > frame_period:
time_last = time_now
else:
continue
iter_count = iter_count + 1
st_n1to0 = []
st_gton1 = []
st_0to1 = {}
st_0to2 = {}
st_1to2 = {}
dist_conn_update()
for i in range(swarm_size):
if robot_states[i] == -1:
if robot_n1_lives[i] < 0:
st_n1to0.append(i)
else:
if len(conn_lists[i]) == 0: continue
state12_list = []
for j in conn_lists[i]:
if robot_states[j] == 1 or robot_states[j] == 2:
state12_list.append(j)
if len(state12_list) != 0:
groups_local, group_id_max = S1_robot_grouping(
state12_list, robot_group_ids, groups)
if len(groups_local.keys()) > 1:
for group_id_temp in groups_local.keys():
if ((group_id_temp != group_id_max) and
(group_id_temp not in st_gton1)):
st_gton1.append(group_id_temp)
elif robot_states[i] == 0:
if len(conn_lists[i]) == 0: continue
state2_list = []
state1_list = []
state0_list = []
for j in conn_lists[i]:
if robot_states[j] == 2:
state2_list.append(j)
elif robot_states[j] == 1:
state1_list.append(j)
elif robot_states[j] == 0:
state0_list.append(j)
state2_quantity = len(state2_list)
state1_quantity = len(state1_list)
state0_quantity = len(state0_list)
if state2_quantity + state1_quantity > 1:
groups_local, group_id_max = S1_robot_grouping(state2_list+state1_list,
robot_group_ids, groups)
for group_id_temp in groups_local.keys():
if (group_id_temp != group_id_max) and (group_id_temp not in st_gton1):
st_gton1.append(group_id_temp)
if state2_quantity != 0:
if state2_quantity == 1:
st_0to1[i] = robot_group_ids[state2_list[0]]
robot_key_neighbors[i] = [state2_list[0]]
else:
groups_local, group_id_max = S1_robot_grouping(state2_list,
robot_group_ids, groups)
robot_closest = S1_closest_robot(i, groups_local[group_id_max])
st_0to1[i] = group_id_max
robot_key_neighbors[i] = [robot_closest]
elif state0_quantity != 0:
st_0to2[i] = S1_closest_robot(i, state0_list)
elif (robot_states[i] == 1) or (robot_states[i] == 2):
state12_list = []
has_other_group = False
host_group_id = robot_group_ids[i]
for j in conn_lists[i]:
if (robot_states[j] == 1) or (robot_states[j] == 2):
state12_list.append(j)
if robot_group_ids[j] != host_group_id:
has_other_group = True
if has_other_group:
groups_local, group_id_max = S1_robot_grouping(state12_list,
robot_group_ids, groups)
for group_id_temp in groups_local.keys():
if (group_id_temp != group_id_max) and (group_id_temp not in st_gton1):
st_gton1.append(group_id_temp)
if robot_states[i] == 1:
key = robot_key_neighbors[i][0]
if (robot_key_neighbors[key][0] == -1 or robot_key_neighbors[key][1] == -1):
if (robot_key_neighbors[key][0] == -1 and
robot_key_neighbors[key][1] != -1):
key_next = robot_key_neighbors[key][1]
vect_next = robot_poses[key_next] - robot_poses[key]
vect_i = robot_poses[i] - robot_poses[key]
if np.dot(vect_next,vect_i) > 0:
if key_next in conn_lists[i]:
st_1to2[i] = [key, 1]
else:
st_1to2[i] = [key, 0]
elif (robot_key_neighbors[key][0] != -1 and
robot_key_neighbors[key][1] == -1):
key_next = robot_key_neighbors[key][0]
vect_next = robot_poses[key_next] - robot_poses[key]
vect_i = robot_poses[i] - robot_poses[key]
if np.dot(vect_next,vect_i) > 0:
if key_next in conn_lists[i]:
st_1to2[i] = [key, 0]
else:
st_1to2[i] = [key, 1]
else:
print("key neighbor error(st check)")
sys.exit()
else:
key_left = robot_key_neighbors[key][0]
key_right = robot_key_neighbors[key][1]
if (key_left in conn_lists[i] and key_right in conn_lists[i]):
side = -1
if dist_table[i,key_left] < dist_table[i,key_right]: side = 0
else: side = 1
st_1to2[i] = [key, side]
elif (key_left in conn_lists[i] and key_right not in conn_lists[i]):
st_1to2[i] = [key, 0]
elif (key_left not in conn_lists[i] and key_right in conn_lists[i]):
st_1to2[i] = [key, 1]
for group_id_temp in groups.keys():
if groups[group_id_temp][1] < 0:
if group_id_temp not in st_gton1:
st_gton1.append(group_id_temp)
while len(st_1to2.keys()) != 0:
joiner = st_1to2.keys()[0]
key = st_1to2[joiner][0]
side = st_1to2[joiner][1]
side_other = 1 - side
st_1to2.pop(joiner)
if robot_key_neighbors[key][side] == -1:
key_rest = st_1to2.keys()[:]
for joiner_temp in key_rest:
if (st_1to2[joiner_temp][0] == key and st_1to2[joiner_temp][1] == side):
st_1to2.pop(joiner_temp)
if dist_table[key,joiner] > dist_table[key,joiner_temp]:
joiner = joiner_temp
robot_states[joiner] = 2
if side == 0: robot_key_neighbors[joiner] = [-1,key]
else: robot_key_neighbors[joiner] = [key,-1]
robot_key_neighbors[key][side] = joiner
else:
key_other = robot_key_neighbors[key][side]
side_other = 1 - side
des_pos = (robot_poses[key] + robot_poses[key_other]) / 2.0
key_rest = st_1to2.keys()[:]
for joiner_temp in key_rest:
if ((st_1to2[joiner_temp][0] == key and st_1to2[joiner_temp][1] == side) or
(st_1to2[joiner_temp][0] == key_next and st_1to2[joiner_temp][1] == side_other)):
st_1to2.pop(joiner_temp)
if dist_table[key,joiner] > dist_table[key,joiner_temp]:
joiner = joiner_temp
robot_states[joiner] = 2
if side == 0:
robot_key_neighbors[joiner] = [key_other,key]
else:
robot_key_neighbors[joiner] = [key,key_other]
robot_key_neighbors[key][side] = joiner
robot_key_neighbors[key_other][side_other] = joiner
for joiner in st_0to1.keys():
group_id_temp = st_0to1[joiner]
robot_states[joiner] = 1
robot_group_ids[joiner] = group_id_temp
groups[group_id_temp][0].append(joiner)
groups[group_id_temp][1] = groups[group_id_temp][1] + life_incre
while len(st_0to2.keys()) != 0:
pair0 = st_0to2.keys()[0]
pair1 = st_0to2[pair0]
st_0to2.pop(pair0)
if (pair1 in st_0to2.keys()) and (st_0to2[pair1] == pair0):
st_0to2.pop(pair1)
if robot_seeds[pair0] or robot_seeds[pair1]:
group_id_temp = np.random.randint(0, group_id_upper)
while group_id_temp in groups.keys():
group_id_temp = np.random.randint(0, group_id_upper)
robot_states[pair0] = 2
robot_states[pair1] = 2
robot_group_ids[pair0] = group_id_temp
robot_group_ids[pair1] = group_id_temp
robot_key_neighbors[pair0] = [-1,pair1]
robot_key_neighbors[pair1] = [pair0,-1]
groups[group_id_temp] = [[pair0, pair1], life_incre*2, False]
for group_id_temp in st_gton1:
for robot_temp in groups[group_id_temp][0]:
robot_states[robot_temp] = -1
robot_n1_lives[robot_temp] = np.random.uniform(n1_life_lower, n1_life_upper)
robot_group_ids[robot_temp] = -1
robot_oris[robot_temp] = np.random.rand() * 2 * math.pi - math.pi
robot_key_neighbors[robot_temp] = []
groups.pop(group_id_temp)
for robot_temp in st_n1to0:
robot_states[robot_temp] = 0
for group_id_temp in groups.keys():
if len(groups[group_id_temp][0]) > swarm_size/2.0:
groups[group_id_temp][2] = True
else:
groups[group_id_temp][2] = False
robot_poses_t = np.copy(robot_poses)
no_state1_robot = True
line_space_good = np.array([-1 for i in range(swarm_size)])
for i in range(swarm_size):
if robot_states[i] == 2:
if robot_key_neighbors[i][0] == -1:
key_next = robot_key_neighbors[i][1]
if (dist_table[i,key_next] > space_good_thres):
line_space_good[i] = 1
else:
line_space_good[i] = 0
elif robot_key_neighbors[i][1] == -1:
key_next = robot_key_neighbors[i][0]
if (dist_table[i,key_next] > space_good_thres):
line_space_good[i] = 1
else:
line_space_good[i] = 0
else:
key_left = robot_key_neighbors[i][0]
key_right = robot_key_neighbors[i][1]
if (dist_table[i,key_left] > space_good_thres and
dist_table[i,key_right] > space_good_thres):
line_space_good[i] = 1
else:
line_space_good[i] = 0
for i in range(swarm_size):
if robot_states[i] == 1:
no_state1_robot = False
center = robot_key_neighbors[i][0]
if dist_table[i,center] > (desired_space + step_moving_dist):
vect_temp = robot_poses_t[center] - robot_poses_t[i]
robot_oris[i] = math.atan2(vect_temp[1], vect_temp[0])
elif (dist_table[i,center] + step_moving_dist) < desired_space:
vect_temp = robot_poses_t[i] - robot_poses_t[center]
robot_oris[i] = math.atan2(vect_temp[1], vect_temp[0])
else:
rotate_dir = 0
if (robot_key_neighbors[center][0] == -1 or
robot_key_neighbors[center][1] == -1):
key_next = -1
if (robot_key_neighbors[center][0] == -1 and
robot_key_neighbors[center][1] != -1):
key_next = robot_key_neighbors[center][1]
elif (robot_key_neighbors[center][0] != -1 and
robot_key_neighbors[center][1] == -1):
key_next = robot_key_neighbors[center][0]
else:
print("key neighbor error(physics update1)")
sys.exit()
vect_next = robot_poses[key_next] - robot_poses[center]
vect_i = robot_poses[i] - robot_poses[center]
if np.dot(vect_next, vect_i) > 0:
if np.cross(vect_i, vect_next) > 0: rotate_dir = 1
else: rotate_dir = -1
else: continue
else:
key_left = robot_key_neighbors[center][0]
key_right = robot_key_neighbors[center][1]
key_next = -1
if dist_table[i,key_left] < dist_table[i,key_right]: key_next = key_left
else: key_next = key_right
vect_next = robot_poses[key_next] - robot_poses[center]
vect_i = robot_poses[i] - robot_poses[center]
if np.cross(vect_i, vect_next) > 0: rotate_dir = 1
else: rotate_dir = -1
vect_i = robot_poses[i] - robot_poses[center]
robot_oris[i] = math.atan2(vect_i[1], vect_i[0])
int_angle_temp = math.acos((math.pow(dist_table[i,center],2) +
math.pow(step_moving_dist,2) - math.pow(desired_space,2)) /
(2.0*dist_table[i,center]*step_moving_dist))
robot_oris[i] = reset_radian(robot_oris[i] +
rotate_dir*(math.pi - int_angle_temp))
elif robot_states[i] == 2:
if (robot_key_neighbors[i][0] == -1 or robot_key_neighbors[i][1] == -1):
key = -1
vect_line = np.zeros(2)
if (robot_key_neighbors[i][0] == -1 and robot_key_neighbors[i][1] != -1):
key = robot_key_neighbors[i][1]
if robot_key_neighbors[key][1] == -1:
vect_line = robot_poses[i] - robot_poses[key]
vect_line = vect_line / np.linalg.norm(vect_line)
else:
key_other = robot_key_neighbors[key][1]
vect_line = robot_poses[key] - robot_poses[key_other]
vect_line = vect_line / np.linalg.norm(vect_line)
elif (robot_key_neighbors[i][0] != -1 and robot_key_neighbors[i][1] == -1):
key = robot_key_neighbors[i][0]
if robot_key_neighbors[key][0] == -1:
vect_line = robot_poses[i] - robot_poses[key]
vect_line = vect_line / np.linalg.norm(vect_line)
else:
key_other = robot_key_neighbors[key][0]
vect_line = robot_poses[key] - robot_poses[key_other]
vect_line = vect_line / np.linalg.norm(vect_line)
else:
print("key neighbor error(physics update2)")
sys.exit()
des_pos = robot_poses[key] + vect_line*desired_space
vect_des = des_pos - robot_poses[i]
if np.linalg.norm(vect_des) < destination_error:
continue
else:
robot_oris[i] = math.atan2(vect_des[1], vect_des[0])
else:
key_left = robot_key_neighbors[i][0]
key_right = robot_key_neighbors[i][1]
if (line_space_good[i] == 0 and
line_space_good[key_left] != line_space_good[key_right]):
if line_space_good[key_left] == 1:
vect_left = robot_poses[key_left] - robot_poses[i]
robot_oris[i] = math.atan2(vect_left[1], vect_left[0])
else:
vect_right = robot_poses[key_right] - robot_poses[i]
robot_oris[i] = math.atan2(vect_right[1], vect_right[0])
else:
des_pos = (robot_poses[key_left] + robot_poses[key_right])/2.0
des_vect = des_pos - robot_poses[i]
if np.linalg.norm(des_vect) < destination_error:
continue
else:
robot_oris[i] = math.atan2(des_vect[1], des_vect[0])
if (robot_states[i] == -1) or (robot_states[i] == 0):
robot_oris[i] = robot_boundary_check(robot_poses_t[i], robot_oris[i])
robot_poses[i] = robot_poses_t[i] + (step_moving_dist *
np.array([math.cos(robot_oris[i]), math.sin(robot_oris[i])]))
disp_poses_update()
screen.fill(color_white)
for i in range(swarm_size):
if robot_seeds[i]:
color_temp = color_red
else:
color_temp = color_grey
if robot_states[i] == -1:
pygame.draw.circle(screen, color_temp, disp_poses[i],
robot_size, robot_empty_width)
elif robot_states[i] == 0:
pygame.draw.circle(screen, color_temp, disp_poses[i],
robot_size, 0)
for group_id_temp in groups.keys():
if groups[group_id_temp][2]:
color_group = color_black
else:
color_group = color_grey
conn_draw_sets = []
for i in groups[group_id_temp][0]:
for j in robot_key_neighbors[i]:
if j == -1: continue
if set([i,j]) not in conn_draw_sets:
pygame.draw.line(screen, color_group, disp_poses[i],
disp_poses[j], conn_width)
conn_draw_sets.append(set([i,j]))
if robot_seeds[i]:
pygame.draw.circle(screen, color_red, disp_poses[i],
robot_size, 0)
else:
pygame.draw.circle(screen, color_group, disp_poses[i],
robot_size, 0)
pygame.display.update()
for i in range(swarm_size):
if robot_states[i] == -1:
robot_n1_lives[i] = robot_n1_lives[i] - frame_period/1000.0
for group_id_temp in groups.keys():
if not groups[group_id_temp][2]:
groups[group_id_temp][1] = groups[group_id_temp][1] - frame_period/1000.0
if not line_formed:
if ((len(groups.keys()) == 1) and (len(groups.values()[0][0]) == swarm_size)
and no_state1_robot):
line_formed = True
if line_formed:
if ending_period <= 0:
print("simulation 1 is finished")
if manual_mode: raw_input("<Press Enter to continue>")
print("")
break
else:
ending_period = ending_period - frame_period/1000.0
robot_starter = -1
for i in range(swarm_size):
if robot_key_neighbors[i][0] == -1:
robot_starter = i
break
line_robots = [robot_starter]
robot_curr = robot_starter
while (robot_key_neighbors[robot_curr][1] != -1):
robot_next = robot_key_neighbors[robot_curr][1]
line_robots.append(robot_next)
robot_curr = robot_next
if (len(set(line_robots)) != swarm_size):
print("line is incomplete after line formation")
sys.exit()
while True:
print("##### simulation 2: consensus decision making #####")
x_max, y_max = np.amax(robot_poses, axis=0)
x_min, y_min = np.amin(robot_poses, axis=0)
robot_middle = np.array([(x_max+x_min)/2.0, (y_max+y_min)/2.0])
world_middle = np.array([world_side_length/2.0, world_side_length/2.0])
for i in range(swarm_size):
robot_poses[i] = robot_poses[i] - robot_middle + world_middle
disp_poses_update()
screen.fill(color_white)
for i in range(swarm_size):
pygame.draw.circle(screen, color_black, disp_poses[i], robot_size, 0)
if robot_key_neighbors[i][1] == -1: continue
pygame.draw.line(screen, color_black, disp_poses[i],
disp_poses[robot_key_neighbors[i][1]], conn_width)
pygame.display.update()
shape_decision = -1
deci_dist = np.random.rand(swarm_size, shape_quantity)
sum_temp = np.sum(deci_dist, axis=1)
for i in range(swarm_size):
deci_dist[i] = deci_dist[i] / sum_temp[i]
deci_domi = np.argmax(deci_dist, axis=1)
groups = []
robot_group_sizes = [0 for i in range(swarm_size)]
color_initialized = False
deci_colors = [-1 for i in range(shape_quantity)]
color_assigns = [0 for i in range(color_quantity)]
group_colors = []
robot_colors = [0 for i in range(swarm_size)]
dist_diff_thres = 0.3
dist_diff_ratio = [0.0 for i in range(swarm_size)]
dist_diff_power = 0.3
sim_haulted = False
time_last = pygame.time.get_ticks()
time_now = time_last
frame_period = 500
sim_freq_control = True
iter_count = 0
sys.stdout.write("iteration {}".format(iter_count))
sys.stdout.flush()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("program exit in simulation 2")
sys.exit()
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
sim_haulted = not sim_haulted
if sim_haulted: continue
if sim_freq_control:
time_now = pygame.time.get_ticks()
if (time_now - time_last) > frame_period:
time_last = time_now
else:
continue
iter_count = iter_count + 1
sys.stdout.write("\riteration {}".format(iter_count))
sys.stdout.flush()
deci_domi = np.argmax(deci_dist, axis=1)
robot_curr = line_robots[0]
groups = [[robot_curr]]
while (robot_key_neighbors[robot_curr][1] != -1):
robot_next = robot_key_neighbors[robot_curr][1]
if (deci_domi[robot_curr] == deci_domi[robot_next]):
groups[-1].append(robot_next)
else:
groups.append([robot_next])
robot_curr = robot_next
group_deci = [deci_domi[groups[i][0]] for i in range(len(groups))]
for group_temp in groups:
group_temp_size = len(group_temp)
for i in group_temp:
robot_group_sizes[i] = group_temp_size
if not color_initialized:
color_initialized = True
color_set = range(color_quantity)
deci_set = set(group_deci)
for deci in deci_set:
if len(color_set) == 0:
color_set = range(color_quantity)
chosen_color = np.random.choice(color_set)
color_set.remove(chosen_color)
deci_colors[deci] = chosen_color
color_assigns[chosen_color] = color_assigns[chosen_color] + 1
else:
deci_set = set(group_deci)
for deci_temp in range(shape_quantity):
color_temp = deci_colors[deci_temp]
if (color_temp != -1 and deci_temp not in deci_set):
color_assigns[color_temp] = color_assigns[color_temp] - 1
deci_colors[deci_temp] = -1
color_set = []
for i in range(len(groups)):
if deci_colors[group_deci[i]] == -1:
if len(color_set) == 0:
color_assigns_min = min(color_assigns)
for color_temp in range(color_quantity):
if color_assigns[color_temp] == color_assigns_min:
color_set.append(color_temp)
chosen_color = np.random.choice(color_set)
color_set.remove(chosen_color)
deci_colors[group_deci[i]] = chosen_color
color_assigns[chosen_color] = color_assigns[chosen_color] + 1
group_colors = []
for i in range(len(groups)):
color_temp = deci_colors[group_deci[i]]
group_colors.append(color_temp)
for j in groups[i]:
robot_colors[j] = color_temp
converged_all = True
deci_dist_t = np.copy(deci_dist)
for i in range(swarm_size):
if robot_key_neighbors[i][0] == -1 or robot_key_neighbors[i][1] == -1:
i_next = -1
if robot_key_neighbors[i][0] == -1:
i_next = robot_key_neighbors[i][1]
elif robot_key_neighbors[i][1] == -1:
i_next = robot_key_neighbors[i][0]
if deci_domi[i] == deci_domi[i_next]:
deci_dist[i] = deci_dist_t[i] + deci_dist_t[i_next]
dist_sum = np.sum(deci_dist[i])
deci_dist[i] = deci_dist[i] / dist_sum
dist_diff = np.linalg.norm(deci_dist_t[i]-deci_dist_t[i_next], 1)
if dist_diff < dist_diff_thres:
dist_diff_ratio[i] = dist_diff/dist_diff_thres
small_end = 1.0/shape_quantity * np.power(dist_diff/dist_diff_thres,
dist_diff_power)
large_end = 2.0/shape_quantity - small_end
dist_t = np.copy(deci_dist[i])
sort_index = range(shape_quantity)
for j in range(shape_quantity-1):
for k in range(shape_quantity-1-j):
if dist_t[k] > dist_t[k+1]:
temp = dist_t[k]
dist_t[k] = dist_t[k+1]
dist_t[k+1] = temp
temp = sort_index[k]
sort_index[k] = sort_index[k+1]
sort_index[k+1] = temp
dist_sum = 0
for j in range(shape_quantity):
multiplier = (small_end +
float(j)/(shape_quantity-1) * (large_end-small_end))
deci_dist[i,sort_index[j]] = deci_dist[i,sort_index[j]] * multiplier
dist_sum = np.sum(deci_dist[i])
deci_dist[i] = deci_dist[i] / dist_sum
else:
dist_diff_ratio[i] = 1.0
else:
if converged_all: converged_all = False
dist_diff_ratio[i] = -1.0
deci_dist[i] = (deci_dist_t[i] +
robot_group_sizes[i_next] * deci_dist_t[i_next])
dist_sum = np.sum(deci_dist[i])
deci_dist[i] = deci_dist[i] / dist_sum
else:
i_l = robot_key_neighbors[i][0]
i_r = robot_key_neighbors[i][1]
converged_l = False
if (deci_domi[i_l] == deci_domi[i]): converged_l = True
converged_r = False
if (deci_domi[i_r] == deci_domi[i]): converged_r = True
if converged_l and converged_r:
deci_dist[i] = deci_dist_t[i_l] + deci_dist_t[i] + deci_dist_t[i_r]
dist_sum = np.sum(deci_dist[i])
deci_dist[i] = deci_dist[i] / dist_sum
dist_diff = [np.linalg.norm(deci_dist_t[i_l]-deci_dist_t[i], 1),
np.linalg.norm(deci_dist_t[i_r]-deci_dist_t[i], 1),
np.linalg.norm(deci_dist_t[i_l]-deci_dist_t[i_r], 1)]
dist_diff_max = max(dist_diff)
if dist_diff_max < dist_diff_thres:
dist_diff_ratio[i] = dist_diff_max/dist_diff_thres
small_end = 1.0/shape_quantity * np.power(dist_diff_max/dist_diff_thres,
dist_diff_power)
large_end = 2.0/shape_quantity - small_end
dist_t = np.copy(deci_dist[i])
sort_index = range(shape_quantity)
for j in range(shape_quantity-1):
for k in range(shape_quantity-1-j):
if dist_t[k] > dist_t[k+1]:
temp = dist_t[k]
dist_t[k] = dist_t[k+1]
dist_t[k+1] = temp
temp = sort_index[k]
sort_index[k] = sort_index[k+1]
sort_index[k+1] = temp
dist_sum = 0
for j in range(shape_quantity):
multiplier = (small_end +
float(j)/(shape_quantity-1) * (large_end-small_end))
deci_dist[i,sort_index[j]] = deci_dist[i,sort_index[j]] * multiplier
dist_sum = np.sum(deci_dist[i])
deci_dist[i] = deci_dist[i] / dist_sum
else:
dist_diff_ratio[i] = 1.0
else:
if converged_all: converged_all = False
dist_diff_ratio[i] = -1.0
deci_dist[i] = (robot_group_sizes[i_l] * deci_dist_t[i_l] +
deci_dist_t[i] +
robot_group_sizes[i_r] * deci_dist_t[i_r])
dist_sum = np.sum(deci_dist[i])
deci_dist[i] = deci_dist[i] / dist_sum
screen.fill(color_white)
for i in range(swarm_size):
i_next = robot_key_neighbors[i][1]
if i_next == -1: continue
if (deci_domi[i] == deci_domi[i_next]):
pygame.draw.line(screen, distinct_color_set[robot_colors[i]],
disp_poses[i], disp_poses[i_next], conn_width_thick_consensus)
else:
pygame.draw.line(screen, color_black, disp_poses[i], disp_poses[i_next],
conn_width_thin_consensus)
for i in range(swarm_size):
pygame.draw.circle(screen, distinct_color_set[robot_colors[i]], disp_poses[i],
robot_size_consensus, 0)
pygame.display.update()
if converged_all:
shape_decision = deci_domi[0]
print("")
print("converged to decision {}".format(shape_decision))
print("simulation 2 is finished")
if manual_mode: raw_input("<Press Enter to continue>")
print("")
break
print("##### simulation 3: curve reshape #####")
print("chosen shape {}: {}".format(shape_decision, shape_catalog[shape_decision]))
filename = str(swarm_size) + "-" + shape_catalog[shape_decision]
filepath = os.path.join(os.getcwd(), curve_folder, filename)
if os.path.isfile(filepath):
with open(filepath, 'r') as f:
target_poses = pickle.load(f)
else:
print("fail to locate shape file: {}".format(filepath))
sys.exit()
inter_target = np.zeros(swarm_size)
for i in range(swarm_size):
if i == 0 or i == (swarm_size-1):
inter_target[i] = 0
continue
vect_l = target_poses[i-1] - target_poses[i]
vect_r = target_poses[i+1] - target_poses[i]
dist_l = np.linalg.norm(vect_l)
dist_r = np.linalg.norm(vect_r)
inter_target[i] = math.acos(np.around(
np.dot(vect_l, vect_r) / (dist_l * dist_r) ,6))
if np.cross(vect_r, vect_l) < 0:
inter_target[i] = 2*math.pi - inter_target[i]
screen.fill(color_white)
for i in range(swarm_size):
pygame.draw.circle(screen, color_black, disp_poses[i], robot_size, 0)
if robot_key_neighbors[i][1] != -1:
pygame.draw.line(screen, color_black, disp_poses[i],
disp_poses[robot_key_neighbors[i][1]], conn_width)
pygame.display.update()
inter_err_thres = 0.1
inter_target_line = math.pi
formation_stretched = False
formation_stretched_err = inter_target_line*0.1
linear_const = 1.0
bend_const = 0.8
disp_coef = 0.05
sim_haulted = False
time_last = pygame.time.get_ticks()
time_now = time_last
frame_period = 200
sim_freq_control = True
print("line is stretching ...")
iter_count = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("program exit in simulation 3")
sys.exit()
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
sim_haulted = not sim_haulted
if sim_haulted: continue
if sim_freq_control:
time_now = pygame.time.get_ticks()
if (time_now - time_last) > frame_period:
time_last = time_now
else:
continue
iter_count = iter_count + 1
robot_poses_t = np.copy(robot_poses)
inter_curr = np.zeros(swarm_size)
for i in range(swarm_size):
if robot_key_neighbors[i][0] == -1 or robot_key_neighbors[i][1] == -1:
i_next = -1
if robot_key_neighbors[i][0] == -1:
i_next = robot_key_neighbors[i][1]
elif robot_key_neighbors[i][1] == -1:
i_next = robot_key_neighbors[i][0]
vect_next = robot_poses_t[i_next]-robot_poses_t[i]
dist_next = np.linalg.norm(vect_next)
u_vect_next = vect_next / dist_next
fb_vect = (dist_next - desired_space) * linear_const * u_vect_next
robot_poses[i] = robot_poses_t[i] + disp_coef * fb_vect
else:
i_l = robot_key_neighbors[i][0]
i_r = robot_key_neighbors[i][1]
vect_l = robot_poses_t[i_l] - robot_poses_t[i]
vect_r = robot_poses_t[i_r] - robot_poses_t[i]
vect_lr = robot_poses_t[i_r] - robot_poses_t[i_l]
dist_l = np.linalg.norm(vect_l)
dist_r = np.linalg.norm(vect_r)
dist_lr = np.linalg.norm(vect_lr)
u_vect_l = vect_l / dist_l
u_vect_r = vect_r / dist_r
u_vect_in = np.array([-vect_lr[1], vect_lr[0]]) / dist_lr
inter_curr[i] = math.acos(np.around(
np.dot(vect_l, vect_r) / (dist_l * dist_r), 6))
if np.cross(vect_r, vect_l) < 0:
inter_curr[i] = 2*math.pi - inter_curr[i]
fb_vect = np.zeros(2)
fb_vect = fb_vect + (dist_l - desired_space) * linear_const * u_vect_l
fb_vect = fb_vect + (dist_r - desired_space) * linear_const * u_vect_r
if formation_stretched:
fb_vect = (fb_vect +
(inter_target[i] - inter_curr[i]) * bend_const * u_vect_in)
else:
fb_vect = (fb_vect +
(inter_target_line - inter_curr[i]) * bend_const * u_vect_in)
robot_poses[i] = robot_poses_t[i] + disp_coef * fb_vect
if not formation_stretched:
formation_stretched = True
for i in range(swarm_size):
if robot_key_neighbors[i][0] != -1 and robot_key_neighbors[i][1] != -1:
if abs(inter_curr[i] - inter_target_line) > formation_stretched_err:
formation_stretched = False
break
if formation_stretched:
print("line is reshaping to " + shape_catalog[shape_decision] + " ...")
disp_poses_update()
screen.fill(color_white)
for i in range(swarm_size):
i_next = robot_key_neighbors[i][1]
if i_next != -1:
pygame.draw.line(screen, color_black, disp_poses[i], disp_poses[i_next],
conn_width)
for i in range(swarm_size):
pygame.draw.circle(screen, color_black, disp_poses[i], robot_size, 0)
pygame.display.update()
inter_err_max = 0
for i in range(swarm_size):
err_curr = abs(inter_curr[i] - inter_target[i])
if err_curr > inter_err_max: inter_err_max = err_curr
if converged_all and inter_err_max < inter_err_thres:
print("simulation 3 is finished")
if manual_mode: raw_input("<Press Enter to continue>")
print("")
break