S curve ramp function
56 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
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 comentarios
John D'Errico
el 17 de Mayo de 2025
Editada: John D'Errico
el 17 de Mayo de 2025
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.
Respuestas (2)
Sam Chak
el 18 de Mayo de 2025
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
2 comentarios
Sam Chak
el 28 de Mayo de 2025
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 comentarios
Ver también
Categorías
Más información sobre Simulink PLC Coder en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!