Migration to OpenModelica 1.25 and FMUs Generation

This commit is contained in:
2026-05-26 09:37:35 +02:00
parent fdf293ece6
commit fe90b840ed
370 changed files with 968105 additions and 743 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,180 @@
"""
simulate_aida_coupled_interactive.py
Interactive co-simulation of the AIDA Drone and Environment FMUs
Choose at runtime between RunFlightPlan FMU or CSV-based flight plan.
"""
from pyfmi import load_fmu
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
# -----------------------------
# 1. Ask the user
# -----------------------------
choice = input("Use CSV flight plan instead of RunFlightPlan FMU? (y/n): ").strip().lower()
USE_CSV = choice == 'y'
# -----------------------------
# 2. Paths
# -----------------------------
FMU_PATH = r".\FMUs_SimulationX"
fmu_drone = os.path.join(FMU_PATH, "AIDA_Drone_FMU.fmu")
fmu_env = os.path.join(FMU_PATH, "Environment.fmu")
fmu_plan = os.path.join(FMU_PATH, "RunFlightPlan.fmu")
flight_plan_csv = os.path.join(FMU_PATH, "RunFlightPlan.csv")
# -----------------------------
# 3. Load FMUs
# -----------------------------
print("Loading FMUs...")
drone = load_fmu(fmu_drone)
env = load_fmu(fmu_env)
print("Drone and Environment FMUs loaded.")
if USE_CSV:
print("Using CSV-based flight plan...")
# Load CSV
plan_df = pd.read_csv(flight_plan_csv)
# Optional: reset index after filtering
plan_df = plan_df.reset_index(drop=True)
# Extract time and consign values
time_points = plan_df['Time'].values
x_consign = plan_df['runFlightPlan1_Drone_Position_Consign_1'].values
y_consign = plan_df['runFlightPlan1_Drone_Position_Consign_2'].values
z_consign = plan_df['runFlightPlan1_Drone_Position_Consign_3'].values
else:
print("Using RunFlightPlan FMU...")
plan = load_fmu(fmu_plan)
time_points = np.arange(0.0, 250.0, 0.002)
# -----------------------------
# 4. Initialize FMUs
# -----------------------------
start_time = float(time_points[0])
stop_time = float(time_points[-1])
step_size = np.mean(np.diff(time_points))
drone.initialize(start_time, stop_time)
env.initialize(start_time, stop_time)
if not USE_CSV:
plan.initialize(time_points[0], time_points[-1])
pos_x, pos_y, pos_z = [], [], []
print("Starting co-simulation...")
# -----------------------------
# 5. Simulation loop
# -----------------------------
for i, t in enumerate(time_points):
# 1. Get position consigns
if USE_CSV:
pos_consign = [x_consign[i], y_consign[i], z_consign[i]]
else:
pos_consign = plan.get([
"runFlightPlan1.Drone_Position_Consign[1]",
"runFlightPlan1.Drone_Position_Consign[2]",
"runFlightPlan1.Drone_Position_Consign[3]",
])
# 2. Send consigns to drone
drone.set([
"controlPosition1.Drone_position_consign[1]",
"controlPosition1.Drone_position_consign[2]",
"controlPosition1.Drone_position_consign[3]"
], pos_consign)
# 3. Get feedback from environment
pos_feedback = env.get([
"generatePositioningSignal1.Positioning_signal[1]",
"generatePositioningSignal1.Positioning_signal[2]",
"generatePositioningSignal1.Positioning_signal[3]",
"generatePositioningSignal1.Positioning_signal[4]"
])
# 4. Send feedback to drone
drone.set([
"acquirePositioningSignal1.Positioning_signal[1]",
"acquirePositioningSignal1.Positioning_signal[2]",
"acquirePositioningSignal1.Positioning_signal[3]",
"acquirePositioningSignal1.Positioning_signal[4]"
], pos_feedback)
# 5. Step simulation
drone.do_step(current_t=t, step_size=step_size, new_step=True)
try:
pos_cmd = drone.get([
"controlPosition1.Position_command[1]",
"controlPosition1.Position_command[2]",
"controlPosition1.Position_command[3]"
])
except Exception as e:
if USE_CSV:
if i == 0:
print(f"Warning: could not read drone outputs at t={t:.2f}s (likely not initialized yet).")
# Use fallback zero values until valid output exists
pos_cmd = [0.0, 0.0, 0.0]
else:
raise # Re-raise the error if it's unexpected in FMU mode
env.set([
"trajectoryManagement1.Position_Command[1]",
"trajectoryManagement1.Position_Command[2]",
"trajectoryManagement1.Position_Command[3]"
], pos_cmd)
env.do_step(current_t=t, step_size=step_size, new_step=True)
if not USE_CSV:
plan.do_step(current_t=t, step_size=step_size, new_step=True)
# 6. Store results
pos_x.append(pos_cmd[0])
pos_y.append(pos_cmd[1])
pos_z.append(pos_cmd[2])
print("Simulation finished.")
# -----------------------------
# 6. Terminate FMUs
# -----------------------------
drone.terminate()
env.terminate()
if not USE_CSV:
plan.terminate()
# -----------------------------
# 7. Plot results
# -----------------------------
plt.figure(figsize=(12, 5))
# Time evolution
plt.subplot(1, 2, 1)
plt.plot(time_points, pos_x, label="X command")
plt.plot(time_points, pos_y, label="Y command")
plt.plot(time_points, pos_z, label="Z command")
plt.xlabel("Time (s)")
plt.ylabel("Position command")
plt.title("Position commands over time")
plt.legend()
plt.grid(True)
# 2D trajectory
plt.subplot(1, 2, 2)
plt.plot(pos_y, pos_z, linewidth=2, color='tab:blue')
plt.xlabel("X position command")
plt.ylabel("Y position command")
plt.title("Drone 2D Trajectory (Y vs X)")
plt.axis('equal')
plt.grid(True)
plt.tight_layout()
plt.show()

View File

