# Inverse Kinematics

Inverse kinematics is a technique in robotics, computer graphics, and animation to find physical configurations of a structure that would put an end-effector in a desired position in space. In other words, it answers the question: "given the desired position of a robot's hand, what should be the angles of all the joints in the robot's body, to take the hand to that position?"

For example, take the system drawn below, attached to a stationary structure on the left. This "arm" has two links of length $$L_1$$ and $$L_2$$, two joints at points $$(0,0)$$ and $$(x_1,y_1)$$, and the end point at $$(x_2,y_2)$$. It is straightforward to write the equations describing the forward kinematics of this mechanism, providing the coordinates of its parts for given angles of joints $$a_1$$ and $$a_2$$.

$\begin{eqnarray*} x_1 &=& L_1 \cos a_1\\ y_1 &=& L_1 \sin a_1\\ x_2 &=& x_1 + L_2 \cos (a_1 + a_2)\\ y_2 &=& y_1 + L_2 \sin (a_1 + a_2)\\ \end{eqnarray*}$

A common approach to the inverse kinematics problem involves the use of Jacobian matrices for linearizing the system describing the position of the end point, in this example, $$(x_2,y_2)$$. This defines how the position of the end point changes locally, relative to the instantaneous changes in the joint angles.

$\mathbf{J} = \begin{bmatrix} \frac{\partial x_2}{\partial a_1} & \frac{\partial x_2}{\partial a_2} \\ \frac{\partial y_2}{\partial a_1} & \frac{\partial y_2}{\partial a_2} \\ \end{bmatrix}$

The Jacobian $$\mathbf{J}$$ approximates the movement of the end point $$\mathbf{x} = (x_2, y_2)$$ with respect to changes in joint angles $$\mathbf{a} = (a_1, a_2)$$:

$\Delta \mathbf{x} \approx \mathbf{J} \Delta \mathbf{a} \; .$

Starting from a given position of the end point $$\mathbf{x} = \mathbf{x}_0$$ and given a target position $$\mathbf{x}_T$$, we can use the inverse of the Jacobian to compute small updates in the angles $$\mathbf{a}$$ using

$\Delta \mathbf{a} = \eta \, (\mathbf{J^{-1}} \mathbf{e}) \; ,$

where $$\mathbf{e} = \mathbf{x}_T - \mathbf{x}$$ is the current position error and $$\eta > 0$$ is a small step size. Computing the new position $$\mathbf{x}$$ with the updated angles $$\mathbf{a}$$ and repeating this process until the error $$\mathbf{e}$$ approaches zero moves the end point of the mechanism towards the target point $$\mathbf{x}_T$$.

Let's use DiffSharp for implementing this system.

  1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:  open DiffSharp.AD.Float64 // Set the lengths of the arm segments let l1 = 4.5 let l2 = 2.5 // Set the initial angles let mutable a = toDV [1.1; -0.9] // Transform angles into (x1, y1) and (x2, y2) positions let transform (a:DV) = let x1, y1 = l1 * cos a., l1 * sin a. let x2, y2 = x1 + l2 * cos (a. + a.), y1 + l2 * sin (a. + a.) toDV [x1; y1; x2; y2] // Forward kinematics of the tip of the arm (x2, y2) let inline forwardK (a:DV) = let t = transform a toDV [t.; t.] // Inverse kinematics using inverse Jacobian-vector product // target is the target position of the tip (x2, y2) // eta is the update coefficient // timeout is the maximum number of iterations let inverseK (target:DV) (eta:float) (timeout:int) = seq {for i in 0 .. timeout do let pos, j = jacobian' forwardK a let error = target - pos let da = (DM.inverse j) * error a <- a + eta * da yield (DV.norm error, a) } |> Seq.takeWhile (fun x -> fst x > D 0.4) |> Seq.map snd 

The given link sizes $$L_1 = 4.5$$, $$L_2 = 2.5$$ and initial angles $$(a_1, a_2) = (1.1, -0.9)$$ put the starting position approximately at $$(x_2, y_2) = (4.5, 4.5)$$.

Let us take the end point of the robot arm to positions $$(4.5, 4.5) \to (5.0, 0.0) \to (3.5, -4.0)$$ and then back to $$(4.5, 4.5)$$.

 1: 2: 3:  let movement1 = inverseK (toDV [5.0; 0.0]) 0.025 100000 let movement2 = inverseK (toDV [3.5; -4.0]) 0.025 100000 let movement3 = inverseK (toDV [4.5; 4.5]) 0.025 100000 
 val movement1 : seq> val movement2 : seq> val movement3 : seq>

