예제 #1
0
class sailcontroller():
    def __init__(self,
                 p_term=1,
                 i_term=0.3,
                 d_term=0.06,
                 Dv_constant=0.4,
                 ideal_angle=0.9):
        self.pid_adjustment = PID(P=p_term, I=i_term, D=d_term)
        self.sail = 0
        self.maxsail = math.pi / 12 * 5

        self.Dv_constant = Dv_constant
        self.ideal_angle = ideal_angle

    def generate_command(self, velocity, position, target, target_v, true_wind,
                         keeping_state, desired_angle, tacking_angle,
                         force_turning_angle):
        app_wind = self.get_app_wind(true_wind, position[3], velocity)
        if target_v == 0.8:
            self.pid_adjustment.clear()
        if keeping_state == 0:
            # print(3333333)
            target_v = self.get_desire_v(velocity, position, target, true_wind,
                                         keeping_state, desired_angle)
        # print(target_v,11111111)
        optimal_sail = self.get_optimal_sail(position[3], app_wind)
        final_sail = self.get_final_sail(target_v, optimal_sail, velocity[0],
                                         position[3], app_wind, tacking_angle)
        if force_turning_angle != None:
            final_sail = 1

        return final_sail, target_v

    def get_desire_v(self, velocity, position, target, true_wind,
                     keeping_state, desired_angle):
        distance_st = math.sqrt(
            pow(target[1] - position[1], 2) + pow(target[0] - position[0], 2))
        if keeping_state == 0:
            target_v = distance_st * self.Dv_constant
            if math.cos(true_wind[1] - position[3]) > 0.3:
                target_v = 0.2
        # elif keeping_state==1:
        #     target_v=1.0
        #     # if math.cos(true_wind[1]-position[3])>math.cos(math.pi-self.ideal_angle):
        #     #     target_v=0.15+0.01*math.asin(math.sin(abs(true_wind[1]-position[3])-(math.pi-self.ideal_angle)))
        #     # else:
        #     #     target_v=0.15
        # elif keeping_state==2:
        #     target_v=0.5
        # elif keeping_state==3:
        #     target_v=0.2
        # elif keeping_state==4:
        #     target_v=0.1
        return target_v

    def get_optimal_sail(self, heading_angle, app_wind):
        # angle_diff=self.get_abs_angle_difference(heading_angle,app_wind[1]+math.pi)
        # print('angle_diff',angle_diff,'heading',heading_angle,app_wind[1])
        if math.cos(app_wind[1]) <= math.cos(3 * math.pi / 4):
            optimal_sail = 0.3 + (-3 * math.pi / 4 + abs(app_wind[1])) * 0.3
            # print(optimal_sail,'3')
        else:
            optimal_sail = 0.3 + (3 / 4 * math.pi - abs(app_wind[1])) * 1.2
            # print(optimal_sail,'4')
        if optimal_sail > self.maxsail:
            optimal_sail = self.maxsail
        return optimal_sail

    def get_app_wind(self, true_wind, heading_angle, velocity):

        ###this part is different from the paper since there might be something wrong in the paper
        ###get coordinates of true wind

        app_wind = [
            true_wind[0] * math.cos(true_wind[1] - heading_angle) -
            velocity[0],
            true_wind[0] * math.sin(true_wind[1] - heading_angle) - velocity[1]
        ]
        ###convert into polar system
        angle = math.atan2(app_wind[1], app_wind[0])
        app_wind = [
            math.sqrt(pow(app_wind[1], 2) + pow(app_wind[0], 2)), angle
        ]
        return app_wind

    def regular_angle(self, angle):

        while angle > math.pi:
            angle -= math.pi * 2
        while angle < -math.pi:
            angle += math.pi * 2
        return angle

    ## return abs(angle1-angle2) which must < pi
    def get_abs_angle_difference(self, angle1, angle2):
        return math.acos(math.cos(angle1 - angle2))

    def get_final_sail(self, target_v, optimal_sail, v, heading_angle,
                       app_wind, tacking_angle):
        ### get maxsail (considering the influence of wind)
        maxsail = min(self.maxsail, abs(app_wind[1]))
        offset = -self.pid_adjustment.update(v, target_v)

        if self.maxsail - optimal_sail > 0.2:
            final_sail = (maxsail + optimal_sail) / 2 + offset
            # print('!!!!!!!!!',(maxsail+optimal_sail)/2)
            if final_sail > maxsail:
                final_sail = maxsail
            elif final_sail < optimal_sail:
                final_sail = optimal_sail

        else:
            final_sail = optimal_sail - 0.35 - offset

            if final_sail > optimal_sail:
                final_sail = optimal_sail
                # print(optimal_sail)
            elif final_sail < 0.4:
                final_sail = 0.4
        # print('offset',offset,'opt_sail',optimal_sail,'final sail',final_sail)
        # print(self.pid_adjustment.PTerm,self.pid_adjustment.ITerm)
        # print(optimal_sail,target_v,offset,final_sail,'22222222')

        # if tacking_angle != None :
        #     # print('!!!!!!!!!!!!!!!!!!')
        #     final_sail=optimal_sail
        return final_sail
