Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions examples/tether_props.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,38 @@ display(plotx(
title="Force step response",
ylabels=["Left power [m]", "Right power [m]", "Left steering [m]", "Right steering [m]"],
))

# --- Calculate Properties and Get Step Response Data ---
find_steady_state!(one_seg_sam; t=10.0, dt=3.0)
axial_stiffness, axial_damping, tether_lens, dt =
SymbolicAWEModels.calc_spring_props(one_seg_sam, one_seg_tether_sam; F_step=-0.1)

# --- Print Comparison Table ---
segments = one_seg_sam.sys_struct.segments
tethers = one_seg_sam.sys_struct.tethers
segments = [segments[tether.segment_idxs[1]] for tether in tethers]
real_axial_stiffness = [segment.axial_stiffness for segment in segments]
real_axial_damping = [segment.axial_damping for segment in segments]

println("\n--- Tether Spring Properties ---")
@printf "%-8s | %-15s %-15s %-10s | %-15s %-15s %-10s\n" "Tether" "Calc. Stiffness" "Real Stiffness" "Error (%)" "Calc. Damping" "Real Damping" "Error (%)"
println(repeat("-", 100))
for i in 1:4
# Calculate relative errors in percent
stiffness_err = 100 * abs(axial_stiffness[i] - real_axial_stiffness[i]) / real_axial_stiffness[i]
damping_err = 100 * abs(axial_damping[i] - real_axial_damping[i]) / real_axial_damping[i]
# Print data rows
@printf "%-8d | %-15.2f %-15.2f %-10.2f | %-15.2f %-15.2f %-10.2f\n" i axial_stiffness[i] real_axial_stiffness[i] stiffness_err axial_damping[i] real_axial_damping[i] damping_err
end

# --- Plot Step Response ---
steps = size(tether_lens, 2) - 1
display(plotx(
dt .* collect(0:steps),
tether_lens[1,:] .- tether_lens[1,1],
tether_lens[2,:] .- tether_lens[2,1],
tether_lens[3,:] .- tether_lens[3,1],
tether_lens[4,:] .- tether_lens[4,1];
title="Force step response",
ylabels=["Left power [m]", "Right power [m]", "Left steering [m]", "Right steering [m]"],
))
16 changes: 10 additions & 6 deletions src/system_structure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1021,8 +1021,9 @@ function copy!(sys1::SystemStructure, sys2::SystemStructure)
if length(sys1.points) > 0
if length(sys1.points) == length(sys2.points)
for (point1, point2) in zip(sys1.points, sys2.points)
point2.pos_w = point1.pos_w
point2.vel_w = point1.vel_w
point2.pos_w .= point1.pos_w
point2.vel_w .= point1.vel_w
point2.disturb .= point1.disturb
end
# if different number of points, copy only the tether points
elseif length(sys1.tethers) > 1 && length(sys1.tethers) == length(sys2.tethers)
Expand All @@ -1035,6 +1036,7 @@ function copy!(sys1::SystemStructure, sys2::SystemStructure)
for (point_idx1, point_idx2) in zip(point_idxs1, point_idxs2)
sys2.points[point_idx2].pos_w .= sys1.points[point_idx1].pos_w
sys2.points[point_idx2].vel_w .= sys1.points[point_idx1].vel_w
sys2.points[point_idx2].disturb .= sys1.points[point_idx1].disturb
end
end
elseif length(tether2.segment_idxs) == 1
Expand All @@ -1046,6 +1048,8 @@ function copy!(sys1::SystemStructure, sys2::SystemStructure)
sys2.points[point_idxs2[2]].pos_w .= sys1.points[point_idxs1[2]].pos_w
sys2.points[point_idxs2[1]].vel_w .= sys1.points[point_idxs1[1]].vel_w
sys2.points[point_idxs2[2]].vel_w .= sys1.points[point_idxs1[2]].vel_w
sys2.points[point_idxs2[1]].disturb .= sys1.points[point_idxs1[1]].disturb
sys2.points[point_idxs2[2]].disturb .= sys1.points[point_idxs1[2]].disturb
simple = true
end
end
Expand Down Expand Up @@ -1094,10 +1098,10 @@ function copy!(sys1::SystemStructure, sys2::SystemStructure)
# copy wing positions and velocities
if length(sys1.wings) > 1 && length(sys1.wings) == length(sys2.wings)
for (wing1, wing2) in zip(sys1.wings, sys2.wings)
wing2.pos_w = wing1.pos_w
wing2.vel_w = wing1.vel_w
wing2.ω_b = wing1.ω_b
wing2.Q_b_w = wing1.Q_b_w
wing2.pos_w .= wing1.pos_w
wing2.vel_w .= wing1.vel_w
wing2.ω_b .= wing1.ω_b
wing2.Q_b_w .= wing1.Q_b_w
end
end
end
5 changes: 5 additions & 0 deletions src/tether_properties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function copy_to_simple!(sys::SystemStructure, ssys::SystemStructure)
spoint_idx = ssys.segments[stether.segment_idxs[1]].point_idxs[2]
ssys.points[spoint_idx].pos_w .= sys.points[point_idx].pos_w
ssys.points[spoint_idx].vel_w .= sys.points[point_idx].vel_w
ssys.points[spoint_idx].disturb .= sys.points[point_idx].disturb
end

# copy wing state
Expand Down Expand Up @@ -170,10 +171,14 @@ function calc_spring_props(sam::SymbolicAWEModel, tether_sam::SymbolicAWEModel;
F_step=-0.1, prn=false)
find_steady_state!(sam; t=10.0, dt=10.0, vsm_interval=0)
copy!(sam.sys_struct, tether_sam.sys_struct)
@show tether_sam.sys_struct.segments[1].force
@show tether_sam.sys_struct.points[1].disturb
OrdinaryDiffEqCore.reinit!(tether_sam.integrator; reinit_dae=true)
update_sys_struct!(tether_sam, tether_sam.sys_struct)
@show tether_sam.sys_struct.segments[1].force

F_0 = [-tether_sam.sys_struct.points[i].force for i in 1:4]
@show norm.(F_0)
steps = 200
tether_lens = step(tether_sam, steps, F_step, F_0)
k_values, c_values = calc_spring_props(sam, tether_lens, F_step; prn)
Expand Down
4 changes: 4 additions & 0 deletions test/test_sam.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ end
one_seg_tether_sam = SymbolicAWEModel(set, "tether")
init!(one_seg_tether_sam)

# run twice to make sure state is reset properly
axial_stiffness, axial_damping =
SymbolicAWEModels.calc_spring_props(one_seg_sam, one_seg_tether_sam)
next_step!(one_seg_sam; dt=1.0)
axial_stiffness, axial_damping =
SymbolicAWEModels.calc_spring_props(one_seg_sam, one_seg_tether_sam)
segments = one_seg_sam.sys_struct.segments
Expand Down
Loading