@@ -0,0 +1,158 @@
"""
simulate_aida_coupled_interactive.py
Interactive co-simulation of the AIDA Drone and Environment FMUs
Choose at runtime between RunFlightPlan FMU or CSV-based flight plan.
"""
from pyfmi import load_fmu
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
# -----------------------------
# 2. Paths
# -----------------------------
FMU_PATH = r".\FMUs_OpenModelica_1.25"
fmu_drone = os.path.join(FMU_PATH, "QuadcopterModel.fmu")
fmu_wind = os.path.join(FMU_PATH, "WindProfile.fmu")
fmu_remote = os.path.join(FMU_PATH, "RemoteControl.fmu")
fmu_control_navigation = os.path.join(FMU_PATH, "ControlDroneNavigation.fmu")
fmu_LowLevelFlightControlSystem = os.path.join(FMU_PATH, "LowLevelFlightControlSystem.fmu")
# -----------------------------
# 3. Load FMUs
# -----------------------------
print("Loading FMUs...")
drone = load_fmu(fmu_drone)
wind = load_fmu(fmu_wind)
remote = load_fmu(fmu_remote)
control_navigation = load_fmu(fmu_control_navigation)
low_level_fcs = load_fmu(fmu_LowLevelFlightControlSystem)
print("All system FMUs loaded.")
FMUS = {
"drone": drone,
"wind": wind,
"remote": remote,
"control_navigation": control_navigation,
"low_level_fcs": low_level_fcs,
}
# -----------------------------
# 4. Initialize FMUs
# -----------------------------
start_time = float(0)
stop_time = float(250)
step_size = 0.1
drone.initialize(start_time, stop_time)
wind.initialize(start_time, stop_time)
remote.initialize(start_time, stop_time)
control_navigation.initialize(start_time, stop_time)
low_level_fcs.initialize(start_time, stop_time)
time_points = np.arange(start_time, stop_time + 0.5 * step_size, step_size)
def safe_get(fmu, names, default=None):
if isinstance(names, str):
names = [names]
try:
vals = fmu.get(names)
return vals
except Exception as e:
print(f"[WARN] get from {fmu.get_name()} failed for {names}: {e}")
if default is None:
return [0.0] * len(names)
return default
def safe_set(fmu, names, values):
if isinstance(names, str):
names = [names]
values = [values]
try:
fmu.set(names, values)
except Exception as e:
print(f"[WARN] set on {fmu.get_name()} failed for {names}: {e}")
# -----------------------------
# 5. Initial values (t = 0)
# -----------------------------
wind_Fx, wind_Fy = safe_get(wind, ["Fx", "Fy"], default=[0.0, 0.0])
# Quadcopter states
# Assuming exported as Position[1..3], Speed[1..3], Attitude[1..3], AngularVelocities[1..3]
quad_pos = safe_get(drone, ["Position[1]", "Position[2]", "Position[3]"], default=[0.0, 0.0, 0.0])
quad_speed = safe_get(drone, ["Speed[1]", "Speed[2]", "Speed[3]"], default=[0.0, 0.0, 0.0])
quad_att = safe_get(drone, ["Attitude[1]", "Attitude[2]", "Attitude[3]"], default=[0.0, 0.0, 0.0])
quad_ang = safe_get(drone, ["AngularVelocities[1]", "AngularVelocities[2]", "AngularVelocities[3]"],
default=[0.0, 0.0, 0.0])
# Remote control commands
rc_names = ["RollCommand", "PitchCommand", "VerticalSpeedCommand",
"YawCommand", "ControlMode", "IndicatorYawConsign"]
rc_vals = safe_get(remote, rc_names, default=[0.0] * len(rc_names))
(rc_roll, rc_pitch, rc_vspeed, rc_yaw, rc_mode, rc_ind_yaw) = rc_vals
# Navigation consigns
nav_pos_consign = safe_get(control_navigation,
["DronPositionConsign[1]", "DronPositionConsign[2]", "DronPositionConsign[3]"],
default=[0.0, 0.0, 0.0],
)
nav_yaw_consign = safe_get(control_navigation, ["YawConsign"], default=[0.0])[0]
nav_selected_mode = safe_get(control_navigation, ["SelectedControlMode"], default=[0.0])[0]
# -----------------------------
# 6. Logging buffers
# -----------------------------
times = []
pos_x = []
pos_y = []
pos_z = []
yaw_log = []
# -----------------------------
# 7. Simulation loop
# -----------------------------
print("Starting co-simulation...")
current_time = start_time
for i, t in enumerate(time_points):
# 7.1 Step RemoteControl
remote.do_step(current_t=current_time, step_size=step_size, new_step=True)
rc_vals = safe_get(remote, rc_names, default=rc_vals)
(rc_roll, rc_pitch, rc_vspeed, rc_yaw, rc_mode, rc_ind_yaw) = rc_vals
# 8.2 Feed RemoteControl -> ControlDroneNavigation
# connect(remoteControl1.ControlMode, controlDroneNavigation1.APEngagement)
# connect(remoteControl1.IndicatorYawConsign, controlDroneNavigation1.IndicatorYawConsign)
safe_set(control_navigation,
["APEngagement", "IndicatorYawConsign"],
[rc_mode, rc_ind_yaw])
# Quadcopter yaw feedback to navigation (connect(controlDroneNavigation1.Yaw, quadcopterModel1.Attitude[3]))
yaw_feedback = quad_att[2] # Attitude[3]
control_navigation.set("Yaw", yaw_feedback)
# 8.3 Step ControlDroneNavigation
control_navigation.do_step(current_t=current_time, step_size=step_size, new_step=True)
# -----------------------------
# 8. Terminate FMUs
# -----------------------------
drone.terminate()
control_navigation.terminate()
low_level_fcs.terminate()
remote.terminate()
wind.terminate()
# -----------------------------
# 9. Plot results
# -----------------------------

View File

@@ -0,0 +1,6 @@
# test_pyfmi.py
from pyfmi.examples import fmi_bouncing_ball_cs
print("Testing PyFMI installation...")
fmi_bouncing_ball_cs.run_demo()
print("✅ PyFMI and FMI Library work correctly!")

View File

