Source

papl / src / PaplTransform.mli

Full commit
(*
  Copyright (c) 2012 Anders Lau Olsen.
  See LICENSE file for terms and conditions.
*)
(** Rigid body transformations
*)

type rng_t = PaplRandom.rng_t

(** 2D rotations *)
module SO2 : sig
  include PaplSpatialGroup.S with type vec = PaplVector.V2D.t

  val dist : t PaplMetric.t
    (** The distance in angle between a pair of configurations.

        Angles wrap around and the shortest route is chosen.
    *)

  val rotate : float -> t
    (** [rotate angle] is a rotation with angle [angle]. *)

  val complex : t -> Complex.t
    (** Complex number representation of the rotation. *)

  val angle : t -> float
    (** The rotation angle. *)

  val in_range : float -> (float * float) -> bool
    (** [in_range x (a, b)] is true if the angle [x] is on the shortest route
        from the angle [a] to the angle [b].
    *)

  module Sampler : sig
    val uniform : ?rng:rng_t -> (float * float) -> t PaplSampler.t
      (** Uniform sampling over a range of angles.

          [uniform range] uniformly samples values [a] from [range] and returns
          values [rotate a].
      *)

    val uniform_all : ?rng:rng_t -> unit -> t PaplSampler.t
      (** Uniform sampling of all possible 2D rotations.
      *)
  end
end

(** 3D rotations *)
module SO3 : sig
  include PaplSpatialGroup.S with type vec = PaplVector.V3D.t

  val rotate_x : float -> t
  (** Rotation about the x-axis.

      [rotate_x angle] is the rotation about the x-axis with angle [angle].
  *)

  val rotate_y : float -> t
  (** Rotation about the y-axis.

      [rotate_x angle] is the rotation about the y-axis with angle [angle].
  *)

  val rotate_z : float -> t
  (** Rotation about the y-axis.

      [rotate_x angle] is the rotation about the z-axis with angle [angle].
  *)

  val rotate_angle_axis : float -> vec -> t
  (** Rotation about an axis.

      [rotate_axis angle axis] is the rotation about the axis [axis] with angle
      [angle].

      [axis] must be non-zero but isn't required to be a unit-vector.
  *)

  val rotate_unit_quaternion :  float * float * float * float -> t
  (** The rotation of a unit quaternion.

      [rotate_unit_quaternion (a, b, c, d)] constructs a unit quaternion with
      coordinates [(a/len, b/len, c/len, d/len)], where [len] is the Euclidean
      length of [(a, b, c, d)].

      If [(a, b, c, d)] is a zero-vector, an exception is raised.
  *)

  val angle_axis : t -> float * vec
  (** Angle-axis representation of a rotation.
  *)

  val angle : t -> float
  (** The magnitude of the angle of rotation.

      [angle r] is equivalent to [fst (angle_axis r)] but faster to compute.
  *)

  val unit_quaternion : t -> float * float * float * float
  (** Unit quaternion representation of a rotation.
  *)

  val dist : t PaplMetric.t
    (** The distance in angle between a pair of rotations, measured by the
        shortest route.

        [dist a b] is equivalent to [angle (mul (inverse a) b)].
    *)

  module Sampler : sig
    val uniform_all : ?rng:rng_t -> unit -> t PaplSampler.t
    (** Uniformly distributed random rotations.
    *)

    val get_uniform_all : ?rng:rng_t -> unit -> t
    (** A single rotation selected uniformly at random. *)

    val uniform_offset : ?rng:rng_t -> float -> t PaplSampler.t
    (** [get_uniform_offset offset] is a stream of rotations selected uniformly
        at random among the rotations with magnitude less than or equal to
        [offset].

        [offset] must be in the range [\[0, pi)].
    *)

    val get_uniform_offset : ?rng:rng_t -> float -> t
    (** [get_uniform_offset offset] is a single rotation selected uniformly at
        random among the rotations with magnitude less than or equal to
        [offset].

        [offset] must be in the range [\[0, pi)].
    *)
  end
