This page reports substantive errors not typos. I am however interested in collecting both classes of errors so please email me at and provide enough information to locate the error, and tell me what you think the error is. By default I will acknowledge you, let me know if you don't want this.

Big thanks to the following bug finders for their careful reading and attention to detail: Walter Lucia, Michael Mustillo, Mark Sheehan, Jana Kosecka, Do Nguyen Tien Thong, Jeff Trinkle, Muhammad Tufail, Frederic Maire, Nino Cauli, ENB339 class of 2011, Ugo Fabrizi, Liam O'Sullivan, Bassam Salameh, Rafael Perrone, Henry Carrillo Lindado, João Pinto, Richard Roberts, Diego Vera, David Breneisen, Stephen Fox, Julien Brisset, Chet Corcos, Diego Saqui, Chao Qu, Hugo Costelha, Geoffrey Vincent, Paul Pounds, Anis Koubaa, Bart Bastings, Hiroyuki Ichihara, Anuj Potnis, Richard Balogh, Murty S. Challa, Diego Cesar, Ulrik Skyt, George Haywood, Iain McCulloch, Troy Woo, Yang Daichuan, Steven Dirven, Dan Richards, Martin Stoelen, Feiteng Lee .

The convention here is that new text is shown in bold, and text to be deleted is shown in strike through font.


There are currently two versions of the book. The first was released in 2011. The most recent, or second printing, was released in early 2013. You can identity the version from the copyright page (page iv), the second version has the words "© Springer-Verlag Berlin Heidelberg, first edition 2011, corrected second printing 2013". Importantly, pagination is the same between the versions so page numbers given below apply equally to both versions.

The second printing provided an opportunity to:

Errata for second printing

p 17

The pose vector from frame {O} to frame {B} should be labelled \xi_B not \xi_P. (thanks Richard Balogh)

p 22

The leading superscript T should all be V.

This is related to the errata below for p. 20. (thanks Anis Koubaa)

The equation just above the box has the wrong signs and should be

(thanks Murty S. Challa)

p 27

Coordinate frame {B} in Fig 2.9 is depicted as a left-handed coordinate frame. In robotics we don't use these, only right-handed coordinate frames. The intent of the figure is to illustrate that point P can be described relative to both the frames, and is is correct (Thanks George Haywood).

p 36

The quaternion-vector product in the sidebar has various sign errors in the matrix part, it should be

(thanks Diego Cesar)

p 39

Table 2.1, the rightmost column gives some examples of Toolbox functions that generate that particular representation. The list of functions given is not exhaustive. For instance the second last row, for SE(3), lists only one function transl(x,y,z) which does generate an SE(3) transform but with a null rotation component. trotx(th) creates a rotation but has a null translation. There is actually no Toolbox function that creates an SE(3) representation with both rotation and translation. (thanks Ulrik Skyt)

p 49

The result shown in sec 3.1.5 is incorrect and should be

>> trinterp(T0, T1, 0.5)
ans =
    0.6667   -0.3333    0.6667         0
   -0.6667   -0.6667    0.3333         0
    0.3333   -0.6667   -0.6667    0.1500
         0         0         0    1.0000
(thanks Ulrik Skyt)

p 53

Equation (3.12) is incorrect and should read

Note the change to the dimensions of the added identity matrix which is 4 x 4. (thanks Paul Pounds)

p 111

Equation (6.1) is incorrect and should read

the arguments of sin and cos should not contain δθ. The other equations on this page are correct. (thanks Hugo Costelha)

p 113

Equation (6.4) is incorrect and should read

There's a spurious minus sign printed before the sine function. (thanks Dan Richards)

p 117

Equation (6.11) is incorrect and should read

The first two elements of the second row are swapped. (thanks Dan Richards)

p 118

Equation (6.14) is incorrect and should read

The first term should not be postmultiplied by a Jacobian matrix. The versions given in Appendix K are correct.

p 123

The top code fragment on this page should read

>> P0 = diag([.01, .01, 0.005].^2);
>> map = Map(20);
>> veh = Vehicle(WV);
>> veh.add_driver( RandomPath(map.dim) );
>> sensor = RangeBearingSensor(veh, map, W); 
>> ekf = EKF(veh, V, P0, sensor, W, []);

that is, in the third line we should use the covariance V not W.

p 125

