Skip to content

Kinematics ​

Kinematics is the geometry of motion, without forces. Forward kinematics maps joint angles to the foot position. Inverse kinematics maps a foot position back to joint angles. The Jacobian links joint velocities to foot velocities. This page derives all three for the Strido leg, including its knee linkage.

In Strido

  • Leg model: packages/strido-core/src/strido/leg.py (foot_position, inverse_kinematics, calf_from_crank, crank_from_calf, transmission_angles), mirrored in C++ in firmware/strido_esp32s3/lib/strido_core/.
  • Dimensions: hardware/kinematics.yaml (legs_linkage, legs_base), measured from the CAD. Limits: hardware/joint_limits.yaml.
  • Practical guide: Kinematics and gaits shows how the gait uses these functions.

The leg as a kinematic chain ​

Each leg has three revolute joints (leg.py docstring; the conventions match the Unitree Go2):

JointAxisZeroPositive
hip q1+xleg verticalfoot towards +y
thigh q2+yfemur straight downknee backwards
calf q3+y, relative to femurcalf in line with femurnegative = knee bent

From hardware/kinematics.yaml (front-left leg, rounded): the hip is at h=(0.1197,0.039,0)m in base_link, the leg plane sits d=38.3mm outboard of the hip (40.2mm on the rear legs), the thigh is l1=130.0mm and the calf is l2=124.1mm to the foot centre.

The thigh and calf move in a vertical leg plane. The hip joint tilts that plane about x. So the problem splits into two easier ones: a planar two-link arm, and one rotation.

Forward kinematics ​

In the leg plane, let u point forward and v point up, both measured from the thigh pivot. Write s2=sin⁡q2 and s23=sin⁡(q2+q3), and similarly for cosines. The knee and the foot are at:

k=[−l1s2−l1c2],[uv]=[−l1s2−l2s23−l1c2−l2c23]

The angles add because q3 is measured relative to the femur, so the calf's absolute angle is q2+q3. The signs are negative because zero means "pointing down" and positive q2 swings the foot backwards (towards −u).

Next, the hip rotation. The foot in the hip frame, before abduction, is (u,d,v). Rotating about x by q1 and adding the hip position gives:

p=h+Rx(q1)[udv]=h+[udcos⁡q1−vsin⁡q1dsin⁡q1+vcos⁡q1]

This is foot_position line for line. For the frame conventions, see frames and rotations.

Inverse kinematics ​

We are given a foot target p and need (q1,q2,q3). Let r=p−h=(rx,ry,rz).

Hip abduction ​

A rotation about x leaves the x component alone and preserves length in the y–z plane:

ry2+rz2=d2+v2

The foot is below the hip, so we take the negative root:

v=−ry2+rz2−d2

If the term under the root is not positive, the target lies inside the cylinder of radius d around the hip axis and cannot be reached. The direction of (ry,rz) is the direction of (d,v) rotated by q1, so:

q1=atan2(rz,ry)−atan2(v,d)

Now set u=rx and solve the two-link arm. The thigh, the calf and the line from pivot to foot form a triangle with sides l1, l2 and ρ=u2+v2. The law of cosines at the knee gives the knee angle. With our convention (the knee interior angle is π+q3):

ρ2=l12+l22+2l1l2cos⁡q3⟹cos⁡q3=u2+v2−l12−l222l1l2

There are two solutions, ±arccos, for knee-forward and knee-backward. Strido uses q3=−arccos⁡(⋅), a bent knee pointing backwards. If |cos⁡q3|>1, the target is out of reach.

The thigh angle is the direction to the foot minus the angle the calf adds inside the triangle:

q2=atan2(−u,−v)−atan2(l2sin⁡q3, l1+l2cos⁡q3)

The minus signs in the first term come from the "zero = straight down, positive = backwards" convention. Use atan2, never atan, so that the quadrant is correct.

The knee four-bar ​

The knee servo does not drive q3 directly. A parallelogram (arm 24.0mm, short link 28.3mm, crank 24.0mm) copies the servo angle onto a crank ψ at the thigh pivot. A four-bar (crank 26.9mm, long link 131mm, tibia crank 24.0mm, and the femur 130.0mm as ground link) then turns the tibia. Because the four-bar's ground link is the femur itself:

q3=f(q2,ψ)

Moving the thigh alone also moves the knee. crank_from_calf inverts this geometrically. The far end of the crank lies on a circle of radius 26.9mm around the pivot, and also on a circle of radius 131mm (the long link) around the tibia pin. Intersecting the two circles gives two candidates, and the assembly branch picks one. circle_intersection returns None when the circles do not meet. That means the linkage cannot be assembled in that pose.

Rendering diagram…

The Jacobian ​

The Jacobian maps joint rates to foot velocity, p˙=J(q)q˙. Differentiating the planar forward kinematics:

