Introduction
After working on the Speedster, it was only fair that my next project should be on something that was more human in character. My aim with this project was to replicate a walking human being (with a humanoid that 'could match its Iron cousin'. With that in mind, the one and only hard-working, but less flamboyant, researcher at Meshack Labs set to work with the aim of privatizing XAML peace).
Requirements
To run the project provided from the download link above, you require either of the following:
- Visual Studio 2010
- Expression Blend 4
NB: If you're using the Express Editions of Visual Studio, ensure that you open the project using Visual Basic Express.
Xaml Man
How It Works
To make Xaml Man walk, just press the right arrow key. Xaml Man will walk on a treadmill inside the well equipped M Labs Humanoid Research Centre so don't worry about him going anywhere. To increase or decrease Xaml Man's walking speed, just move the slider. Moving the slider to the right increases his walking speed and vice versa.
Design and Layout
I designed the Humanoid
, Treadmill
, and Lab_TV
in Expression Design. The rest of the elements were designed/added in Expression Blend.
I will focus primarily on the movement of the legs as their motion is integral in replicating a walking human being. The layout of the legs is as shown in the following screenshot, with element names at the bottom (the same applies to the left leg).
Leg Movements
In order to get a good idea of how to implement the desired motion, I grabbed a pencil and a piece of paper and made good use of a mirror. I walked in front of the mirror posing occasionally to sketch stick figures at positions which I assumed would give me suitable results. I then adjusted the legs/elements in Expression Blend and noted down the angles at positions similar to those of the limbs of the stick figures in my sketches. I only focused on the legs and these were the results (but more elegantly presented than on my piece of paper),
NB: You get to Phase 1 from a standing position where all the angles of the elements of concern are at zero degrees.
The Code
The calculations that make the magic happen are contained in the module MovementCalculations
:
Module MovementCalculations
Public RhtLegAngles() As Integer = {-30, -34, -24, 0}
Public RhtForeLegAngles() As Integer = {56, 26, 18, 1}
Public RhtFootAngles() As Integer = {0, -4, 6, -1}
Public LeftLegAngles() As Integer = {0, 2, 10, -30}
Public LeftForeLegAngles() As Integer = {1, 2, 10, 56}
Public LeftFootAngles() As Integer = {-1, -3, -19, 0}
Public RhtForeLegShift1 As Double = _
Math.Abs(RhtForeLegAngles(0) / RhtLegAngles(0))
Public LeftForeLegShift1 As Double = _
Math.Abs(LeftForeLegAngles(0) / RhtLegAngles(0))
Public LeftFootShift1 As Double = _
(LeftFootAngles(0) / RhtLegAngles(0))
Public PhaseShift2 As Double = _
Math.Abs(RhtLegAngles(1) - RhtLegAngles(0))
Public RhtForeLegShift2 As Decimal = _
Math.Abs(RhtForeLegAngles(1) - RhtForeLegAngles(0)) / PhaseShift2
Public RhtFootShift2 As Double = _
Math.Abs(RhtFootAngles(1) - RhtFootAngles(0)) / PhaseShift2
Public LeftLegShift2 As Double = _
(LeftLegAngles(1) - LeftLegAngles(0)) / PhaseShift2
Public LeftForeLegShift2 As Double = _
(LeftForeLegAngles(1) - LeftForeLegAngles(0)) / PhaseShift2
Public LeftFootShift2 As Double = _
(Math.Abs(LeftFootAngles(1) - LeftFootAngles(0))) / PhaseShift2
Public PhaseShift3 As Double = _
Math.Abs(RhtLegAngles(2) - RhtLegAngles(1))
Public RhtForeLegShift3 As Double = _
(Math.Abs(RhtForeLegAngles(2) - RhtForeLegAngles(1))) / PhaseShift3
Public RhtFootShift3 As Double = _
(RhtFootAngles(2) - RhtFootAngles(1)) / PhaseShift3
Public LeftLegShift3 As Double = _
(LeftLegAngles(2) - LeftLegAngles(1)) / PhaseShift3
Public LeftForeLegShift3 As Double = _
(LeftForeLegAngles(2) - LeftForeLegAngles(1)) / PhaseShift3
Public LeftFootShift3 As Double = _
(Math.Abs(LeftFootAngles(2) - LeftFootAngles(1))) / PhaseShift3
Public PhaseShift4 As Double = _
(RhtLegAngles(3) - RhtLegAngles(2))
Public RhtForeLegShift4 As Double = _
(Math.Abs(RhtForeLegAngles(3) - RhtForeLegAngles(2))) / PhaseShift4
Public RhtFootShift4 As Double = _
(Math.Abs(RhtFootAngles(3) - RhtFootAngles(2))) / PhaseShift4
Public LeftLegShift4 As Double = _
(Math.Abs(LeftLegAngles(3) - LeftLegAngles(2))) / PhaseShift4
Public LeftForeLegShift4 As Double = _
(LeftForeLegAngles(3) - LeftForeLegAngles(2)) / PhaseShift4
Public LeftFootShift4 As Double = _
(LeftFootAngles(3) - LeftFootAngles(2)) / PhaseShift4
End Module
We check which key has been pressed in the MainWindow KeyDown
event handler:
Private Sub MainWindow_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Input.KeyEventArgs) Handles Me.KeyDown
If e.Key = Key.Right Then
Speed = SpeedSlider.Value
WalkForward()
MoveArms()
End If
End Sub
The WalkForward
method does as its name suggests.
Private Sub WalkForward()
If FocusOnRightLeg = True Then
If MoveRightLegUp = True Then
RightLegUp()
Else
RightLegDown()
End If
Else
If MoveLeftLegUp = True Then
LeftLegUp()
Else
LeftLegDown()
End If
End If
RightLeg.RenderTransform = RightLegTr
RghtFrLegFoot.RenderTransform = RightForeLegTr
RightFoot.RenderTransform = RightFootTr
LeftLeg.RenderTransform = LeftLegTr
LeftFrLegFoot.RenderTransform = LeftForeLegTr
LeftFoot.RenderTransform = LeftFootTr
Treadmiller.RenderTransform = TreadmillerTr
RightArm.RenderTransform = RightArmTr
LeftArm.RenderTransform = LeftArmTr
End Sub
In the WalkForward
method, we make method calls based on various boolean values. The RightLegUp
method rotates the RightLeg
and its appendages, together with those of the LeftLeg
, from Phase 1 to Phase 2.
Private Sub RightLegUp()
If RightLegTr.Angle = 0 And LeftLegTr.Angle = 0 Then
RightLegTr.Angle -= 1 * Speed
End If
If RightLegTr.Angle > -30 Then
RightLegTr.Angle -= 1 * Speed
If RightForeLegTr.Angle < 56 Then
RightForeLegTr.Angle += RhtForeLegShift1 * Speed
End If
If LeftForeLegTr.Angle < 1 Then
LeftForeLegTr.Angle += LeftForeLegShift1 * Speed
LeftFootTr.Angle -= LeftFootShift1 * Speed
End If
End If
If RightLegTr.Angle <= -30 And RightLegTr.Angle > -34 Then
RightLegTr.Angle -= 0.5 * Speed
RightForeLegTr.Angle -= (RhtForeLegShift2 * 0.5) * Speed
RightFootTr.Angle -= (RhtFootShift2 * 0.5) * Speed
LeftLegTr.Angle += (LeftLegShift2 * 0.5) * Speed
LeftForeLegTr.Angle += (LeftForeLegShift2 * 0.5) * Speed
LeftFootTr.Angle -= (LeftFootShift2 * 0.5) * Speed
End If
TreadmillerTr.Angle -= (3 * Speed)
If RightLegTr.Angle <= -34 Then
MoveRightLegUp = False
End If
End Sub
The RightLegDown
method rotates the RightLeg
and its appendages, together with those of the LeftLeg
, from Phase 3 to Phase 4.
Private Sub RightLegDown()
If RightLegTr.Angle < -24 Then
RightLegTr.Angle += 1 * Speed
RightForeLegTr.Angle -= RhtForeLegShift3 * Speed
RightFootTr.Angle += RhtFootShift3 * Speed
LeftLegTr.Angle += LeftLegShift3 * Speed
LeftForeLegTr.Angle += LeftForeLegShift3 * Speed
LeftFootTr.Angle -= LeftFootShift3 * Speed
ShiftHumanoidDown()
End If
If RightLegTr.Angle < 0 And RightLegTr.Angle >= -24 Then
RightLegTr.Angle += 1 * Speed
RightForeLegTr.Angle -= RhtForeLegShift4 * Speed
RightFootTr.Angle -= RhtFootShift4 * Speed
LeftLegTr.Angle -= LeftLegShift4 * Speed
LeftForeLegTr.Angle += LeftForeLegShift4 * Speed
LeftFootTr.Angle += LeftFootShift4 * Speed
ShiftHumanoidUp()
End If
TreadmillerTr.Angle -= (3 * Speed)
If RightLegTr.Angle >= 0 Then
FocusOnRightLeg = False
RightLegTr.Angle = 0
RightForeLegTr.Angle = 1
RightFootTr.Angle = -1
LeftLegTr.Angle = -30
LeftForeLegTr.Angle = 56
LeftFootTr.Angle = 0
Canvas.SetTop(Humanoid, Y_Pos)
End If
End Sub
The code in the LeftLegUp
method is similar to that of the RightLegUp
method with a change of some variable names, but the logic is the same. The code for the initial position and Phase 1 is also missing.
Private Sub LeftLegUp()
If LeftLegTr.Angle <= -30 And LeftLegTr.Angle > -34 Then
LeftLegTr.Angle -= 0.5 * Speed
LeftForeLegTr.Angle -= (RhtForeLegShift2 * 0.5) * Speed
LeftFootTr.Angle -= (RhtFootShift2 * 0.5) * Speed
RightLegTr.Angle += (LeftLegShift2 * 0.5) * Speed
RightForeLegTr.Angle += (LeftForeLegShift2 * 0.5) * Speed
RightFootTr.Angle -= (LeftFootShift2 * 0.5) * Speed
End If
TreadmillerTr.Angle -= (3 * Speed)
If LeftLegTr.Angle <= -34 Then
MoveLeftLegUp = False
End If
End Sub
The code in the LeftLegDown
method is also similar to RightLegDown
method with a change of some variable names.
Private Sub LeftLegDown()
If LeftLegTr.Angle < -24 Then
LeftLegTr.Angle += 1 * Speed
LeftForeLegTr.Angle -= RhtForeLegShift3 * Speed
LeftFootTr.Angle += RhtFootShift3 * Speed
RightLegTr.Angle += LeftLegShift3 * Speed
RightForeLegTr.Angle += LeftForeLegShift3 * Speed
RightFootTr.Angle -= LeftFootShift3 * Speed
ShiftHumanoidDown()
End If
If LeftLegTr.Angle < 0 And LeftLegTr.Angle >= -24 Then
LeftLegTr.Angle += 1 * Speed
LeftForeLegTr.Angle -= RhtForeLegShift4 * Speed
LeftFootTr.Angle -= RhtFootShift4 * Speed
RightLegTr.Angle -= LeftLegShift4 * Speed
RightForeLegTr.Angle += LeftForeLegShift4 * Speed
RightFootTr.Angle += LeftFootShift4 * Speed
ShiftHumanoidUp()
End If
TreadmillerTr.Angle -= (3 * Speed)
If LeftLegTr.Angle >= 0 Then
FocusOnRightLeg = True
MoveRightLegUp = True
MoveLeftLegUp = True
LeftLegTr.Angle = 0
LeftForeLegTr.Angle = 1
LeftFootTr.Angle = -1
RightLegTr.Angle = -30
RightForeLegTr.Angle = 56
RightFootTr.Angle = 0
Canvas.SetTop(Humanoid, Y_Pos)
End If
End Sub
Conclusion
Thanks for taking the time out to read this article. I hope it was of benefit in one way or another. I have already done the design work and a bit of coding so if you want to add some extra features to the Xaml Man, the M Labs Humanoid Research Centre is available in Expression Blend and Visual Studio once you download the source files. Cheers!
History
- 3rd January, 2011: Initial post