Buffon's needle problem. The probability should be h/n = 2l/tπ, where t is the strip width.

p 138

In (7.2) row 2, column 4, the subscript i should be a j. (thanks Yang Daichuan).

p 142

The model mdl_twolink now includes a base transform so that the robot arm moves in the xz-plane and is thus influenced by gravity. Use the model mdl_planar2 instead.

>> mdl_planar2

which creates a workspace variable called p2 (thanks Steven Dirven)

p 151

In the MATLAB output showing the parameters of the p8 robot there is an error in the displayed base transform. The third column is shown as all zeros but it should be [1 0 0 0]. (thanks Julien Brisset)

p 152

The inverse kinematic results shown cannot be replicated with ikine() as of RTB 9.10. Use the method ikunc() instead.

>> p8.ikunc(T)
ans =
   -0.2833    1.0642    0.1103   -0.5412   -0.6024   -0.0831   -1.2168    0.1070

but note you will need the Optimization Toolbox. (thanks Steven Dirven)

p 152

The plot command does not work, giving an error about missing 'workspace' option. This is due to a change in the Robotics Toolbox. The toolbox uses a simple heuristic to determine the size of the volume in which the robot moves, it needs this to size the plot correctly. For a robot with a prismatic link this is difficult, so you need to specify the size of the workspace. The toolbox used to make assumptions that worked for this example but were not general.

You have 2 options:

  1. Always put the workspace command when you call plot
    >> p8.plot([0 0 0 0 0 0 0 0], 'workspace', [-2 2 -2 2 -2 2])
  2. This can be tedious, but you can specify the default options for plot which get used every time you call plot
    >> p8.plotopt={'workspace', [-2 2 -2 2 -2 2]}
    >> p8.plot([0 0 0 0 0 0 0 0])

p 152

The manipulability results shown differ with recent versions of the Toolbox. The results now are:

>> p560.maniplty(qn)
ans =

>> p8.maniplty([0 0 qn])
ans =

These measures are derived from the radii of the velocity ellipsoid, but some of the radii have dimensions of m/s and others have rad/s so the radii are not directly comparable. The toolbox by default now considers the translational degrees of freedom only. The options 'R' gives manipulability for all rotational degrees of freedom and 'all' considers all degrees of freedom and gives the old toolbox behaviour, for example:

>> p560.maniplty(qn, 'all')
ans =

>> p8.maniplty([0 0 qn], 'all')
ans =

(thanks Julien Brisset)

p 157

Fig 7.12(b) is wrong, it's the same as 7.12(c). To create this subfigure we would use numerical inverse kinematics. As of RTB 9.10, the ikine() method failes on this example, but the new ikunc() method works fine, but you would need the Optimisation Toolbox.

>> qik2=p560.ikunc(Ts);
>> qplot(qik2);

(thanks Steven Dirven)

p 159

Fig 7.14(a) has incorrect axis labels, it should be (click to enlarge)

(thanks Bart Bastings)

p 173

In the equation at the top of the page the subscript should be 2, not 1. (thanks Feiteng Lee)

p 191

p 174

In the top highlight box, there's a missing equal sign before the left opening bracket. (thanks Martin Stoelen)

p 191

In (9.1) I use the symbol g to represent a wrench, whereas in the rest of the chapter I use an f. (thanks Steven Dirven)

p 196

Section 9.1.3 is quite wrong, sorry. The Coriolis matrix computed by the Toolbox was incorrect, now fixed in RTB. The numerical result printed on page 197 is wrong. However the result for C*q' is correct.

p 223

Equation (10.1), Planck's radiation formula, the units are missing an inverse steradian, and should be W sr-1 m-2 m-1. (thanks Iain McCulloch and Troy Woo)

p 253

The unnumbered equation just above Fig 11.3 should be

When expressed in homogenous coordinates the denominator is replaced by an implicit division by the third homogeneous coordinate. (Thanks Chao Qu).

p 265

The function plot_frame has been replaced by trplot.

>> trplot(eye(4,4), 'frame', 'T', 'color', 'b', 'length', 0.3)

(Thanks Anuj Potnis).

p 270

The top unnumbered equation on this page should read

the argument of the arccosine are inverted in the book (Thanks Geoffrey Vincent).

p 300

Section 12.4.1 has a number of errors where I misuse/confuse cross-correlation and convolution. They are similar but different and there's a nice tutorial that explains clearly the difference.

