Esempio n. 1
0
def formation_callback(data, args):
    global nodes_assigned
    robots = args[0]
    goal_positions = args[1]

    camera = {
        data.tagid1: [data.x1, data.y1],
        data.tagid2: [data.x2, data.y2],
        data.tagid3: [data.x3, data.y3],
        data.tagid4: [data.x4, data.y4],
        data.tagid5: [data.x5, data.y5],
        data.tagid6: [data.x6, data.y6],
        data.tagid7: [data.x7, data.y7],
        data.tagid8: [data.x8, data.y8]
    }

    # Assign where the robots belong in the system (shortest total distance required to travel to be in formation).
    simulation = False
    robot_to_node_assignment.assign_nodes(robots, goal_positions, simulation)

    # Move all the robots in the system to their desired goal.
    for i in range(0, len(robots)):
        robot = robots[i]

        # Convert the tags' positions to meters. If not able to detect the tag, use last information recieved.
        if camera.get(1) is not None:
            robot_position_back = vectors.multiply(camera.get(i * 2 + 1),
                                                   0.001)
            robot.set_position(robot_position_back)
        if camera.get(2) is not None:
            robot_position_front = vectors.multiply(camera.get(i * 2 + 2),
                                                    0.001)
            robot.set_front_position(robot_position_front)

        robot_position_front = robot.get_front_position()
        robot_position_back = robot.get_position()

        # Calculate orientation of robot, it should take a value from 0 to 2pi
        robot_orientation = math.atan2(
            robot_position_front[1] - robot_position_back[1],
            robot_position_front[0] - robot_position_back[0])
        if robot_orientation < 0:
            robot_orientation += 2 * math.pi

        # Set orientation of robot, so that it can be used later on when needed.
        robot.set_orientation(robot_orientation)

        # Find the specific robot's goal using information calculated in the node assignment algorithm.
        goal_position = goal_positions[robot.get_node_in_system()]

        # It is always a good idea to limit the speed when using real robots with risk of collisions.
        max_speed = 0.2
        move_robot_to_goal(robot, goal_position, max_speed)
Esempio n. 2
0
def path_callback(data, robots):
    camera = {
        data.tagid1: [data.x1, data.y1],
        data.tagid2: [data.x2, data.y2],
        data.tagid3: [data.x3, data.y3],
        data.tagid4: [data.x4, data.y4],
        data.tagid5: [data.x5, data.y5],
        data.tagid6: [data.x6, data.y6],
        data.tagid7: [data.x7, data.y7],
        data.tagid8: [data.x8, data.y8]
    }

    if camera.get(1) is not None:
        robot_0_position = vectors.multiply(camera.get(1), 0.001)
        robots[0].set_position(robot_0_position)
    else:
        print "Can't see robot 0"
    if camera.get(3) is not None:
        robot_1_position = vectors.multiply(camera.get(3), 0.001)
        robots[1].set_position(robot_1_position)
    else:
        print "Can't see robot 1"
    if camera.get(5) is not None:
        robot_2_position = vectors.multiply(camera.get(5), 0.001)
        robots[2].set_position(robot_2_position)
    else:
        print "Can't see robot 2"

    global obstacles
    if camera.get(7) is not None:
        obstacle_0_position = vectors.multiply(camera.get(7), 0.001)
        obstacles[0] = obstacle_0_position
    else:
        obstacles[0] = 0
    if camera.get(8) is not None:
        obstacle_1_position = vectors.multiply(camera.get(8), 0.001)
        obstacles[1] = obstacle_1_position
    else:
        obstacles[1] = 0

    global subscriber
    subscriber.unregister()