The following code draws the movement of the arm.

  1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:  open FSharp.Charting let armPoints (a:DV) = let t = a |> transform |> primal |> convert seq [0., 0.; t., t.; t., t.] let drawArmLive (aa:seq) = let pp = aa |> Array.ofSeq |> Array.map armPoints let pp2 = Array.copy pp Chart.Combine( [ LiveChart.Line(Event.cycle 10 pp, Color = System.Drawing.Color.Purple) LiveChart.Point(Event.cycle 10 pp2, MarkerSize = 20) ]) .WithXAxis(Min = 0.0, Max = 10.0, LabelStyle = ChartTypes.LabelStyle(Interval = 2.), MajorGrid = ChartTypes.Grid(Interval = 2.), MajorTickMark = ChartTypes.TickMark(Enabled = false)) .WithYAxis(Min = -5.0, Max = 5.0, LabelStyle = ChartTypes.LabelStyle(Interval = 2.), MajorGrid = ChartTypes.Grid(Interval = 2.), MajorTickMark = ChartTypes.TickMark(Enabled = false)) drawArmLive (movement3 |> Seq.append movement2 |> Seq.append movement1) It is known that one can use the transposed Jacobian $$\mathbf{J}^\textrm{T}$$ instead of the inverse Jacobian $$\mathbf{J^{-1}}$$ and obtain similar results, albeit with slightly different behavior.

The DiffSharp.AD module provides the operation jacobianTv making use of reverse mode AD to calculate the transposed Jacobian-vector product in a matrix-free and highly efficient way. This is in contrast to the above code, which comes with the cost of computing the full Jacobian matrix and its inverse in every step of the iteration. (See the API Overview and Benchmarks pages for a comparison of these operations.)

Using this method with the same arm positions gives us the following result:

  1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:  // Inverse kinematics using transposed Jacobian-vector product let inverseK' (target:DV) (eta:float) (timeout:int) = seq {for i in 0 .. timeout do let pos, jTv = jacobianTv'' forwardK a let error = target - pos let da = jTv error a <- a + eta * da yield (DV.norm error, a) } |> Seq.takeWhile (fun x -> fst x > D 0.4) |> Seq.map snd namespace DiffSharp
module Float64

val l1 : float

Full name: Examples-inversekinematics.l1
val l2 : float

Full name: Examples-inversekinematics.l2
val mutable a : DV

Full name: Examples-inversekinematics.a
val toDV : v:seq<'a> -> DV (requires member op_Explicit)

val transform : a:DV -> DV

Full name: Examples-inversekinematics.transform
val a : DV
Multiple items
union case DV.DV: float [] -> DV

--------------------
module DV