end

(** Metrics for SE2 and SE3. *)
module type SE_METRIC = sig
  type t

  val dist1 : float -> float -> t PaplMetric.t
    (** Manhattan distance.

        The distance [dist1 w_pos w_rot a b] is measured as

        [(w_pos *. d_pos) +. (wo *. d_rot)]

        where [d_pos] is the Euclidean distance from [a] to [b] and [d_rot] is
        the difference in angle.

        The weights must be non-negative.
    *)

  val dist2_sqr : float -> float -> t PaplMetric.t
    (** Squared Euclidean distance.

        The distance [dist w_pos w_rot a b] is measured as

        [(w_pos *. d_pos)**2 +. (wo *. d_rot)**2]

        where [d_pos] is the Euclidean distance from [a] to [b] and [d_rot] is
        the difference in angle.

        The weights must be non-negative.
    *)

  val dist2 : float -> float -> t PaplMetric.t
    (** Euclidean distance.

        [dist2 w_pos w_rot a b] is equivalent to [sqrt (dist2_sqr w_pos w_rot a
        b)].

        The weights must be non-negative.
    *)

  val dist_inf : float -> float -> t PaplMetric.t
    (** Max-distance.

        The distance [dist_inf w_pos w_rot a b] is measured as

        [max (w_pos *. d_pos) (wo *. d_rot)]

        where [d_pos] is the Euclidean distance from [a] to [b] and [d_rot] is
        the difference in angle.

        The weights must be non-negative.
    *)
end

(** Interface common to SE2 and SE3. *)
module type SE = sig
  type t
  type vec
  type rot

  include PaplSpatialGroup.S with type t := t and type vec := vec
  include SE_METRIC with type t := t

  val make : vec -> rot -> t
  val make_rotate : rot -> t
  val make_translate : vec -> t

  val rotation : t -> rot
  val translation : t -> vec
  val get : t -> vec * rot
end

(** 2D transformations *)
module SE2 : sig
  include SE with type vec = SO2.vec and type rot = SO2.t

  val make_pos_angle : vec -> float -> t
  val make_angle : float -> t

  val pos_angle : t -> vec * float
  val pos_complex : t -> vec * Complex.t

  module Sampler : sig
    type box_t = vec * vec

    val make : vec PaplSampler.t -> SO2.t PaplSampler.t -> t PaplSampler.t

    val uniform : ?rng:rng_t -> box_t -> (float * float) -> t PaplSampler.t

    val uniform_all : ?rng:rng_t -> box_t -> t PaplSampler.t
  end
end

(** 3D transformations *)
module SE3 : sig
  include SE with type vec = SO3.vec and type rot = SO3.t

  module Sampler : sig
    type box_t = vec * vec

    val make : vec PaplSampler.t -> SO3.t PaplSampler.t -> t PaplSampler.t

    val uniform_offset : ?rng:rng_t -> box_t -> float -> t PaplSampler.t
    (** [uniform_offset box angle_offset] are random transformations with
        positions sampled from [box] and rotations sampled such that their
        magnitudes are the range [\[0, angle_offset)].

        Positions and rotations are sampled uniformly from within the given
        regions.
    *)

    val uniform_all : ?rng:rng_t -> box_t -> t PaplSampler.t
    (** [uniform_all box] are random transformations with positions sampled from
        [box] and rotations sampled among all rotations.

        Positions and rotations are sampled uniformly from within the given
        regions.
    *)
  end

  val to_array : t -> float array
  (** Convert a transformation to 12 element array of floats.

      The layout of the array is

      [\[| r11; r12; r13; px;
          r21; r22; r23; py;
          r31; r32; r33; pz |\]]

      where the [r] is the rotation matrix representation of the orientation
      and [(px, py, pz)] is the translation vector.
  *)
end