The first equation in this section defines cross-correlation not convolution. For convolution the two plus-signs would be minus-signs. The result is the same for the case of a symmetric kernel. The Toolbox function iconv() does in fact perform cross-correlation, not convolution. The documentation is wrong but will be updated in MVTB 3.4. (Thanks Chet Corcos).

p 432

The code for the mosacing example in the topmost codebox on the page

>> surf = isurf(im1)
>> surf = isurf(im2)
>> m = surf.match(surf);

should be

>> surf1 = isurf(im1)
>> surf2 = isurf(im2)
>> m = surf1.match(surf2);

p 456

There's an error in the second equation on this page

The "hats" are transposed and it should be

(Thanks Diego Saqui).

p 457

The expression to compute the relative pose of the target with respect to the camera is incorrect. The line of code

Tdelta = TcStar_t * inv(Tc_t_est)

should be

Tdelta = Tc_t_est * inv(TcStar_t)

(thanks Hiroyuki Ichihara)

p 461

In (15.6) the elements [1,4] and [2,5] of the Jacobian have the pixel dimensions σ swapped. Element [1,4] should contain σv and element [2,5] should contain σu. (thanks Rafael Perrone)

Note also that the pixel dimensions are referred to here as σu x σv, but on page 255 they are introduced as σw x σh respectively. (thanks Murty Challa)

p 515

In the definition of SVD note that A is Rmxn and that Σ is Rnxmmxn.

Errata for first printing

All the errata listed above apply to this version of the book as well.

p 20

The subscripts and superscripts T in (2.3) should all be V. (thanks Walter Lucia)

p 28

The code example

>> rotx(pi/2) * roty(pi/2) 
ans =
 0.0000       0  1.0000
 1.0000  0.0000 -0.0000
-0.0000  1.0000  0.0000
>> trplot(R)

won't work because the result of computing the product of rotation matrices is stored in ans not in R. Instead it should be

>> R = rotx(pi/2) * roty(pi/2) 
R =
 0.0000       0  1.0000
 1.0000  0.0000 -0.0000
-0.0000  1.0000  0.0000
>> trplot(R)

(thanks Rafael Perrone)

p 30

There is an error in the simple rpy2r() example on this page.

>> R = rpy2r(0.1,0.2,0.3)
R =
0.9752  -0.370  0.2184
0.0978  0.9564  -0.2751
-0.1987 0.2896  0.9363

Whereas the actual MATLAB result is

R =
0.9363   -0.2896    0.1987
0.3130    0.9447   -0.0978
-0.1593    0.1538    0.9752

The cause of this is a change in the definition of the function. As per (2.14) roll-pitch-yaw angles are defined as a rotation sequence about the x- then y- then z-axes, and this is what the code implements.

In older versions of the Toolbox the sequence used was z- then y- then x-axes, which is consistent with early textbooks such as that by Paul. This convention makes a bit more sense for a robot manipulator where the z-axis is considered forward, but is inconsistent with the notation for vehicles. This behaviour can be invoked using the 'zyx' option to rpy2r() and will give the result shown in the book. (thanks Michael Mustillo)

p 32

The caption for Fig 2.13 is incorrect. The coordinate system is such that the x-axis points in vertical direction, the thrust axis. (thanks Rafael Perrone)

p 35

The quote in the blue box about Hamilton gives the fundamental quaternion equation which should read i2 = j2 = k2 = ijk = -1. (thanks Mark Sheehan)

p 37

In the right-most vector term the third element should have a leading superscript of A not B, that is it should read

(thanks Richard Roberts)

p 39

Figure 2.15, two graph arcs are labeled with "quaternion" which should be "Quaternion". All classes begin with an uppercase letter. The arcs labelled "q.t" and "q.r" should be "q.T" and "q.R" respectively. The arcs "rotvec2tr" and "tr2rotvec" should be "angvec2tr" and "tr2angvec" respectively. (thanks Jeff Trinkle)

p 47

In Fig 3.4 the first red segment should be initially flat to reflect an initial zero velocity and acceleration. Similarly, the final red segment should be flat as it enters the point X4. (thanks Jeff Trinkle)

The motion comprises linear segments with polynomial blends, like lpsblspb, but here we choose... (thanks Walter Lucia)

