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

Amble Avalona

0.00/5 (No votes)
2 Feb 2011 1  
A WPF animaloid
Screenshot1.png

Introduction

Following in the footsteps of my previous article, it would have been improper not to take on the task of xamlizing a four-legged creature. In short, I decided to work on a WPF project that replicated a walking four-legged animal.

Requirements

To run the project provided from the download link above, you require either of the following:

  • Visual Studio 2010
  • Expression Blend

If you're using VS 2008, you can download the source files from here.

NB: Ensure that you open the solution using Visual Basic Express if you're using the Express edition of Visual Studio.

Avalona

How It Works

To make Avalona walk, just press the right arrow key. Avalona will amble on a treadmill, this time the action taking place inside the M Labs Animaloid Research Centre.

Ambling

The amble is an easy gait (way of walking), most common in horses, where at least one leg/hoof touches the ground during the phases of motion. There is no suspension phase, i.e., a phase where all the legs are entirely off the ground. This was the primary reason I decided to replicate the amble. During this gait, a maximum of two legs can/will support the weight of the animal. The following sequence of photographs show the phases followed during this gait.

Screenshot2.png

A short and detailed explanation of the phases of movement shown above can be found here.

There are 11 phases in the photos above, which are a bit of a handful, so I narrowed it down to 5 phases which would offer me equally suitable results.

Screenshot3.png

From the initial sequence of photos, I chose the 4th, 5th, 6th, 7th, and 9th phases.

If you want to, you can watch a video of a horse ambling here.

Design and Layout

I designed Avalona, Treadmill, and the Lab_Screen in Expression Design. The rest of the elements were added in Expression Blend. The following image shows the layout of the elements of concern and their names (the same applies to the left legs),

Screenshot4.png

NB: The center of the joints of each section of Avalona act as center points.

Leg Movement

The standing posture of Avalona and that of a horse are slightly different. Avalona's limbs are more slightly angled especially those of the hind legs.

Screenshot5.png

This presented a bit of a challenge in my attempt at replicating the amble. Because of this difference, Avalona's gait is a slightly modified version of a horse's amble.

In order to get a better picture of how to proceed, I drew stick figures of the ambling horse and then drew stick figures of a ambling Avalona, taking into account their differences in standing posture. I then adjusted the elements of concern in Expression Blend, at positions similar to those of the stick figures, noting down the angles which I felt would offer suitable results. These were the results:

Screenshot6.png

Screenshot7.png

The Code

The calculations that provide us with the necessary wizardry are found in the module MovementCalculations:

