def __init__(self):
     self.sock_sender = SocketNumpyArray()
     self.sock_sender.initialize_sender('localhost', 9999)
     self.n = None
     self.x = None
     self.y = None
     self.theta = None
     self.phero = None
    def __init__(self):

        # Receiving 
        self.num_robots = 0
        self.num_robots = self.sock_receiver.receive_number()
        print("num_robots: {}".format(self.num_robots))

        # Pheromone initialization
        self.pheromone = [None]*self.num_robots
        for i in range(self.num_robots):
            self.pheromone[i] = Pheromone('dynamic {}'.format(i), 0.5, 0)
        self.pheromone.append(Pheromone('static', 180, 0))

        self.phero_max = 1.0
        self.phero_min = 0.0
        self.is_phero_inj = True

        # Socket Communication
        self.sock_receiver = SocketNumpyArray()
        self.sock_receiver.initalize_receiver(9999) # the 9999 is the port you can change it with your own.
        
        self.theta = 0 
        
        self.log_timer = time.clock()
        #self.log_file = open("phero_value.txt", "a+")
        self.is_saved = False
        self.is_loaded = False
        self.is_reset = True # False for reset

        for i in range(len(phero)):
            self.pheromone[i].isDiffusion = False
            self.pheromone[i].isEvaporation = True
        self.startTime = time.time()

        # Robot positions
        self.positions = [0,0]*self.num_robots
        self.x_idx = [0, 0]
        self.y_idx = [0, 0]

        # PosToIndex for pheromone circle
        # x_2, y_0 = self.posToIndex(2,0)
        # x_n3, y_n3 = self.posToIndex(-3,-3)
        # x_0, y_0 = self.posToIndex(0,0)
        # Pheromone Initilaisation
        # self.pheromone.circle(x_2, y_0, 1, 1)
        # self.pheromone.circle(x_3, y_0, 1, 1)
        # self.pheromone.circle(x_n3, y_0, 1, 1)
        # self.pheromone.circle(x_0, y_3, 1, 1)
        # self.pheromone.circle(x_0,y_n3, 1, 1)

        print("Initialisation completed")
Example #3
0
    def __init__(self):
        self.sock_sender = SocketNumpyArray()
        self.sock_sender.initialize_sender('localhost', 9998)
        self.n = None
        self.x = None
        self.y = None
        self.theta = None 
        self.phero = None

        # Object initialisation
        # Robot initial positions
        self.robot_positions = [[-2.5,0],[2.5,0],[0,-2.5],[0,2.5]]
        self.robot_angles = [0, pi, pi/2, -pi/2]
        self.target_positions = [[2.5,0],[-2.5,0],[0,2.5],[0,-2.5]]
Example #4
0
    def __init__(self):
        self.sock_sender = SocketNumpyArray()
        self.sock_sender.initialize_sender('localhost', 9998)
        self.n = None
        self.x = None
        self.y = None
        self.theta = None
        self.phero = None

        # Target
        self.target_x = 4.0
        self.target_y = 0.0
        self.target_index = 0
        self.radius = 4
        self.num_experiments = 20
    def __init__(self, phero):
        self.pheromone = phero
        self.phero_max = 1.0
        self.phero_min = 0.0
        self.is_phero_inj = True

        # Socket Communication
        self.sock_receiver = SocketNumpyArray()
        self.sock_receiver.initalize_receiver(
            9998)  # the 9999 is the port you can change it with your own.

        self.is_service_requested = False
        self.theta = 0

        self.log_timer = time.clock()
        self.log_file = open("phero_value.txt", "a+")
        self.is_saved = False
        self.is_loaded = False
        self.is_reset = True  # False for reset

        self.pheromone.isDiffusion = True
        self.pheromone.isEvaporation = False
        self.startTime = time.time()

        # PosToIndex for pheromone circle
        # x_2, y_2 = self.posToIndex(2,2)
        # x_n2, y_n2 = self.posToIndex(-2,-2)
        # x_1p4, y_1p4 = self.posToIndex(1.4, 1.4)
        # x_n1p4, y_n1p4 = self.posToIndex(-1.4, -1.4)
        # x_0, y_0 = self.posToIndex(0,0)

        # Pheromone Initilaisation
        # self.pheromone.circle(x_2, y_0, 1, 0.7)
        # self.pheromone.circle(x_n2, y_0, 1, 0.7)
        # self.pheromone.circle(x_0, y_2, 1, 0.7)
        # self.pheromone.circle(x_0, y_n2, 1, 0.7)
        # self.pheromone.circle(x_1p4, y_1p4, 1, 0.5)
        # self.pheromone.circle(x_1p4, y_n1p4, 1, 0.5)
        # self.pheromone.circle(x_n1p4, y_n1p4, 1, 0.5)
        # self.pheromone.circle(x_n1p4, y_1p4, 1, 0.5)
        self.num_robots = self.sock_receiver.receive_number()
        print("num_robots: {}".format(self.num_robots))
        print("Initialisation completed")
Example #6
0
class Scenario(BaseScenario):
    def __init__(self):
        self.sock_sender = SocketNumpyArray()
        self.sock_sender.initialize_sender('localhost', 9998)
        self.n = None
        self.x = None
        self.y = None
        self.theta = None
        self.phero = None

        # Target
        self.target_x = 4.0
        self.target_y = 0.0
        self.target_index = 0
        self.radius = 4
        self.num_experiments = 20

    def make_world(self):
        world = World()
        # set any world properties first
        world.dim_c = 2
        num_agents = 1
        num_obstacle = 4
        num_target = 1
        world.collaborative = True
        # add agents
        world.agents = [Agent() for i in range(num_agents)]
        for i, agent in enumerate(world.agents):
            agent.name = 'agent %d' % i
            agent.collide = True
            agent.silent = True
            agent.size = 0.1
        # add obstacles
        world.landmarks = [Landmark() for i in range(num_obstacle)]
        for i, landmark in enumerate(world.landmarks):
            landmark.name = 'obstacle %d' % i
            landmark.collide = True
            landmark.movable = False
            landmark.size = 0.1

        # add target
        target = Landmark()
        target.name = 'target'
        target.collide = False
        target.movable = False
        target.size = 0.1

        # Merge the landmarks (obstacles + target)
        world.landmarks.append(target)

        # make initial conditions
        self.n = num_agents
        self.x = [0.0, 0.0] * num_agents
        self.y = [0.0, 0.0] * num_agents
        self.theta = [0.0, 0.0] * num_agents
        self.reset_world(world)

        # Send initial information to pheromone system
        self.sock_sender.send_number(self.n)

        return world

    def reset_world(self, world):
        # random properties for agents
        for i, agent in enumerate(world.agents):
            agent.color = np.array([0.35, 0.35, 0.85])
        # random properties for landmarks
        for i, landmark in enumerate(world.landmarks):
            landmark.color = np.array([0.25, 0.25, 0.25])
            if i == len(world.landmarks) - 1:
                landmark.color = np.array([0.9, 0.1, 0.1])

        # ========================================================================= #
