Click here to Skip to main content
16,016,882 members
Articles / Desktop Programming / WPF

XAML Man

Rate me:
Please Sign up or sign in to vote.
4.92/5 (79 votes)
3 Jan 2011CPOL3 min read 136.6K   3.3K   86   64
A WPF humanoid

Screenshot1.png

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).

Screenshot2.png

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),

Screenshot3.png

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:

VB.NET
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}

    ' Get variable values for getting limbs 
    ' to Phase 1.
    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))

    ' Get variable values for getting limbs
    ' to Phase 2.
    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

    ' Phase 3s
    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

    ' Phase 4s
    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:

VB.NET
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.

VB.NET
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.

VB.NET
Private Sub RightLegUp()
    ' The initial start of the walk...
    If RightLegTr.Angle = 0 And LeftLegTr.Angle = 0 Then
        RightLegTr.Angle -= 1 * Speed
    End If

    ' This only executes once to get to Phase 1.
    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

    ' Get to Phase 2.
    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.

VB.NET
Private Sub RightLegDown()
    ' Get to Phase 3.
    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

        ' Adjust Y position to ensure base of foot
        ' is always on the treadmill.
        ShiftHumanoidDown()
    End If

    ' Get to Phase 4.
    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

    ' Rotate red rectangle on treadmill.
    TreadmillerTr.Angle -= (3 * Speed)

    If RightLegTr.Angle >= 0 Then
        FocusOnRightLeg = False
        ' Set angles to Phase 1 stance.
        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.

VB.NET
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.

VB.NET
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

        ' Set angles to Phase 1 stance.
        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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Kenya Kenya
Experienced C# software developer with a passion for WPF.

Awards,
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • CodeProject MVP 2021

Comments and Discussions

 
GeneralRe: Great man !!! Pin
Meshack Musundi3-Jan-11 22:24
professionalMeshack Musundi3-Jan-11 22:24 
GeneralMy vote of 5 Pin
Mamta D3-Jan-11 17:35
Mamta D3-Jan-11 17:35 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 18:34
professionalMeshack Musundi3-Jan-11 18:34 
GeneralMy vote of 5 Pin
Kunal Chowdhury «IN»3-Jan-11 16:16
professionalKunal Chowdhury «IN»3-Jan-11 16:16 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 18:29
professionalMeshack Musundi3-Jan-11 18:29 
GeneralMy vote of 5 Pin
Judah Gabriel Himango3-Jan-11 15:50
sponsorJudah Gabriel Himango3-Jan-11 15:50 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 18:23
professionalMeshack Musundi3-Jan-11 18:23 
GeneralYou're the man Pin
BigWCat3-Jan-11 5:03
professionalBigWCat3-Jan-11 5:03 
Out of this world. My vote of BIG 5.
GeneralRe: You're the man Pin
Meshack Musundi3-Jan-11 6:32
professionalMeshack Musundi3-Jan-11 6:32 
GeneralMy vote of 5 Pin
Slacker0073-Jan-11 4:55
professionalSlacker0073-Jan-11 4:55 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 4:57
professionalMeshack Musundi3-Jan-11 4:57 
GeneralMy vote of 5 Pin
SledgeHammer013-Jan-11 4:50
SledgeHammer013-Jan-11 4:50 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 4:53
professionalMeshack Musundi3-Jan-11 4:53 
GeneralMy vote of 5 Pin
prasad023-Jan-11 4:31
prasad023-Jan-11 4:31 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 4:50
professionalMeshack Musundi3-Jan-11 4:50 
Generalman in the mirror Pin
Member 35930643-Jan-11 4:26
Member 35930643-Jan-11 4:26 
GeneralRe: man in the mirror Pin
Meshack Musundi3-Jan-11 4:50
professionalMeshack Musundi3-Jan-11 4:50 
GeneralMy vote of 5 Pin
Nish Nishant3-Jan-11 4:20
sitebuilderNish Nishant3-Jan-11 4:20 
GeneralRe: My vote of 5 Pin
Meshack Musundi3-Jan-11 4:46
professionalMeshack Musundi3-Jan-11 4:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.