--------------------
type DV =
| DV of float []
| DVF of DV * DV * uint32
| DVR of DV * DV ref * TraceOp * uint32 ref * uint32
member Copy : unit -> DV
member GetForward : t:DV * i:uint32 -> DV
member GetReverse : i:uint32 -> DV
member GetSlice : lower:int option * upper:int option -> DV
member ToArray : unit -> D []
member ToColDM : unit -> DM
member ToMathematicaString : unit -> string
member ToMatlabString : unit -> string
member ToRowDM : unit -> DM
override ToString : unit -> string
member Visualize : unit -> string
member A : DV
member F : uint32
member Item : i:int -> D with get
member Length : int
member P : DV
member PD : DV
member T : DV
member A : DV with set
member F : uint32 with set
static member Abs : a:DV -> DV
static member Acos : a:DV -> DV
static member AddItem : a:DV * i:int * b:D -> DV
static member AddSubVector : a:DV * i:int * b:DV -> DV
static member Append : a:DV * b:DV -> DV
static member Asin : a:DV -> DV
static member Atan : a:DV -> DV
static member Atan2 : a:int * b:DV -> DV
static member Atan2 : a:DV * b:int -> DV
static member Atan2 : a:float * b:DV -> DV
static member Atan2 : a:DV * b:float -> DV
static member Atan2 : a:D * b:DV -> DV
static member Atan2 : a:DV * b:D -> DV
static member Atan2 : a:DV * b:DV -> DV
static member Ceiling : a:DV -> DV
static member Cos : a:DV -> DV
static member Cosh : a:DV -> DV
static member Exp : a:DV -> DV
static member Floor : a:DV -> DV
static member L1Norm : a:DV -> D
static member L2Norm : a:DV -> D
static member L2NormSq : a:DV -> D
static member Log : a:DV -> DV
static member Log10 : a:DV -> DV
static member LogSumExp : a:DV -> D
static member Max : a:DV -> D
static member Max : a:D * b:DV -> DV
static member Max : a:DV * b:D -> DV
static member Max : a:DV * b:DV -> DV
static member MaxIndex : a:DV -> int
static member Mean : a:DV -> D
static member Min : a:DV -> D
static member Min : a:D * b:DV -> DV
static member Min : a:DV * b:D -> DV
static member Min : a:DV * b:DV -> DV
static member MinIndex : a:DV -> int
static member Normalize : a:DV -> DV
static member OfArray : a:D [] -> DV
static member Op_DV_D : a:DV * ff:(float [] -> float) * fd:(DV -> D) * df:(D * DV * DV -> D) * r:(DV -> TraceOp) -> D
static member Op_DV_DM : a:DV * ff:(float [] -> float [,]) * fd:(DV -> DM) * df:(DM * DV * DV -> DM) * r:(DV -> TraceOp) -> DM
static member Op_DV_DV : a:DV * ff:(float [] -> float []) * fd:(DV -> DV) * df:(DV * DV * DV -> DV) * r:(DV -> TraceOp) -> DV
static member Op_DV_DV_D : a:DV * b:DV * ff:(float [] * float [] -> float) * fd:(DV * DV -> D) * df_da:(D * DV * DV -> D) * df_db:(D * DV * DV -> D) * df_dab:(D * DV * DV * DV * DV -> D) * r_d_d:(DV * DV -> TraceOp) * r_d_c:(DV * DV -> TraceOp) * r_c_d:(DV * DV -> TraceOp) -> D
static member Op_DV_DV_DM : a:DV * b:DV * ff:(float [] * float [] -> float [,]) * fd:(DV * DV -> DM) * df_da:(DM * DV * DV -> DM) * df_db:(DM * DV * DV -> DM) * df_dab:(DM * DV * DV * DV * DV -> DM) * r_d_d:(DV * DV -> TraceOp) * r_d_c:(DV * DV -> TraceOp) * r_c_d:(DV * DV -> TraceOp) -> DM
static member Op_DV_DV_DV : a:DV * b:DV * ff:(float [] * float [] -> float []) * fd:(DV * DV -> DV) * df_da:(DV * DV * DV -> DV) * df_db:(DV * DV * DV -> DV) * df_dab:(DV * DV * DV * DV * DV -> DV) * r_d_d:(DV * DV -> TraceOp) * r_d_c:(DV * DV -> TraceOp) * r_c_d:(DV * DV -> TraceOp) -> DV
static member Op_DV_D_DV : a:DV * b:D * ff:(float [] * float -> float []) * fd:(DV * D -> DV) * df_da:(DV * DV * DV -> DV) * df_db:(DV * D * D -> DV) * df_dab:(DV * DV * DV * D * D -> DV) * r_d_d:(DV * D -> TraceOp) * r_d_c:(DV * D -> TraceOp) * r_c_d:(DV * D -> TraceOp) -> DV
static member Op_D_DV_DV : a:D * b:DV * ff:(float * float [] -> float []) * fd:(D * DV -> DV) * df_da:(DV * D * D -> DV) * df_db:(DV * DV * DV -> DV) * df_dab:(DV * D * D * DV * DV -> DV) * r_d_d:(D * DV -> TraceOp) * r_d_c:(D * DV -> TraceOp) * r_c_d:(D * DV -> TraceOp) -> DV
static member Pow : a:int * b:DV -> DV
static member Pow : a:DV * b:int -> DV
static member Pow : a:float * b:DV -> DV
static member Pow : a:DV * b:float -> DV
static member Pow : a:D * b:DV -> DV
static member Pow : a:DV * b:D -> DV
static member Pow : a:DV * b:DV -> DV
static member ReLU : a:DV -> DV
static member ReshapeToDM : m:int * a:DV -> DM
static member Round : a:DV -> DV
static member Sigmoid : a:DV -> DV
static member Sign : a:DV -> DV
static member Sin : a:DV -> DV
static member Sinh : a:DV -> DV
static member SoftMax : a:DV -> DV
static member SoftPlus : a:DV -> DV
static member SoftSign : a:DV -> DV
static member Split : d:DV * n:seq<int> -> seq<DV>
static member Sqrt : a:DV -> DV
static member StandardDev : a:DV -> D
static member Standardize : a:DV -> DV
static member Sum : a:DV -> D
static member Tan : a:DV -> DV
static member Tanh : a:DV -> DV
static member Variance : a:DV -> D
static member ZeroN : n:int -> DV
static member Zero : DV
static member ( + ) : a:int * b:DV -> DV
static member ( + ) : a:DV * b:int -> DV
static member ( + ) : a:float * b:DV -> DV
static member ( + ) : a:DV * b:float -> DV
static member ( + ) : a:D * b:DV -> DV
static member ( + ) : a:DV * b:D -> DV
static member ( + ) : a:DV * b:DV -> DV
static member ( &* ) : a:DV * b:DV -> DM
static member ( / ) : a:int * b:DV -> DV
static member ( / ) : a:DV * b:int -> DV
static member ( / ) : a:float * b:DV -> DV
static member ( / ) : a:DV * b:float -> DV
static member ( / ) : a:D * b:DV -> DV
static member ( / ) : a:DV * b:D -> DV
static member ( ./ ) : a:DV * b:DV -> DV
static member ( .* ) : a:DV * b:DV -> DV
static member op_Explicit : d:float [] -> DV
static member op_Explicit : d:DV -> float []
static member ( * ) : a:int * b:DV -> DV
static member ( * ) : a:DV * b:int -> DV
static member ( * ) : a:float * b:DV -> DV
static member ( * ) : a:DV * b:float -> DV
static member ( * ) : a:D * b:DV -> DV
static member ( * ) : a:DV * b:D -> DV
static member ( * ) : a:DV * b:DV -> D
static member ( - ) : a:int * b:DV -> DV
static member ( - ) : a:DV * b:int -> DV
static member ( - ) : a:float * b:DV -> DV
static member ( - ) : a:DV * b:float -> DV
static member ( - ) : a:D * b:DV -> DV
static member ( - ) : a:DV * b:D -> DV
static member ( - ) : a:DV * b:DV -> DV
static member ( ~- ) : a:DV -> DV