#                            TARGET UPDATE                                  #
# ========================================================================= #
# set random initial states
# robot position (0, 0), distance between robots and target (4 m)
        angle_target = self.target_index * 2 * pi / self.num_experiments

        self.target_x = self.radius * cos(angle_target)
        self.target_y = self.radius * sin(angle_target)

        if self.target_index < self.num_experiments - 1:
            self.target_index += 1
        else:
            self.target_index = 0

        # ========================================================================= #
#                             OBJECT RESET                                  #
# ========================================================================= #

# Agent update
        world.agents[0].state.p_pose = np.asarray([0.0, 0.0, 0.0])
        world.agents[0].state.p_pos = world.agents[0].state.p_pose[:2]
        self.target = [[self.x[1], self.y[1]], [self.x[0],
                                                self.y[0]]]  #20201130 Target
        for i, agent in enumerate(world.agents):
            #agent.state.p_pos = np.random.uniform(-1, +1, world.dim_p)
            agent.state.p_vel = np.zeros(world.dim_p)
            agent.state.c = np.zeros(world.dim_c)
            agent.state.target = [self.target_x,
                                  self.target_y]  # 20201201 target

        # for i, landmark in enumerate(world.landmarks):
        #     if landmark.name[0] == 'o':
        #         landmark.state.p_pos = [0, 0] #np.random.uniform(-1, +1, world.dim_p)
        #         landmark.state.p_vel = np.zeros(world.dim_p)

        # Obstacle update
        world.landmarks[0].state.p_pos = np.asarray([2, 0])
        world.landmarks[0].state.p_vel = np.zeros(world.dim_p)
        world.landmarks[1].state.p_pos = np.asarray([0, 2])
        world.landmarks[1].state.p_vel = np.zeros(world.dim_p)
        world.landmarks[2].state.p_pos = np.asarray([-2, 0])
        world.landmarks[2].state.p_vel = np.zeros(world.dim_p)
        world.landmarks[3].state.p_pos = np.asarray([0, -2])
        world.landmarks[3].state.p_vel = np.zeros(world.dim_p)

        # Target update
        world.landmarks[4].state.p_pos = np.asarray(
            [self.target_x, self.target_y])
        world.landmarks[4].state.p_vel = np.zeros(world.dim_p)

    def benchmark_data(self, agent, world):
        rew = 0
        collisions = 0
        occupied_landmarks = 0
        min_dists = 0
        for l in world.landmarks:
            dists = [
                np.sqrt(np.sum(np.square(a.state.p_pos - l.state.p_pos)))
                for a in world.agents
            ]
            min_dists += min(dists)
            rew -= min(dists)
            if min(dists) < 0.1:
                occupied_landmarks += 1
        if agent.collide:
            for a in world.agents:
                if self.is_collision(a, agent):
                    rew -= 1
                    collisions += 1
        return (rew, collisions, min_dists, occupied_landmarks)

    def is_collision(self, agent1, agent2):
        delta_pos = agent1.state.p_pos - agent2.state.p_pos
        dist = np.sqrt(np.sum(np.square(delta_pos)))
        dist_min = agent1.size + agent2.size
        return True if dist < dist_min else False

    def reward(self, agent, world):
        '''
        Compute rewards
        '''
        distance_reward = 0.0
        phero_reward = 0.0
        goal_reward = 0.0
        collision_reward = 0.0
        angular_reward = 0.0
        #angular_punish_rewards = [0.0]*self.num_robots
        #linear_punish_rewards = [0.0]*self.num_robots

        # 1. Distance Reward
        goal_progress = agent.state.distance_to_goal_prev - agent.state.distance_to_goal
        if abs(goal_progress) < 0.1:
            #print("Goal Progress: {}".format(goal_progress))
            #print("Angle: {}".format(agent.state.angle_diff))
            if goal_progress >= 0:
                distance_reward = goal_progress * 1.2
            else:
                distance_reward = goal_progress
        else:
            distance_reward = 0.0

        # Scaling distance_reward
        distance_reward = distance_reward * (5 / world.dt)

        # 2. Phero Reward
        #phero_sum = np.sum(self.phero)
        #phero_reward = -phero_sum*2

        # 3. Goal Reward
        if agent.state.distance_to_goal <= 0.3:
            goal_reward = 100.0
            #done = True
            #self.reset(model_state, id_bots=idx[i])

        # 4. Collision Penalty
        for i, obstacle in enumerate(
            [ob for ob in world.landmarks if 'obstacle' in ob.name]):
            is_collision = self.is_collision(agent, obstacle)
            if is_collision == True:
                collision_reward = -50.0

        # 5. Angular velocity penalty
        if abs(agent.action.twist[1]) > 0.8:
            angular_reward = -1

        reward = distance_reward + phero_reward + goal_reward + collision_reward
        print("----------------")
        print("GP: {}".format(goal_progress))
        print("Distance R: {}".format(distance_reward))
        print("Collision R: {}".format(collision_reward))
        print("Goal R: {}".format(goal_reward))
        print("Angular R: {}".format(angular_reward))
        print("Reward: {}".format(reward))

        return reward

    def observation(self, agent, world):

        id = int(agent.name[-1])
        # get positions of all entities in this agent's reference frame
        entity_pos = []
        for entity in world.landmarks:  # world.entities:
            entity_pos.append(entity.state.p_pos - agent.state.p_pos)
        # entity colors
        entity_color = []
        for entity in world.landmarks:  # world.entities:
            entity_color.append(entity.color)

        positions = np.asarray(agent.state.p_pos)
        self.sock_sender.send_numpy_array(positions)
        data = self.sock_sender.receive_from_server()
        self.phero = phero = np.asarray(data).reshape(1, 9)

        obs = np.hstack(
            (phero, [agent.action.twist],
             np.asarray([agent.state.distance_to_goal]).reshape(1, 1),
             np.asarray([agent.state.angle_diff]).reshape(1, 1)))
        #print("obs: {}".format(obs))
        #print("Observation: {}".format(obs))
        world.obs_n = np.shape(obs)[1]
        return obs  # 20201201 observation is changed (pheromone + velocity, distance, anglediff ) 1*13

    def done(self, agent, world):
        agent.state.done = False

        # 1. Goal arrival
        if agent.state.distance_to_goal <= 0.3:
            print("Goal Arrived!")
            agent.state.done = True

        # 2. Out of range
        if abs(agent.state.p_pos[0]) > 4.6 or abs(agent.state.p_pos[1]) > 4.6:
            agent.state.done = True
            print("out of range!!!!")

        # 3. collision
        for i, obstacle in enumerate(
            [ob for ob in world.landmarks if 'obstacle' in ob.name]):
            is_collision = self.is_collision(agent, obstacle)
            if is_collision == True:
                agent.state.done = True
                print("Collision!!")
                time.sleep(1)

        done = agent.state.done

        return done

    def info(self, agent, world):
        info = [{"targets": agent.state.target}]
        return info
