

7.3 Assignment Solutions  Lecture 7
We begin with the first task of including regen braking. This requires us to change only one line from
exercise_terrain. Instead of keeping the cumulative energy level E_{csum} the same in case angle alpha < 0, we merely add the amount of energy that would have been required by travelling at the opposite angle. We must also multiply the amount of energy by the efficiency value eff_{overall}. The statement in exercise_terrain was:
else E_{csum}(:, i + 1) = E_{csum} end
We change this statement to:
else E_{csum}(:, i + 1) = E_{csum}(:, i) + (dE(:, i) * eff_{overall}) end


Figure 7.27 Click image to enlarge, or click here to open


We can now run the assignment in the
Command Window.
The resulting graph has a few parts in which the cumulative energy level increases somewhat  these parts correspond to the downhill motion in which energy is regained.


Figure 7.28 Click image to enlarge, or click here to open


We now begin changing the code from computing a vector of results (distance travelled) to computing a matrix of results (distance travelled per weight of rider). We will have to make several changes throughout the mfile, most of which deal with converting a computation of a scalar to a computation of a vector. The advantageous aspect of this is that an operation of a scalar and a scaler is not too different from an operation of a scalar and a vector. Thus, we don't have to worry about changing the equations at all.
First, we need to define the vector of weights:
m_{rider} = [40:1:110]


Figure 7.29 Click image to enlarge, or click here to open


The block of code that computes angles for the specified terrain does not change. After all, the terrain remains the same regardless of weight.
Since the energy level depends on the weight of the rider, we will need to change the next block of code. The computation of Torque and
P_{mech effective} remains the same, because the operations work for both scalars and vectors.
The resulting vector, however, needs to be stored in the matrix dE. Before we stored a scalar in each column of a vector (remember that a vector is a single row matrix). Now, we would like to store each result vector in a column of the matrix, where each column represents values for each different weight of the rider. To address a column in a matrix, we use the notation
A(:, c), where A is the matrix, c is the column of the matrix, and : denotes that we are not addressing all rows. The code changes from:
dE(i) = P_{mech effective} * ds(i) / v_{kmh2msec}(v_{const}) * (1 / eff_{overall})
to:
dE(:, i) = (P_{mech effective} * ds(i) / v_{kmh2msec}(v_{const}) * (1 / eff_{overall}))'
Note that we are transposing the result vector using the single quote
' operator. Without transposing, the result is a vector (a row), but we instead require a column. Hence we transpose the row.


Figure 7.30 Click image to enlarge, or click here to open


We previously initialized an empty array for the results of cumulative energy level E_{csum}. This definition remains the same. We also set the first element of the array to be the energy level of a fully charged battery:
E_{csum(1)} = E_{batteries total}
Because our result is now a matrix, in which every row accounts for a different weight of the rider, we need to initialize a matrix. Since at the very beginning, every rider starts out with the same amount of energy in their Segway's batteries, we need to initialize the first column (previously the first element) of the matrix with the initial energy level:
for i=1:length(m_{rider}) E_{csum} = [E_{csum}; E_{batteries total}] end


Figure 7.31 Click image to enlarge, or click here to open


We continue changing the next block of code in a similar fashion. We now only need to add the notation for addressing columns in the matrices of
E_{csum} and dE. The code changes on two lines from:
E_{csum}(i + 1) = E_{csum}(i)  dE(i) E_{csum}(i + 1) = E_{csum}(i) + (dE(i) * eff_{overall})
to:
E_{csum}(:, i + 1) = E_{csum}(:, i)  dE(:, i) E_{csum}(:, i + 1) = E_{csum}(:, i) + (dE(:, i) * eff_{overall})


Figure 7.32 Click image to enlarge, or click here to open


Instead of using function
plot to plot a 2D graph, we now use mesh to plot the 3D graph:
mesh(x, m_{rider}, E_{csum}), xlabel('Distance in meters'), ylabel('Weight of rider in kg'), zlabel('Energy left in batteries')