Module MovementCalculations
    Public RhtHindLeg_A_Angles() As Integer = {4, 8, 14, -4, -14}
    Public RhtHindLeg_B_Angles() As Integer = {4, 8, 14, 20, -10}
    Public RhtHindLeg_C_Angles() As Integer = {-4, -10, -31, -42, 4}
    Public RhtHindLegPawAngles() As Integer = {-4, 2, 3, 22, 20}

    Public LeftHindLeg_A_Angles() As Integer = {-14, -12, -9, -5, 4}
    Public LeftHindLeg_B_Angles() As Integer = {-10, -14, -20, -10, 4}
    Public LeftHindLeg_C_Angles() As Integer = {4, 9, 21, 12, -4}
    Public LeftHindLegPawAngles() As Integer = {20, 22, 8, 3, -4}

    Public RhtForeLeg_A_Angles() As Integer = {3, 4, 5, 9, 6}
    Public RhtForeLeg_B_Angles() As Integer = {2, 9, 13, 15, -41}
    Public RhtForeLeg_C_Angles() As Integer = {0, 0, 0, 18, 68}
    Public RhtForeLegPawAngles() As Integer = {-5, -13, -18, -25, -31}

    Public LeftForeLeg_A_Angles() As Integer = {6, 9, 1, -8, 3}
    Public LeftForeLeg_B_Angles() As Integer = {-41, -60, -46, -8, 2}
    Public LeftForeLeg_C_Angles() As Integer = {68, 66, 55, 0, 0}
    Public LeftForeLegPawAngles() As Integer = {-31, -16, -8, 29, -5}

    ' Get to Phase 1
    Public LeftHindLeg_A_Shift1 As Double = _
    Math.Abs(LeftHindLeg_A_Angles(0) / RhtHindLeg_A_Angles(0))
    Public LeftHindLeg_B_Shift1 As Double = _
    Math.Abs(LeftHindLeg_B_Angles(0) / RhtHindLeg_A_Angles(0))
    Public LeftHindLeg_C_Shift1 As Double = _
    (LeftHindLeg_C_Angles(0) / RhtHindLeg_A_Angles(0))
    Public LeftHindLegPawShift1 As Double = _
    (LeftHindLegPawAngles(0) / RhtHindLeg_A_Angles(0))

    Public RhtForeLeg_A_Shift1 As Double = _
    (RhtForeLeg_A_Angles(0) / RhtHindLeg_A_Angles(0))
    Public RhtForeLeg_B_Shift1 As Double = _
    (RhtForeLeg_B_Angles(0) / RhtHindLeg_A_Angles(0))
    Public RhtForeLegPawShift1 As Double = _
    Math.Abs(RhtForeLegPawAngles(0) / RhtHindLeg_A_Angles(0))

    Public LeftForeLeg_A_Shift1 As Double = _
    (LeftForeLeg_A_Angles(0) / RhtHindLeg_A_Angles(0))
    Public LeftForeLeg_B_Shift1 As Double = _
    Math.Abs(LeftForeLeg_B_Angles(0) / RhtHindLeg_A_Angles(0))
    Public LeftForeLeg_C_Shift1 As Double = _
    (LeftForeLeg_C_Angles(0) / RhtHindLeg_A_Angles(0))
    Public LeftForeLegPawShift1 As Double = _
    Math.Abs(LeftForeLegPawAngles(0) / RhtHindLeg_A_Angles(0))

    ' Phase 2s
    Public Phase2Shift As Double = _
    (RhtHindLeg_A_Angles(1) - RhtHindLeg_A_Angles(0))

    Public RhtHindLeg_B_Shift2 As Double = _
    (RhtHindLeg_B_Angles(1) - RhtHindLeg_B_Angles(0)) / Phase2Shift
    Public RhtHindLeg_C_Shift2 As Double = _
    Math.Abs(RhtHindLeg_C_Angles(1) - RhtHindLeg_C_Angles(0)) / Phase2Shift
    Public RhtHindLegPawShift2 As Double = _
    (RhtHindLegPawAngles(1) - RhtHindLegPawAngles(0)) / Phase2Shift

    Public LeftHindLeg_A_Shift2 As Double = _
    (LeftHindLeg_A_Angles(1) - LeftHindLeg_A_Angles(0)) / Phase2Shift
    Public LeftHindLeg_B_Shift2 As Double = _
    Math.Abs(LeftHindLeg_B_Angles(1) - LeftHindLeg_B_Angles(0)) / Phase2Shift
    Public LeftHindLeg_C_Shift2 As Double = _
    (LeftHindLeg_C_Angles(1) - LeftHindLeg_C_Angles(0)) / Phase2Shift
    Public LeftHindLegPawShift2 As Double = _
    (LeftHindLegPawAngles(1) - LeftHindLegPawAngles(0)) / Phase2Shift

    Public RhtForeLeg_A_Shift2 As Double = _
    (RhtForeLeg_A_Angles(1) - RhtForeLeg_A_Angles(0)) / Phase2Shift
    Public RhtForeLeg_B_Shift2 As Double = _
    (RhtForeLeg_B_Angles(1) - RhtForeLeg_B_Angles(0)) / Phase2Shift
    Public RhtForeLegPawShift2 As Double = _
    Math.Abs(RhtForeLegPawAngles(1) - RhtForeLegPawAngles(0)) / Phase2Shift

    Public LeftForeLeg_A_Shift2 As Double = _
    (LeftForeLeg_A_Angles(1) - LeftForeLeg_A_Angles(0)) / Phase2Shift
    Public LeftForeLeg_B_Shift2 As Double = _
    Math.Abs(LeftForeLeg_B_Angles(1) - LeftForeLeg_B_Angles(0)) / Phase2Shift
    Public LeftForeLeg_C_Shift2 As Double = _
    Math.Abs(LeftForeLeg_C_Angles(1) - LeftForeLeg_C_Angles(0)) / Phase2Shift
    Public LeftForeLegPawShift2 As Double = _
    (LeftForeLegPawAngles(1) - LeftForeLegPawAngles(0)) / Phase2Shift

    ' Phase 3s
    Public Phase3Shift As Double = _
    (RhtHindLeg_A_Angles(2) - RhtHindLeg_A_Angles(1))

    Public RhtHindLeg_B_Shift3 As Double = _
    (RhtHindLeg_B_Angles(2) - RhtHindLeg_B_Angles(1)) / Phase3Shift
    Public RhtHindLeg_C_Shift3 As Double = _
    Math.Abs(RhtHindLeg_C_Angles(2) - RhtHindLeg_C_Angles(1)) / Phase3Shift
    Public RhtHindLegPawShift3 As Double = _
    (RhtHindLegPawAngles(2) - RhtHindLegPawAngles(1)) / Phase3Shift

    Public LeftHindLeg_A_Shift3 As Double = _
    (LeftHindLeg_A_Angles(2) - LeftHindLeg_A_Angles(1)) / Phase3Shift
    Public LeftHindLeg_B_Shift3 As Double = _
    Math.Abs(LeftHindLeg_B_Angles(2) - LeftHindLeg_B_Angles(1)) / Phase3Shift
    Public LeftHindLeg_C_Shift3 As Double = _
    (LeftHindLeg_C_Angles(2) - LeftHindLeg_C_Angles(1)) / Phase3Shift
    Public LeftHindLegPawShift3 As Double = _
    Math.Abs(LeftHindLegPawAngles(2) - LeftHindLegPawAngles(1)) / Phase3Shift

    Public RhtForeLeg_A_Shift3 As Double = _
    (RhtForeLeg_A_Angles(2) - RhtForeLeg_A_Angles(1)) / Phase3Shift
    Public RhtForeLeg_B_Shift3 As Double = _
    (RhtForeLeg_B_Angles(2) - RhtForeLeg_B_Angles(1)) / Phase3Shift
    Public RhtForeLegPawShift3 As Double = _
    Math.Abs(RhtForeLegPawAngles(2) - RhtForeLegPawAngles(1)) / Phase3Shift

    Public LeftForeLeg_A_Shift3 As Double = _
    Math.Abs(LeftForeLeg_A_Angles(2) - LeftForeLeg_A_Angles(1)) / Phase3Shift
    Public LeftForeLeg_B_Shift3 As Double = _
    (LeftForeLeg_B_Angles(2) - LeftForeLeg_B_Angles(1)) / Phase3Shift
    Public LeftForeLeg_C_Shift3 As Double = _
    Math.Abs(LeftForeLeg_C_Angles(2) - LeftForeLeg_C_Angles(1)) / Phase3Shift
    Public LeftForeLegPawShift3 As Double = _
    (LeftForeLegPawAngles(2) - LeftForeLegPawAngles(1)) / Phase3Shift

    ' Phase 4s
    Public Phase4Shift As Double = _
    Math.Abs(RhtHindLeg_A_Angles(3) - RhtHindLeg_A_Angles(2))

    Public RhtHindLeg_B_Shift4 As Double = _
    (RhtHindLeg_B_Angles(3) - RhtHindLeg_B_Angles(2)) / Phase4Shift
    Public RhtHindLeg_C_Shift4 As Double = _
    Math.Abs(RhtHindLeg_C_Angles(3) - RhtHindLeg_C_Angles(2)) / Phase4Shift
    Public RhtHindLegPawShift4 As Double = _
    (RhtHindLegPawAngles(3) - RhtHindLegPawAngles(2)) / Phase4Shift

    Public LeftHindLeg_A_Shift4 As Double = _
    (LeftHindLeg_A_Angles(3) - LeftHindLeg_A_Angles(2)) / Phase4Shift
    Public LeftHindLeg_B_Shift4 As Double = _
    (LeftHindLeg_B_Angles(3) - LeftHindLeg_B_Angles(2)) / Phase4Shift
    Public LeftHindLeg_C_Shift4 As Double = _
    Math.Abs(LeftHindLeg_C_Angles(3) - LeftHindLeg_C_Angles(2)) / Phase4Shift
    Public LeftHindLegPawShift4 As Double = _
    Math.Abs(LeftHindLegPawAngles(3) - LeftHindLegPawAngles(2)) / Phase4Shift

    Public RhtForeLeg_A_Shift4 As Double = _
    (RhtForeLeg_A_Angles(3) - RhtForeLeg_A_Angles(2)) / Phase4Shift
    Public RhtForeLeg_B_Shift4 As Double = _
    (RhtForeLeg_B_Angles(3) - RhtForeLeg_B_Angles(2)) / Phase4Shift
    Public RhtForeLeg_C_Shift4 As Double = _
    (RhtForeLeg_C_Angles(3)) / Phase4Shift
    Public RhtForeLegPawShift4 As Double = _
    Math.Abs(RhtForeLegPawAngles(3) - RhtForeLegPawAngles(2)) / Phase4Shift

    Public LeftForeLeg_A_Shift4 As Double = _
    Math.Abs(LeftForeLeg_A_Angles(3) - LeftForeLeg_A_Angles(2)) / Phase4Shift
    Public LeftForeLeg_B_Shift4 As Double = _
    (LeftForeLeg_B_Angles(3) - LeftForeLeg_B_Angles(2)) / Phase4Shift
    Public LeftForeLeg_C_Shift4 As Double = _
    CDbl((LeftForeLeg_C_Angles(2)) / Phase4Shift)
    Public LeftForeLegPawShift4 As Double = _
    (LeftForeLegPawAngles(3) - LeftForeLegPawAngles(2)) / Phase4Shift

    ' Phase 5s
    Public Phase5Shift As Double = _
    Math.Abs(RhtHindLeg_A_Angles(4) - RhtHindLeg_A_Angles(3))

    Public RhtHindLeg_B_Shift5 As Double = _
    Math.Abs(RhtHindLeg_B_Angles(4) - RhtHindLeg_B_Angles(3)) / Phase5Shift
    Public RhtHindLeg_C_Shift5 As Double = _
    (RhtHindLeg_C_Angles(4) - RhtHindLeg_C_Angles(3)) / Phase5Shift
    Public RhtHindLegPawShift5 As Double = _
    Math.Abs(RhtHindLegPawAngles(4) - RhtHindLegPawAngles(3)) / Phase5Shift

    Public LeftHindLeg_A_Shift5 As Double = _
    (LeftHindLeg_A_Angles(4) - LeftHindLeg_A_Angles(3)) / Phase5Shift
    Public LeftHindLeg_B_Shift5 As Double = _
    (LeftHindLeg_B_Angles(4) - LeftHindLeg_B_Angles(3)) / Phase5Shift
    Public LeftHindLeg_C_Shift5 As Double = _
    Math.Abs(LeftHindLeg_C_Angles(4) - LeftHindLeg_C_Angles(3)) / Phase5Shift
    Public LeftHindLegPawShift5 As Double = _
    Math.Abs(LeftHindLegPawAngles(4) - LeftHindLegPawAngles(3)) / Phase5Shift

    Public RhtForeLeg_A_Shift5 As Double = _
    Math.Abs(RhtForeLeg_A_Angles(4) - RhtForeLeg_A_Angles(3)) / Phase5Shift
    Public RhtForeLeg_B_Shift5 As Double = _
    Math.Abs(RhtForeLeg_B_Angles(4) - RhtForeLeg_B_Angles(3)) / Phase5Shift
    Public RhtForeLeg_C_Shift5 As Double = _
    (RhtForeLeg_C_Angles(4) - RhtForeLeg_C_Angles(3)) / Phase5Shift
    Public RhtForeLegPawShift5 As Double = _
    (RhtForeLegPawAngles(4) - RhtForeLegPawAngles(3)) / Phase5Shift

    Public LeftForeLeg_A_Shift5 As Double = _
    (LeftForeLeg_A_Angles(4) - LeftForeLeg_A_Angles(3)) / Phase5Shift
    Public LeftForeLeg_B_Shift5 As Double = _
    (LeftForeLeg_B_Angles(4) - LeftForeLeg_B_Angles(3)) / Phase5Shift
    Public LeftForeLegPawShift5 As Double = _
    Math.Abs(LeftForeLegPawAngles(4) - LeftForeLegPawAngles(3)) / Phase5Shift
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
        WalkForward()
    End If