class Node():

    def __init__(self, phero):
        self.num_robots = 2
        self.pheromone = [None] * self.num_robots
        for i in range(len(phero)):
            self.pheromone[i] = phero[i]
        self.phero_max = 1.0
        self.phero_min = 0.0
        self.is_phero_inj = True

        # Socket Communication
        self.sock_receiver = SocketNumpyArray()
        self.sock_receiver.initalize_receiver(9999) # the 9999 is the port you can change it with your own.
        
        self.theta = 0 
        
        self.log_timer = time.clock()
        #self.log_file = open("phero_value.txt", "a+")
        self.is_saved = False
        self.is_loaded = False
        self.is_reset = True # False for reset

        for i in range(len(phero)):
            self.pheromone[i].isDiffusion = False
            self.pheromone[i].isEvaporation = True
        self.startTime = time.time()

        # Robot positions
        self.positions = [0,0]*self.num_robots
        self.x_idx = [0, 0]
        self.y_idx = [0, 0]

        # PosToIndex for pheromone circle
        # x_2, y_0 = self.posToIndex(2,0)
        # x_n3, y_n3 = self.posToIndex(-3,-3)
        # x_0, y_0 = self.posToIndex(0,0)
        # Pheromone Initilaisation
        # self.pheromone.circle(x_2, y_0, 1, 1)
        # self.pheromone.circle(x_3, y_0, 1, 1)
        # self.pheromone.circle(x_n3, y_0, 1, 1)
        # self.pheromone.circle(x_0, y_3, 1, 1)
        # self.pheromone.circle(x_0,y_n3, 1, 1)
        print("Initialisation completed")

        

    def posToIndex(self, x, y):
        phero = self.pheromone
        x_tmp = x
        y_tmp = y
        # Read pheromone value at the robot position
        x_index = [0]*len(phero)
        y_index = [0]*len(phero)
        for i in range(len(phero)):
            res = phero[i].resolution
            round_dp = int(log10(res))
            x_tmp[i] = round(x_tmp[i], round_dp) # round the position value so that they fit into the centre of the cell.
            y_tmp[i] = round(y_tmp[i], round_dp) # e.g. 0.13 -> 0.1
            x_tmp[i] = int(x_tmp[i]*res)
            y_tmp[i] = int(y_tmp[i]*res)
        
            # Position conversion from Robot into pheromone matrix (0, 0) -> (n+1, n+1) of 2n+1 matrix
            x_index[i] = int(x_tmp[i] + (phero[i].num_cell-1)/2)
            y_index[i] = int(y_tmp[i] + (phero[i].num_cell-1)/2)
            if x_index[i] < 0 or y_index[i] < 0 or x_index[i] > phero[i].num_cell-1 or y_index[i] > phero[i].num_cell-1:
                raise Exception("The pheromone matrix index is out of range.")
        return x_index, y_index

    def indexToPos(self, x_index, y_index):
        phero = self.pheromone[0]
        x = x_index - (phero.num_cell-1)/2
        y = y_index - (phero.num_cell-1)/2

        x = float(x) / phero.resolution 
        
    def pheroCallback(self):
        # Reading from arguments
        pos = self.sock_receiver.receive_array()
        # twist = message.twist[-[]
        # ori = pose.orientation
        #print("pos0x: {}".format(pos[0].x))
        phero = self.pheromone
        x = [pos[0][0], pos[1][0]]
        y = [pos[0][1], pos[1][1]]
        print("x, y: {}, {}".format(x, y))
        x_idx, y_idx = self.posToIndex(x, y)
        
        print("x_idx, y_idx: {}, {}".format(x_idx, y_idx))
        # ========================================================================= #
	    #                           Pheromone Reading                               #
	    # ========================================================================= #

        '''
        Pheromone Value Reading
        '''

        '''2 pheromone values'''
        # Add two wheel position
        # wheel_distance = 0.2
        # pos_l = np.array([x+(cos(pi/2)*cos(self.theta)*(wheel_distance/2) - sin(pi/2)*sin(self.theta)*(wheel_distance/2)), y+(sin(pi/2)*cos(self.theta)*(wheel_distance/2) + cos(pi/2)*sin(self.theta)*(wheel_distance/2))])
        # pos_r = np.array([x+(cos(pi/2)*cos(self.theta)*(wheel_distance/2) + sin(pi/2)*sin(self.theta)*(wheel_distance/2)), y+(-sin(pi/2)*cos(self.theta)*(wheel_distance/2) + cos(pi/2)*sin(self.theta)*(wheel_distance/2))])
        
        # x_index, y_index = self.posToIndex(pos.x, pos.y)
        # x_l_index, y_l_index = self.posToIndex(pos_l[0], pos_l[1])
        # x_r_index, y_r_index = self.posToIndex(pos_r[0], pos_r[1]) 

        # # Assign pheromone values from two positions and publish it
        # phero_val = Float32MultiArray()
        # phero_val.data = [phero.getPhero(x_l_index, y_l_index), phero.getPhero(x_r_index, y_r_index)]
        # self.pub_phero.publish(phero_val)

        '''9 pheromone values'''
        # Position of 9 cells surrounding the robot
        # x_index, y_index = self.posToIndex(x, y)
        # phero_val = Float32MultiArray()
        # #phero_arr = np.array( )
        # for i in range(3):
        #     for j in range(3):
        #         phero_val.data.append(self.pheromone[0].getPhero(x_index+i-1, y_index+j-1)) # TODO: Randomly select the cell if the values are equal
        #print("phero_avg: {}".format(np.average(np.asarray(phero_val.data))))
        # self.pub_phero.publish(phero_val)
        # # Assign pheromone value and publish it
        # phero_val = phero.getPhero(x_index, y_index)
        # self.pub_phero.publish(phero_val)
        
        ''' Read Pheromone from each pheromone grid '''
        # 9 pheromone value for two robots read from the other's pheromone grid. 

        phero_val = [None] * self.num_robots
        #phero_arr = np.array( )
        for n in range(self.num_robots):
            phero_val[n] = list()     
            for i in range(3):
                for j in range(3):
                    phero_val[n].append(self.pheromone[1-n].getPhero(x_idx[n]+i-1, y_idx[n]+j-1)) # Read the other's pheromone
        self.sock_receiver.return_to_client(np.asarray(phero_val))

        # ========================================================================= #
	    #                           Pheromone Injection                             #
	    # ========================================================================= #

        # Pheromone injection (uncomment it when injection is needed)
        ## Two robots inject pheromone in different grids
        if self.is_phero_inj is True:
            for i in range(len(self.pheromone)):
                #phero[i].injection(x_idx[i], y_idx[i], 1, 25, self.phero_max)
                phero[i].gradInjection(x_idx[i], y_idx[i], 1, 0.3, 1.2, self.phero_max)

        # ========================================================================= #
	    #                           Pheromone Update                                #
	    # ========================================================================= #

        # Update pheromone matrix in every 0.1s
        time_cur = time.clock()
        if time_cur-phero[0].step_timer >= 0.1: 
            phero[0].update(self.phero_min, self.phero_max)
            phero[0].step_timer = time_cur

        #log_time_cur = time.clock()
        # Logging Pheromone grid
        # if log_time_cur - self.log_timer >= 2:
        #     self.log_file = open("phero_value.txt", "a+")
        #     np.savetxt(self.log_file, self.pheromone.grid, delimiter=',')
        #     self.log_file.close()

        # ========================================================================= #
	    #                           Save Pheromone                                  #
	    # ========================================================================= #
        
        '''Saving pheromone'''
        # # Save after 20s
        # time_check = time.time()
        # if time_check - self.startTime >= 20 and self.is_saved is False:
        #     self.pheromone.save("simple_collision_diffused")
        #     self.is_saved = True
        
        # Save the pheromone when robot return home.
        # distance_to_origin = sqrt(x**2+y**2)
        # if self.is_saved is False and distance_to_origin < 0.05:
        #     self.pheromone.save("foraging_static")
        #     self.is_saved = True
        #     self.is_phero_inj = False

        # ========================================================================= #
	    #                           Load Pheromone                                  #
	    # ========================================================================= #
        
        '''Loading Pheromone'''
        # Load the pheromone
        # 1. When use continuous contoller. (1) It hasn't previously loaded, (2) pheromone injection is disabled, 
        #    (3) service is requested by continuous controller script
        # if self.is_loaded is False and self.is_phero_inj is False and self.is_service_requested is True:
        #     try:
        #         self.pheromone.load("foraging")
        #         self.is_loaded = True
        #     except IOError as io:
        #         print("No pheromone to load: %s"%io)
        
        # 2. When reset is requested.
        if self.is_reset == True:
            try:
                for i in range(self.num_robots):  # Reset the pheromone grid
                    self.pheromone[i].reset()
                #self.pheromone.load("simple_collision_diffused") # you can load any types of pheromone grid
                print("Pheromone grid reset!")
                self.is_reset = False           # Reset the flag for next use
            except IOError as io:
                print("No pheromone to load: %s"%io)