val x1 : D
val y1 : D
val cos : value:'T -> 'T (requires member Cos)

Full name: Microsoft.FSharp.Core.Operators.cos
val sin : value:'T -> 'T (requires member Sin)

Full name: Microsoft.FSharp.Core.Operators.sin
val x2 : D
val y2 : D
val forwardK : a:DV -> DV

Full name: Examples-inversekinematics.forwardK
val t : DV
val inverseK : target:DV -> eta:float -> timeout:int -> seq<DV>

Full name: Examples-inversekinematics.inverseK
val target : DV
val eta : float
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = System.Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val timeout : int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val i : int
val pos : DV
val j : DM
val jacobian' : f:(DV -> DV) -> x:DV -> DV * DM

val error : DV
val da : DV
Multiple items
union case DM.DM: float [,] -> DM

--------------------
module DM

--------------------
type DM =
| DM of float [,]
| DMF of DM * DM * uint32
| DMR of DM * DM ref * TraceOp * uint32 ref * uint32
member Copy : unit -> DM
member GetCols : unit -> seq<DV>
member GetForward : t:DM * i:uint32 -> DM
member GetReverse : i:uint32 -> DM
member GetRows : unit -> seq<DV>
member GetSlice : rowStart:int option * rowFinish:int option * col:int -> DV
member GetSlice : row:int * colStart:int option * colFinish:int option -> DV
member GetSlice : rowStart:int option * rowFinish:int option * colStart:int option * colFinish:int option -> DM
member ToMathematicaString : unit -> string
member ToMatlabString : unit -> string
override ToString : unit -> string
member Visualize : unit -> string
member A : DM
member Cols : int
member F : uint32
member Item : i:int * j:int -> D with get
member Length : int
member P : DM
member PD : DM
member Rows : int
member T : DM
member A : DM with set
member F : uint32 with set
static member Abs : a:DM -> DM
static member Acos : a:DM -> DM
static member AddDiagonal : a:DM * b:DV -> DM
static member AddItem : a:DM * i:int * j:int * b:D -> DM
static member AddSubMatrix : a:DM * i:int * j:int * b:DM -> DM
static member Asin : a:DM -> DM
static member Atan : a:DM -> DM
static member Atan2 : a:int * b:DM -> DM
static member Atan2 : a:DM * b:int -> DM
static member Atan2 : a:float * b:DM -> DM
static member Atan2 : a:DM * b:float -> DM
static member Atan2 : a:D * b:DM -> DM
static member Atan2 : a:DM * b:D -> DM
static member Atan2 : a:DM * b:DM -> DM
static member Ceiling : a:DM -> DM
static member Cos : a:DM -> DM
static member Cosh : a:DM -> DM
static member Det : a:DM -> D
static member Diagonal : a:DM -> DV
static member Exp : a:DM -> DM
static member Floor : a:DM -> DM
static member Inverse : a:DM -> DM
static member Log : a:DM -> DM
static member Log10 : a:DM -> DM
static member Max : a:DM -> D
static member Max : a:D * b:DM -> DM
static member Max : a:DM * b:D -> DM
static member Max : a:DM * b:DM -> DM
static member MaxIndex : a:DM -> int * int
static member Mean : a:DM -> D
static member Min : a:DM -> D
static member Min : a:D * b:DM -> DM
static member Min : a:DM * b:D -> DM
static member Min : a:DM * b:DM -> DM
static member MinIndex : a:DM -> int * int
static member Normalize : a:DM -> DM
static member OfArray : m:int * a:D [] -> DM
static member OfArray2D : a:D [,] -> DM
static member OfCols : n:int * a:DV -> DM
static member OfRows : s:seq<DV> -> DM
static member OfRows : m:int * a:DV -> DM
static member Op_DM_D : a:DM * ff:(float [,] -> float) * fd:(DM -> D) * df:(D * DM * DM -> D) * r:(DM -> TraceOp) -> D
static member Op_DM_DM : a:DM * ff:(float [,] -> float [,]) * fd:(DM -> DM) * df:(DM * DM * DM -> DM) * r:(DM -> TraceOp) -> DM
static member Op_DM_DM_DM : a:DM * b:DM * ff:(float [,] * float [,] -> float [,]) * fd:(DM * DM -> DM) * df_da:(DM * DM * DM -> DM) * df_db:(DM * DM * DM -> DM) * df_dab:(DM * DM * DM * DM * DM -> DM) * r_d_d:(DM * DM -> TraceOp) * r_d_c:(DM * DM -> TraceOp) * r_c_d:(DM * DM -> TraceOp) -> DM
static member Op_DM_DV : a:DM * ff:(float [,] -> float []) * fd:(DM -> DV) * df:(DV * DM * DM -> DV) * r:(DM -> TraceOp) -> DV
static member Op_DM_DV_DM : a:DM * b:DV * ff:(float [,] * float [] -> float [,]) * fd:(DM * DV -> DM) * df_da:(DM * DM * DM -> DM) * df_db:(DM * DV * DV -> DM) * df_dab:(DM * DM * DM * DV * DV -> DM) * r_d_d:(DM * DV -> TraceOp) * r_d_c:(DM * DV -> TraceOp) * r_c_d:(DM * DV -> TraceOp) -> DM
static member Op_DM_DV_DV : a:DM * b:DV * ff:(float [,] * float [] -> float []) * fd:(DM * DV -> DV) * df_da:(DV * DM * DM -> DV) * df_db:(DV * DV * DV -> DV) * df_dab:(DV * DM * DM * DV * DV -> DV) * r_d_d:(DM * DV -> TraceOp) * r_d_c:(DM * DV -> TraceOp) * r_c_d:(DM * DV -> TraceOp) -> DV
static member Op_DM_D_DM : a:DM * b:D * ff:(float [,] * float -> float [,]) * fd:(DM * D -> DM) * df_da:(DM * DM * DM -> DM) * df_db:(DM * D * D -> DM) * df_dab:(DM * DM * DM * D * D -> DM) * r_d_d:(DM * D -> TraceOp) * r_d_c:(DM * D -> TraceOp) * r_c_d:(DM * D -> TraceOp) -> DM
static member Op_DV_DM_DM : a:DV * b:DM * ff:(float [] * float [,] -> float [,]) * fd:(DV * DM -> DM) * df_da:(DM * DV * DV -> DM) * df_db:(DM * DM * DM -> DM) * df_dab:(DM * DV * DV * DM * DM -> DM) * r_d_d:(DV * DM -> TraceOp) * r_d_c:(DV * DM -> TraceOp) * r_c_d:(DV * DM -> TraceOp) -> DM
static member Op_DV_DM_DV : a:DV * b:DM * ff:(float [] * float [,] -> float []) * fd:(DV * DM -> DV) * df_da:(DV * DV * DV -> DV) * df_db:(DV * DM * DM -> DV) * df_dab:(DV * DV * DV * DM * DM -> DV) * r_d_d:(DV * DM -> TraceOp) * r_d_c:(DV * DM -> TraceOp) * r_c_d:(DV * DM -> TraceOp) -> DV
static member Op_D_DM_DM : a:D * b:DM * ff:(float * float [,] -> float [,]) * fd:(D * DM -> DM) * df_da:(DM * D * D -> DM) * df_db:(DM * DM * DM -> DM) * df_dab:(DM * D * D * DM * DM -> DM) * r_d_d:(D * DM -> TraceOp) * r_d_c:(D * DM -> TraceOp) * r_c_d:(D * DM -> TraceOp) -> DM
static member Pow : a:int * b:DM -> DM
static member Pow : a:DM * b:int -> DM
static member Pow : a:float * b:DM -> DM
static member Pow : a:DM * b:float -> DM
static member Pow : a:D * b:DM -> DM
static member Pow : a:DM * b:D -> DM
static member Pow : a:DM * b:DM -> DM
static member ReLU : a:DM -> DM
static member ReshapeToDV : a:DM -> DV
static member Round : a:DM -> DM
static member Sigmoid : a:DM -> DM
static member Sign : a:DM -> DM
static member Sin : a:DM -> DM
static member Sinh : a:DM -> DM
static member SoftPlus : a:DM -> DM
static member SoftSign : a:DM -> DM
static member Solve : a:DM * b:DV -> DV
static member SolveSymmetric : a:DM * b:DV -> DV
static member Sqrt : a:DM -> DM
static member StandardDev : a:DM -> D
static member Standardize : a:DM -> DM
static member Sum : a:DM -> D
static member Tan : a:DM -> DM
static member Tanh : a:DM -> DM
static member Trace : a:DM -> D
static member Transpose : a:DM -> DM
static member Variance : a:DM -> D
static member ZeroMN : m:int -> n:int -> DM
static member Zero : DM
static member ( + ) : a:int * b:DM -> DM
static member ( + ) : a:DM * b:int -> DM
static member ( + ) : a:float * b:DM -> DM
static member ( + ) : a:DM * b:float -> DM
static member ( + ) : a:DM * b:DV -> DM
static member ( + ) : a:DV * b:DM -> DM
static member ( + ) : a:D * b:DM -> DM
static member ( + ) : a:DM * b:D -> DM
static member ( + ) : a:DM * b:DM -> DM
static member ( / ) : a:int * b:DM -> DM
static member ( / ) : a:DM * b:int -> DM
static member ( / ) : a:float * b:DM -> DM
static member ( / ) : a:DM * b:float -> DM
static member ( / ) : a:D * b:DM -> DM
static member ( / ) : a:DM * b:D -> DM
static member ( ./ ) : a:DM * b:DM -> DM
static member ( .* ) : a:DM * b:DM -> DM
static member op_Explicit : d:float [,] -> DM
static member op_Explicit : d:DM -> float [,]
static member ( * ) : a:int * b:DM -> DM
static member ( * ) : a:DM * b:int -> DM
static member ( * ) : a:float * b:DM -> DM
static member ( * ) : a:DM * b:float -> DM
static member ( * ) : a:D * b:DM -> DM
static member ( * ) : a:DM * b:D -> DM
static member ( * ) : a:DV * b:DM -> DV
static member ( * ) : a:DM * b:DV -> DV
static member ( * ) : a:DM * b:DM -> DM
static member ( - ) : a:int * b:DM -> DM
static member ( - ) : a:DM * b:int -> DM
static member ( - ) : a:float * b:DM -> DM
static member ( - ) : a:DM * b:float -> DM
static member ( - ) : a:D * b:DM -> DM
static member ( - ) : a:DM * b:D -> DM
static member ( - ) : a:DM * b:DM -> DM
static member ( ~- ) : a:DM -> DM