End Sub

The WalkForward method does as its name suggests:

    Private Sub WalkForward()
        If FocusOnRightHind = True Then
            If MoveRhtLegBackwards = True Then
                RightHindBack()
            Else
                RightHindForward()
            End If
        Else
            If MoveLeftLegBackwards = True Then
                LeftHindBack()
            Else
                LeftHindForward()
            End If
        End If

        TreadmillRedTr.Angle -= 5

        RightHindLeg_A.RenderTransform = RhtHindLeg_A_Tr
        RightHindLeg_B.RenderTransform = RhtHindLeg_B_Tr
        RightHindLeg_C.RenderTransform = RhtHindLeg_C_Tr
        RightHindLegPaw.RenderTransform = RhtHindPawTr

        LeftHindLeg_A.RenderTransform = LeftHindLeg_A_Tr
        LeftHindLeg_B.RenderTransform = LeftHindLeg_B_Tr
        LeftHindLeg_C.RenderTransform = LeftHindLeg_C_Tr
        LeftHindLegPaw.RenderTransform = LeftHindPawTr

        RightForeLeg_A.RenderTransform = RhtForeLeg_A_Tr
        RightForeLeg_B.RenderTransform = RhtForeLeg_B_Tr
        RightForeLeg_C.RenderTransform = RhtForeLeg_C_Tr
        RightForeLegPaw.RenderTransform = RhtForePawTr

        LeftForeLeg_A.RenderTransform = LeftForeLeg_A_Tr
        LeftForeLeg_B.RenderTransform = LeftForeLeg_B_Tr
        LeftForeLeg_C.RenderTransform = LeftForeLeg_C_Tr
        LeftForeLegPaw.RenderTransform = LeftForePawTr

        TreadmillRedGroup.RenderTransform = TreadmillRedTr
    End Sub

