def get_jib_winch_position(self, apparentWindAngleRad, X1, X2): """ Calculates the winch position of the jib according to the apparent wind angle. Arguments --------- float : apparentWindAngleRad The wind angle in radians float : X1 Parameter for jib saturation function float : X2 Parameter for jib saturation function Returns ------- int The winch position of the jib """ jibAngle = JibController.get_jib_angle(apparentWindAngleRad, X1, X2) smallChange = not ControllerOutputRefiner.lowPowerAngle( inputSignal=jibAngle, currAngle=self.__currJibAngleRad) if (self.__controlModeID == ControlModes.LOW_POWER.value) and (smallChange): winchPosition = JibController.get_winch_position( self.__currJibAngleRad, self.__winchQuantParam) else: self.__currJibAngleRad = jibAngle winchPosition = JibController.get_winch_position( jibAngle, self.__winchQuantParam) return winchPosition
def get_heading_error(self, current_heading, desired_heading, apparent_wind_angle): """ Calculates the heading error. The heading error varies depending on the current control mode of the boat. Arguments --------- float : current_heading The current direction of the boat in radians. float : desired_heading The desired direction of the boat in radians. float : apparent_wind_angle The apparent wind angle in radians. Returns ------- float Returns the heading error depending on the current control mode in radians. """ if (self.__controlModeID == ControlModes.JIBE_ONLY.value): jibe_direction = JibeOnlyRudderController.get_jibe_controller_direction( current_heading=current_heading, desired_heading=desired_heading, apparent_wind_angle=apparent_wind_angle) error = JibeOnlyRudderController.get_jibe_controller_error( current_heading=current_heading, desired_heading=desired_heading, jibe_direction=jibe_direction) return error # TACKABLE elif (self.__controlModeID == ControlModes.TACKABLE.value): error = TackController.get_heading_error_tackable( setPoint=desired_heading, measure=current_heading) return error # LOW POWER or UNKNOWN else: if (ControllerOutputRefiner.lowPowerAngle( inputSignal=desired_heading, currAngle=current_heading)): error = TackController.get_heading_error_tackable( setPoint=desired_heading, measure=current_heading) return error else: return 0
def test_lowPowerAngle_min_angle_difference4(self): self.assertTrue( ControllerOutputRefiner.lowPowerAngle( -2.0453 + 5.1 * math.pi / 180.0, -2.0453))
def test_lowPowerAngle_min_angle_difference2(self): self.assertFalse( ControllerOutputRefiner.lowPowerAngle(1.0 + 4.9 * math.pi / 180.0, 1.0))
def test_lowPowerAngle_min_angle_difference3(self): self.assertTrue( ControllerOutputRefiner.lowPowerAngle( -1.076, -1.076 + 5.0 * math.pi / 180.0))
def test_lowPowerAngle_min_angle_difference1(self): self.assertTrue( ControllerOutputRefiner.lowPowerAngle(1.0, 1.0 + 5.1 * math.pi / 180.0))
def test_lowPowerAngle_equal3(self): self.assertFalse(ControllerOutputRefiner.lowPowerAngle(-2.567, -2.567))
def test_lowPowerAngle_equal2(self): self.assertFalse(ControllerOutputRefiner.lowPowerAngle(0.0, 0.0))
def test_lowPowerAngle_dont_switch2(self): self.assertFalse( ControllerOutputRefiner.lowPowerAngle(-2.0756, -2.0851))
def test_lowPowerAngle_dont_switch1(self): self.assertFalse(ControllerOutputRefiner.lowPowerAngle(1.0054, 1.0))