Jplane=∂(u,v)∂(q2,q3)=[−l1c2−l2c23−l2c23−l1s2+l2s23−l2s23],detJplane=−l1l2sin⁡q3

The full 3×3 Jacobian adds the hip column, ∂p/∂q1=x^×(p−h), and rotates the planar columns by Rx(q1). The Jacobian also governs forces through τ=J⊤F (see statics and dynamics).

For the drive, the chain rule adds one more factor. The knee servo's rate is ψ˙, and

q˙3=∂f∂q2q˙2+∂f∂ψψ˙

Workspace and singularities ​

Ignoring joint limits, the planar foot reaches an annulus:

|l1−l2|≤ρ≤l1+l2⇒5.9mm≤ρ≤254.1mm

The joint limits and self-collisions cut this down. hardware/joint_limits.yaml limits q3 to [−150∘,−45∘] and the front q2 to [−45∘,125∘], found by sweeping the posed CAD for collisions on a 5∘ grid.

A singularity is a pose where detJ=0. There the foot cannot move in some direction, however fast the joints turn, and inverse kinematics becomes ill-conditioned. For the planar leg this happens at sin⁡q3=0: the leg fully straight (q3=0, on the outer workspace boundary) or fully folded. The calf limit keeps |sin⁡q3|≥sin⁡30∘=0.5 (at the −150∘ end; at least 0.71 at the −45∘ end), so the leg never gets close. This is one reason the stand pose keeps the knee well bent.

The four-bar has its own singularities. When the long link lines up with the crank or with the tibia crank (a transmission angle near 0 or 180∘), ∂f/∂ψ blows up or vanishes. transmission_angles measures both angles, and joint_limits.yaml requires at least 25∘ (transmission_min_deg).

Worked example: the stand pose ​

The stand pose puts each foot straight below its hip, 0.17m down (stand_pose(height=0.17) in strido/gait.py). For the front-left leg, r=(0, 0.0383, −0.170)m.

Hip. v=−0.03832+0.1702−0.03832=−0.170, so q1=atan2(−0.170,0.0383)−atan2(−0.170,0.0383)=0.

Knee. With u=0:

cos⁡q3=0.1702−0.13002−0.124122⋅0.1300⋅0.1241=−0.003390.03226=−0.105⇒q3=−96.0∘

Thigh. l2sin⁡q3=−0.1234 and l1+l2cos⁡q3=0.1170, so

q2=atan2(0,0.170)−atan2(−0.1234,0.1170)=0+46.5∘=46.5∘

These match stand_pose(), which returns (0∘,46.53∘,−96.03∘) for every leg. The calf's absolute angle is q2+q3=−49.5∘: the knee sits behind and above the foot, and the calf leans forward to reach it.

Jacobian. At this pose,

Jplane=[−0.170−0.08060−0.0943]m/rad,det=0.0160m2

A thigh rate of 1rad/s moves the foot 0.17m/s backwards and not at all vertically. To lift the foot you mostly need the knee.

Linkage. leg.py gives a crank angle of ψ=38.9∘ and transmission angles of 84∘ and 86∘, close to the ideal 90∘. The sensitivity is ∂q3/∂ψ=−1.12: the knee turns 1.12∘ for each degree of crank.

Check yourself ​

  1. Why can the hip angle be solved before, and separately from, the thigh and knee?
  2. What does |cos⁡q3|>1 mean physically?
  3. At the stand pose, which joint mainly moves the foot forward, and which mainly moves it vertically?
  4. Why do the transmission angles matter even when detJplane is far from zero?
Answers
  1. The hip axis is the x axis, and q2, q3 never change the foot's distance from it. So ry2+rz2 depends only on the planar depth v and the fixed offset d.
  2. The target is farther than l1+l2 or closer than |l1−l2|, so no triangle exists.
  3. The thigh moves it forward and back (J11=−0.170, J21=0). Only the knee column has a vertical component.
  4. They describe the drive linkage, not the leg. Near 0∘ or 180∘ the knee servo loses leverage and the crank–knee map becomes ill-conditioned, whatever the leg Jacobian says.

Further reading ​

  • K. M. Lynch and F. C. Park, Modern Robotics, Cambridge University Press, 2017, ch. 4–6 (forward kinematics, velocity kinematics, inverse kinematics).
  • B. Siciliano et al., Robotics: Modelling, Planning and Control, Springer, 2009, ch. 2–3.
  • R. L. Norton, Design of Machinery, McGraw-Hill, ch. 4 (four-bar position analysis and transmission angle).
  • Kinematics and gaits in this wiki.

MIT licence. Mechanical design derived from Yertle by Jerome Graves. CAD, simulation and native tests are not hardware evidence — see Verification.