The equation for acceleration during the blend is misleading. This is the average acceleration over the blend interval and can be used to determine whether or not the actuator acceleration limit is exceeded. Because the blend is a polynomial the peak acceleration will likely be higher than the average acceleration, and should properly be taken into consideration.

p 48

The equation near the bottom of the page is missing a factor 's' and should be

(thanks Jana Kosecka)

p 56

In further reading there is a reference to Corke et. al. (2007) which refers to the paper: P. Corke, J. Lobo, and J. Dias, ``An introduction to inertial and visual sensing'', Int. J. Robotics Research, vol. 26 pp. 519-536, June 2007 which is omitted from the bibliography. (thanks Diego Vera)

p 68

The second line of text refers to Fig 15.1, it should be Fig 4.2. (thanks Rafael Perrone)

p 70

The Simulink Bicycle model shown in Figure 4.3 differs from equation (4.2). The Simulink block does not include the tan function or the division by the wheel length. (thanks Liam O'Sullivan)

This is a bug in the Toolbox, but fixing the bug will change the shape of responses all through Chapter 4. The best solution is to add another model to roblocks called Bicycle2 which does include the full model, or to make it switchable (no tan function by default). Added to the TODO list.

p 75-77

In Section 4.2.4 there is a mistake in the first equation where γ (the steer angle) should be replaced by ω the angular steering rate. The two quantities are related by equation (4.2). All instances of γ in this section should be replaced by ω.

In Fig 4.13 the input to Bicycle block is steer angle γ but we should in fact input the steering rate ω. If we assume that the steer angle is small (tan γ ≅ γ) then we convert from steer angle rate to steer angle by dividing by the velocity, and clearly this will be problematic as the velocity converges on zero. We could also multiply by the wheel base L but this overall gain is already incorporated in the control gains. (thanks João Pinto).

p 94

The code example

>> dx.plan(goal, show 0.1);
is incorrect (and syntactically invalid), it should read
>> dx.plan(goal, 0.1);

The optional second argument causes the planner to display the evolution of the distance field every 0.1 seconds.

p 112

The covariance in the text "σd = 2cm" does not match the code.

>> V = diag([0.005, 0.5*pi/180].^2)

should be

>> V = diag([0.02, 0.5*pi/180].^2)

The rest of the example is in fact done with "σd = 2cm" as can be seen by the value of V in the next code block.

p 117

The top equation in (6.9) is incorrect and should be

(thanks Frederic Maire)

p 138

Equation (7.2), the element at row 2 column 4 should be aj sin θi not αj sin θi. (thanks Do Nguyen Tien Thong)

p 139

fifth element σ indicates whether the joint is revolute i=0)j=0) or prismatic i=0)j=1).

(thanks Do Nguyen Tien Thong)

p 140

indicates that the link is prismaticrevolute. (thanks Walter Lucia)

p 152

The inverse kinematics for the 8-link robot are not unique. Recent changes to the ikine() method will give slightly different numerical values for joint coordinates.

p 179

Fig 8.2b is incorrect and should look like

The ellipsoid is a zero-thickness plate in the yz-plane, with zero-width in the x-direction. This indicates (as the book correctly states) that the end-effector can rotate about the y- or z-axes but not the x-axis. (thanks Richard Roberts)

p 184

>> xd = J*qd;
ans =
0.0829 -0.0266  0   0   0 -0.0266

should read

>> xd = J*qd;
>> xd'
ans =
0.0829 -0.0266  0   0   0 -0.0266

(thanks Rafael Perrone).

p 175

An important clarification here is that (8.4) applies for the case where {A} and {B} are attached to the same body, that is, they move together. If the frames are not rigidly attached then (8.4) is simpler and the top-right block is zero.

Although not explicitly stated, the code example is for the case where the two frames are attached to the same body. (thanks Jeff Trinkle)

p 176

The equation for mapping velocity from frame {N} to frame {0} is incorrect, since those frames are not rigidly attached we must use the velocity transform with the top-right block set to zero (see item above).

(thanks Jeff Trinkle)

p 186

An important clarification here is that this relationship applies for the case where {A} and {B} are attached to the same body, that is, they move together. Equation (8.10) is also written the wrong way around and should be

Although not explicitly stated, the code example is for the case where the two frames are attached to the same body. (thanks Jeff Trinkle)

p 188

For (8.15) the leading superscript on the Jacobian should be E not N. (thanks Jeff Trinkle)