val inverse : m:DM -> DM

val norm : v:DV -> D

module Seq

from Microsoft.FSharp.Collections
val takeWhile : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.takeWhile
val x : D * DV
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
union case D.D: float -> D
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val movement1 : seq<DV>

Full name: Examples-inversekinematics.movement1
val movement2 : seq<DV>

Full name: Examples-inversekinematics.movement2
val movement3 : seq<DV>

Full name: Examples-inversekinematics.movement3
val printf : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
namespace FSharp
namespace FSharp.Charting
val armPoints : a:DV -> seq<float * float>

Full name: Examples-inversekinematics.armPoints
val t : float []
val primal : d:'a -> 'a (requires member get_P)

val convert : v:'a -> 'b (requires member op_Explicit)

val drawArmLive : aa:seq<DV> -> ChartTypes.GenericChart

Full name: Examples-inversekinematics.drawArmLive
val aa : seq<DV>
val pp : seq<float * float> []
module Array

from Microsoft.FSharp.Collections
val ofSeq : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofSeq
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val pp2 : seq<float * float> []
val copy : array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.copy
type Chart =
static member Area : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
static member Area : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
static member Bar : data:seq<#value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
static member Bar : data:seq<#key * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
static member BoxPlotFromData : data:seq<#key * #seq<'a2>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string * ?Percentile:int * ?ShowAverage:bool * ?ShowMedian:bool * ?ShowUnusualValues:bool * ?WhiskerPercentile:int -> GenericChart (requires 'a2 :> value)
static member BoxPlotFromStatistics : data:seq<#key * #value * #value * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?Percentile:int * ?ShowAverage:bool * ?ShowMedian:bool * ?ShowUnusualValues:bool * ?WhiskerPercentile:int -> GenericChart
static member Bubble : data:seq<#value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
static member Bubble : data:seq<#key * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
static member Candlestick : data:seq<#value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
static member Candlestick : data:seq<#key * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Labels:#seq<string> * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
...