@@ -1,91 +0,0 @@
model AIDA_System "AIDAModel-integrationProSivic_reference.isx"
AIDAModelica.QuadcopterModel quadcopterModel1(
rigidBodyKinematicModel1(
computeDronePosition1(
integrator10(initType = Modelica.Blocks.Types.Init.SteadyState, y_start = -0.29),
integrator11(initType = Modelica.Blocks.Types.Init.InitialOutput),
integrator12(initType = Modelica.Blocks.Types.Init.InitialOutput))),
rigidBodyDynamicModel1(
computeDroneVelocity1(
integrator4(initType = Modelica.Blocks.Types.Init.SteadyState)))) annotation(
Placement(visible = true, transformation(extent = {{29, -8}, {49, 17}}, rotation = 0)));
AIDAModelica.LowLevelFlightControlSystem lowLevelFlightControlSystem1(
controlAltitude1(computeAltitudeConsign1(
PID1(k = 30, Ti = 1, Td = 0.1, Nd = 10, initType=Modelica.Blocks.Types.InitPID.InitialOutput)),
pID_2(k = 25, Ti = 0.5, Td = 0.08, initType=Modelica.Blocks.Types.InitPID.InitialOutput)),
attitudeControl1(Test_CstMomentumActiv = false, Test_open_loop = {false, false, false},
controlRollAngle1(xAngularSpeedErrorModel1(Kwphi = 1.5),
PID(k = 0.07, Ti = 30, Td = 0.02, Nd = 0.1,initType=Modelica.Blocks.Types.InitPID.InitialOutput,
Add(k1 = 1, k2 = 1, k3 = 1))),
controlPitchAngle1(yAngularSpeedErrorModel1(Kwteta = 1.5, RTStepConsign = false),
PID1(k = 0.07, Ti = 30, Td = 0.02, Nd = 0.1,initType=Modelica.Blocks.Types.InitPID.InitialOutput,
Add(k1 = 1, k2 = 1, k3 = 1))),
controlYawAngle1(zAngularSpeedErrorModel1(Kwyaw = 2),
PID2(k = 0.04, Ti = 20, Td = 0.5, Nd = 2.5,initType=Modelica.Blocks.Types.InitPID.InitialOutput,
Add(k1 = 1, k2 = 1, k3 = 1)))),
positionControl1(
controlSpeed1(
PID(k = 0.8, Ti = 1,initType=Modelica.Blocks.Types.InitPID.InitialOutput),
PID2(k = 0.8, Ti = 1,initType=Modelica.Blocks.Types.InitPID.InitialOutput),
PID1(k = 30, Ti = 1, Td=0.1,initType=Modelica.Blocks.Types.InitPID.InitialOutput)))) annotation(
Placement(visible = true, transformation(extent = {{-37, -6}, {-12, 19}}, rotation = 0)));
AIDAModelica.ControlDroneNavigation controlDroneNavigation1 annotation(
Placement(visible = true, transformation(extent = {{-79, -3}, {-59, 17}}, rotation = 0)));
AIDAModelica.RemoteControl remoteControl1(
VS_cmd=-0.5,
VS_cmd_t={0.1,5},
Pitch_cmd=0.02,
Pitch_cmd_t={6,12},
Yaw_cmd_t={15,19},
Roll_cmd=0.02,
Roll_cmd_t={3,9},
Auto_Ctl_t=0.2) annotation(
Placement(visible = true, transformation(extent = {{-57, 49}, {-32, 69}}, rotation = 0)));
equation
connect(lowLevelFlightControlSystem1.AngularSpeed, quadcopterModel1.AngularVelocities) annotation(
Line(points = {{-33, -6}, {-33, -30}, {81.1667, -30}, {81.1667, 12}, {49.1667, 12}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.Attitude, quadcopterModel1.Attitude) annotation(
Line(points = {{-29, -6}, {-29, -26}, {69.3333, -26}, {69.3333, 8}, {49.3333, 8}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.Position, quadcopterModel1.Position) annotation(
Line(points = {{-24.5, -6}, {-24.5, -22}, {61.5, -22}, {61.5, 4}, {49.5, 4}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.Speed, quadcopterModel1.Speed) annotation(
Line(points = {{-21, -6}, {-17.6667, -6}, {-17.6667, -18}, {57.3333, -18}, {57.3333, 0}, {49.3333, 0}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.Accelerations, quadcopterModel1.Accelerations) annotation(
Line(points = {{-17, -6}, {-13.8333, -6}, {-13.8333, -16.0333}, {54.9167, -16.0333}, {54.9167, -4.0333}, {48.4167, -4.0333}}, color = {0, 0, 127}));
connect(quadcopterModel1.ThrottleCommand1, lowLevelFlightControlSystem1.ThrottleCommand1) annotation(
Line(points = {{29, 10.75}, {1, 10.75}, {1, 14}, {-12, 14}}, color = {0, 0, 127}, thickness = 0.015625));
connect(lowLevelFlightControlSystem1.ThrottleCommand2, quadcopterModel1.ThrottleCommand2) annotation(
Line(points = {{-12, 9}, {8.5, 9}, {8.5, 7}, {29, 7}}, color = {0, 0, 127}, thickness = 0.015625));
connect(quadcopterModel1.ThrottleCommand3, lowLevelFlightControlSystem1.ThrottleCommand3) annotation(
Line(points = {{29, 2.41667}, {12.5, 2.41667}, {12.5, 4}, {-12, 4}}, color = {0, 0, 127}, thickness = 0.015625));
connect(lowLevelFlightControlSystem1.ThrottleCommand4, quadcopterModel1.ThrottleCommand4) annotation(
Line(points = {{-12, -1}, {26, -1}, {26, -2}, {29, -2}}, color = {0, 0, 127}, thickness = 0.015625));
connect(quadcopterModel1.Speed[:], lowLevelFlightControlSystem1.Speed[:]) annotation(
Line);
connect(controlDroneNavigation1.YawConsign, lowLevelFlightControlSystem1.YawConsign) annotation(
Line(points = {{-59, 7}, {-34, 7}, {-34, 4}, {-37, 4}}, color = {0, 0, 127}, thickness = 0.0625));
connect(controlDroneNavigation1.DronPositionConsign[:], lowLevelFlightControlSystem1.DronePositionConsign[:]) annotation(
Line(points = {{-59, 12}, {-48, 12}, {-48, 14}, {-37, 14}}, color = {0, 0, 127}, thickness = 0.0625));
connect(lowLevelFlightControlSystem1.SelectedControlMode, controlDroneNavigation1.SelectedControlMode) annotation(
Line(points = {{-37, -1}, {-54, -1}, {-54, 2}, {-59, 2}}, color = {255, 0, 255}, thickness = 0.0625));
connect(lowLevelFlightControlSystem1.RCVerticalSpeedCommand, remoteControl1.VerticalSpeedCommand) annotation(
Line(points = {{-31, 19}, {-52.75, 19}, {-52.75, 49}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.RCYawCommand, remoteControl1.YawCommand) annotation(
Line(points = {{-22, 19}, {-36.4167, 19}, {-36.4167, 51}, {-35.4167, 51}, {-35.4167, 49}, {-36.4167, 49}}, color = {0, 0, 127}));
connect(remoteControl1.RollCommand, lowLevelFlightControlSystem1.RCAttitudeCommands[1]) annotation(
Line(points = {{-47, 49}, {-47, 22}, {-27, 22}, {-27, 19}}, color = {0, 0, 127}, thickness = 0.0625));
connect(remoteControl1.PitchCommand, lowLevelFlightControlSystem1.RCAttitudeCommands[2]) annotation(
Line(points = {{-42, 49}, {-42, 22}, {-27, 22}, {-27, 19}}, color = {0, 0, 127}, thickness = 0.0625));
connect(remoteControl1.IndicatorYawConsign, controlDroneNavigation1.IndicatorYawConsign) annotation(
Line(points = {{-57, 59}, {-94, 59}, {-94, 6}, {-80, 6}, {-80, 8}, {-78, 8}, {-78, 8}, {-78, 8}}, color = {255, 0, 255}));
connect(remoteControl1.ControlMode, controlDroneNavigation1.APEngagement) annotation(
Line(points = {{-57, 54}, {-84, 54}, {-84, 12}, {-79, 12}}, color = {255, 0, 255}, thickness = 0.015625));
connect(controlDroneNavigation1.Yaw, quadcopterModel1.Attitude[3]) annotation(
Line(points = {{-79, 2}, {-87, 2}, {-87, -36}, {91, -36}, {91, 8}, {49, 8}, {49, 8}, {49, 8}, {49, 8}}, color = {0, 0, 127}));
annotation(
Icon(coordinateSystem(grid = {3, 2})),
experiment(StartTime = 0, StopTime = 30, Tolerance = 1e-06, Interval = 0.002),
__OpenModelica_simulationFlags(jacobian = "coloredNumerical", s = "dassl", lv = "LOG_STATS"));
end AIDA_System;

View File

@@ -1,215 +0,0 @@
within AIDAModelica;
// CP: 65001
// SimulationX Version: 3.8.2.45319 x64
model RemoteControl "RemoteControl"
Real VerticalSpeedCommand_i(start=0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput VerticalSpeedCommand(
quantity="Mechanics.Translation.Velocity",
displayUnit="m/s") "'output Real' as connector" annotation(Placement(
transformation(extent={{12,28},{32,48}}),
iconTransformation(
origin={-75,-100},
extent={{-10,-10},{10,10}},
rotation=-90)));
Real RollCommand_i(start=0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput RollCommand(
quantity="Mechanics.Rotation.Angle",
displayUnit="rad") "'output Real' as connector" annotation(Placement(
transformation(extent={{56,8},{76,28}}),
iconTransformation(
origin={-25,-100},
extent={{-10,-10},{10,10}},
rotation=-90)));
Real PitchCommand_i(start=0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput PitchCommand(
quantity="Mechanics.Rotation.Angle",
displayUnit="rad") "'output Real' as connector" annotation(Placement(
transformation(extent={{-38,-46},{-18,-26}}),
iconTransformation(
origin={25,-100},
extent={{-10,-10},{10,10}},
rotation=-90)));
Real YawCommand_i(start=0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput YawCommand(
quantity="Mechanics.Rotation.Angle",
displayUnit="rad") "'output Real' as connector" annotation(Placement(
transformation(extent={{18,-52},{38,-32}}),
iconTransformation(
origin={75,-100},
extent={{-10,-10},{10,10}},
rotation=-90)));
Modelica.Blocks.Interfaces.BooleanOutput ControlMode "'output Boolean' as connector" annotation(Placement(
transformation(extent={{-10,-10},{10,10}}),
iconTransformation(
origin={-125,-50},
extent={{-10,-10},{10,10}},
rotation=180)));
Modelica.Blocks.Interfaces.BooleanOutput IndicatorYawConsign "'output Boolean' as connector" annotation(Placement(
transformation(
origin={-45,45},
extent={{-17,-17},{17,17}}),
iconTransformation(
origin={-125,0},
extent={{-10,-10},{10,10}},
rotation=-180)));
parameter Real VS_cmd=0.5;
parameter Real[2] VS_cmd_t={3, 5} "Instants de démarrage et fin du step";
parameter Real Pitch_cmd=0.03;
parameter Real[2] Pitch_cmd_t={1, 4} "Instants de démarrage et fin du step, après stabilisation verticale";
parameter Real Yaw_cmd=0.5;
parameter Real[2] Yaw_cmd_t={6, 8} "Instants de démarrage et fin du step";
parameter Real Roll_cmd=0.2 "Amplitude step ";
parameter Real Roll_cmd_t[2]={1, 100} "Instants de démarrage et fin du step";
parameter Real Tcst=0.1 "constante de temps pour filter les sorties du remote ctl";
Boolean Auto_Ctl_Enabled(start=true);
parameter Real Auto_Ctl_t=0.1 "Instant de déclenchement du mode auto";
initial equation
PitchCommand = 0;
RollCommand = 0;
YawCommand = 0;
VerticalSpeedCommand = 0;
PitchCommand_i = 0;
RollCommand_i = 0;
YawCommand_i = 0;
VerticalSpeedCommand_i = 0;
ControlMode = false;
IndicatorYawConsign = false;
Auto_Ctl_Enabled=true;
algorithm
when time > Auto_Ctl_t and Auto_Ctl_Enabled==true then
ControlMode:=true;
end when;
when time > VS_cmd_t[1] then
VerticalSpeedCommand_i := VS_cmd;
ControlMode:=false;
Auto_Ctl_Enabled:=false;
end when;
when time > VS_cmd_t[2] then
VerticalSpeedCommand_i := 0;
end when;
when time > VS_cmd_t[2]+ Pitch_cmd_t[1] then
PitchCommand_i := Pitch_cmd;
ControlMode:=false;
end when;
when time > VS_cmd_t[2]+ Pitch_cmd_t[2] then
PitchCommand_i := 0;
end when;
when time > VS_cmd_t[2]+ Roll_cmd_t[1] then
RollCommand_i := Roll_cmd;
ControlMode:=false;
end when;
when time > VS_cmd_t[2]+ Roll_cmd_t[2] then
RollCommand_i := 0;
end when;
//Yaw command
when time > VS_cmd_t[2]+ Yaw_cmd_t[1] then
YawCommand_i := Yaw_cmd;
ControlMode:=false;
IndicatorYawConsign:=true;
end when;
//IndicatorYawConsign := true;
when time > VS_cmd_t[2]+ Yaw_cmd_t[2] then
YawCommand_i := 0;
end when;
//IndicatorYawConsign := false;
/*if time>Yaw_cmd_t[2] then
int_yaw := 0;
IndicatorYawConsign := false;
elseif time>Yaw_cmd_t[1] then
int_yaw := DYaw_cmd;
IndicatorYawConsign := true;
else
int_yaw := 0;
IndicatorYawConsign := false;
end if;*/
equation
// remote control filter with Tcst time constant
der(VerticalSpeedCommand) = (VerticalSpeedCommand_i - VerticalSpeedCommand) / Tcst;
der(RollCommand) = (RollCommand_i - RollCommand) / Tcst;
der(PitchCommand) = (PitchCommand_i - PitchCommand) / Tcst;
der(YawCommand) = (YawCommand_i - YawCommand) / Tcst;
/* initial code of Andrii VAKULKO, destined to be used with manual button included in the SimulationX interface
if VSCommand1 > 0 then
VerticalSpeedCommand = -1;
elseif VSCommand2 > 0 then
VerticalSpeedCommand = -0.8;
elseif VSCommand3 > 0 then
VerticalSpeedCommand = -0.6;
elseif VSCommand4 > 0 then
VerticalSpeedCommand = -0.4;
elseif VSCommand5 > 0 then
VerticalSpeedCommand = -0.2;
elseif VSCommand6 > 0 then
VerticalSpeedCommand = 0.2;
elseif VSCommand7 > 0 then
VerticalSpeedCommand = 0.4;
elseif VSCommand8 > 0 then
VerticalSpeedCommand = 0.6;
elseif VSCommand9 > 0 then
VerticalSpeedCommand = 0.8;
elseif VSCommand10 > 0 then
VerticalSpeedCommand = 1;
else
VerticalSpeedCommand = 0;
end if;
if YCommandP > 0 then
der(YawCommand) = 0.01;
//IndicatorYawConsign = true;
elseif YCommandM > 0 then
der(YawCommand) = -0.01;
//IndicatorYawConsign = true;
else
YawCommand = 0;
//IndicatorYawConsign = false;
end if;
if RCommandP > 0 then
RollCommand = 0.0261799; //15 deg
elseif RCommandM > 0 then
RollCommand = -0.0261799;
else
RollCommand = 0;
end if;
if PCommandP > 0 then
PitchCommand = 0.0261799;
elseif PCommandM > 0 then
PitchCommand = -0.0261799;
else
PitchCommand = 0;
end if;*/
annotation(
VerticalSpeedCommand(flags=2),
RollCommand(flags=2),
PitchCommand(flags=2),
YawCommand(flags=2),
ControlMode(flags=2),
IndicatorYawConsign(flags=2),
Icon(
coordinateSystem(extent={{-125,-100},{125,100}}),
graphics={
Rectangle(
fillColor={255,255,255},
fillPattern=FillPattern.Solid,
extent={{-123.3,100},{123.3,-100}}),
Text(
textString="%name",
fillPattern=FillPattern.None,
extent={{-86,20},{86,-20}},
origin={-2,6})}),
experiment(
StopTime=10,
StartTime=0,
Interval=0.02,
MaxInterval="0.001"));
end RemoteControl;

View File

@@ -0,0 +1,78 @@
model AIDA_System "AIDAModel-integrationProSivic_reference.isx"
AIDAModelica.QuadcopterModel quadcopterModel1(rigidBodyKinematicModel1(computeDronePosition1(integrator10(initType = Modelica.Blocks.Types.Init.SteadyState, y_start = -0.29), integrator11(initType = Modelica.Blocks.Types.Init.InitialOutput, y_start = 39), integrator12(initType = Modelica.Blocks.Types.Init.InitialOutput))), rigidBodyDynamicModel1(computeDroneVelocity1(integrator4(initType = Modelica.Blocks.Types.Init.SteadyState)))) annotation(
Placement(visible = true, transformation(origin = {16.4, 7.25}, extent = {{-10.6, -13.25}, {10.6, 13.25}}, rotation = 0)));
AIDAModelica.LowLevelFlightControlSystem lowLevelFlightControlSystem1(controlAltitude1(computeAltitudeConsign1(PID1(k = 30, Ti = 1, Td = 0.1, Nd = 10, initType = Modelica.Blocks.Types.InitPID.InitialOutput)), pID_2(k = 25, Ti = 0.5, Td = 0.08, initType = Modelica.Blocks.Types.InitPID.InitialOutput)), attitudeControl1(Test_CstMomentumActiv = false, Test_open_loop = {false, false, false}, controlRollAngle1(xAngularSpeedErrorModel1(Kwphi = 1.5), PID(k = 0.07, Ti = 30, Td = 0.02, Nd = 0.1, initType = Modelica.Blocks.Types.InitPID.InitialOutput, Add(k1 = 1, k2 = 1, k3 = 1))), controlPitchAngle1(yAngularSpeedErrorModel1(Kwteta = 1.5, RTStepConsign = false), PID1(k = 0.07, Ti = 30, Td = 0.02, Nd = 0.1, initType = Modelica.Blocks.Types.InitPID.InitialOutput, Add(k1 = 1, k2 = 1, k3 = 1))), controlYawAngle1(zAngularSpeedErrorModel1(Kwyaw = 2), PID2(k = 0.04, Ti = 20, Td = 0.5, Nd = 2.5, initType = Modelica.Blocks.Types.InitPID.InitialOutput, Add(k1 = 1, k2 = 1, k3 = 1)))), positionControl1(controlSpeed1(PID(k = 0.8, Ti = 1, initType = Modelica.Blocks.Types.InitPID.InitialOutput), PID2(k = 0.8, Ti = 1, initType = Modelica.Blocks.Types.InitPID.InitialOutput), PID1(k = 30, Ti = 1, Td = 0.1, initType = Modelica.Blocks.Types.InitPID.InitialOutput)))) annotation(
Placement(visible = true, transformation(origin = {-2.96, 1.52}, extent = {{-34.04, -5.52}, {-11.04, 17.48}}, rotation = 0)));
AIDAModelica.ControlDroneNavigation controlDroneNavigation1 annotation(
Placement(visible = true, transformation(origin = {15.9, 0.3}, extent = {{-86.9, -3.3}, {-64.9, 18.7}}, rotation = 0)));
AIDAModelica.RemoteControl remoteControl1(VS_cmd = -0.5, Pitch_cmd = 0.02, VS_cmd_t = {1000, 1001}, Roll_cmd_t = {1000, 1001}, Pitch_cmd_t = {1000, 1001}, Yaw_cmd_t = {1000, 1001}, Auto_Ctl_t = 0.1) annotation(
Placement(visible = true, transformation(extent = {{-37, 29}, {-12, 49}}, rotation = 0)));
AIDAModelica.WindProfile windProfile1 annotation(
Placement(visible = true, transformation(origin = {16, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Requirements.StabilityRequirement stabilityRequirement1 annotation(
Placement(visible = true, transformation(origin = {-44, -32}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
connect(windProfile1.Fy, quadcopterModel1.Fy) annotation(
Line(points = {{21, 29}, {22, 29}, {22, 22}}, color = {0, 0, 127}));
connect(windProfile1.Fx, quadcopterModel1.Fx) annotation(
Line(points = {{11, 29}, {11, 26.5}, {12, 26.5}, {12, 22}}, color = {0, 0, 127}));
connect(remoteControl1.RollCommand, lowLevelFlightControlSystem1.RCAttitudeCommands[1]) annotation(
Line(points = {{-27, 29}, {-27, 19}}, color = {0, 0, 127}, thickness = 0.0625));
connect(remoteControl1.PitchCommand, lowLevelFlightControlSystem1.RCAttitudeCommands[2]) annotation(
Line(points = {{-22, 29}, {-22, 22}, {-27, 22}, {-27, 19}}, color = {0, 0, 127}, thickness = 0.0625));
connect(lowLevelFlightControlSystem1.RCVerticalSpeedCommand, remoteControl1.VerticalSpeedCommand) annotation(
Line(points = {{-31, 19}, {-31.75, 19}, {-31.75, 29}, {-32, 29}}, color = {0, 0, 127}));
connect(remoteControl1.YawCommand, lowLevelFlightControlSystem1.RCYawCommand) annotation(
Line(points = {{-17, 29}, {-18, 29}, {-18, 20}, {-24, 20}, {-24, 18}}, color = {0, 0, 127}));
connect(remoteControl1.ControlMode, controlDroneNavigation1.APEngagement) annotation(
Line(points = {{-37, 34}, {-76, 34}, {-76, 14}, {-71, 14}}, color = {255, 0, 255}, thickness = 0.015625));
connect(remoteControl1.IndicatorYawConsign, controlDroneNavigation1.IndicatorYawConsign) annotation(
Line(points = {{-37, 39}, {-78, 39}, {-78, 8}, {-71, 8}}, color = {255, 0, 255}));
connect(quadcopterModel1.Attitude[3], stabilityRequirement1.yaw) annotation(
Line(points = {{28, 12}, {44, 12}, {44, -31}, {-34, -31}}, color = {0, 0, 127}));
connect(controlDroneNavigation1.YawConsign, stabilityRequirement1.yawConsign) annotation(
Line(points = {{-50, 8}, {-48, 8}, {-48, -22}}, color = {0, 0, 127}));
connect(quadcopterModel1.Position[1], stabilityRequirement1.posX) annotation(
Line(points = {{28, 8}, {48, 8}, {48, -26}, {-34, -26}}, color = {0, 0, 127}));
connect(quadcopterModel1.Position[2], stabilityRequirement1.posY) annotation(
Line(points = {{28, 8}, {48, 8}, {48, -38}, {-34, -38}}, color = {0, 0, 127}));
connect(controlDroneNavigation1.DronPositionConsign[1], stabilityRequirement1.DronePositionConsign[1]) annotation(
Line(points = {{-50, 14}, {-44, 14}, {-44, -22}}, color = {0, 0, 127}));
connect(controlDroneNavigation1.DronPositionConsign[2], stabilityRequirement1.DronePositionConsign[2]) annotation(
Line(points = {{-50, 14}, {-44, 14}, {-44, -22}}, color = {0, 0, 127}));
connect(controlDroneNavigation1.DronPositionConsign[3], stabilityRequirement1.DronePositionConsign[3]) annotation(
Line(points = {{-50, 14}, {-44, 14}, {-44, -22}}, color = {0, 0, 127}));
connect(controlDroneNavigation1.Yaw, quadcopterModel1.Attitude[3]) annotation(
Line(points = {{-71, 3}, {-75, 3}, {-75, -18}, {39, -18}, {39, 12}, {28, 12}}, color = {0, 0, 127}));
connect(quadcopterModel1.Speed[:], lowLevelFlightControlSystem1.Speed[:]) annotation(
Line);
connect(lowLevelFlightControlSystem1.ThrottleCommand1, quadcopterModel1.ThrottleCommand1) annotation(
Line(points = {{-14, 14}, {6, 14}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.ThrottleCommand2, quadcopterModel1.ThrottleCommand2) annotation(
Line(points = {{-14, 10}, {-5.5, 10}, {-5.5, 9}, {6, 9}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.ThrottleCommand3, quadcopterModel1.ThrottleCommand3) annotation(
Line(points = {{-14, 6}, {-5, 6}, {-5, 5}, {6, 5}}, color = {0, 0, 127}));
connect(lowLevelFlightControlSystem1.ThrottleCommand4, quadcopterModel1.ThrottleCommand4) annotation(
Line(points = {{-14, 0}, {-3.5, 0}, {-3.5, 1}, {6, 1}}, color = {0, 0, 127}));
connect(quadcopterModel1.Accelerations, lowLevelFlightControlSystem1.Accelerations) annotation(
Line(points = {{28, -1}, {30, -1}, {30, -8}, {-18, -8}, {-18, -4}}, color = {0, 0, 127}));
connect(quadcopterModel1.Speed, lowLevelFlightControlSystem1.Speed) annotation(
Line(points = {{28, 3}, {32, 3}, {32, -10}, {-22, -10}, {-22, -4}}, color = {0, 0, 127}));
connect(quadcopterModel1.Position, lowLevelFlightControlSystem1.Position) annotation(
Line(points = {{28, 7}, {34, 7}, {34, -12}, {-26, -12}, {-26, -4}}, color = {0, 0, 127}));
connect(quadcopterModel1.Attitude, lowLevelFlightControlSystem1.Attitude) annotation(
Line(points = {{28, 12}, {36, 12}, {36, -14}, {-29, -14}, {-29, -4}}, color = {0, 0, 127}));
connect(quadcopterModel1.AngularVelocities, lowLevelFlightControlSystem1.AngularSpeed) annotation(
Line(points = {{28, 16}, {42, 16}, {42, -16}, {-33, -16}, {-33, -4}}, color = {0, 0, 127}));
connect(controlDroneNavigation1.YawConsign, lowLevelFlightControlSystem1.YawConsign) annotation(
Line(points = {{-49, 8}, {-45, 8}, {-45, 5}, {-37, 5}}, color = {0, 0, 127}, thickness = 0.0625));
connect(controlDroneNavigation1.DronPositionConsign[:], lowLevelFlightControlSystem1.DronePositionConsign[:]) annotation(
Line(points = {{-49, 14}, {-37, 14}}, color = {0, 0, 127}, thickness = 0.0625));
connect(lowLevelFlightControlSystem1.SelectedControlMode, controlDroneNavigation1.SelectedControlMode) annotation(
Line(points = {{-37, 1}, {-43, 1}, {-43, 3}, {-49, 3}}, color = {255, 0, 255}, thickness = 0.0625));
annotation(
Icon(coordinateSystem(grid = {3, 2})),
experiment(StartTime = 0, StopTime = 30, Tolerance = 1e-06, Interval = 0.002),
__OpenModelica_simulationFlags(jacobian = "coloredNumerical", s = "dassl", lv = "LOG_STATS"),
uses(Modelica(version = "3.2.2")));
end AIDA_System;

View File

@@ -12,6 +12,7 @@ model ControlMotor "[SF1.1/2/3/4.1] Control motor"
equation
// enter your equations here
ComdKD = (DAngVel - wb) / cR;
annotation(
Icon(graphics = {Rectangle(fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, 100}, {103.3, -100}}), Text(origin = {-7, 44}, extent = {{-39, 12}, {39, -12}}, textString = "%name")}, coordinateSystem(initialScale = 0.1)));
end ControlMotor;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
within AIDAModelica;
model RemoteControl "RemoteControl"
// CP: 65001
// SimulationX Version: 3.8.2.45319 x64
Real VerticalSpeedCommand_i(start = 0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput VerticalSpeedCommand(quantity = "Mechanics.Translation.Velocity", displayUnit = "m/s") "'output Real' as connector" annotation(
Placement(transformation(extent = {{12, 28}, {32, 48}}), iconTransformation(origin = {-75, -100}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Real RollCommand_i(start = 0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput RollCommand(quantity = "Mechanics.Rotation.Angle", displayUnit = "rad") "'output Real' as connector" annotation(
Placement(transformation(extent = {{56, 8}, {76, 28}}), iconTransformation(origin = {-25, -100}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Real PitchCommand_i(start = 0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput PitchCommand(quantity = "Mechanics.Rotation.Angle", displayUnit = "rad") "'output Real' as connector" annotation(
Placement(transformation(extent = {{-38, -46}, {-18, -26}}), iconTransformation(origin = {25, -100}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Real YawCommand_i(start = 0) "commande interne non filtree";
Modelica.Blocks.Interfaces.RealOutput YawCommand(quantity = "Mechanics.Rotation.Angle", displayUnit = "rad") "'output Real' as connector" annotation(
Placement(transformation(extent = {{18, -52}, {38, -32}}), iconTransformation(origin = {75, -100}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Modelica.Blocks.Interfaces.BooleanOutput ControlMode "'output Boolean' as connector" annotation(
Placement(transformation(extent = {{-10, -10}, {10, 10}}), iconTransformation(origin = {-125, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 180)));
Modelica.Blocks.Interfaces.BooleanOutput IndicatorYawConsign "'output Boolean' as connector" annotation(
Placement(transformation(origin = {-45, 45}, extent = {{-17, -17}, {17, 17}}), iconTransformation(origin = {-125, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -180)));
parameter Real VS_cmd = 0.5;
parameter Real[2] VS_cmd_t = {3, 5} "Instants de démarrage et fin du step";
parameter Real Pitch_cmd = 0.03;
parameter Real[2] Pitch_cmd_t = {1, 4} "Instants de démarrage et fin du step, après stabilisation verticale";
parameter Real Yaw_cmd = 0.5;
parameter Real[2] Yaw_cmd_t = {6, 8} "Instants de démarrage et fin du step";
parameter Real Roll_cmd = 0.2 "Amplitude step ";
parameter Real Roll_cmd_t[2] = {1, 100} "Instants de démarrage et fin du step";
parameter Real Tcst = 0.1 "constante de temps pour filter les sorties du remote ctl";
Boolean Auto_Ctl_Enabled(start = true);
parameter Real Auto_Ctl_t = 0.1 "Instant de déclenchement du mode auto";
initial equation
PitchCommand = 0;
RollCommand = 0;
YawCommand = 0;
VerticalSpeedCommand = 0;
PitchCommand_i = 0;
RollCommand_i = 0;
YawCommand_i = 0;
VerticalSpeedCommand_i = 0;
ControlMode = false;
IndicatorYawConsign = false;
Auto_Ctl_Enabled = true;
algorithm
when time > Auto_Ctl_t and Auto_Ctl_Enabled == true then
ControlMode := true;
end when;
when time > VS_cmd_t[1] then
VerticalSpeedCommand_i := VS_cmd;
ControlMode := false;
Auto_Ctl_Enabled := false;
end when;
when time > VS_cmd_t[2] then
VerticalSpeedCommand_i := 0;
end when;
when time > VS_cmd_t[2] + Pitch_cmd_t[1] then
PitchCommand_i := Pitch_cmd;
ControlMode := false;
end when;
when time > VS_cmd_t[2] + Pitch_cmd_t[2] then
PitchCommand_i := 0;
end when;
when time > VS_cmd_t[2] + Roll_cmd_t[1] then
RollCommand_i := Roll_cmd;
ControlMode := false;
end when;
when time > VS_cmd_t[2] + Roll_cmd_t[2] then
RollCommand_i := 0;
end when;
//Yaw command
when time > VS_cmd_t[2] + Yaw_cmd_t[1] then
YawCommand_i := Yaw_cmd;
ControlMode := false;
IndicatorYawConsign := true;
end when;
//IndicatorYawConsign := true;
when time > VS_cmd_t[2] + Yaw_cmd_t[2] then
YawCommand_i := 0;
end when;
//IndicatorYawConsign := false;
/*if time>Yaw_cmd_t[2] then
int_yaw := 0;
IndicatorYawConsign := false;
elseif time>Yaw_cmd_t[1] then
int_yaw := DYaw_cmd;
IndicatorYawConsign := true;
else
int_yaw := 0;
IndicatorYawConsign := false;
end if;*/
equation
// remote control filter with Tcst time constant
der(VerticalSpeedCommand) = (VerticalSpeedCommand_i - VerticalSpeedCommand) / Tcst;
der(RollCommand) = (RollCommand_i - RollCommand) / Tcst;
der(PitchCommand) = (PitchCommand_i - PitchCommand) / Tcst;
der(YawCommand) = (YawCommand_i - YawCommand) / Tcst;
/* initial code of Andrii VAKULKO, destined to be used with manual button included in the SimulationX interface
if VSCommand1 > 0 then
VerticalSpeedCommand = -1;
elseif VSCommand2 > 0 then
VerticalSpeedCommand = -0.8;
elseif VSCommand3 > 0 then
VerticalSpeedCommand = -0.6;
elseif VSCommand4 > 0 then
VerticalSpeedCommand = -0.4;
elseif VSCommand5 > 0 then
VerticalSpeedCommand = -0.2;
elseif VSCommand6 > 0 then
VerticalSpeedCommand = 0.2;
elseif VSCommand7 > 0 then
VerticalSpeedCommand = 0.4;
elseif VSCommand8 > 0 then
VerticalSpeedCommand = 0.6;
elseif VSCommand9 > 0 then
VerticalSpeedCommand = 0.8;
elseif VSCommand10 > 0 then
VerticalSpeedCommand = 1;
else
VerticalSpeedCommand = 0;
end if;
if YCommandP > 0 then
der(YawCommand) = 0.01;
//IndicatorYawConsign = true;
elseif YCommandM > 0 then
der(YawCommand) = -0.01;
//IndicatorYawConsign = true;
else
YawCommand = 0;
//IndicatorYawConsign = false;
end if;
if RCommandP > 0 then
RollCommand = 0.0261799; //15 deg
elseif RCommandM > 0 then
RollCommand = -0.0261799;
else
RollCommand = 0;
end if;
if PCommandP > 0 then
PitchCommand = 0.0261799;
elseif PCommandM > 0 then
PitchCommand = -0.0261799;
else
PitchCommand = 0;
end if;*/
annotation(
VerticalSpeedCommand(flags = 2),
RollCommand(flags = 2),
PitchCommand(flags = 2),
YawCommand(flags = 2),
ControlMode(flags = 2),
IndicatorYawConsign(flags = 2),
Icon(coordinateSystem(extent = {{-125, -100}, {125, 100}}, initialScale = 0.1), graphics = {Rectangle(fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-123.3, 100}, {123.3, -100}}), Text(origin = {-12, 10}, extent = {{-78, 18}, {86, -20}}, textString = "RemoteControl")}),
experiment(StopTime = 10, StartTime = 0, Interval = 0.02, MaxInterval = "0.001"));
end RemoteControl;

View File

@@ -0,0 +1,19 @@
within AIDAModelica;
model WindProfile
Modelica.Blocks.Sources.Constant const(k = 0) annotation(
Placement(visible = true, transformation(origin = {-54, -30}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Modelica.Blocks.Sources.Constant const1(k = 0) annotation(
Placement(visible = true, transformation(origin = {50, -30}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Modelica.Blocks.Interfaces.RealOutput Fx annotation(
Placement(visible = true, transformation(origin = {-50, -110}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-50, -110}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Modelica.Blocks.Interfaces.RealOutput Fy annotation(
Placement(visible = true, transformation(origin = {50, -110}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {50, -110}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
equation
connect(const.y, Fx) annotation(
Line(points = {{-54, -41}, {-54, -75.5}, {-50, -75.5}, {-50, -110}}, color = {0, 0, 127}));
connect(const1.y, Fy) annotation(
Line(points = {{50, -41}, {50, -110}}, color = {0, 0, 127}));
annotation(
Icon(graphics = {Rectangle(extent = {{-100, 100}, {100, -100}}), Text(origin = {-23, 18}, extent = {{57, -26}, {-11, 4}}, textString = "WindProfile")}));end WindProfile;

File diff suppressed because it is too large Load Diff

View File

@@ -68,3 +68,4 @@ YAngularSpeedErrorModel
YawConsignProducing
ZAngularSpeedErrorModel
ModelicaLicense2
WindProfile

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 286 KiB

View File

@@ -0,0 +1,102 @@
within Requirements;
model StabilityRequirement
"SR-WIND-02: The UAS shall maintain lateral and yaw stability under wind disturbance and recover within limits"
// ---- System-level parameters (traceable to SR-WIND-02) ----
parameter Real hoverTolerance = 2.5
"Maximum allowed lateral deviation during hover [m]";
parameter Real yawTolerance = 5
"Maximum allowed yaw error [deg]";
parameter Real recoveryBand = 0.5
"Position error band for recovery after disturbance [m]";
parameter Real recoveryTime = 3
"Time to remain within recovery band [s]";
// ---- Inputs from the system ----
Modelica.Blocks.Interfaces.RealInput posX
"Measured X position [m]" annotation(
Placement(transformation(extent={{120,40},{80,80}})));
Modelica.Blocks.Interfaces.RealInput posY
"Measured Y position [m]" annotation(
Placement(transformation(extent={{120,-80},{80,-40}})));
Modelica.Blocks.Interfaces.RealInput yaw
"Measured yaw angle [deg]" annotation(
Placement(transformation(extent={{120,-10},{80,30}})));
Modelica.Blocks.Interfaces.RealInput DronePositionConsign[3]
"Commanded reference position [m]" annotation(
Placement(transformation(extent={{-20,120},{20,80}}, rotation=-90)));
Modelica.Blocks.Interfaces.RealInput yawConsign
"Commanded yaw angle [deg]" annotation(
Placement(transformation(extent={{-60,120},{-20,80}}, rotation=-90)));
// ---- Outputs for monitoring ----
Modelica.Blocks.Interfaces.RealOutput lateralError
"2D lateral position error magnitude [m]" annotation(
Placement(transformation(extent={{-90,50},{-110,70}})));
Modelica.Blocks.Interfaces.RealOutput yawError
"Yaw error magnitude [deg]" annotation(
Placement(transformation(extent={{-90,20},{-110,40}})));
Modelica.Blocks.Interfaces.BooleanOutput withinHoverLimit
"true if lateralError < hoverTolerance" annotation(
Placement(visible = true, transformation(extent = {{-110, -10}, {-90, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Blocks.Interfaces.BooleanOutput withinYawLimit
"true if yawError < yawTolerance" annotation(
Placement(visible = true, transformation(extent = {{-110, -40}, {-90, -20}}, rotation = 0), iconTransformation(origin = {-100, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Blocks.Interfaces.BooleanOutput recovered
"true if position remains within recoveryBand for recoveryTime" annotation(
Placement(visible = true, transformation(extent = {{-110, -70}, {-90, -50}}, rotation = 0), iconTransformation(origin = {-100, -60}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Blocks.Interfaces.BooleanOutput pass
"true if all criteria are satisfied" annotation(
Placement(visible = true, transformation(extent = {{-110, -100}, {-90, -80}}, rotation = 0), iconTransformation(origin = {-100, -90}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
protected
Real t_within(start=0) "Timer for recovery criterion";
equation
// --- Lateral and yaw errors ---
lateralError = sqrt((posX - DronePositionConsign[1])^2 +
(posY - DronePositionConsign[2])^2);
yawError = abs(yaw - yawConsign);
withinHoverLimit = lateralError < hoverTolerance;
withinYawLimit = yawError < yawTolerance;
// --- Recovery logic (after gust disturbance) ---
der(t_within) = if lateralError < recoveryBand then 1 else 0;
// Reset timer whenever the drone leaves the recovery band
when lateralError > recoveryBand then
reinit(t_within, 0);
end when;
recovered = t_within >= recoveryTime;
// --- Overall requirement pass flag ---
//pass = withinHoverLimit and withinYawLimit and recovered;
pass = withinHoverLimit and withinYawLimit;
annotation(
Documentation(info="
<html>
<h4>SR-WIND-02 Performance in Wind</h4>
<p>
Source: EASA Means of Compliance Light-UAS.2512,
ISO 21384-3 (Clause 10 Operational limitations).
</p>
<p>
<b>Requirement:</b><br>
Under a steady 8 m/s wind with 12 m/s gusts, the UAS shall:
<ul>
<li>Maintain lateral position error ≤ 1.5 m (95th percentile) during hover.</li>
<li>Maintain yaw pointing error ≤ 5° (95th percentile).</li>
<li>Recover to within 0.5 m position error within 3 s after gust disturbance.</li>
</ul>
</p>
<p>
<b>Simulation Inputs:</b> Connect to AIDA_System position, yaw, and
reference signals.
</p>
</html>"),
uses(Modelica(version="3.2.2")),
Icon(graphics = {Text(extent = {{-100, 100}, {100, -100}}, textString = "SR-WIND-02"), Rectangle(extent = {{-104, -2}, {-104, -2}}), Rectangle(origin = {0, -1}, extent = {{-100, 101}, {100, -99}})}, coordinateSystem(initialScale = 0.1)));
end StabilityRequirement;

View File

@@ -0,0 +1,3 @@
package Requirements
end Requirements;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 234 KiB

Some files were not shown because too many files have changed in this diff Show More