HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Generating Position

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
generatingpositionstackoverflow

Problem

I'm written the following code to calculate the position of a motor during each timestep, the result of which will be compared with feedback from a quadrature encoder and subjected to a PID algorithm. The trajectory will follow a trapezoidal profile. i.e. Accelerate to a maximum velocity, coast and then decelerate to the target position:

program ideone;
VAR
Pos : Real;
Vel : Real;
Acc : Real;
Demand : Real;
Max_Vel : Real;
AccDist : Real;
DecelPoint : Real;
Error : Real;

begin
Pos:=0;
Vel:=0;
Acc:=5;
Demand:=150;
Max_Vel:=10;

AccDist := (Max_vel/Acc * Max_vel) / 2;
DecelPoint := Demand - AccDist;
Writeln('AccelDist ',AccDist:5:2);
Writeln('DecelPoint ',DecelPoint:5:2);

Writeln('ACCEL');
While Vel <> Max_vel
Do Begin

Pos := Pos + Vel + Acc/2;

Vel := Vel + Acc;

If Vel >= Max_Vel
Then Begin
Vel := Max_Vel;
Pos := AccDist
End;

Writeln('Position:',Pos:5:2);

End;

Writeln('FLAT');    
While Pos  0
Do Begin

If Error > 0 
Then Begin 
Pos := DecelPoint;
Error := 0;
End;

Pos := Pos + Vel - Acc/2;
Vel := Vel - Acc;

If Vel <= 0
Then Pos := Demand;

Writeln('Position:',Pos:5:2);

End;

end.


How can the accuracy of the algorithm be improved?

Solution

First things first. Pascal is a very readable language, if written clearly. One of the main reasons of writing Pascal is because you want readable code. I'll start with some styling and naming, the actual calculations will be handled in the second part.

Style

Regardless of which standard you follow, make sure you're consistent. I'm following the GNU Pascal Coding Standards.

Keywords are lower-case

var while do if then begin end


No capitals. Although Pascal accepts the keywords as valid regardless of capitalisation, it's good style to follow the standard.

If then

Keep your if and then on the same line.

if Error > 0 then


Indentation

Your code isn't indented. Indentation is a major step forward in readability.

Spaces

A single space goes before and after operators. There are also spaces after commas.

Semi-colons

You are missing a ; here:

Pos := AccDist


Variable naming

Your variable names could use some love. You may think Pos is a good name for a position, but Pos() is also an already existing function in Pascal. Your variable has nothing to do with the function, so avoid the confusion.

DecelPoint is according to the standard. Max_Vel isn't.

Result

I've fixed the above (except part of the naming, I'm not too good at that either). The result:

program ideone;
var
    Pos : Real;
    Vel : Real;
    Acc : Real;
    Demand : Real;
    MaxVel : Real;
    AccDist : Real;
    DecelPoint : Real;
    Error : Real;

begin
    Pos := 0;
    Vel := 0;
    Acc := 5;
    Demand := 150;
    MaxVel := 10;

    AccDist := (MaxVel / Acc * MaxVel) / 2;
    DecelPoint := Demand - AccDist;
    Writeln('AccelDist ', AccDist:5:2);
    Writeln('DecelPoint ', DecelPoint:5:2);
    Writeln('ACCEL');

    while Vel <> MaxVel do
    begin
        Pos := Pos + Vel + Acc / 2;
        Vel := Vel + Acc;

        if Vel >= MaxVel then
        begin
            Vel := MaxVel;
            Pos := AccDist;
        end;

        Writeln('Position:',Pos:5:2);
    end;

    Writeln('FLAT');    

    while Pos  0 do
    begin

        if Error > 0 then
        begin 
            Pos := DecelPoint;
            Error := 0;
        end;

        Pos := Pos + Vel - Acc / 2;
        Vel := Vel - Acc;

        if Vel <= 0 then
            Pos := Demand;

    Writeln('Position:', Pos:5:2);
    end;
end.


Algorithm

Increasing the accuracy of the graph is a matter of increasing the amount of measurements. If every second isn't good enough, measure every half a second. If that's still not good enough, measure every tenth of a second. Or whatever your time unit may be. Your current set-up does not allow for such modifications.

You'll either need a MaxNumIterations and divide the whole course over that or put in a modifier which does basically the same under water. I'd go with the first.

Code Snippets

var while do if then begin end
if Error > 0 then
Pos := AccDist
program ideone;
var
    Pos : Real;
    Vel : Real;
    Acc : Real;
    Demand : Real;
    MaxVel : Real;
    AccDist : Real;
    DecelPoint : Real;
    Error : Real;

begin
    Pos := 0;
    Vel := 0;
    Acc := 5;
    Demand := 150;
    MaxVel := 10;

    AccDist := (MaxVel / Acc * MaxVel) / 2;
    DecelPoint := Demand - AccDist;
    Writeln('AccelDist ', AccDist:5:2);
    Writeln('DecelPoint ', DecelPoint:5:2);
    Writeln('ACCEL');

    while Vel <> MaxVel do
    begin
        Pos := Pos + Vel + Acc / 2;
        Vel := Vel + Acc;

        if Vel >= MaxVel then
        begin
            Vel := MaxVel;
            Pos := AccDist;
        end;

        Writeln('Position:',Pos:5:2);
    end;

    Writeln('FLAT');    

    while Pos < DecelPoint do
    begin
        Pos := Pos + Vel;
        Writeln('Position:', Pos:5:2);
    end;

    Error := Pos - DecelPoint;
    Writeln('DECEL');

    while Vel > 0 do
    begin

        if Error > 0 then
        begin 
            Pos := DecelPoint;
            Error := 0;
        end;

        Pos := Pos + Vel - Acc / 2;
        Vel := Vel - Acc;

        if Vel <= 0 then
            Pos := Demand;

    Writeln('Position:', Pos:5:2);
    end;
end.

Context

StackExchange Code Review Q#97747, answer score: 3

Revisions (0)

No revisions yet.