Full name: FSharp.Charting.Chart
static member Chart.Combine : charts:seq<ChartTypes.GenericChart> -> ChartTypes.GenericChart
type LiveChart =
static member Area : data:IObservable<#seq<'a1 * 'a2>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart (requires 'a1 :> key and 'a2 :> value)
static member Bar : data:IObservable<#seq<'a1 * 'a2>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart (requires 'a1 :> key and 'a2 :> value)
static member Bubble : data:IObservable<#seq<'a1 * 'a2 * 'a3>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart (requires 'a1 :> key and 'a2 :> value and 'a3 :> value)
static member BubbleIncremental : data:IObservable<#key * #value * #value> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string * ?BubbleMaxSize:int * ?BubbleMinSize:int * ?BubbleScaleMax:float * ?BubbleScaleMin:float * ?UseSizeForLabel:bool -> GenericChart
static member Candlestick : data:IObservable<#seq<'a1 * 'a2 * 'a3 * 'a4 * 'a5>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart (requires 'a1 :> key and 'a2 :> value and 'a3 :> value and 'a4 :> value and 'a5 :> value)
static member Candlestick : data:IObservable<seq<#value * #value * #value * #value>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
static member CandlestickIncremental : data:IObservable<#key * #value * #value * #value * #value> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart
static member CandlestickIncremental : data:IObservable<'a0 * #value * #value * #value> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> CandlestickChart (requires 'a0 :> key and 'a0 :> value)
static member Column : data:IObservable<#seq<'a1 * 'a2>> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart (requires 'a1 :> key and 'a2 :> value)
static member ColumnIncremental : data:IObservable<#key * #value> * ?Name:string * ?Title:string * ?Color:Color * ?XTitle:string * ?YTitle:string -> GenericChart
...