Esempio n. 3
0
def find_path(goal, robots, minx, maxx, miny, maxy):
    global subscriber
    subscriber = rospy.Subscriber("/position", Pos, path_callback, robots)

    # Make sure we've collected the data by waiting a while (the subscriber will unsubscribe itself when done).
    time.sleep(1)

    # Set the robot closest to the target as leader.
    leader_assignment.set_leader(goal, robots, False)

    # Find the robots' positions.
    for i in range(0, len(robots)):
        if robots[i].get_node_in_system() == 0:
            leader_position = robots[i].get_position()
        elif robots[i].get_node_in_system() == 1:
            follower_1_position = robots[i].get_position()
        elif robots[i].get_node_in_system() == 2:
            follower_2_position = robots[i].get_position()

    # Now let's create a matrix representing the space in which the robots operate.
    # Number of intervals per meter.
    scale = 10
    nx = int((maxx - minx) * scale)
    ny = int((maxy - miny) * scale)
    # A matrix filled with zeros representing the area that the camera sees.
    matrix = [[0 for j in range(ny)] for i in range(nx)]

    # The start and goal positions represented in the matrix.
    start_matrix = (int((leader_position[0] - minx) * scale),
                    int((leader_position[1] - miny) * scale))
    goal_matrix = (int((goal[0] - minx) * scale), int(
        (goal[1] - miny) * scale))

    # Place followers in matrix and add some margins around them so that the leader at least not is aiming straight
    # towards them.
    follower_1_position_matrix = [
        int((follower_1_position[0] - minx) * scale),
        int((follower_1_position[1] - miny) * scale)
    ]
    follower_2_position_matrix = [
        int((follower_2_position[0] - minx) * scale),
        int((follower_2_position[1] - miny) * scale)
    ]

    # Set size of the followers so that they are represented correctly in the matrix. Number in meters, later scaled.
    width_follower = 0.7 * scale
    # Place ones in the matrix where the followers are + a region around them so that the leader will not move there.
    for i in range(nx):
        for j in range(ny):
            if vectors.distance_points(follower_1_position_matrix, [i,j]) <= width_follower or \
                            vectors.distance_points(follower_2_position_matrix, [i, j]) <= width_follower:
                matrix[i][j] = 1

    # Place obstacles in matrix and add some space around them so that they are not just one matrix element wide.
    global obstacles
    width_obstacle = 1 * scale
    if obstacles[0] != 0:
        obstacle_0_position_matrix = [
            int((obstacles[0][0] - minx) * scale),
            int((obstacles[0][1] - miny) * scale)
        ]
        for i in range(nx):
            for j in range(ny):
                if vectors.distance_points(obstacle_0_position_matrix,
                                           [i, j]) <= width_obstacle:
                    matrix[i][j] = 1

    if obstacles[1] != 0:
        obstacle_1_position_matrix = [
            int((obstacles[1][0] - minx) * scale),
            int((obstacles[1][1] - miny) * scale)
        ]
        for i in range(nx):
            for j in range(ny):
                if vectors.distance_points(obstacle_1_position_matrix,
                                           [i, j]) <= width_obstacle:
                    matrix[i][j] = 1

    # Find the shortest path using the A* algorithm
    cam_area = numpy.array(matrix)
    path = astar.astar(cam_area, goal_matrix, start_matrix)

    # Shift the path so that it corresponds to the actual area that is considered.
    if path is not False:
        for i in range(len(path)):
            path[i] = vectors.add(vectors.multiply(path[i], 1. / scale),
                                  [minx, miny])

    # It seems to be a good idea to not tell the robot to go to a point really close to it, so just cut out the first
    # 5 or so points. Also add the goal position at the end since it is not given from the A* algorithm.
    short_path = [0 for i in range(len(path) - 4)]
    for i in range(5, len(path)):
        short_path[i - 5] = path[i]
    short_path[len(short_path) - 1] = goal

    return short_path
