Migration to OpenModelica 1.25 and FMUs Generation
This commit is contained in:
BIN
CoSimulation/FMUs_OpenModelica_1.25/ControlDroneNavigation.fmu
Normal file
BIN
CoSimulation/FMUs_OpenModelica_1.25/ControlDroneNavigation.fmu
Normal file
Binary file not shown.
Binary file not shown.
BIN
CoSimulation/FMUs_OpenModelica_1.25/QuadcopterModel.fmu
Normal file
BIN
CoSimulation/FMUs_OpenModelica_1.25/QuadcopterModel.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/FMUs_OpenModelica_1.25/RemoteControl.fmu
Normal file
BIN
CoSimulation/FMUs_OpenModelica_1.25/RemoteControl.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/FMUs_OpenModelica_1.25/StabilityRequirement.fmu
Normal file
BIN
CoSimulation/FMUs_OpenModelica_1.25/StabilityRequirement.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/FMUs_OpenModelica_1.25/Wind2DModel.fmu
Normal file
BIN
CoSimulation/FMUs_OpenModelica_1.25/Wind2DModel.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/FMUs_OpenModelica_1.25/WindProfile.fmu
Normal file
BIN
CoSimulation/FMUs_OpenModelica_1.25/WindProfile.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/FMUs_SimulationX/AIDA_Drone_FMU.fmu
Normal file
BIN
CoSimulation/FMUs_SimulationX/AIDA_Drone_FMU.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/FMUs_SimulationX/Environment.fmu
Normal file
BIN
CoSimulation/FMUs_SimulationX/Environment.fmu
Normal file
Binary file not shown.
6002
CoSimulation/FMUs_SimulationX/RunFlightPlan.csv
Normal file
6002
CoSimulation/FMUs_SimulationX/RunFlightPlan.csv
Normal file
File diff suppressed because it is too large
Load Diff
BIN
CoSimulation/FMUs_SimulationX/RunFlightPlan.fmu
Normal file
BIN
CoSimulation/FMUs_SimulationX/RunFlightPlan.fmu
Normal file
Binary file not shown.
BIN
CoSimulation/Tutorial_PyCharm_PyFMI_Setup.docx
Normal file
BIN
CoSimulation/Tutorial_PyCharm_PyFMI_Setup.docx
Normal file
Binary file not shown.
180
CoSimulation/simulate_aida_coupled_FMUSimX.py
Normal file
180
CoSimulation/simulate_aida_coupled_FMUSimX.py
Normal 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()
|
||||||
158
CoSimulation/simulate_aida_coupled_FMUs_OM125.py
Normal file
158
CoSimulation/simulate_aida_coupled_FMUs_OM125.py
Normal 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
|
||||||
|
# -----------------------------
|
||||||
6
CoSimulation/test_pyfmi.py
Normal file
6
CoSimulation/test_pyfmi.py
Normal 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!")
|
||||||
@@ -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;
|
|
||||||
@@ -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;
|
|
||||||
@@ -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;
|
||||||
@@ -12,6 +12,7 @@ model ControlMotor "[SF1.1/2/3/4.1] Control motor"
|
|||||||
equation
|
equation
|
||||||
// enter your equations here
|
// enter your equations here
|
||||||
ComdKD = (DAngVel - wb) / cR;
|
ComdKD = (DAngVel - wb) / cR;
|
||||||
|
|
||||||
annotation(
|
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)));
|
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;
|
end ControlMotor;
|
||||||
1720
SimulationModels/OpenModelica 1.11/AIDAModelica/QuadcopterModel.mo
Normal file
1720
SimulationModels/OpenModelica 1.11/AIDAModelica/QuadcopterModel.mo
Normal file
File diff suppressed because it is too large
Load Diff
164
SimulationModels/OpenModelica 1.11/AIDAModelica/RemoteControl.mo
Normal file
164
SimulationModels/OpenModelica 1.11/AIDAModelica/RemoteControl.mo
Normal 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;
|
||||||
@@ -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;
|
||||||
14790
SimulationModels/OpenModelica 1.11/AIDAModelica/package.mo
Normal file
14790
SimulationModels/OpenModelica 1.11/AIDAModelica/package.mo
Normal file
File diff suppressed because it is too large
Load Diff
@@ -68,3 +68,4 @@ YAngularSpeedErrorModel
|
|||||||
YawConsignProducing
|
YawConsignProducing
|
||||||
ZAngularSpeedErrorModel
|
ZAngularSpeedErrorModel
|
||||||
ModelicaLicense2
|
ModelicaLicense2
|
||||||
|
WindProfile
|
||||||
BIN
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.bmp
Normal file
BIN
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 MiB |
BIN
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.pdf
Normal file
BIN
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.pdf
Normal file
Binary file not shown.
BIN
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.png
Normal file
BIN
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
6662
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.svg
Normal file
6662
SimulationModels/OpenModelica 1.11/Requirements/AIDA_System.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 286 KiB |
@@ -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;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package Requirements
|
||||||
|
|
||||||
|
end Requirements;
|
||||||
2289
SimulationModels/OpenModelica 1.11/images/AIDA_System.eps
Normal file
2289
SimulationModels/OpenModelica 1.11/images/AIDA_System.eps
Normal file
File diff suppressed because it is too large
Load Diff
BIN
SimulationModels/OpenModelica 1.11/images/AIDA_System.pdf
Normal file
BIN
SimulationModels/OpenModelica 1.11/images/AIDA_System.pdf
Normal file
Binary file not shown.
4559
SimulationModels/OpenModelica 1.11/images/AIDA_System.svg
Normal file
4559
SimulationModels/OpenModelica 1.11/images/AIDA_System.svg
Normal file
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
Reference in New Issue
Block a user