Full name: FSharp.Charting.LiveChart
static member LiveChart.Line : data:System.IObservable<#seq<'a1 * 'a2>> * ?Name:string * ?Title:string * ?Color:System.Drawing.Color * ?XTitle:string * ?YTitle:string -> ChartTypes.GenericChart (requires 'a1 :> key and 'a2 :> value)
Multiple items
module Event

--------------------
module Event

from Microsoft.FSharp.Control

--------------------
type Event<'T> =
new : unit -> Event<'T>
member Trigger : arg:'T -> unit
member Publish : IEvent<'T>

Full name: Microsoft.FSharp.Control.Event<_>

--------------------
type Event<'Delegate,'Args (requires delegate and 'Delegate :> Delegate)> =
new : unit -> Event<'Delegate,'Args>
member Trigger : sender:obj * args:'Args -> unit
member Publish : IEvent<'Delegate,'Args>

Full name: Microsoft.FSharp.Control.Event<_,_>

--------------------
new : unit -> Event<'T>

--------------------
new : unit -> Event<'Delegate,'Args>
val cycle : interval:int -> values:seq<'a> -> IEvent<'a>

Full name: Event.cycle

Cycle through the values at the given interval
namespace System
namespace System.Drawing
type Color =
struct
member A : byte
member B : byte
member Equals : obj:obj -> bool
member G : byte
member GetBrightness : unit -> float32
member GetHashCode : unit -> int
member GetHue : unit -> float32
member GetSaturation : unit -> float32
member IsEmpty : bool
member IsKnownColor : bool
...
end

Full name: System.Drawing.Color
property System.Drawing.Color.Purple: System.Drawing.Color
static member LiveChart.Point : data:System.IObservable<#seq<'a1 * 'a2>> * ?Name:string * ?Title:string * ?Color:System.Drawing.Color * ?XTitle:string * ?YTitle:string * ?MarkerColor:System.Drawing.Color * ?MarkerSize:int -> ChartTypes.GenericChart (requires 'a1 :> key and 'a2 :> value)
module ChartTypes

from FSharp.Charting
Multiple items
type LabelStyle =
new : ?Angle:int * ?Color:Color * ?Format:string * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:DateTimeIntervalType * ?IntervalType:DateTimeIntervalType * ?IsEndLabelVisible:bool * ?IsStaggered:bool * ?TruncatedLabels:bool * ?FontName:string * ?FontStyle:FontStyle * ?FontSize:float -> LabelStyle
member private Style : LabelStyle
static member Create : ?Angle:int * ?Color:Color * ?Format:string * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:DateTimeIntervalType * ?IntervalType:DateTimeIntervalType * ?IsEndLabelVisible:bool * ?IsStaggered:bool * ?TruncatedLabels:bool * ?FontName:string * ?FontStyle:FontStyle * ?FontSize:float -> LabelStyle

Full name: FSharp.Charting.ChartTypes.LabelStyle

--------------------
new : ?Angle:int * ?Color:System.Drawing.Color * ?Format:string * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:ChartTypes.DateTimeIntervalType * ?IntervalType:ChartTypes.DateTimeIntervalType * ?IsEndLabelVisible:bool * ?IsStaggered:bool * ?TruncatedLabels:bool * ?FontName:string * ?FontStyle:System.Drawing.FontStyle * ?FontSize:float -> ChartTypes.LabelStyle
Multiple items
type Grid =
new : ?Enabled:bool * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:DateTimeIntervalType * ?LineColor:Color * ?LineDashStyle:ChartDashStyle * ?LineWidth:int -> Grid
member private Handle : Grid

Full name: FSharp.Charting.ChartTypes.Grid

--------------------
new : ?Enabled:bool * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType * ?LineColor:System.Drawing.Color * ?LineDashStyle:System.Windows.Forms.DataVisualization.Charting.ChartDashStyle * ?LineWidth:int -> ChartTypes.Grid
Multiple items
type TickMark =
new : ?Size:TickMarkStyle * ?Style:float32 * ?Enabled:bool * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:DateTimeIntervalType * ?LineColor:Color * ?LineDashStyle:ChartDashStyle * ?LineWidth:int -> TickMark
member private Handle : TickMark

Full name: FSharp.Charting.ChartTypes.TickMark

--------------------
new : ?Size:System.Windows.Forms.DataVisualization.Charting.TickMarkStyle * ?Style:float32 * ?Enabled:bool * ?Interval:float * ?IntervalOffset:float * ?IntervalOffsetType:System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType * ?LineColor:System.Drawing.Color * ?LineDashStyle:System.Windows.Forms.DataVisualization.Charting.ChartDashStyle * ?LineWidth:int -> ChartTypes.TickMark
val append : source1:seq<'T> -> source2:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.append
val inverseK' : target:DV -> eta:float -> timeout:int -> seq<DV>

Full name: Examples-inversekinematics.inverseK'
val jTv : (DV -> DV)
val jacobianTv'' : f:('a -> 'b) -> x:'a -> 'b * ('b -> 'a) (requires member GetReverse and member get_A and member get_P)