Esempio n. 4
0
def move_follower(robot, robots, max_speed, pid_leader, pid_follower,
                  distances):
    global at_goal

    # Find what the other robots are in the system.
    for i in range(0, len(robots)):
        if robots[i].get_node_in_system() == 0:
            leader = robots[i]
        elif (robots[i].get_node_in_system() != 0) and (robots[i]
                                                        is not robot):
            follower = robots[i]

    # Desired distances to keep to the other robots. Leader and follower are either correctly assigned or something else
    # is terribly wrong. Shouldn't initialise them as a safety since that wouldn't allow you to identify the problem.
    desired_distance_leader = distances[leader.get_node_in_system()][
        robot.get_node_in_system()]
    desired_distance_follower = distances[follower.get_node_in_system()][
        robot.get_node_in_system()]

    # The robots' positions.
    robot_position = robot.get_position()
    follower_position = follower.get_position()
    leader_position = leader.get_position()

    # This follower's orientation
    robot_orientation = robot.get_orientation()

    # The orientation of the leader
    leader_orientation = leader.get_orientation()

    # Calculate the actual distances to the other robots.
    distance_leader = vectors.distance_points(leader_position, robot_position)
    distance_follower = vectors.distance_points(follower_position,
                                                robot_position)

    # Use PID-controller to go to a position which is at the desired distance from both the other robots.
    error_leader = distance_leader - desired_distance_leader
    error_follower = distance_follower - desired_distance_follower
    u_leader = pid_leader.pid(error_leader)
    u_follower = pid_follower.pid(error_follower)

    # u is always going to be a positive value. As long as the robots don't overshoot this shouldn't be a problem, but
    # if they do they might keep moving and even crash into the leader. Have this in consideration.
    u = math.sqrt(u_follower**2 + u_leader**2)

    # Create vectors to the leader, the other follower, the orientation of the leader and from these decide on a
    # direction vector, which this follower should move along. The further away the robot is from either the leader or
    # the other follower, the bigger the tendency is to move towards that robot. If it's more or less at the right
    # distance from the other robots it is favorable to move in the orientation of the leader, which is implemented by
    # the usage of the variable scale which is an exponential decaying function squared and scaled by 2/3, in other
    # words the follower will only move in the direction of the leader's orientation if it's more or less perfectly in
    # the right position.
    if u_leader != 0 and u_follower != 0:
        vector_leader = vectors.multiply(
            vectors.normalise(vectors.subtract(leader_position,
                                               robot_position)),
            u_leader * u_follower)
    else:
        vector_leader = vectors.multiply(
            vectors.normalise(vectors.subtract(leader_position,
                                               robot_position)), 0.001)

    if u_follower != 0:
        vector_follower = vectors.multiply(
            vectors.normalise(
                vectors.subtract(follower_position, robot_position)),
            u_follower)
    else:
        vector_follower = vectors.multiply(
            vectors.normalise(
                vectors.subtract(follower_position, robot_position)), 0.001)

    scale = (math.exp(-u)**2) * 2 / 3
    vector_orientation_leader = vectors.multiply(
        [math.cos(leader_orientation),
         math.sin(leader_orientation)], scale)

    direction_vector = vectors.add(vectors.add(vector_follower, vector_leader),
                                   vector_orientation_leader)

    # Calculate a goal angle from the direction vector.
    goal_angle = math.atan2(direction_vector[1], direction_vector[0])
    if goal_angle < 0:
        goal_angle += 2 * math.pi

    # Calculate a target angle from the goal angle and the orientation of this robot.
    target_angle = angles.angle_difference(goal_angle, robot_orientation)

    # Spin the robot towards the desired orientation. In general a P-regulator should be enough.
    twist.angular.z = target_angle * 0.5

    # Move the robot forward. The further away it is from the goal, as well as earlier error and predicted future error
    # by the PID is considered in the variable u. Also the robot will move by full speed when oriented correctly, but
    # slower the further away it is from its desired orientation given by target_angle.
    twist.linear.x = u * math.fabs(math.pi - math.fabs(target_angle)) / math.pi

    # If the robot is within an acceptable range, named tol, it is considered "in position". The robot will still keep
    # moving though until all robots are at the goal, which is taken care of later.
    tol = 0.05
    if math.fabs(error_follower) < tol and math.fabs(error_leader) < tol:
        robot.set_at_position(True)
    else:
        robot.set_at_position(False)

    # Make sure the robot is not moving too fast.
    if twist.linear.x > max_speed:
        twist.linear.x = max_speed

    if u_leader < 0:
        twist.linear.x = 0.07

    # If all the robots are at goal we have to stop moving of course.
    if at_goal:
        twist.linear.x = 0
        twist.angular.z = 0

    # If the robots are colliding it would be a good thing to just stop before an accident happens.
    if distance_leader < 0.7 or distance_follower < 0.5:
        twist.linear.x = 0
        twist.angular.z = 0

    robot.pub.publish(twist)
Esempio n. 5
0
def move_formation_callback(data, args):
    camera = {
        data.tagid1: [data.x1, data.y1],
        data.tagid2: [data.x2, data.y2],
        data.tagid3: [data.x3, data.y3],
        data.tagid4: [data.x4, data.y4],
        data.tagid5: [data.x5, data.y5],
        data.tagid6: [data.x6, data.y6],
        data.tagid7: [data.x7, data.y7],
        data.tagid8: [data.x8, data.y8]
    }

    robots = args[0]
    goal = args[1]
    distances = args[2]
    pid_list = args[3]

    # Calculate the positions and orientations of the robots in the system and store them in their respective objects.
    for i in range(0, len(robots)):
        robot = robots[i]

        # Convert the tags' positions to meters. If not able to detect the tag, use last information recieved.
        if camera.get(1) is not None:
            robot_position_back = vectors.multiply(camera.get(i * 2 + 1),
                                                   0.001)
            robot.set_position(robot_position_back)
        if camera.get(2) is not None:
            robot_position_front = vectors.multiply(camera.get(i * 2 + 2),
                                                    0.001)
            robot.set_front_position(robot_position_front)

        robot_position_front = robot.get_front_position()
        robot_position_back = robot.get_position()

        # Calculate orientation of robot, it should take a value from 0 to 2pi
        robot_orientation = math.atan2(
            robot_position_front[1] - robot_position_back[1],
            robot_position_front[0] - robot_position_back[0])
        if robot_orientation < 0:
            robot_orientation += 2 * math.pi

        # Set orientation of robot, so that it can be used later on when needed.
        robot.set_orientation(robot_orientation)

    # Check if the robot is a leader or follower and take action accordingly.
    for i in range(0, len(robots)):

        max_speed_leader = 0.1
        max_speed_follower = 0.2

        if robots[i].get_node_in_system() == 0:
            move_leader(robots[i], goal, max_speed_leader)

        elif robots[i].get_node_in_system() == 1:
            pid_leader = pid_list[0]
            pid_follower = pid_list[1]
            move_follower(robots[i], robots, max_speed_follower, pid_leader,
                          pid_follower, distances)

        elif robots[i].get_node_in_system() == 2:
            pid_leader = pid_list[2]
            pid_follower = pid_list[3]
            move_follower(robots[i], robots, max_speed_follower, pid_leader,
                          pid_follower, distances)

        else:
            print "---WARNING--- THIS ROBOTS IS NEITHER LEADER NOR FOLLOWER. ---WARNING---"