Figure 7.33 Click image to enlarge, or click here to open


The result is a steplike surface denoting the energy levels for the various weights and distances travelled.


Figure 7.34 Click image to enlarge, or click here to open


While not required, you may wish to plot a plane at the z=0, which corresponds to an energy level of 0. This would help in distinguishing the two states of energy levels. A plane at z=0 is represented by a matrix of zeros, which must have the same dimensions as the matrix of results. We use function
zeros to initialize a matrix of this kind:
zero_{plane} = zeros(length(m_{rider}), length(x))
To plot 2 or more graphs in the same window, we use the command
hold on
between all pairs of plots:
mesh(x, m_{rider}, E_{csum}), xlabel('Distance in meters'), ylabel('Weight of rider in kg'), zlabel('Energy left in batteries') hold on mesh(x, m_{rider}, zero_{plane})


Figure 7.35 Click image to enlarge, or click here to open


The resulting graph includes 2 meshes. However, the plane is not very distinct in color.


Figure 7.36 Click image to enlarge, or click here to open


To change the color of the plane, we can issue the
mesh function with 4 instead of 3 arguments. The 4th argument is a matrix with dimensions of the result matrix, whose values set the color scheme used for the mesh. The color scheme is a scale that corresponds in index values to the result from the first mesh. We note that values below 0 are drawn in dark blue colors, while values above 0 are drawn in light colors. In order to set the color of the plane to be darker, we need to some low value below 0, which corresponds to the lowest value in the previous graph. We merely use the zero matrix and subtract some large value from it (1000000), in order to obtain a dark color. The value of 1000000 was experimentally derived:
mesh(x, m_{rider}, zero_{plane}  1000000)


Figure 7.37 Click image to enlarge, or click here to open


The result is much easier to look at and better distinguishable.


Figure 7.38 Click image to enlarge, or click here to open


Finally, we compute the values of distance at which the energy level becomes 0. Instead of printing out the verbal response for each weight value, we print out a table.
First, we initialize the result vector:
dist_{empty} = []


Figure 7.39 Click image to enlarge, or click here to open


We now encapsulate the previous
while loop in another loop, which iterates over the different weights of the rider. The statement
while (i <= n) end
becomes:
for m=1:length(m_{rider}) while (i <= n) end end


Figure 7.40 Click image to enlarge, or click here to open


The previously used
E_{csum}(i) pointed to a scalar. In our changed version, it now points to a vector. However, we still need to work with a scalar, as the computation for exhaustive energy level requires us to look at each individual element of E_{csum}. Since E_{csum} is now a matrix, we need to address an element by row and column as E_{csum}(m, i), where m is the index for weight, and i is the index for cumulative energy level. The code changes on two lines from:
if (E_{csum}(i) < 0) x_{cross} = interp1([E_{csum}(i  1), E_{csum}(i)], [x(i  1), x(i)], 0)
to:
if (E_{csum}(m, i) < 0) x_{cross} = interp1([E_{csum}(m, i  1), E_{csum}(m, i)], [x(i  1), x(i)], 0)
We also put the result into the results vector dist_{empty}:
dist_{empty}(m) = d_{travelled}


Figure 7.41 Click image to enlarge, or click here to open


Finally we print out the results using function
disp:
disp('Weight of rider Distance after which batteries are empty') disp([m_{rider}; dist_{empty}]');
Note that m_{rider} and dist_{empty} are vectors that are combined in a matrix of 2 rows and N many columns. We transpose this matrix using the quote ' operator to obtain a matrix of N rows and 2 columns.


Figure 7.42 Click image to enlarge, or click here to open


Looking at the results, we notice that below a weight of 48kg, the results are 0. This is due to the fact that the energy has not been exhausted on the modelled terrain for riders with such low weights. We can append a few more kilometer intervals to the terrain in order to obtain more useful data.


Figure 7.43 Click image to enlarge, or click here to open



