S curve ramp function
55 ビュー (過去 30 日間)
古いコメントを表示
I need help creating a function for an s curve ramp. The code below will create the inserted picture below. However, this code only works for a constant ramp block (connected to x). This code from the piecewise function on the Matlab smf() help file page.
I need two additional inputs (acceleration rate and jerk rate). The output should ramp the input velocity (x) signal based on the acceleration rate (a), and jerk rate (j). I need the block or code to be dynamic. I do not want to put a time value inside of my code. I will be exporting the code to structure text and input the code into a Siemens PLC.
I don't want to include a fixed dt in my code because I will be running the code in a PLC. Maybe it would be better to design this function in simulink and set a fixed time solver and use integrator blocks?
x = 0:0.01:10; % domain
a = 1; % unsaturated interval's left endpoint
b = 8; % unsaturated interval's right endpoint
y = smf(x, a, b);
plot(x, y), grid on
xline(a, '--')
xline(b, '--')
title("S-curve piecewise function")
xlabel("x")
ylabel("Amplitude")
ylim([-0.05 1.05])
%% S-curve piecewise function
function y = smf(x, a, b)
m = (a + b)/2;
y = (x > a & x <= m) .* ( 2*((x-a)/(b-a)).^2) + ...
(x > m & x <= b) .* (1-2*((x-b)/(b-a)).^2) + ...
(x > b);
end

4 件のコメント
John D'Errico
2025 年 5 月 17 日
編集済み: John D'Errico
2025 年 5 月 17 日
Ah. You have a limit on acceleration AND jerk. Note that the set of curves that satisfy such a constraint will require nonlinear bounds on the curve. It should not be too difficult though.
回答 (2 件)
Sam Chak
2025 年 5 月 18 日
This might not be what PLC users like to do.
%% 99% Math-free Jerk-based Velocity
% parameter
c = 1e-3; % control parameter for accuracy purposes
% Velocity and Jerk settings
Vref = 10; % desired velocity (specified by PLC user)
Jlimit = 40/49; % Jerk limit (specified by PLC user)
Jon = 1.0; % Jerk on time (specified by PLC user)
Joff = 2/sqrt(Jlimit/Vref) + Jon; % Jerk off time <-- this is math!
Jmid = (Jon + Joff)/2; % Jerk half-time <-- this is math!
% simulation time
tStart = 0; % start running but not producing velocity until Jerk on time
h = 0.1; % sampling time
tEnd = round(1.2*Joff); % stop running
t = (tStart:h:tEnd);
% Jerk specifications on the PLC
tdata = [tStart Jon-c Jon+c Jmid-c Jmid+c Joff-c Joff+c tEnd];
Jdata = [0.0 0.0 Jlimit Jlimit -Jlimit -Jlimit 0.0 0.0];
% maybe call ordinary Jerk function?
d2y = @(t) interp1(tdata, Jdata, t); % OpenPLC can perform interpolation
Jerkode = @(t, y) [ y(2); % dy = y(2) acceleration
d2y(t)]; % d2y = dy(2)/dt jerk
% initial condition
y0 = [0; 0]; % zero velocity, zero acceleration
% set solver options
options = odeset('RelTol', 1e-6, 'AbsTol', 1e-8);
% call ode45 Solver (OpenPLC can solve simple ODEs)
[t, y] = ode45(@(t, y) Jerkode(t, y), t, y0, options);
% True Velocity Profile
tt = linspace(tStart, tEnd, 51);
TrueVel = Vref*smf(tt, Jon, Joff);
% Plot the solution
figure
hold on
plot(t, y(:,1))
plot(tt, TrueVel, 'o')
hold off
grid on
xlabel('Time')
ylabel('Amplitude')
title('Jerk-based S-curve Velocity')
legend('Numerical solution', 'True Velocity Profile', 'location', 'best')
%% S-curve membership function (borrowed from Fuzzy Logic Toolbox)
function y = smf(x, a, b)
m = (a + b)/2;
y = (x > a & x <= m) .* ( 2*((x-a)/(b-a)).^2) + ...
(x > m & x <= b) .* (1-2*((x-b)/(b-a)).^2) + ...
(x > b);
end
Sam Chak
2025 年 5 月 28 日
Hi @David Cole

In addition to your user inputs (Vin, accel, and jerk), you also need to provide the "Jerk On" time. You can use my S-curvy function to generate the desired S-shaped velocity profile that satisfies the acceleration and jerk constraints.
If you find my solution helpful, please remember to vote and click "Accept".
%% user inputs
Vref = 10; % Target Velocity
Alimit = 0.5; % hardware Acceleration limit
Jlimit = 0.1; % hardware Jerk limit
Jon = 5.0; % Preferred Jerk-Trigger 'on' time
%% call my S-curvy fun
[t, V] = scurve(Vref, Alimit, Jlimit, Jon);
acc = gradient(V)./gradient(t);
jerk = gradient(acc)./gradient(t);
%% plot results
figure
plot(t, V), grid on
xlabel('Time')
ylabel('Amplitude')
title('I''m S-curve Velocity')
figure
subplot(211)
mv = min(acc);
Mv = max(acc);
yL = 0.2*(Mv - mv);
plot(t, acc), grid on
ylim([mv-yL, Mv+yL])
title('I''m acceleration')
subplot(212)
mv = min(jerk);
Mv = max(jerk);
yL = 0.2*(Mv - mv);
plot(t, jerk), grid on
ylim([mv-yL, Mv+yL])
title('I''m jerk')
%% S-curvy function
function [t, out] = scurve(Vref, Alimit, Jlimit, Jon)
% parameter
c = 1e-3; % control parameter for accuracy purposes
% Jerk settings
Alim = sqrt(Jlimit*Vref);
if Alim <= Alimit
Jlim = Jlimit;
else
Jlim = Alimit^2/Vref;
end
Joff = 2/sqrt(Jlim/Vref) + Jon; % Jerk off time
Jmid = (Jon + Joff)/2; % Jerk half-time
% simulation time
tStart = 0; % start running but not producing velocity until Jerk on time
h = 0.01; % sampling time
tEnd = round(Joff) + Jon; % stop running
t = (tStart:h:tEnd);
% Jerk specifications on the PLC
tdata = [tStart Jon-c Jon+c Jmid-c Jmid+c Joff-c Joff+c tEnd];
Jdata = [0.0 0.0 Jlim Jlim -Jlim -Jlim 0.0 0.0];
% maybe call ordinary Jerk function?
d2y = @(t) interp1(tdata, Jdata, t); % OpenPLC can perform interpolation
Jerkode = @(t, y) [ y(2); % dy = y(2) acceleration
d2y(t)]; % d2y = dy(2)/dt jerk
% initial condition
y0 = [0; 0]; % zero velocity, zero acceleration
% set solver options
options = odeset('RelTol', 1e-6, 'AbsTol', 1e-8);
% call ode45 Solver (OpenPLC can solve simple ODEs)
[t, y] = ode45(@(t, y) Jerkode(t, y), t, y0, options);
out = y(:,1);
end
0 件のコメント
参考
カテゴリ
Help Center および File Exchange で Simulink PLC Coder についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!