Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

XAML Man

0.00/5 (No votes)
3 Jan 2011 1  
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:

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here