예제 #2
0
class rudder_controller():
    def __init__(self):
        self.command_generator = PID(P=0.8, I=0.2, D=0.1)
        self.rudder = 0
        self.maxrudder = math.pi / 4  ##max angle of rudder
        self.command_generator.setBoundary(self.maxrudder, -self.maxrudder)
        self.sign_signal = 1

    def generate_command(self, desired_angle, current_angle, keeping_state,
                         velocity, tacking_angle, force_turning_angle,
                         boat_to_target_angle, true_wind):

        if keeping_state != 2:

            if math.cos(current_angle - desired_angle) > 0:  ##防止坐标在-pi到pi时跳跃
                if current_angle - desired_angle > math.pi / 2:
                    current_angle = current_angle - math.pi * 2
                elif current_angle - desired_angle < -math.pi / 2:
                    current_angle = current_angle + math.pi * 2
                else:
                    current_angle = current_angle

                self.rudder = -self.command_generator.update(
                    current_angle, desired_angle)
                current_angle = self.regular_angle(current_angle)
                # print(self.rudder,'1')
            else:
                self.rudder = self.maxrudder * self.sign(
                    math.sin(current_angle - desired_angle))

            if tacking_angle != None:
                self.rudder == self.maxrudder * self.sign(
                    math.sin(tacking_angle - true_wind[1]))
                # print(self.rudder,'2')
            elif force_turning_angle != None:
                if self.sign(self.rudder) == self.sign(
                        math.sin(force_turning_angle - true_wind[1])):
                    self.rudder = -self.rudder
                # print(self.rudder,'3')
        else:
            self.rudder = self.maxrudder * self.sign(
                math.sin(boat_to_target_angle - true_wind[1]))

        if keeping_state == 4:
            self.rudder = self.maxrudder * self.sign(self.rudder)

        if velocity[0] < 0 and self.sign_signal > -0.8:
            self.sign_signal -= 0.2
        elif velocity[0] > 0 and self.sign_signal < 0.8:
            self.sign_signal += 0.2

        if self.sign_signal < 0:
            self.rudder = -self.maxrudder * self.sign(
                math.sin(desired_angle - true_wind[1])) / 2
        # print(self.rudder)
        return self.rudder

    def regular_angle(self, angle):

        while angle > math.pi:
            angle -= math.pi * 2
        while angle < -math.pi:
            angle += math.pi * 2
        return angle

    def sign(self, p):

        if p > 0:
            return 1
        elif p == 0:
            return 0
        else:
            return -1