In the method above, method calls are made based on the values of various variables, of Boolean type. The RightHindBack method rotates the various sections of Avalona's legs from the standing position to Phase 3. It later alternates to rotating elements from Phase 1 to Phase 3.

    Private Sub RightHindBack()
        ' Get to Phase 1. This executes only once.
        If RhtHindLeg_A_Tr.Angle < 4 Then
            RhtHindLeg_A_Tr.Angle += 1 * speed
            RhtHindLeg_B_Tr.Angle += 1 * speed
            RhtHindLeg_C_Tr.Angle -= 1 * speed
            RhtHindPawTr.Angle -= 1 * speed

            LeftHindLeg_A_Tr.Angle -= LeftHindLeg_A_Shift1 * speed
            LeftHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift1 * speed
            LeftHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift1 * speed
            LeftHindPawTr.Angle += LeftHindLegPawShift1 * speed

            RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift1 * speed
            RhtForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift1 * speed
            RhtForePawTr.Angle -= RhtForeLegPawShift1 * speed

            LeftForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift1 * speed
            LeftForeLeg_B_Tr.Angle -= LeftForeLeg_B_Shift1 * speed
            LeftForeLeg_C_Tr.Angle += LeftForeLeg_C_Shift1 * speed
            LeftForePawTr.Angle -= LeftForeLegPawShift1 * speed
        End If
        ' Get to Phase 2
        If RhtHindLeg_A_Tr.Angle >= 4 And RhtHindLeg_A_Tr.Angle < 8 Then
            RhtHindLeg_A_Tr.Angle += 1 * speed
            RhtHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift2 * speed
            RhtHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift2 * speed
            RhtHindPawTr.Angle += RhtHindLegPawShift2 * speed

            LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift2 * speed
            LeftHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift2 * speed
            LeftHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift2 * speed
            LeftHindPawTr.Angle += LeftHindLegPawShift2 * speed

            RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift2 * speed
            RhtForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift2 * speed
            RhtForePawTr.Angle -= RhtForeLegPawShift2 * speed

            LeftForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift2 * speed
            LeftForeLeg_B_Tr.Angle -= LeftForeLeg_B_Shift2 * speed
            LeftForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift2 * speed
            LeftForePawTr.Angle += LeftForeLegPawShift2 * speed
        End If
        ' Get to Phase 3
        If RhtHindLeg_A_Tr.Angle >= 8 And RhtHindLeg_A_Tr.Angle < 14 Then
            RhtHindLeg_A_Tr.Angle += 1 * speed
            RhtHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift3 * speed
            RhtHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift3 * speed
            RhtHindPawTr.Angle += RhtHindLegPawShift3 * speed

            LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift3 * speed
            LeftHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift3 * speed
            LeftHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift3 * speed
            LeftHindPawTr.Angle -= LeftHindLegPawShift3 * speed

            RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift3 * speed
            RhtForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift3 * speed
            RhtForePawTr.Angle -= RhtForeLegPawShift3 * speed

            LeftForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift3 * speed
            LeftForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift3 * speed
            LeftForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift3 * speed
            LeftForePawTr.Angle += LeftForeLegPawShift3 * speed
        End If

        If RhtHindLeg_A_Tr.Angle = 14 Then
            MoveRhtLegBackwards = False
        End If
    End Sub