p 198

The gravity load increase for the payload case is not as shown. I get

>> mdl_puma560
>> gravload = p560.gravload(qn);
>> p560.payload(2.5, [0, 0, 0.1]);
>> p560.gravload(qn) ./ gravload
ans =
    0.3737    1.5222    2.5416   18.7826   86.8056       NaN

Note that the result for elements 1, 4 and 6 are all to be ignored since they involve division of two almost zero quantities

>> gravload
gravload =
   -0.0000   31.6399    6.0351    0.0000    0.0283         0

The example in 9.1.5 is correct for the case of the robot without payload. This requires that the robot model be reset before this example

>> mdl_puma560

p 205

Error in (9.9) which should read

(thanks Rafael Perrone)

p 213

The top equation on this page should read

The feedforward acceleration should be outside the term Kv(...) (thanks Jeff Trinkle)

p 214

Fig. 9.20 should properly include the feedforward acceleration. That is, the qdd output from the trajectory generator q ¨ * should be added to the signal going into the qdd input of the RNE block. Doing so would improve the error performance of the controller. (thanks Muhammad Tufail)

p 223

Equation (10.1), Planck's radiation formula should not have π in the numerator.

p 247

The matrix cxy should be transposed, that is, the columns are the 2-vectors of cluster chromaticity. Note that the colorseg() function is deprecated and colorkmeans() should be used instead.

p 260

>> cam.T = transl(-1, 0, 0.5) * troty(0.8);
>> cam.mesh(X, Y, Z, 'Tcam', Tcam);

should be

>> Tcam = transl(-1, 0, 0.5) * troty(0.8);
>> cam.mesh(X, Y, Z, 'Tcam', Tcam);

which defines the variable Tcam which is passed to the method cam.mesh() and overrides its default pose.

An alternative approach is to change the pose of the camera and view the mesh

>> cam.T = transl(-1, 0, 0.5) * troty(0.8);
>> cam.mesh(X, Y, Z);

Both approaches are equivalent, but the latter leaves the camera pose unchanged. The code in the book mixes up the two use cases.

p 261

Line 5 of the top code example is wrong

cam.mesh(X, Y, Z, T_cube);

should be

cam.mesh(X, Y, Z, 'Tobj', T_cube);

(thanks Bassam Salameh)

p 294

The function peak returns the peak value not the position of the peak. To obtain the peak positions as shown in this example we need to assign two output arguments and use the value of the second one.

>> peak(n, v)'

should be

>> [py,px] = peak(n, v);
>> px'

The same error appears later on the page

>> peak(n, v, 'scale', 25)'

should be

>> [py,px] = peak(n, v, 'scale', 25);
>> px'

For both examples the values shown as returned by peak() are wrong, they should be one higher.

p 306

Fig 12.16 (a) and (b). Observant readers will note that the gradients have the wrong sign. For Fig 12.16(a) the white strip around the sign should lead, left to right, a strong positive gradient (blue) followed by a strong negative gradient (red).

The figures have this reversed, and this is due to a bug (effective sign flip) in the iconv() function, now fixed.

p 309

(12.4) is not strictly correct. The definition of ∇2I is given by (12.3) whereas this equation describes a Gaussian smoothed Laplacian operator.

p 319

The equation

is incorrect and should read

The last two equations on this page are introduced with the comment that "morphological operations are associative". Only the first equation, for dilations, is associative. The second equation is correct, but it does not represent associativity. (thanks Frederic Maire)

p 329

The code block mid page

delta_v = v .* (k(1) * r.^2 + k(2) * r.^4 + k(3) * r.^6) + ...
     p(1) * (r.^2 + 2 * v.^2) + 2 * p(1) * u .* v;

should be

delta_v = v .* (k(1) * r.^2 + k(2) * r.^4 + k(3) * r.^6) + ...
     p(1) * (r.^2 + 2 * v.^2) + 2 * p(2) * u .* v;

That is, the last term should be have a coefficient of p(2) not p(1). This change will subtly alter Fig 12.36b as well. (thanks Nino Cauli)

p 321

Fig 12.27 uses an inverted color map, where the set pixels are black. This was an aesthetic choice to avoid large areas of black but is confusing since generally I have associated set pixels with the color white.

p 332

The arguments to the function pnmfilt are reversed.

>> rlena = pnmfilt(lena, 'pnmrotate 30');