# a=rudder_controller()
# b=a.generate_command(0.6,0,0,[1,1,0,0])
# print(b)
# a=rudder_controller()
# b=a.generate_command(0.6,0,0,[1,1,0,0])
# print(b)
class sailcontroller():
    def __init__(self,
                 p_term=1,
                 i_term=0.3,
                 d_term=0.03,
                 Dv_constant=0.4,
                 ideal_angle=0.9):
        self.pid_adjustment = PID(P=p_term, I=i_term, D=d_term)
        self.sail = 0
        self.maxsail = math.pi / 12 * 5

        self.Dv_constant = Dv_constant
        self.ideal_angle = ideal_angle

    def generate_command(self, velocity, position, target, true_wind,
                         keeping_state, desired_angle, tacking_angle,
                         force_turning_angle):
        app_wind = self.get_app_wind(true_wind, position[3], velocity)
        target_v = self.get_desire_v(velocity, position, target, true_wind,
                                     keeping_state, desired_angle)
        optimal_sail = self.get_optimal_sail(position[3], app_wind)
        final_sail = self.get_final_sail(target_v, optimal_sail, velocity[0],
                                         position[3], app_wind, tacking_angle)
        if force_turning_angle != None:
            final_sail = 1

        return final_sail, target_v

    def get_desire_v(self, velocity, position, target, true_wind,
                     keeping_state, desired_angle):
        distance_st = math.sqrt(
            pow(target[1] - position[1], 2) + pow(target[0] - position[0], 2))
        if keeping_state == 0:
            target_v = distance_st * self.Dv_constant
            if math.cos(true_wind[1] - position[3]) > 0.3:
                target_v = 0.2
        elif keeping_state == 1:
            target_v = 0.45
        elif keeping_state == 2:
            target_v = 0.1
        else:
            target_v = 0
        return target_v

    def get_optimal_sail(self, heading_angle, app_wind):
        # angle_diff=self.get_abs_angle_difference(heading_angle,app_wind[1]+math.pi)
        if math.cos(app_wind[1]) <= math.cos(3 * math.pi / 4):
            optimal_sail = 0.3 + (-3 * math.pi / 4 + abs(app_wind[1])) * 0.3
        else:
            optimal_sail = 0.3 + (3 / 4 * math.pi - abs(app_wind[1])) * 1.2
        if optimal_sail > self.maxsail:
            optimal_sail = self.maxsail
        return optimal_sail

    def get_app_wind(self, true_wind, heading_angle, velocity):
        ###this part is different from the paper since there might be something wrong in the paper
        ###get coordinates of true wind
        app_wind = [
            true_wind[0] * math.cos(true_wind[1] - heading_angle) -
            velocity[0],
            true_wind[0] * math.sin(true_wind[1] - heading_angle) - velocity[1]
        ]
        ###convert into polar system
        angle = math.atan2(app_wind[1], app_wind[0])
        app_wind = [
            math.sqrt(pow(app_wind[1], 2) + pow(app_wind[0], 2)), angle
        ]
        return app_wind

    def regular_angle(self, angle):

        while angle > math.pi:
            angle -= math.pi * 2
        while angle < -math.pi:
            angle += math.pi * 2
        return angle

    def get_abs_angle_difference(self, angle1, angle2):
        return math.acos(math.cos(angle1 - angle2))

    def get_final_sail(self, target_v, optimal_sail, v, heading_angle,
                       app_wind, tacking_angle):
        maxsail = min(self.maxsail, abs(app_wind[1]))
        offset = -self.pid_adjustment.update(v, target_v)
        if self.maxsail - optimal_sail > 0.2:
            final_sail = (maxsail + optimal_sail) / 2 + offset
            if final_sail > maxsail:
                final_sail = maxsail
            elif final_sail < optimal_sail:
                final_sail = optimal_sail

        else:
            final_sail = optimal_sail - 0.35 - offset

            if final_sail > optimal_sail:
                final_sail = optimal_sail
            elif final_sail < 0.4:
                final_sail = 0.4

        if tacking_angle != None:
            final_sail = self.maxsail
        return final_sail