The RightHindForward method rotates the various sections of Avalona's legs from Phase 3 to Phase 5.

    Private Sub RightHindForward()
        ' Get to Phase 4
        If RhtHindLeg_A_Tr.Angle <= 14 And RhtHindLeg_A_Tr.Angle > -4 Then
            RhtHindLeg_A_Tr.Angle -= 1 * speed
            RhtHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift4 * speed
            RhtHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift4 * speed
            RhtHindPawTr.Angle += RhtHindLegPawShift4 * speed

            LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift4 * speed
            LeftHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift4 * speed
            LeftHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift4 * speed
            LeftHindPawTr.Angle -= LeftHindLegPawShift4 * speed

            RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift4 * speed
            RhtForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift4 * speed
            RhtForePawTr.Angle -= RhtForeLegPawShift4 * speed

            LeftForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift4 * speed
            LeftForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift4 * speed
            LeftForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift4 * speed
            LeftForePawTr.Angle += LeftForeLegPawShift4 * speed

            ShiftAvalonaUp()
        End If
        If RhtHindLeg_A_Tr.Angle = -4 Then
            LeftForeLeg_C_Tr.Angle = 0
        End If
        ' Get to Phase 5
        If RhtHindLeg_A_Tr.Angle <= -4 And RhtHindLeg_A_Tr.Angle > -14 Then
            ' Multiply by 0.5 since Phase 8 in the original sequence  
            ' was jumped when creating the 5 Phase sequence.
            RhtHindLeg_A_Tr.Angle -= 1 * speed * 0.5
            RhtHindLeg_B_Tr.Angle -= RhtHindLeg_B_Shift5 * speed * 0.5
            RhtHindLeg_C_Tr.Angle += RhtHindLeg_C_Shift5 * speed * 0.5
            RhtHindPawTr.Angle -= RhtHindLegPawShift5 * speed * 0.5

            LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift5 * speed * 0.5
            LeftHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift5 * speed * 0.5
            LeftHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift5 * speed * 0.5
            LeftHindPawTr.Angle -= LeftHindLegPawShift5 * speed * 0.5

            RhtForeLeg_A_Tr.Angle -= RhtForeLeg_A_Shift5 * speed * 0.5
            RhtForeLeg_B_Tr.Angle -= RhtForeLeg_B_Shift5 * speed * 0.5
            RhtForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift5 * speed * 0.5
            RhtForePawTr.Angle += RhtForeLegPawShift5 * speed * 0.5

            LeftForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift5 * speed * 0.5
            LeftForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift5 * speed * 0.5
            LeftForePawTr.Angle -= LeftForeLegPawShift5 * speed * 0.5

            ShiftAvalonaDown()
        End If

        If RhtHindLeg_A_Tr.Angle = -14 Then
            FocusOnRightHind = False
            ' Set angles to Phase 5 stance
            RhtHndFocusPhase5Stance()
        End If
    End Sub

