Click here to Skip to main content
Click here to Skip to main content

XAML Man

, 3 Jan 2011
Rate this:
Please Sign up or sign in to vote.
A WPF humanoid
Prize winner in Competition "Best VB.NET article of January 2011"

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:

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:

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

    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.

    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

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

About the Author

Meshack Musundi
Software Developer
Kenya Kenya
Meshack is an avid programmer with a bias towards WPF and VB.NET. He has about 5 years of programming experience initially starting off with Java before shifting to .NET, thanks to the allure of WPF. He has developed several applications, and written several articles about them, which can be viewed here on CodeProject. He currently resides in a small town in Kiambu county, Kenya.
 
Awards;
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • Best VB.NET article of August 2013
  • Best VB.NET article of February 2013
  • Best VB.NET article of October 2012
  • Best VB.NET article of July 2012
  • Best VB.NET article of February 2012
  • Best VB.NET article of January 2012
  • Best VB.NET article of November 2011
  • Best VB.NET article of June 2011
  • Best VB.NET article of May 2011
  • Best VB.NET article of March 2011
  • Best VB.NET article of February 2011
  • Best VB.NET article of January 2011
  • Best VB.NET article of December 2010
  • Best VB.NET article of November 2010

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermoethuta1106591i8-Aug-12 9:37 
GeneralRe: My vote of 5 PinmvpMeshack Musundi20-Aug-12 20:48 
QuestionMy vote 5 PinmemberManoj K Bhoir27-Jun-12 1:19 
GeneralRe: My vote 5 PinmvpMeshack Musundi27-Jun-12 21:32 
GeneralMy vote of 5 PinmvpRichard MacCutchan23-May-12 22:59 
GeneralRe: My vote of 5 PinmvpMeshack Musundi27-Jun-12 21:31 
Questionvery nice PinmemberCIDev29-Jul-11 3:02 
AnswerRe: very nice PinmemberMeshack Musundi29-Jul-11 4:52 
GeneralVote of 5 PinmemberJyothikarthk11-Apr-11 20:57 
GeneralRe: Vote of 5 PinmemberMeshack Musundi11-Apr-11 22:08 
GeneralMy vote of 5 PinmemberGeorg Kalus28-Feb-11 12:34 
GeneralRe: My vote of 5 PinmemberMeshack Musundi28-Feb-11 19:30 
GeneralCongratulations PinmemberBryian Tan25-Feb-11 14:26 
GeneralRe: Congratulations PinmemberMeshack Musundi25-Feb-11 19:07 
GeneralRe: Congratulations PinmemberZac Greve1-May-12 3:31 
GeneralRe: Congratulations PinmvpMeshack Musundi3-May-12 21:40 
GeneralMy vote of 5 PinmemberAnt210025-Feb-11 9:06 
GeneralRe: My vote of 5 PinmemberMeshack Musundi25-Feb-11 19:05 
GeneralMy vote of 5 PinmemberBryian Tan21-Feb-11 4:24 
GeneralRe: My vote of 5 PinmemberMeshack Musundi21-Feb-11 19:27 
GeneralMy vote of 5 PinmvpAbhinav S9-Feb-11 3:04 
GeneralRe: My vote of 5 PinmemberMeshack Musundi11-Feb-11 18:58 
GeneralMy Vote of 5 PinmemberRaviRanjankr8-Feb-11 18:49 
GeneralRe: My Vote of 5 PinmemberMeshack Musundi8-Feb-11 19:04 
GeneralMy vote of 5 PinmemberStewBob20-Jan-11 9:51 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 3 Jan 2011
Article Copyright 2011 by Meshack Musundi
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid