예제 #1
0
    def draw_axis(self, axis, color):
        ticks = self._p._axis_ticks[axis]
        radius = self._p._tick_length / 2.0
        if len(ticks) < 2:
            return

        # calculate the vector for this axis
        axis_lines = [[0, 0, 0], [0, 0, 0]]
        axis_lines[0][axis], axis_lines[1][axis] = ticks[0], ticks[-1]
        axis_vector = vec_sub(axis_lines[1], axis_lines[0])

        # calculate angle to the z direction vector
        pos_z = get_direction_vectors()[2]
        d = abs(dot_product(axis_vector, pos_z))
        d = d / vec_mag(axis_vector)

        # don't draw labels if we're looking down the axis
        labels_visible = abs(d - 1.0) > 0.02

        # draw the ticks and labels
        for tick in ticks:
            self.draw_tick_line(axis, color, radius, tick, labels_visible)

        # draw the axis line and labels
        self.draw_axis_line(axis, color, ticks[0], ticks[-1], labels_visible)
예제 #2
0
    def draw_axis(self, axis, color):
        ticks = self._p._axis_ticks[axis]
        radius = self._p._tick_length / 2.0
        if len(ticks) < 2:
            return

        # calculate the vector for this axis
        axis_lines = [[0, 0, 0], [0, 0, 0]]
        axis_lines[0][axis], axis_lines[1][axis] = ticks[0], ticks[-1]
        axis_vector = vec_sub(axis_lines[1], axis_lines[0])

        # calculate angle to the z direction vector
        pos_z = get_direction_vectors()[2]
        d = abs(dot_product(axis_vector, pos_z))
        d = d / vec_mag(axis_vector)

        # don't draw labels if we're looking down the axis
        labels_visible = abs(d - 1.0) > 0.02

        # draw the ticks and labels
        for tick in ticks:
            self.draw_tick_line(axis, color, radius, tick, labels_visible)

        # draw the axis line and labels
        self.draw_axis_line(axis, color, ticks[0], ticks[-1], labels_visible)