should be

>> rlena = pnmfilt('pnmrotate 30', lena);

p 336-7

The captions for Fig 13.1 are incorrect. The rows should be labelled a, b, c, d; that is, the top two images are a, the next two images are b and so on. (thanks Frederic Maire).

p 352

The RegionFeature class contains a shape measure (aspect ratio) which is the ratio of the major (a) and minor (b) axis lengths of the equivalent ellipse. The shape measure property, .shape, is b/a which is always less than or equal to one. The display method of the RegionFeature class shows the shape measure correctly but incorrectly labels it as a/b and this is shown in the code examples on pages 352-353, 357 and 358. (thanks ENB339 class)

p 357

It is not stated explicitly in the text, but iblobs() computes the 8-neighbour chain code.

The blob perimeter length was computed incorrectly in the book, and this affects also the value of circularity. The correct answers as given by the fixed code is:

(1) area=1434, cent=(132.9,135.8), theta=-3.10, b/a=0.852, class=1, label=2, touch=0, parent=1, perim=178.0, circ=0.569
(2) area=3380, cent=(95.9,210.9), theta=2.83, b/a=0.888, class=1, label=3, touch=1, parent=0, perim=222.4, circ=0.859  
(3) area=456, cent=(11.7,228.4), theta=-2.98, b/a=0.864, class=1, label=4, touch=1, parent=0, perim=81.0, circ=0.874 

Note also that the property b/a is listed now, not a/b as shown in the book. See also the errata for p. 352.

p 358

The blob perimeter length was computed incorrectly in the book, and this affects also the value of circularity. The correct answers as given by the fixed code is:

(1) area=1375, cent=(94.9,108.2), theta=1.98, b/a=0.648, color=1, label=2, touch=0, parent=1, perim=214.8, circ=0.375
(2) area=795, cent=(204.6,122.4), theta=2.76, b/a=0.645, color=1, label=4, touch=0, parent=1, perim=162.5, circ=0.379

p 365

The property length_v does not exist, it should be length, ie.

>> k = find( lines.length > 100);

p 366

Equation at bottom of page, the last term + 2 δu δv … (thanks Ugo Fabrizi)

p 367

In equation 13.16 the trace value should be squared. (thanks Stephen Fox)

p 420

More formally, given two sets of points MiMj, DjDi ...

p 417

The caption for Fig. 14.36(b) is wrong. The figure is an anaglyph of the rock scene from Fig. 14.20, and clearly not an image of parking meters.

p 421

and consequently some datamodel points DjMj will be unpaired.

p 427

Missing closing parenthesis at the end of the third code example on this page, it should be

>> xc = homtrans(inv(T_est(:,:,k-1), x))

p 438

Figure 14.53, the images caption are incorrect. From top left to bottom right they should be images: 11, 9, 13, and 10 respectively.

p 461

The first equation in (15.2) should read

(thanks Liam O'Sullivan)

(thanks Liam O'Sullivan)

p 482

>> sl_xyzpartitioned

should be

>> sl_partitioned

p 489

>> r = sim('sl_ibvs')

should be

>> r = sim('sl_arm_ibvs')

p 505

At the bottom of the page the code should read

>> q = Quaternion( rotx(0.2) );

p 507

>> q2 = quaternion( roty(0.3) );

should be

>> q2 = Quaternion( roty(0.3) );

p 519

which correspond to ab and ba respectively.

p 523

Note that the second argument to gaussfunc is the variance not standard deviation

p 524

If the variables are uncorrelated the matrix V C would be diagonal.

p 527-528

There's an overall problem with this example in that the referenced equation 6.9 from p117 is itself in error (see errata above). Therefore everything that follows in this appendix does not represent the range and bearing Jacobian discussed on p.117. (thanks David Breneisen)

However the appendix is correct for the MATLAB function as written on p.527, except that the value given for h0 is incorrect, it should be

h0 =

(thanks Henry Carrillo Lindado)

p 536

Errors in the two examples. The first example, top of page, after the vertices have been added, should give.

>> g
     g =
     2 dimensions
     5 vertices
     0 edges
     5 components

note 5 not 4 components.

For the second example on the page, after the edges are added

>> g
     g =
     2 dimensions
     5 vertices
     6 edges
     1 components

note 6 not 5 edges. (thanks Bassam Salameh)