Esempio n. 6
0
 def update(self, slowvalue):
     for p in self.particles:
         p.pos = vectors.add_vec(
             p.pos, vectors.multiply(config.dt * slowvalue, p.v))
def find_path(goal, robots, minx, maxx, miny, maxy):

    # Set the robot closest to the target as leader. Either check them here or go to a formation at first.
    leader_assignment.set_leader(goal, robots, True)

    # Find the robots' positions.
    for i in range(0, len(robots)):
        if robots[i].get_node_in_system() == 0:
            leader_position = robots[i].get_position_simulation()
        elif robots[i].get_node_in_system() == 1:
            follower_1_position = robots[i].get_position_simulation()
        elif robots[i].get_node_in_system() == 2:
            follower_2_position = robots[i].get_position_simulation()

    # Now let's create a matrix representing the space in which the robots operate.

    # 10 intervals per meter
    scale = 10
    nx = int((maxx - minx) * scale)
    ny = int((maxy - miny) * scale)

    matrix = [[0 for i in range(ny)] for j in range(nx)]

    # Place the goal and start in the matrix (or get their representation at least).
    start_matrix = (int((leader_position[0] - minx) * scale),
                    int((leader_position[1] - miny) * scale))
    goal_matrix = (int((goal[0] - minx) * scale), int(
        (goal[1] - miny) * scale))

    # Place followers in matrix and add some margins around them so that the leader at least not is aiming straight
    # towards them.
    follower_1_position_matrix = [
        int((follower_1_position[0] - minx) * scale),
        int((follower_1_position[1] - miny) * scale)
    ]
    follower_2_position_matrix = [
        int((follower_2_position[0] - minx) * scale),
        int((follower_2_position[1] - miny) * scale)
    ]

    # How big are they (in meters * scale)?
    width_follower = 0.8 * scale
    for i in range(nx):
        for j in range(ny):
            if vectors.distance_points(follower_1_position_matrix, [i,j]) <= width_follower or \
                            vectors.distance_points(follower_2_position_matrix, [i, j]) <= width_follower:
                matrix[i][j] = 1

    # Place obstacles in matrix and add some space around them so that they are not just one matrix element wide.
    global obstacles
    width_obstacle = 1.5 * scale
    if obstacles[0] != [0]:
        obstacle_0_position_matrix = [
            int((obstacles[0][0] - minx) * scale),
            int((obstacles[0][1] - miny) * scale)
        ]
        print obstacle_0_position_matrix
        for i in range(nx):
            for j in range(ny):
                if vectors.distance_points(obstacle_0_position_matrix,
                                           [i, j]) <= width_obstacle:
                    matrix[i][j] = 1

    if obstacles[1] != [0]:
        obstacle_1_position_matrix = [
            int((obstacles[1][0] - minx) * scale),
            int((obstacles[1][1] - miny) * scale)
        ]
        for i in range(nx):
            for j in range(ny):
                if vectors.distance_points(obstacle_1_position_matrix,
                                           [i, j]) <= width_obstacle:
                    matrix[i][j] = 1

    # Find the shortest path using the A* algorithm
    sim_area = numpy.array(matrix)
    path = astar.astar(sim_area, goal_matrix, start_matrix)

    # Shift the path so that it corresponds to the actual area that is considered.
    if path is not False:
        for i in range(len(path)):
            path[i] = vectors.add(vectors.multiply(path[i], 1. / scale),
                                  [minx, miny])

    # It seems to be a good idea to not tell the robot to go to a point really close to it, so just cut out the first
    # 5 or so points. Also add the goal position at the end since it is not given from the A* algorithm.
    short_path = [0 for i in range(len(path) - 4)]
    for i in range(4, len(path) - 1):
        short_path[i - 4] = path[i]
    short_path[len(short_path) - 1] = goal

    return short_path