예제 #3
0
    def run(self):
        """
        Run the Vicsek IROS 2014 algorithm thread.
        """
        # ============== Vicsek Algorithm -- Parameters ===============
        R0 = 12.0  # Pair potential lattice constant (Unit: m)
        Dp = 1.0  # Pair potential spring constant (Unit: s^-2)
        Cf = 18.0  # Viscous friction coefficient, or damp factor (Unit: m^2/s)
        Cs = 5.0  # Viscous friction coefficient for the shill agent (Unit: s^-1)
        Vf = 1.0  # Flocking speed for the MAS to maintain (Unit: m/s)
        V0 = 2.0  # Maximum tracking velocity
        Vmax = 3.0  # Maximum navigating velocity (the copter's total max V)

        Alpha = 0.6  # TRG coefficient (0 <= Alpha <= 1)
        Beta = 0.8  # COM coefficient (0 <= Beta <= 1)
        Rp = 0.5 * R0  # Upper threshold for coping with over-excitation (Short-range)
        Rs1 = 0.8 * R0  # Upper threshold incase division by 0 (Mid-range)
        Rs2 = 0.3 * R0  # Constant slope factor around R0

        Tau = 0.10  # Characteristc time for reaching velocity
        Del_t = 0.10  # Feed-forward estimation time
        Ts = Del_t  # Let sampling period equal to del_t

        Rw = 100.0  # Radius for wall (Unit: m)
        Rt = 1.0  # Radius for target (Unit: m)
        Dw = 5.0  # Transition bandwith for wall (Unit: m)
        Ds = 2.0  # Transition bandwith for shape (Unit: m)
        Dt = 1.0  # Transition bandwith for target point (Unit: m)

        loop_count = 1  # for calculate loop time
        average_time = 0

        is_on_hold = False  # a flag marking if the copter is holding position
        no_rendezvous = False  # a flag marking if there's a rendezvous point

        while not self._stopflag:
            time.sleep(0.001)

            [self._stopflag,
             exit_number] = _check_terminate_condition(self._vehicle, 'Vicsek')

            is_on_hold = _check_satellite_low(self._xbee, is_on_hold)
            if is_on_hold: continue

            loop_begin_time = default_timer()  # Flocking algorithm begins
            # -------------- <Part I> Repulsion and Viscous -------------- #
            friends = copy(self._neighbors)
            my_location = self._vehicle.location.global_relative_frame
            my_velocity = self._vehicle.velocity
            # attributes from Vehicle returns a newly spwaned object, no need to
            # `copy`. But the dictionary is mutable so it should be copied.

            if shared.rendezvous is None:  # hold position if no rendezvous
                if not no_rendezvous:
                    _log_and_broadcast(
                        self._xbee, "IFO,%s no rendezvous." % shared.AGENT_ID)
                    no_rendezvous = True

                time.sleep(0.5)
                continue

            else:
                no_rendezvous = False

            # Self-propelling term
            my_speed = util.vec_norm2(my_velocity)
            V_spp = util.vec_scal(my_velocity, Vf / my_speed)

            # potential term and slipping term
            sum_potential = [0.0, 0.0, 0.0]
            sum_slipping = [0.0, 0.0, 0.0]

            # go thru each neighbor
            for j in friends:
                # location error (form: [dNorth, dEast, dDown], unit: meters)
                # distance, metres (get_distance_metres is also ok)
                X_ij = nav.get_position_error(
                    my_location, friends[j].location_global_relative)
                D_ij = util.vec_norm2(
                    X_ij[0:2])  # only measure ground distance, ignore altitude

                # velocity error (form: [dVx, dVy, dVz], unit: m/s)
                V_ij = util.vec_sub(my_velocity, friends[j].velocity)

                # i. short-range repulsion, when D_ij < R0
                if D_ij < R0:
                    temp_vector = util.vec_scal(X_ij,
                                                min(Rp, R0 - D_ij) / D_ij)
                    sum_potential = util.vec_add(sum_potential, temp_vector)

                # ii. mid-range viscous friction
                temp_vector = util.vec_scal(
                    V_ij, 1.0 / pow(max(Rs1, D_ij - R0 + Rs2), 2))
                sum_slipping = util.vec_add(sum_slipping, temp_vector)
            # End of for j in friends

            # ---- collective potential acceleration ----
            A_potential = util.vec_scal(sum_potential, -Dp)
            A_slipping = util.vec_scal(sum_slipping, Cf)

            # ------------ <Part II> Global Positional Constraint --------------
            # alias for the rendezvous point (a comm.WrappedData object)
            X_trg = shared.rendezvous.location_global_relative

            # i. Flocking: Shill agent wall
            X_tmp = nav.get_position_error(my_location, X_trg)
            D_tmp = util.vec_norm2(X_tmp[0:2])
            # normally the X_trg cannot equal to my_location, but there is still room
            # to add algorithm twitches to improve robustness.

            # The force of the wall only applies when agents are out of the area
            # A_wall = Cs * bump(D_tmp, Rw, Dw) * (Vf/D_tmp*X_tmp - V_i)
            temp_vector = util.vec_scal(X_tmp, Vf / D_tmp)
            temp_vector = util.vec_sub(my_velocity, temp_vector)
            A_wall = util.vec_scal(temp_vector,
                                   Cs * bump_function(D_tmp, Rw, Dw))

            # ii. Formation: Shape shift and CoM
            [X_shp, X_CoM, Rs] = get_shape_factor(my_location, friends, R0,
                                                  'grid')

            X_tmp = nav.get_position_error(my_location, X_shp)
            D_tmp = util.vec_norm2(X_tmp[0:2])

            if D_tmp:  # deals with divide-by-zero
                V_shp = util.vec_scal(
                    X_tmp,
                    Beta * V0 * bump_function(D_tmp, Rs, Ds) / D_tmp)
            else:
                V_shp = util.vec_scal(X_tmp, 0)

            # rendezvous target vector
            X_tmp = nav.get_position_error(X_CoM, X_trg)
            D_tmp = util.vec_norm2(X_tmp[0:2])
            V_trg = util.vec_scal(
                X_tmp,
                Alpha * V0 * bump_function(D_tmp, Rt, Dt) / D_tmp)
            # normally the X_trg cannot equal to X_CoM, but there is still room
            # to add algorithm twitches to improve robustness

            # tracking vector (normalize if saturated)
            V_trk = util.vec_add(V_shp, V_trg)
            S_trk = util.vec_norm2(V_trk)
            if S_trk > V0: V_trk = util.vec_scal(V_trk, V0 / S_trk)

            # ------------ <Part III> Full Dynamic ------------
            # V(t+1) = V(t) + 1/Tau*(V_spp + V_trk - V(t))*Del_t + (A_pot + A_slip + A_wall)*del_t
            acceleration = util.vec_add(A_wall,
                                        util.vec_add(A_potential, A_slipping))
            velocity = util.vec_add(V_spp, util.vec_sub(my_velocity, V_trk))

            acceleration = util.vec_scal(acceleration, Del_t)
            velocity = util.vec_scal(velocity, Del_t / Tau)

            inc_velocity = util.vec_add(acceleration, velocity)
            des_velocity = util.vec_add(my_velocity, inc_velocity)
            des_speed = util.vec_norm2(des_velocity)

            if des_speed > Vmax:
                des_velocity = util.vec_scal(des_velocity, Vmax / des_speed)

            loop_end_time = default_timer()  # Time marker ends
            elapsed_time = (loop_end_time -
                            loop_begin_time) * 1000000  # convert into us
            inv_count = 1.0 / loop_count  # incremental averaging method
            average_time = (
                1.0 - inv_count) * average_time + inv_count * elapsed_time
            loop_count = loop_count + 1

            # Send thru Mavlink
            nav.send_ned_velocity(
                self._vehicle,
                des_velocity[0],
                des_velocity[1],
                0,  # Vz is ignored
                Ts)
        # End of While #
        _log_and_broadcast(
            self._xbee, "IFO,%s Vicsek ended with number %d." %
            (shared.AGENT_ID, exit_number))
        util.log_info("Average loop time: %d us" % average_time)