class Node():
    def __init__(self, phero):
        self.pheromone = phero
        self.phero_max = 1.0
        self.phero_min = 0.0
        self.is_phero_inj = True

        # Socket Communication
        self.sock_receiver = SocketNumpyArray()
        self.sock_receiver.initalize_receiver(
            9998)  # the 9999 is the port you can change it with your own.

        self.is_service_requested = False
        self.theta = 0

        self.log_timer = time.clock()
        self.log_file = open("phero_value.txt", "a+")
        self.is_saved = False
        self.is_loaded = False
        self.is_reset = True  # False for reset

        self.pheromone.isDiffusion = True
        self.pheromone.isEvaporation = False
        self.startTime = time.time()

        # PosToIndex for pheromone circle
        # x_2, y_2 = self.posToIndex(2,2)
        # x_n2, y_n2 = self.posToIndex(-2,-2)
        # x_1p4, y_1p4 = self.posToIndex(1.4, 1.4)
        # x_n1p4, y_n1p4 = self.posToIndex(-1.4, -1.4)
        # x_0, y_0 = self.posToIndex(0,0)

        # Pheromone Initilaisation
        # self.pheromone.circle(x_2, y_0, 1, 0.7)
        # self.pheromone.circle(x_n2, y_0, 1, 0.7)
        # self.pheromone.circle(x_0, y_2, 1, 0.7)
        # self.pheromone.circle(x_0, y_n2, 1, 0.7)
        # self.pheromone.circle(x_1p4, y_1p4, 1, 0.5)
        # self.pheromone.circle(x_1p4, y_n1p4, 1, 0.5)
        # self.pheromone.circle(x_n1p4, y_n1p4, 1, 0.5)
        # self.pheromone.circle(x_n1p4, y_1p4, 1, 0.5)
        self.num_robots = self.sock_receiver.receive_number()
        print("num_robots: {}".format(self.num_robots))
        print("Initialisation completed")

    def posToIndex(self, x, y):
        '''
        Convert 2D coordinates (x, y) into the matrix index (x_index, y_index) 
        '''
        phero = self.pheromone
        x_tmp = x
        y_tmp = y
        x_index = 0
        y_index = 0
        # Read pheromone value at the robot position
        res = self.pheromone.resolution
        round_dp = int(log10(res))
        x_tmp = round(
            x, round_dp
        )  # round the position value so that they fit into the centre of the cell.
        y_tmp = round(y, round_dp)  # e.g. 0.13 -> 0.1
        x_tmp = int(x * res)
        y_tmp = int(y * res)

        # Position conversion from Robot into pheromone matrix (0, 0) -> (n+1, n+1) of 2n+1 matrix
        x_index = int(x_tmp + (phero.num_cell - 1) / 2)
        y_index = int(y_tmp + (phero.num_cell - 1) / 2)
        if x_index < 0 or y_index < 0 or x_index > phero.num_cell - 1 or y_index > phero.num_cell - 1:
            raise Exception("The pheromone matrix index is out of range.")
        return x_index, y_index

    def indexToPos(self, x_index, y_index):
        '''
        Convert matrix indices into 2D coordinate (x, y)
        '''

        x = x_index - (self.pheromone.num_cell - 1) / 2
        y = y_index - (self.pheromone.num_cell - 1) / 2

        x = float(x) / self.pheromone.resolution
        y = float(y) / self.pheromone.resolution

        return x, y

    def pheroCallback(self):

        # Reading from arguments
        pos = self.sock_receiver.receive_array()
        print("pos: {}".format(pos))
        phero = self.pheromone
        x = pos[0]
        y = pos[1]
        print("x, y: {}, {}".format(x, y))

        # ========================================================================= #
        #                           Pheromone Reading                               #
        # ========================================================================= #
        '''
        Pheromone Value Reading
        '''
        '''2 pheromone values'''
        # Add two wheel position
        # wheel_distance = 0.2
        # pos_l = np.array([x+(cos(pi/2)*cos(self.theta)*(wheel_distance/2) - sin(pi/2)*sin(self.theta)*(wheel_distance/2)), y+(sin(pi/2)*cos(self.theta)*(wheel_distance/2) + cos(pi/2)*sin(self.theta)*(wheel_distance/2))])
        # pos_r = np.array([x+(cos(pi/2)*cos(self.theta)*(wheel_distance/2) + sin(pi/2)*sin(self.theta)*(wheel_distance/2)), y+(-sin(pi/2)*cos(self.theta)*(wheel_distance/2) + cos(pi/2)*sin(self.theta)*(wheel_distance/2))])

        # x_index, y_index = self.posToIndex(pos.x, pos.y)
        # x_l_index, y_l_index = self.posToIndex(pos_l[0], pos_l[1])
        # x_r_index, y_r_index = self.posToIndex(pos_r[0], pos_r[1])

        # # Assign pheromone values from two positions and publish it
        # phero_val = Float32MultiArray()
        # phero_val.data = [phero.getPhero(x_l_index, y_l_index), phero.getPhero(x_r_index, y_r_index)]
        # self.pub_phero.publish(phero_val)
        '''9 pheromone values'''
        # Position of 9 cells surrounding the robot
        x_index, y_index = self.posToIndex(x, y)
        print("x_idx, y_idx: {}, {}".format(x_index, y_index))
        phero_val = []
        #phero_arr = np.array( )
        for i in range(3):
            for j in range(3):
                phero_val.append(
                    self.pheromone.getPhero(x_index + i - 1, y_index + j - 1))
        self.sock_receiver.return_to_client(np.asarray(phero_val))

        # ========================================================================= #
        #                           Pheromone Injection                             #
        # ========================================================================= #
        ''' Pheromone injection (uncomment it when injection is needed) '''
        # if self.is_phero_inj is True:
        #     phero.injection(x_index, y_index, 0.2, 5, self.phero_max)

        # ========================================================================= #
        #                           Pheromone Update                                #
        # ========================================================================= #
        ''' Pheromone Update '''
        # time_cur = time.clock()
        # if time_cur-phero.step_timer >= 0.1:
        #     phero.update(self.phero_min, self.phero_max)
        #     phero.step_timer = time_cur

        # ========================================================================= #
        #                           Save Pheromone                                  #
        # ========================================================================= #
        '''Saving pheromone'''
        # # Save after 20s
        # time_check = time.time()
        # if time_check - self.startTime >= 20 and self.is_saved is False:
        #     self.pheromone.save("simple_collision_diffused3")
        #     self.is_saved = True

        # Save the pheromone when robot return home.
        # distance_to_origin = sqrt(x**2+y**2)
        # if self.is_saved is False and distance_to_origin < 0.05:
        #     self.pheromone.save("foraging_static")
        #     self.is_saved = True
        #     self.is_phero_inj = False

        # ========================================================================= #
        #                           Load Pheromone                                  #
        # ========================================================================= #
        '''Loading Pheromone'''
        # Load the pheromone
        # 1. When use continuous contoller. (1) It hasn't previously loaded, (2) pheromone injection is disabled,
        #    (3) service is requested by continuous controller script
        # if self.is_loaded is False and self.is_phero_inj is False and self.is_service_requested is True:
        #     try:
        #         self.pheromone.load("foraging")
        #         self.is_loaded = True
        #     except IOError as io:
        #         print("No pheromone to load: %s"%io)

        # 2. When reset is requested.
        if self.is_reset == True:
            try:
                self.pheromone.load(
                    "simple_collision_diffused3"
                )  # you can load any types of pheromone grid
                self.is_reset = False  # Reset the flag for next use
            except IOError as io:
                print("No pheromone to load: %s" % io)

    def injAssign(self, req):
        '''
        Service Function that takes whether robot injects pheromone or not. 
        '''
        self.is_phero_inj = req.is_inj
        service_ok = True
        self.is_service_requested = True
        return PheroInjResponse(service_ok)

    def serviceReset(self, req):
        '''
        When request is received, pheromone grid is reset and load the prepared pheromone grid.
        '''
        self.is_reset = req.reset
        is_reset = True
        return PheroResetResponse(is_reset)

    def nextGoal(self, req):

        # Turn off pheromone injection
        self.is_phero_inj = False

        # Convert the robot position to index for the pheromone matrix
        x = req.x
        y = req.y
        x_index, y_index = self.posToIndex(x, y)

        # read the 9 nearby values and choose the cell with maximum value
        max_phero = self.pheromone.getPhero(x_index, y_index)
        phero_index = np.array([0, 0])
        phero_value = np.zeros((3, 3))
        rand_index = 0

        ## Get the indices that contains maximum pheromone
        for i in range(3):
            for j in range(3):
                if self.pheromone.getPhero(
                        x_index + i - 1, y_index + j - 1
                ) > max_phero:  # TODO: Randomly select the cell if the values are equal
                    phero_index = np.array([i - 1, j - 1])
                    max_phero = self.pheromone.getPhero(
                        x_index + i - 1, y_index + j - 1)
                    print("Set new max")
                elif self.pheromone.getPhero(x_index + i - 1,
                                             y_index + j - 1) == max_phero:
                    phero_index = np.vstack((phero_index, [i - 1, j - 1]))
                phero_value[i, j] = self.pheromone.getPhero(
                    x_index + i - 1, y_index + j - 1)
                print(
                    "At the point ({}, {}), the pheromone value is {}".format(
                        i, j,
                        self.pheromone.getPhero(x_index + i - 1,
                                                y_index + j - 1)))
                #print("Append phero val")
        print("Phero_index: {}".format(phero_index))
        print("Phero_value: {}".format(phero_value))

        # Choose the index as a next goal from the array
        ## Check the front cells (highest priority)
        # if self.theta > (7/4) * pi or self.theta < (1/4) * pi:
        #     for x in phero_index:
        #         if x is np.array([1,0]) or x is np.array([1,1]) or x is np.array([1,2]):
        #             np.append(final_index, x, axis=0)
        rand_index = np.random.choice(phero_index.shape[0], 1)
        final_index = phero_index[rand_index]
        next_x_index = x_index + final_index[0, 0]
        next_y_index = y_index + final_index[0, 1]

        # Reconvert index values into position.
        next_x, next_y = self.indexToPos(next_x_index, next_y_index)
        print("Pheromone value of goal: {}".format(
            self.pheromone.getPhero(next_x_index, next_y_index)))

        return PheroGoalResponse(next_x, next_y)
