Aqua Phoenix
     >>  Lectures >>  Matlab 7  
 

Navigator
   
 
       
   

7.3 Assignment Solutions - Lecture 7

  assignment_terrain.m  
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 Ecsum 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 effoverall. The statement in exercise_terrain was:

else
  Ecsum(:, i + 1) = Ecsum
end
We change this statement to:

else
  Ecsum(:, i + 1) = Ecsum(:, i) + (dE(:, i) * effoverall)
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 m-file, 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:

mrider = [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 Pmech 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) = Pmech effective * ds(i) / vkmh2msec(vconst) * (1 / effoverall) to:

dE(:, i) = (Pmech effective * ds(i) / vkmh2msec(vconst) * (1 / effoverall))' 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 Ecsum. This definition remains the same. We also set the first element of the array to be the energy level of a fully charged battery:

Ecsum(1) = Ebatteries 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(mrider)
  Ecsum = [Ecsum; Ebatteries 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 Ecsum and dE. The code changes on two lines from:

Ecsum(i + 1) = Ecsum(i) - dE(i)
Ecsum(i + 1) = Ecsum(i) + (dE(i) * effoverall)
to:

Ecsum(:, i + 1) = Ecsum(:, i) - dE(:, i)
Ecsum(:, i + 1) = Ecsum(:, i) + (dE(:, i) * effoverall)

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, mrider, Ecsum), 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 step-like 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:

zeroplane = zeros(length(mrider), 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, mrider, Ecsum), xlabel('Distance in meters'), ylabel('Weight of rider in kg'), zlabel('Energy left in batteries')
hold on
mesh(x, mrider, zeroplane)

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, mrider, zeroplane - 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:

distempty = []

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(mrider)
  while (i <= n)
  end
end

Figure 7.40
Click image to enlarge, or click here to open
The previously used Ecsum(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 Ecsum. Since Ecsum is now a matrix, we need to address an element by row and column as Ecsum(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 (Ecsum(i) < 0)
  xcross = interp1([Ecsum(i - 1), Ecsum(i)], [x(i - 1), x(i)], 0)
to:

if (Ecsum(m, i) < 0)
  xcross = interp1([Ecsum(m, i - 1), Ecsum(m, i)], [x(i - 1), x(i)], 0)
We also put the result into the results vector distempty:

distempty(m) = dtravelled

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([mrider; distempty]');
Note that mrider and distempty 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