The LeftHindBack method is similar to the RightHindBack method, with the code for shifting from the standing position missing and an interchange of variables. The logic is still the same.

    Private Sub LeftHindBack()
        ' Get to Phase 2
        If LeftHindLeg_A_Tr.Angle >= 4 And LeftHindLeg_A_Tr.Angle < 8 Then
            LeftHindLeg_A_Tr.Angle += 1 * speed
            LeftHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift2 * speed
            LeftHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift2 * speed
            LeftHindPawTr.Angle += RhtHindLegPawShift2 * speed

            RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift2 * speed
            RhtHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift2 * speed
            RhtHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift2 * speed
            RhtHindPawTr.Angle += LeftHindLegPawShift2 * speed

            LeftForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift2 * speed
            LeftForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift2 * speed
            LeftForePawTr.Angle -= RhtForeLegPawShift2 * speed

            RhtForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift2 * speed
            RhtForeLeg_B_Tr.Angle -= LeftForeLeg_B_Shift2 * speed
            RhtForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift2 * speed
            RhtForePawTr.Angle += LeftForeLegPawShift2 * speed
        End If
        ' Get to Phase 3
        If LeftHindLeg_A_Tr.Angle >= 8 And LeftHindLeg_A_Tr.Angle < 14 Then
            LeftHindLeg_A_Tr.Angle += 1 * speed
            LeftHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift3 * speed
            LeftHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift3 * speed
            LeftHindPawTr.Angle += RhtHindLegPawShift3 * speed

            RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift3 * speed
            RhtHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift3 * speed
            RhtHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift3 * speed
            RhtHindPawTr.Angle -= LeftHindLegPawShift3 * speed

            LeftForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift3 * speed
            LeftForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift3 * speed
            LeftForePawTr.Angle -= RhtForeLegPawShift3 * speed

            RhtForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift3 * speed
            RhtForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift3 * speed
            RhtForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift3 * speed
            RhtForePawTr.Angle += LeftForeLegPawShift3 * speed
        End If

        If LeftHindLeg_A_Tr.Angle = 14 Then
            MoveLeftLegBackwards = False
        End If
    End Sub