Example #9
0
class Scenario(BaseScenario):
    '''
    Experiment 3
    - 4 robots navigation + obstacle avoidance
    - Dynamic & Static obstacle avoidance
    '''

    def __init__(self):
        self.sock_sender = SocketNumpyArray()
        self.sock_sender.initialize_sender('localhost', 9998)
        self.n = None
        self.x = None
        self.y = None
        self.theta = None 
        self.phero = None

        # Object initialisation
        # Robot initial positions
        self.robot_positions = [[-2.5,0],[2.5,0],[0,-2.5],[0,2.5]]
        self.robot_angles = [0, pi, pi/2, -pi/2]
        self.target_positions = [[2.5,0],[-2.5,0],[0,2.5],[0,-2.5]]
        ## 20201209 - add random positions if the fixed training works.
        # self.target_index = 0
        # self.num_experiments = 20
        # self.radius = 4

    def make_world(self):
        world = World()
        # set any world properties first
        world.dim_c = 2
        num_agents = 4
        num_obstacle = 1
        num_target = 4
        world.collaborative = False
        # add agents
        world.agents = [Agent() for i in range(num_agents)]
        for i, agent in enumerate(world.agents):
            agent.name = 'agent %d' % i
            agent.collide = True
            agent.silent = True
            agent.size = 0.1

        # add obstacles
        obstacles = [Landmark() for i in range(num_obstacle)]
        for i, obstacle in enumerate(obstacles):
            obstacle.name = 'obstacle %d' % i
            obstacle.collide = True
            obstacle.movable = False
            obstacle.size = 0.1

        # add target
        targets = [Landmark() for i in range(num_target)]
        for i, target in enumerate(targets):
            target.name = 'target %d' % i 
            target.collide = False
            target.movable = False
            target.size = 0.1

        # Merge the landmarks (obstacles + target)
        world.landmarks = obstacles + targets

        # make initial conditions
        self.n = num_agents
        self.x = [0.0, 0.0]*num_agents
        self.y = [0.0, 0.0]*num_agents
        self.theta = [0.0, 0.0]*num_agents
        self.reset_world(world)
        
        return world

    def reset_world(self, world):
        # random properties for agent
        for i, agent in enumerate(world.agents):
            agent.color = np.array([0.35, 0.35, 0.85])
        # random properties for landmarks
        for i, landmark in enumerate(world.landmarks):
            if 'obstacle' in landmark.name:
                landmark.color = np.array([0.25, 0.25, 0.25])
            if 'target' in landmark.name:
                landmark.color = np.array([0.9, 0.1, 0.1])
        
        # ========================================================================= #
	    #                            TARGET UPDATE                                  #
	    # ========================================================================= #
        # set random initial states
        # robot position (0, 0), distance between robots and target (4 m)
        # angle_target = self.target_index*2*pi/self.num_experiments        

        # self.target_x = self.radius*cos(angle_target)
        # self.target_y = self.radius*sin(angle_target)
        
        # if self.target_index < self.num_experiments-1:
        #     self.target_index += 1
        # else:
        #     self.target_index = 0

        # ========================================================================= #
	    #                             OBJECT RESET                                  #
	    # ========================================================================= #

        # Agent update 
        # 20201209 Fixed initial positions (later, I'll apply random initial positions)
        for i, agent in enumerate(world.agents):
            agent.state.p_pose = np.asarray(self.robot_positions[i] + self.robot_angles[i]) 
            agent.state.p_pos  = self.robot_positions[i]
            # self.target = [[self.x[1], self.y[1]], [self.x[0], self.y[0]]] 

            agent.state.p_vel = np.zeros(world.dim_p)
            agent.state.c = np.zeros(world.dim_c)
            agent.state.target = self.target_positions[i] # 20201201 target
            
        # for i, landmark in enumerate(world.landmarks):
        #     if landmark.name[0] == 'o':
        #         landmark.state.p_pos = [0, 0] #np.random.uniform(-1, +1, world.dim_p)
        #         landmark.state.p_vel = np.zeros(world.dim_p)
        
        # Obstacle update
        for i, obstacle in enumerate([ob for ob in world.landmarks if 'obstacle' in ob]):
            obstacle.state.p_pos = np.asarray([0,0])
            obstacle.state.p_vel = np.zeros(world.dim_p)
            
        # Target update
        for i, target in enumerate([tg for tg in world.landmarks if 'target' in tg]):
            target.state.p_pos = np.asarray(self.target_positions[i])
            target.state.p_vel = np.zeros(world.dim_p)

    def benchmark_data(self, agent, world):
        rew = 0
        collisions = 0
        occupied_landmarks = 0
        min_dists = 0
        for l in world.landmarks:
            dists = [np.sqrt(np.sum(np.square(a.state.p_pos - l.state.p_pos))) for a in world.agents]
            min_dists += min(dists)
            rew -= min(dists)
            if min(dists) < 0.1:
                occupied_landmarks += 1
        if agent.collide: 
            for a in world.agents:
                if self.is_collision(a, agent):
                    rew -= 1
                    collisions += 1
        return (rew, collisions, min_dists, occupied_landmarks)


    def is_collision(self, agent1, agent2):
        delta_pos = agent1.state.p_pos - agent2.state.p_pos
        dist = np.sqrt(np.sum(np.square(delta_pos)))
        dist_min = agent1.size + agent2.size
        return True if dist < dist_min else False

    def reward(self, agent, world):
        '''
        Compute rewards
        '''
        distance_reward = 0.0
        phero_reward = 0.0
        goal_reward = 0.0
        collision_reward = 0.0
        #angular_punish_rewards = [0.0]*self.num_robots
        #linear_punish_rewards = [0.0]*self.num_robots

        # 1. Distance Reward
        goal_progress = agent.state.distance_to_goal_prev - agent.state.distance_to_goal
        if abs(goal_progress) < 0.1:
            print("Goal Progress: {}".format(goal_progress))
            if goal_progress >= 0:
                    distance_reward = goal_progress * 1.2
            else:
                    distance_reward = goal_progress
        else:
            distance_reward = 0.0

        # 2. Phero Reward
        # phero_sum = np.sum(self.phero)
        # phero_reward = -phero_sum*2

        # 3. Goal Reward
        if agent.state.distance_to_goal <= 0.3:
            goal_reward = 50.0
            #done = True
            #self.reset(model_state, id_bots=idx[i])

        # 4. Collision Penalty
        
        for i, obstacle in enumerate([ob for ob in world.landmarks if 'obstacle' in ob]):
            is_collision = self.is_collision(agent, obstacle)
            if is_collision == True:
                collision_reward = -50.0
        
        reward = distance_reward*(5/world.dt)+phero_reward+goal_reward+collision_reward
        print("distance reward: {}".format(distance_reward))
        print("collision_reward: {}".format(collision_reward))
        print("goal_reward: {}".format(goal_reward))

        return reward

    def observation(self, agent, world):
        
        id = int(agent.name[-1])
        # get positions of all entities in this agent's reference frame
        entity_pos = []
        for entity in world.landmarks:  # world.entities:
            entity_pos.append(entity.state.p_pos - agent.state.p_pos)

        # entity colors
        entity_color = []
        for entity in world.landmarks:  # world.entities:
            entity_color.append(entity.color)

        positions = np.asarray(agent.state.p_pos)
        self.sock_sender.send_numpy_array(positions)
        data = self.sock_sender.receive_from_server()
        self.phero = phero = np.asarray(data).reshape(1,9)
        
        # 20201209 needs to work on merging static & dynamic pheromone values
        
        obs = np.hstack((phero, [agent.action.twist], np.asarray([agent.state.distance_to_goal]).reshape(1,1), np.asarray([agent.state.angle_diff]).reshape(1,1)))
        world.obs_n = np.shape(obs)[1]
        return obs 

    def done(self, agent, world):
        agent.state.done = False
        
        # 1. Goal arrival
        if agent.state.distance_to_goal <= 0.3:
            agent.state.done = True

        # 2. Out of range
        if abs(agent.state.p_pos[0]) > 4.6 or abs(agent.state.p_pos[1]) > 4.6:
            agent.state.done = True
            print("out of range!!!!")

        # 3. collision
        for i, obstacle in enumerate([ob for ob in world.landmarks if 'obstacle' in ob]):
            is_collision = self.is_collision(agent, obstacle)
            if is_collision == True:
                agent.state.done = True

        done = agent.state.done

        return done
    
    def info(self, agent, world):
        info = [{"targets": agent.state.target}]
        return info
