DiffSharp


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)\).

Chart

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.[0], l1 * sin a.[0]
    let x2, y2 = x1 + l2 * cos (a.[0] + a.[1]), y1 + l2 * sin (a.[0] + a.[1])
    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.[2]; t.[3]]

// 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<Vector<D>>
val movement2 : seq<Vector<D>>
val movement3 : seq<Vector<D>>

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.[0], t.[1]; t.[2], t.[3]]

let drawArmLive (aa:seq<DV>) =
    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)
Chart

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
Chart
namespace DiffSharp
namespace DiffSharp.AD
module Float64

from DiffSharp.AD
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)

Full name: DiffSharp.AD.Float64.DOps.toDV
val transform : a:DV -> DV

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

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

from DiffSharp.AD.Float64

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

Full name: DiffSharp.AD.Float64.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

Full name: DiffSharp.AD.Float64.DiffOps.jacobian'
val error : DV
val da : DV
Multiple items
union case DM.DM: float [,] -> DM

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

from DiffSharp.AD.Float64

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

Full name: DiffSharp.AD.Float64.DM
val inverse : m:DM -> DM

Full name: DiffSharp.AD.Float64.DM.inverse
val norm : v:DV -> D

Full name: DiffSharp.AD.Float64.DV.norm
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)

Full name: DiffSharp.AD.Float64.DOps.primal
val convert : v:'a -> 'b (requires member op_Explicit)

Full name: DiffSharp.AD.Float64.DOps.convert
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)

Full name: DiffSharp.AD.Float64.DiffOps.jacobianTv''