S curve ramp function
    80 次查看(过去 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 个评论
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!