class Scenario(BaseScenario):
    def __init__(self):
        self.sock_sender = SocketNumpyArray()
        self.sock_sender.initialize_sender('localhost', 9999)
        self.n = None
        self.x = None
        self.y = None
        self.theta = None
        self.phero = None

    def make_world(self):
        world = World()
        # set any world properties first
        world.dim_c = 2
        num_agents = 2
        num_landmarks = 1
        world.collaborative = True
        # add agents
        world.agents = [Agent() for i in range(num_agents)]
        for i, agent in enumerate(world.agents):
            agent.name = 'agent %d' % i
            agent.collide = True
            agent.silent = True
            agent.size = 0.1
        # add landmarks
        world.landmarks = [Landmark() for i in range(num_landmarks)]
        for i, landmark in enumerate(world.landmarks):
            landmark.name = 'landmark %d' % i
            landmark.collide = True
            landmark.movable = False
            landmark.size = 0.06

        # make initial conditions
        self.n = num_agents
        self.x = [0.0, 0.0] * num_agents
        self.y = [0.0, 0.0] * num_agents
        self.theta = [0.0, 0.0] * num_agents
        self.reset_world(world)

        return world

    def reset_world(self, world):
        # random properties for agents
        for i, agent in enumerate(world.agents):
            agent.color = np.array([0.35, 0.35, 0.85])
        # random properties for landmarks
        for i, landmark in enumerate(world.landmarks):
            landmark.color = np.array([0.25, 0.25, 0.25])
        # set random initial states
        d = 3
        angle = pi * np.random.uniform(-1, +1)

        self.x[0] = (d / 2) * cos(angle)
        self.y[0] = (d / 2) * sin(angle)

        self.x[1] = (d / 2) * cos(angle + pi)
        self.y[1] = (d / 2) * sin(angle + pi)

        self.theta[0] = angle + pi
        self.theta[1] = angle

        world.agents[0].state.p_pose = np.asarray(
            [self.x[0], self.y[0], self.theta[0]])
        world.agents[1].state.p_pose = np.asarray(
            [self.x[1], self.y[1], self.theta[1]])
        world.agents[0].state.p_pos = world.agents[0].state.p_pose[:2]
        world.agents[1].state.p_pos = world.agents[1].state.p_pose[:2]
        self.target = [[self.x[1], self.y[1]], [self.x[0],
                                                self.y[0]]]  #20201130 Target
        for i, agent in enumerate(world.agents):
            #agent.state.p_pos = np.random.uniform(-1, +1, world.dim_p)
            agent.state.p_vel = np.zeros(world.dim_p)
            agent.state.c = np.zeros(world.dim_c)
            agent.state.target = self.target[i]  # 20201201 target

        for i, landmark in enumerate(world.landmarks):
            landmark.state.p_pos = [0,
                                    0]  #np.random.uniform(-1, +1, world.dim_p)
            landmark.state.p_vel = np.zeros(world.dim_p)

    def benchmark_data(self, agent, world):
        rew = 0
        collisions = 0
        occupied_landmarks = 0
        min_dists = 0
        for l in world.landmarks:
            dists = [
                np.sqrt(np.sum(np.square(a.state.p_pos - l.state.p_pos)))
                for a in world.agents
            ]
            min_dists += min(dists)
            rew -= min(dists)
            if min(dists) < 0.1:
                occupied_landmarks += 1
        if agent.collide:
            for a in world.agents:
                if self.is_collision(a, agent):
                    rew -= 1
                    collisions += 1
        return (rew, collisions, min_dists, occupied_landmarks)

    def is_collision(self, agent1, agent2):
        delta_pos = agent1.state.p_pos - agent2.state.p_pos
        dist = np.sqrt(np.sum(np.square(delta_pos)))
        dist_min = agent1.size + agent2.size
        return True if dist < dist_min else False

    def reward(self, agent, world):
        # Agents are rewarded based on minimum agent distance to each landmark, penalized for collisions
        rew = 0
        for l in world.landmarks:
            dists = [
                np.sqrt(np.sum(np.square(a.state.p_pos - l.state.p_pos)))
                for a in world.agents
            ]
            rew -= min(dists)
        if agent.collide:
            for a in world.agents:
                if self.is_collision(a, agent):
                    rew -= 1
        distance_reward = 0.0
        phero_reward = 0.0
        goal_reward = 0.0
        #angular_punish_rewards = [0.0]*self.num_robots
        #linear_punish_rewards = [0.0]*self.num_robots

        # 1. Distance Reward
        goal_progress = agent.state.distance_to_goal_prev - agent.state.distance_to_goal
        if abs(goal_progress) < 0.1:
            print("Goal Progress: {}".format(goal_progress))
            if goal_progress >= 0:
                distance_reward = goal_progress * 1.2
            else:
                distance_reward = goal_progress
        else:
            distance_reward = 0.0

        # 2. Phero Reward
        phero_sum = np.sum(self.phero)
        phero_reward = -phero_sum * 2

        # 3. Goal Reward
        if agent.state.distance_to_goal <= 0.3:
            goal_reward = 50.0
            #done = True
            #self.reset(model_state, id_bots=idx[i])

        reward = distance_reward * (5 / world.dt) + phero_reward + goal_reward

        return reward

    def observation(self, agent, world):

        id = int(agent.name[-1])
        # get positions of all entities in this agent's reference frame
        entity_pos = []
        for entity in world.landmarks:  # world.entities:
            entity_pos.append(entity.state.p_pos - agent.state.p_pos)
        # entity colors
        entity_color = []
        for entity in world.landmarks:  # world.entities:
            entity_color.append(entity.color)
        # communication of all other agents
        comm = []
        other_pos = []
        for other in world.agents:
            if other is agent: continue
            comm.append(other.state.c)
            other_pos.append(other.state.p_pos - agent.state.p_pos)
        positions = np.asarray([agent.state.p_pos for agent in world.agents])
        #print(positions)
        self.sock_sender.send_numpy_array(positions)
        data = self.sock_sender.receive_from_server()
        #print("Data received from receiver: {}, size: {}".format(data, data.shape))
        #print("twist: {}".format(agent.action.twist))
        self.phero = phero = data[id].reshape(1, 9)
        #print("distances: {}, {}".format(agent.distance_to_goal_prev, agent.distance_to_goal))
        # Distance to Goal (state)
        #self.distance_to_goal =
        # Difference of local angle and global angle to head to the goal
        #self.angle_diff
        #print("shape 0: {}, shape 1: {}".format(phero.shape, agent.state.p_vel))
        obs = np.hstack(
            (phero, [agent.action.twist],
             np.asarray([agent.state.distance_to_goal]).reshape(1, 1),
             np.asarray([agent.state.angle_diff]).reshape(1, 1)))
        world.obs_n = np.shape(obs)[1]
        print("obs size: {}".format(np.shape(obs)))
        return obs  # 20201201 observation is changed (pheromone + velocity, distance, anglediff ) 1*13

    def done(self, agent, world):
        agent.state.done = False

        # 1. Goal arrival
        if agent.state.distance_to_goal <= 0.3:
            agent.state.done = True

        # 2. Out of range
        print("pos[0]: {}, pos[1]: {}".format(agent.state.p_pos[0],
                                              agent.state.p_pos[1]))
        print("abspos[0]: {}, abspos[1]: {}".format(abs(agent.state.p_pos[0]),
                                                    abs(agent.state.p_pos[1])))
        if abs(agent.state.p_pos[0]) > 4.8 or abs(agent.state.p_pos[1]) > 4.8:
            agent.state.done = True
            print("out of range!!!!")

        # 3. collision
        agents = [agent for agent in world.agents]
        is_collision = self.is_collision(agents[0], agents[1])
        if is_collision == True:
            agent.state.done = True

        done = agent.state.done

        return done

    def info(self, agent, world):
        info = [{"targets": agent.state.target}]
        return info
Example #11
0
import numpy as np
from npsocket_sn import SocketNumpyArray
sock_receiver = SocketNumpyArray()
sock_receiver.initalize_receiver(9999) # the 9999 is the port you can change it with your own. 
while True:
    positions = sock_receiver.receive_array()  # Receiving the image as numpy array. 
    # Display
    print("Received positions: {}, Size: {}".format(positions, np.shape(positions)))
    positions_re = positions.reshape(4,1)
    sock_receiver.return_to_client(positions_re)