123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- #include "SIM_Sailboat.h"
- #include <AP_Math/AP_Math.h>
- #include <AP_AHRS/AP_AHRS.h>
- #include <string.h>
- #include <stdio.h>
- extern const AP_HAL::HAL& hal;
- namespace SITL {
- #define STEERING_SERVO_CH 0
- #define MAINSAIL_SERVO_CH 3
- #define THROTTLE_SERVO_CH 2
-
- #define WAVE_ANGLE_GAIN 1
- #define WAVE_HEAVE_GAIN 1
- Sailboat::Sailboat(const char *frame_str) :
- Aircraft(frame_str),
- steering_angle_max(35),
- turning_circle(1.8)
- {
- motor_connected = (strcmp(frame_str, "sailboat-motor") == 0);
- }
- void Sailboat::calc_lift_and_drag(float wind_speed, float angle_of_attack_deg, float& lift, float& drag) const
- {
- const uint16_t index_width_deg = 10;
- const uint8_t index_max = ARRAY_SIZE(lift_curve) - 1;
-
- if (angle_of_attack_deg <= 0.0f) {
- lift = lift_curve[0];
- drag = drag_curve[0];
- } else if (angle_of_attack_deg >= index_max * index_width_deg) {
- lift = lift_curve[index_max];
- drag = drag_curve[index_max];
- } else {
- uint8_t index = constrain_int16(angle_of_attack_deg / index_width_deg, 0, index_max);
- float remainder = angle_of_attack_deg - (index * index_width_deg);
- lift = linear_interpolate(lift_curve[index], lift_curve[index+1], remainder, 0.0f, index_width_deg);
- drag = linear_interpolate(drag_curve[index], drag_curve[index+1], remainder, 0.0f, index_width_deg);
- }
-
- lift *= wind_speed;
- drag *= wind_speed;
- }
- float Sailboat::get_turn_circle(float steering) const
- {
- if (is_zero(steering)) {
- return 0;
- }
- return turning_circle * sinf(radians(steering_angle_max)) / sinf(radians(steering * steering_angle_max));
- }
- float Sailboat::get_yaw_rate(float steering, float speed) const
- {
- if (is_zero(steering) || is_zero(speed)) {
- return 0;
- }
- float d = get_turn_circle(steering);
- float c = M_PI * d;
- float t = c / speed;
- float rate = 360.0f / t;
- return rate;
- }
- float Sailboat::get_lat_accel(float steering, float speed) const
- {
- float yaw_rate = get_yaw_rate(steering, speed);
- float accel = radians(yaw_rate) * speed;
- return accel;
- }
- void Sailboat::update_wave(float delta_time)
- {
- const float wave_heading = sitl->wave.direction;
- const float wave_speed = sitl->wave.speed;
- const float wave_lenght = sitl->wave.length;
- const float wave_amp = sitl->wave.amp;
-
-
- float r, p, y;
- dcm.to_euler(&r, &p, &y);
-
- if (sitl->wave.enable == 0 || !hal.util->get_soft_armed() || is_zero(wave_amp) ) {
- wave_gyro = Vector3f(-r,-p,0.0f) * WAVE_ANGLE_GAIN;
- wave_heave = -velocity_ef.z * WAVE_HEAVE_GAIN;
- wave_phase = 0.0f;
- return;
- }
-
- const float boat_speed = velocity_ef.x * sinf(radians(wave_heading)) + velocity_ef.y * cosf(radians(wave_heading));
-
- const float aprarent_wave_distance = (wave_speed - boat_speed) * delta_time;
- const float apparent_wave_phase_change = (aprarent_wave_distance / wave_lenght) * M_2PI;
- wave_phase += apparent_wave_phase_change;
- wave_phase = wrap_2PI(wave_phase);
-
-
-
- const float wave_slope = (wave_amp * 0.5f) * (M_2PI / wave_lenght) * cosf(wave_phase);
- const float wave_angle = atanf(wave_slope);
-
- const float heading_dif = wave_heading - y;
- float angle_error_x = (sinf(heading_dif) * wave_angle) - r;
- float angle_error_y = (cosf(heading_dif) * wave_angle) - p;
-
- wave_gyro.x = angle_error_x * WAVE_ANGLE_GAIN;
- wave_gyro.y = angle_error_y * WAVE_ANGLE_GAIN;
- wave_gyro.z = 0.0f;
-
- if (sitl->wave.enable == 2) {
- wave_heave = (wave_slope - velocity_ef.z) * WAVE_HEAVE_GAIN;
- } else {
- wave_heave = 0.0f;
- }
- }
- void Sailboat::update(const struct sitl_input &input)
- {
-
- update_wind(input);
-
- float steering = 2*((input.servos[STEERING_SERVO_CH]-1000)/1000.0f - 0.5f);
-
- float mainsail_angle_bf = constrain_float((input.servos[MAINSAIL_SERVO_CH]-1000)/1000.0f * 90.0f, 0.0f, 90.0f);
-
-
-
- Vector3f wind_apparent_ef = wind_ef + velocity_ef;
- const float wind_apparent_dir_ef = degrees(atan2f(wind_apparent_ef.y, wind_apparent_ef.x));
- const float wind_apparent_speed = safe_sqrt(sq(wind_apparent_ef.x)+sq(wind_apparent_ef.y));
- const float wind_apparent_dir_bf = wrap_180(wind_apparent_dir_ef - degrees(AP::ahrs().yaw));
-
- rpm1 = wind_apparent_speed;
- airspeed_pitot = wind_apparent_speed;
-
- float aoa_deg = MAX(fabsf(wind_apparent_dir_bf) - mainsail_angle_bf, 0);
-
- float lift_wf, drag_wf;
- calc_lift_and_drag(wind_apparent_speed, aoa_deg, lift_wf, drag_wf);
-
- const float sin_rot_rad = sinf(radians(wind_apparent_dir_bf));
- const float cos_rot_rad = cosf(radians(wind_apparent_dir_bf));
- const float force_fwd = fabsf(lift_wf * sin_rot_rad) - (drag_wf * cos_rot_rad);
-
- float delta_time = frame_time_us * 1.0e-6f;
-
- Vector3f velocity_body = dcm.transposed() * velocity_ef_water;
-
- float speed = velocity_body.x;
-
- float yaw_rate = get_yaw_rate(steering, speed);
- gyro = Vector3f(0,0,radians(yaw_rate)) + wave_gyro;
-
- dcm.rotate(gyro * delta_time);
- dcm.normalize();
-
- float hull_drag = sq(speed) * 0.5f;
- if (!is_positive(speed)) {
- hull_drag *= -1.0f;
- }
-
-
- float throttle_force = 0.0f;
- if (motor_connected) {
- const uint16_t throttle_out = constrain_int16(input.servos[THROTTLE_SERVO_CH], 1000, 2000);
- throttle_force = (throttle_out-1500) * 0.1f;
- }
-
- accel_body = Vector3f((throttle_force + force_fwd) - hull_drag, 0, 0);
- accel_body /= mass;
-
- accel_body.y += radians(yaw_rate) * speed;
-
-
- float r, p, y;
- dcm.to_euler(&r, &p, &y);
- Matrix3f temp_dcm;
- temp_dcm.from_euler(0.0f, 0.0f, y);
- Vector3f accel_earth = temp_dcm * accel_body;
-
- accel_earth.z = 0 + wave_heave;
-
-
- accel_body = dcm.transposed() * (accel_earth + Vector3f(0, 0, -GRAVITY_MSS));
-
- Vector3f tide_velocity_ef;
- if (hal.util->get_soft_armed() && !is_zero(sitl->tide.speed) ) {
- tide_velocity_ef.x = -cosf(radians(sitl->tide.direction)) * sitl->tide.speed;
- tide_velocity_ef.y = -sinf(radians(sitl->tide.direction)) * sitl->tide.speed;
- tide_velocity_ef.z = 0.0f;
- }
-
- velocity_ef_water += accel_earth * delta_time;
- velocity_ef = velocity_ef_water + tide_velocity_ef;
-
- position += velocity_ef * delta_time;
-
- update_position();
- time_advance();
-
- update_mag_field_bf();
-
- update_wave(delta_time);
- }
- }
|