The LeftHindForward method is similar to the RightHindForward method with an interchange of variables.

    Private Sub LeftHindForward()
        ' Get to Phase 4
        If LeftHindLeg_A_Tr.Angle <= 14 And LeftHindLeg_A_Tr.Angle > -4 Then
            LeftHindLeg_A_Tr.Angle -= 1 * speed
            LeftHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift4 * speed
            LeftHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift4 * speed
            LeftHindPawTr.Angle += RhtHindLegPawShift4 * speed

            RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift4 * speed
            RhtHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift4 * speed
            RhtHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift4 * speed
            RhtHindPawTr.Angle -= LeftHindLegPawShift4 * speed

            LeftForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift4 * speed
            LeftForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift4 * speed
            LeftForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift4 * speed
            LeftForePawTr.Angle -= RhtForeLegPawShift4 * speed

            RhtForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift4 * speed
            RhtForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift4 * speed
            RhtForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift4 * speed
            RhtForePawTr.Angle += LeftForeLegPawShift4 * speed

            ShiftAvalonaUp()
        End If
        If LeftHindLeg_A_Tr.Angle = -4 Then
            RhtForeLeg_C_Tr.Angle = 0
        End If
        ' Get to Phase 5
        If LeftHindLeg_A_Tr.Angle <= -4 And LeftHindLeg_A_Tr.Angle > -14 Then
            ' Multiply by 0.5 since Phase 8 in the original sequence
            ' was jumped when creating the 5 Phase sequence.
            LeftHindLeg_A_Tr.Angle -= 1 * speed * 0.5
            LeftHindLeg_B_Tr.Angle -= RhtHindLeg_B_Shift5 * speed * 0.5
            LeftHindLeg_C_Tr.Angle += RhtHindLeg_C_Shift5 * speed * 0.5
            LeftHindPawTr.Angle -= RhtHindLegPawShift5 * speed * 0.5

            RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift5 * speed * 0.5
            RhtHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift5 * speed * 0.5
            RhtHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift5 * speed * 0.5
            RhtHindPawTr.Angle -= LeftHindLegPawShift5 * speed * 0.5

            LeftForeLeg_A_Tr.Angle -= RhtForeLeg_A_Shift5 * speed * 0.5
            LeftForeLeg_B_Tr.Angle -= RhtForeLeg_B_Shift5 * speed * 0.5
            LeftForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift5 * speed * 0.5
            LeftForePawTr.Angle += RhtForeLegPawShift5 * speed * 0.5

            RhtForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift5 * speed * 0.5
            RhtForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift5 * speed * 0.5
            RhtForePawTr.Angle -= LeftForeLegPawShift5 * speed * 0.5

            ShiftAvalonaDown()
        End If

        If LeftHindLeg_A_Tr.Angle = -14 Then
            FocusOnRightHind = True
            MoveRhtLegBackwards = True
            MoveLeftLegBackwards = True
            LeftHndFocusPhase5Stance()
        End If
    End Sub

Extra Resources

I'm sure that Avalona can do more than just amble. It can run, walk,... maybe even swim. If you are of the same opinion and have the time and interest, the following resources could prove to be useful:

Conclusion

I hope you enjoyed reading the article and taking Avalona for a walk, even if it was only on a treadmill. Stay tuned for the next episode when the Speedster, Xaml Man, and Avalona join forces in an epic battle against Winn Fommz... just kidding. If you want to add some enhancements to Avalona, the doors of the M Labs Animaloid Research Center are wide open once you download the source files and open the solution. Cheers!

History

  • 1st February, 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