Capítulo 11. Poses temporales

Tabla de contenidos

Poses estáticas
Entrada y salida
Constructores
Conversión de tipos
Accesores
Transformaciones
Sistema de referencia espacial
Comparaciones
Soporte de OGC GeoPose v1.0
Poses temporales
Validez de las poses temporales
Entrada y salida
Constructores
Conversión de tipos
Accesores
Transformaciones
Modificaciones
Restricciones
Sistema de referencia espacial
Operaciones de cuadro delimitador
Operaciones de distancia
Relaciones espaciales
Comparaciones
Agregaciones
Indexación

El tipo pose se utiliza para representar la ubicación y la orientación de objetos geométricos dentro de sistemas de coordenadas anclados a la superficie de la Tierra o dentro de otros sistemas de coordenadas astronómicas. La ubicación se representa mediante un punto 2D o 3D. Para las poses 2D, la orientación se define mediante un ángulo de rotación en (-π, π] expresado en radianes. Para las poses 3D, la orientación se define mediante cuatro valores flotantes W, X, Y, Z, que representan un cuaternión unitario Q = W , X , Y , Z donde Q2 = W2 + X2 + Y2 + Z2 = 1 .

El grupo de trabajo de estándares GeoPose (SWG), que trabaja bajo los auspicios del Open Geospatial Consortium, ha definido un estándar para intercambiar información de poses entre distintos usuarios, dispositivos y plataformas. Se puede encontrar más información sobre el estándar en el repositorio de GitHub del SWG GeoPose.

El tipo pose sirve como tipo base para definir el tipo de pose temporal tpose. El tipo tpose tiene una funcionalidad similar al tipo de punto temporal tgeompoint. Por lo tanto, la mayoría de las funciones y operadores descritos anteriormente para el tipo tgeompoint también son aplicables para el tipo tpose. Además, hay funciones específicas definidas para el tipo tpose.

En este capítulo cubrimos estas funciones.

El tipo tpose se utiliza para definir el tipo trgeometry (es decir, geometría rígida temporal) definido en el siguiente capítulo. La implementación de estos tipos en MobilityDB se ha estudiado en la siguiente tesis doctoral.

Poses estáticas

Una pose 2D es un par de la forma (point2D,radius) donde point2D es un punto geométrico 2D y radius es un valor float que representa un ángulo de rotación en (-π, π] expresado en radianes. Una pose 3D es una tupla de la forma (point3D,W,Y,X,Z) donde point3D es un punto geométrico 3D, y W, X, Y y Z son cuatro floats que representan un cuaternión unitario. Ejemplos de entrada de valores de pose son los siguientes:

SELECT pose 'Pose(Point(1 1), 0.5)';
SELECT pose 'Pose(Point Z(1 1 1), 0.5, 0.5, 0.5, 0.5)';

Se puede especificar un SRID para una pose ya sea al comienzo del literal de pose o antes del literal de punto, como se muestra a continuación.

SELECT pose 'SRID=3812;Pose(Point(1 1), 0.5)';
SELECT pose 'Pose(SRID=5676;Point Z(1 1 1), 0.5, 0.5, 0.5, 0.5)';

Los valores del tipo pose deben satisfacer varias restricciones para que estén bien definidos. Ejemplos de valores incorrectos del tipo pose son los siguientes.

-- Punto vacío
select pose 'Pose(Point empty, 0.5)';
-- Valor de punto incorrecto
SELECT pose 'Pose(Linestring(1 1,2 2), 1.0)';
-- Valor de radio incorrecto
SELECT pose 'Pose(Point(1 1), -10.0)';
-- Punto 3D incorrecto
SELECT pose 'Pose(Point Z(1 1), 1.0)';
-- Orientación 3D incompleta
SELECT pose 'Pose(Point Z(1 1 1), 1.0)';

A continuación damos las funciones y operadores para el tipo pose.

Entrada y salida

  • Devuelve la representación de texto conocido (Well-Known Text o WKT) o la representación extendida de texto conocido (Extended Well-Known Text o EWKT)

    asText({pose,pose[]}) → {text,text[]}

    asEWKT({pose,pose[]}) → {text,text[]}

    SELECT asText(pose 'SRID=4326;Pose(Point(0 0),1)');
    -- Pose(POINT(0 0),1)
    SELECT asText(ARRAY[pose 'Pose(Point(0 0),1)', 'Pose(Point(1 1),2)']);
    -- {"Pose(POINT(0 0),1)","Pose(POINT(1 1),2)"}
    SELECT asEWKT(pose 'SRID=4326;Pose(Point(0 0),1)');
    -- SRID=4326;Pose(Point(0 0),1)
    SELECT asEWKT(ARRAY[pose 'Pose(SRID=5676;Point(0 0),1)', 'Pose(SRID=5676;Point(1 1),2)']);
    -- {"Pose(SRID=5676;POINT(0 0),1)","Pose(SRID=5676;POINT(1 1),2))"}
    
  • Devuelve la representación binaria conocida (Well-Known Binary o WKB), la representación extendida binaria conocida (Extended Well-Known Binary o EWKB), o la representación hexadecimal extendida binaria conocida (Hexadecimal Extended Well-Known Binary o HexEWKB)

    asBinary(pose,endian text='') → bytea

    asEWKB(pose,endian text='') → bytea

    asHexEWKB(pose,endian text='') → text

    El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza la codificación de la máquina.

    SELECT asBinary(pose 'Pose(Point(1 2),1)');
    -- \x0101000000000000f03f0000000000000040000000000000f03f
    SELECT asEWKB(pose 'SRID=7844;Pose(Point(1 2),1)');
    -- \x0141a41e0000000000000000f03f0000000000000040000000000000f03f
    SELECT asHexEWKB(pose 'SRID=3812;Pose(Point(1 2),1)');
    -- 0141E40E0000000000000000F03F0000000000000040000000000000F03F
    
  • Entrada desde la representación de texto conocido (Well-Known Text o WKT) o desde la representación extendida de texto conocido (Extended Well-Known Text o EWKT)

    poseFromText(text) → pose

    poseFromEWKT(text) → pose

    SELECT asEWKT(poseFromText(text 'Pose(Point(1 2),1)'));
    -- Pose(POINT(1 2),1)
    SELECT asEWKT(poseFromEWKT(text 'SRID=3812;Pose(Point(1 2),1)'));
    -- SRID=3812;Pose(Point(1 2),1)
    
  • Entrada desde la representación binaria conocida (Well-Known Binary o WKB), desde la representación extendida binaria conocida (Extended Well-Known Binary o EWKB), o desde la representación hexadecimal extendida binaria conocida (Hexadecimal Extended Well-Known Binary o HexEWKB)

    poseFromBinary(bytea) → pose

    poseFromEWKB(bytea) → pose

    poseFromHexEWKB(text) → pose

    SELECT asEWKT(poseFromBinary(
      '\x0101000000000000f03f0000000000000040000000000000f03f'));
    -- Pose(POINT(1 2),1)
    SELECT asEWKT(poseFromEWKB(
      '\x0141a41e0000000000000000f03f0000000000000040000000000000f03f'));
    -- SRID=7844;Pose(Point(1 2),1)
    SELECT asEWKT(poseFromHexEWKB(
      '0141E40E0000000000000000F03F0000000000000040000000000000F03F'));
    -- SRID=3812;Pose(POINT(1 2),1)
    

Constructores

  • Constructor para poses

    pose(geompoint2D,float) → pose

    pose(geompoint3D,float,float,float,float) → pose

    SELECT asText(pose(ST_Point(1,1), radians(45)), 6);
    -- Pose(POINT(1 1),0.785398)
    SELECT asEWKT(pose(ST_Point(1,1,3812), radians(45)), 6);
    -- SRID=3812;Pose(POINT(1 1),0.785398)
    SELECT asText(pose(ST_PointZ(1,1,1), 1, 0, 0, 0));
    -- Pose(POINT Z (1 1 1),1,0,0,0)
    

Conversión de tipos

Los valores del tipo pose se pueden convertir al tipo de punto geometry utilizando un CAST explícito o utilizando la notación :: como se muestra a continuación.

  • Convertir una pose y, opcionalmente, una marca de tiempo o un período, en una caja espaciotemporal

    pose::stbox

    stbox(pose) → stbox

    stbox(pose,{timestamptz,tstzspan}) → stbox

    SELECT stbox(pose 'SRID=5676;Pose(Point(1 1),0.3)');
    -- SRID=5676;STBOX X((1,1),(1,1))
    SELECT stbox(pose 'Pose(Point(1 1),0.3)', timestamptz '2001-01-01');
    -- STBOX XT(((1,1),(1.3,1.3)),[2001-01-01, 2001-01-01])
    SELECT stbox(pose 'Pose(Point(1 1),0.3)', tstzspan '[2001-01-01,2001-01-02]');
    -- STBOX XT(((1,1),(1.3,1.3)),[2001-01-01, 2001-01-02])
    
  • Convertir una pose en un punto geométrico

    pose::geompoint

    SELECT ST_AsText(pose(ST_Point(1, 1), 1)::geometry);
    -- Point(1 1)
    SELECT ST_AsEWKT(pose(ST_PointZ(1, 1, 1, 5676), 1, 0, 0, 0)::geometry);
    -- SRID=5676;POINT(1 1 1)
    

Accesores

  • Devuelve el punto

    point(pose) → geompoint

    SELECT ST_AsText(point(pose 'Pose(Point(1 1), 0.3)'));
    -- Point(1 1)
    
  • Devuelve la rotación

    rotation(pose2D) → float

    SELECT rotation(pose 'Pose(Point(1 1), 0.3)');
    -- 0.3
    
  • Devuelve la orientación

    orientation(pose3D) → (X,W,Z,T)

    SELECT orientation(pose 'Pose(Point Z(1 1 1), 0, 0, 0, 1)');
    -- (0, 0, 0, 1)
    

Transformaciones

  • Redondear el punto y la orientación de la pose al número de posiciones decimales

    round(pose,integer=0) → pose

    SELECT asText(round(pose(ST_Point(1.123456789,1.123456789), 0.123456789), 6));
    -- Pose(POINT(1.123457 1.123457),0.123457)
    

Sistema de referencia espacial

  • Devuelve o establece el identificador de referencia espacial

    srid(pose) → integer

    setSRID(pose) → pose

    SELECT SRID(pose 'Pose(SRID=5676;Point(1 1), 0.3)');
    -- 5676
    SELECT asEWKT(setSRID(pose 'Pose(Point(0 0),1)', 4326));
    -- SRID=4326;Pose(POINT(0 0),1)
    
  • Transformar a un identificador de referencia espacial

    transform(pose,integer) → pose

    transformPipeline(pose,pipeline text,to_srid integer,is_forward bool=true) → pose

    La función transform especifica la transformación con un SRID de destino. Se genera un error cuando la pose de entrada tiene un SRID desconocido (representado por 0).

    La función transformPipeline especifica la transformación con una canalización de transformación de coordenadas definida representada con el siguiente formato de cadena:

    urn:ogc:def:coordinateOperation:AUTHORITY::CODE

    El SRID de la pose de entrada se ignora y el SRID de la pose de salida se establecerá en cero a menos que se proporcione un valor a través del parámetro opcional to_srid. Como se indica en el último parámetro, la canalización se ejecuta de forma predeterminada en dirección hacia adelante; al establecer el parámetro en falso, la canalización se ejecuta en la dirección inversa.

    SELECT asEWKT(transform(pose 'SRID=4326;Pose(Point(4.35 50.85),1)', 3812), 6);
    -- SRID=4326;Pose(POINT(648679.018035 671067.055638),1)
    
    WITH test(pose, pipeline) AS (
      SELECT pose 'Pose(SRID=4326;Point(4.3525 50.846667),1)',
        text 'urn:ogc:def:coordinateOperation:EPSG::16031' )
    SELECT asEWKT(transformPipeline(transformPipeline(pose, pipeline, 4326), pipeline,
      4326, false), 6)
    FROM test;
    -- SRID=4326;Pose(POINT(4.3525 50.846667),1)
    

Comparaciones

Los operadores de comparación (=, < y así sucesivamente) están disponibles para poses. Excepto la igualdad y la desigualdad, los otros operadores de comparación no son útiles en el mundo real pero permiten que los índices de árbol B se construyan en poses.

  • Comparaciones tradicionales

    pose {=, <>, <, >, <=, >=} pose

    SELECT pose 'Pose(Point(3 3), 0.5)' = pose 'Pose(Point(3 3), 0.5)';
    -- true
    SELECT pose 'Pose(Point(3 3), 0.5)' <> pose 'Pose(Point(3 3), 0.6)';
    -- true
    SELECT pose 'Pose(Point(3 3), 0.5)' < pose 'Pose(Point(3 3), 0.6)';
    -- true
    SELECT pose 'Pose(Point(3 3), 0.6)' > pose 'Pose(Point(2 2), 0.6)';
    -- true
    SELECT pose 'Pose(Point Z(1 1 1), 0.5, 0.5, 0.5, 0.5)' <= pose 'Pose(Point Z(2 2 2), 0.5, 0.5, 0.5, 0.5)';
    -- true
    SELECT pose 'Pose(Point(1 1), 0.6)' >= pose 'Pose(Point(1 1), 0.5)';
    -- true
    
  • ¿Son las poses aproximadamente iguales con respecto a un valor épsilon?

    pose ~= pose → boolean

    SELECT pose 'Pose(SRID=5676;Point(1 1), 0.3)' ~= 
      pose 'Pose(SRID=5676;Point(1 1.0000001), 0.30000001)';
    -- true
    

Soporte de OGC GeoPose v1.0

El tipo pose de MobilityDB implementa el modelo de datos que subyace al estándar OGC GeoPose v1.0 (21-056r10): una position más una orientation en un marco de referencia conocido, donde la orientación es un cuaternión unitario en la convención de Hamilton o, de forma equivalente, una terna yaw / pitch / roll bajo la convención Tait-Bryan intrínseca ZYX. Esta sección agrupa la superficie SQL que expone esa interoperabilidad: E/S JSON para las clases de conformidad Basic del estándar, una función auxiliar de renormalización explícita para quienes ejecutan composiciones largas, y los accesores de ángulos de Euler que esperan los consumidores Basic-YPR.

Entrada y salida JSON

  • Convertir hacia o desde la codificación JSON de OGC GeoPose v1.0 (clase de conformidad Basic-Quaternion o Basic-YPR)

    asGeoPose(pose,conformance int4=0,maxdecimaldigits int4=-1) → text

    poseFromGeoPose(text) → pose

    El argumento conformance selecciona la clase de salida: 0 = Basic-Quaternion (predeterminado, sin pérdida), 1 = Basic-YPR (yaw, pitch, roll en grados, Tait-Bryan intrínseco ZYX). El argumento maxdecimaldigits es el número de dígitos significativos que se conservan en los números JSON; -1 utiliza el valor predeterminado sin pérdida de json-c. La función de entrada detecta automáticamente la clase de conformidad a partir de las claves JSON (el miembro quaternion → Basic-Quaternion, el miembro angles → Basic-YPR). Las clases de conformidad Basic exigen un marco exterior geográfico; la implementación acepta el SRID 4326 (o 0, tratado como geográfico) y rechaza los SRID proyectados en el límite de la conversión.

    SELECT asGeoPose(pose 'Pose(Point(8 47 1500), 0.7071067811865476, 0, 0, 0.7071067811865475)', 0, 6);
    -- {"position":{"lat":47,"lon":8,"h":1500},"quaternion":{"x":0,"y":0,"z":0.707107,"w":0.707107}}
    SELECT asGeoPose(pose 'Pose(Point(8 47 1500), 0.7071067811865476, 0, 0, 0.7071067811865475)', 1, 6);
    -- {"position":{"lat":47,"lon":8,"h":1500},"angles":{"yaw":90,"pitch":0,"roll":0}}
    SELECT asEWKT(poseFromGeoPose(
      '{"position":{"lat":47,"lon":8,"h":1500},"angles":{"yaw":90,"pitch":0,"roll":0}}'));
    -- Pose(POINT Z (8 47 1500),0.7071067811865476,0,0,0.7071067811865475)
    

Renormalización de cuaterniones

  • Devuelve una pose cuyo cuaternión de orientación se ha llevado de nuevo a la norma unitaria. Una pose 2D se devuelve sin cambios, ya que su orientación es un único ángulo que no deriva. A una pose 3D se le divide el cuaternión por su norma euclidiana, de modo que composiciones largas de SLERP (o cualquier otra vía que acumule deriva de punto flotante en |q|) pueden restaurarse al invariante |q| = 1 que requiere el código de SLERP y de descomposición de Euler.

    poseNormalize(pose) → pose

    SELECT asText(poseNormalize(pose 'Pose(Point(1 1 1), 0.5, 0.5, 0.5, 0.5)'));
    -- Pose(POINT Z (1 1 1),0.5,0.5,0.5,0.5)
    

Accesores de ángulos de Euler

  • Devuelve el ángulo yaw, pitch o roll de una pose, en radianes, bajo la convención Tait-Bryan intrínseca ZYX que exige la clase de conformidad Basic-YPR de OGC GeoPose

    yaw(pose) → float

    pitch(pose) → float

    roll(pose) → float

    Para una pose 2D, yaw devuelve la rotación almacenada theta —por convención, el yaw del marco del cuerpo— y pitch y roll devuelven 0. Para una pose 3D, los tres valores provienen de la descomposición Tait-Bryan intrínseca ZYX del cuaternión de orientación. El término de pitch asin se acota a [-1, 1] para absorber la pequeña deriva numérica que pueden introducir las composiciones largas de cuaterniones.

    SELECT yaw(pose 'Pose(Point(1 1), 0.5)');
    -- 0.5
    SELECT pitch(pose 'Pose(Point(1 1), 0.5)');
    -- 0
    SELECT roll(pose 'Pose(Point(0 0 0), 0.7071067811865476, 0, 0, 0.7071067811865475)');
    -- 0
    SELECT yaw(pose 'Pose(Point(0 0 0), 0.7071067811865476, 0, 0, 0.7071067811865475)');
    -- 1.5707963267948966
    
  • Eleva los accesores de ángulos de Euler a través de una pose temporal, devolviendo un flotante temporal (radianes) por cada instante bajo la convención Tait-Bryan intrínseca ZYX

    yaw(tpose) → tfloat

    pitch(tpose) → tfloat

    roll(tpose) → tfloat

    SELECT asText(yaw(tpose '[Pose(Point(0 0), 0.0)@2000-01-01, Pose(Point(1 1), 0.5)@2000-01-02]'));
    -- [0@2000-01-01, 0.5@2000-01-02]
    

Registro de metadatos de marcos

El estándar OGC GeoPose v1.0 distingue el marco exterior (la referencia global, por ejemplo, WGS-84 geográfico o ECEF) del marco interior (el marco del cuerpo cuya orientación es el cuaternión de la pose). Las clases de conformidad Basic exigen WGS-84 geográfico como marco exterior y un marco interior implícito de ejes de cuerpo dextrógiros; la clase Advanced admite pilas de marcos con nombre.

En MobilityDB v1, el tipo pose codifica el marco exterior de forma implícita mediante su SRID y utiliza el marco interior convencional de ejes de cuerpo dextrógiros. La tabla geopose_frames documenta esta correspondencia y siembra un registro paralelo a la tabla pointcloud_formats de pgPointCloud, de modo que el soporte futuro de la clase Advanced solo necesite ampliar el catálogo en lugar de rediseñarlo.

SELECT frame_id, authority, code, name, is_geographic
FROM geopose_frames ORDER BY frame_id;
-- 1 | EPSG | 4326 | WGS-84 geographic (lat/lon/h)                | t
-- 2 | EPSG | 4978 | WGS-84 ECEF (Earth-Centred Earth-Fixed)      | f
-- 3 | OGC  | LTP  | Local Tangent Plane (East-North-Up)          | f
-- 4 | OGC  | BODY | Right-handed body axes (default inner frame) | f

Tres funciones auxiliares SQL proporcionan una interfaz de consulta estable para el código que no quiere codificar de forma rígida la disposición de la tabla:

  • geopose_frame_srid(int) → int — el SRID de PostGIS de un marco, o NULL si el marco es paramétrico (LTP, BODY).

  • geopose_frame_name(int) → text — el nombre legible del marco.

  • geopose_frame_is_geographic(int) → booleantrue para los marcos lat/lon/h, false para los cartesianos o proyectados.

Los usuarios pueden registrar marcos personalizados insertándolos en geopose_frames; el catálogo está marcado como una tabla de configuración, por lo que pg_dump preserva las filas del usuario.

Transformación rígida cuerpo↔mundo

La función applyPose aplica la transformación de cuerpo rígido codificada por una pose (la correspondencia cuerpo→mundo de OGC GeoPose) a una geometría en el marco del cuerpo, produciendo la geometría correspondiente en el marco del mundo. La transformación es

world = R(q) · body + p

donde (p, q) son la posición y la orientación de la pose. La forma estática toma una única pose y una geometría estática; la forma temporal eleva la transformación rígida por instante de una tpose a lo largo de sus instantes, produciendo una trayectoria tgeompoint en el marco del mundo de la geometría del cuerpo. La versión v1 admite geometrías de cuerpo de tipo punto y multipunto; las líneas y los polígonos quedan aplazados. La interpolación lineal de la trayectoria resultante es la cuerda de cada segmento, que aproxima la verdadera trayectoria de cuerpo rígido (un arco circular bajo SLERP), la misma concesión que MobilityDB ya adopta para las trayectorias espaciales.

applyPose(geometry, pose) → geometry

applyPose(geometry, tpose) → tgeompoint

-- A body sensor offset 1 unit along the body X axis, traced through a
-- tpose that ends 90 degrees yawed and translated to (10, 20).
SELECT asText(applyPose(ST_Point(1,0),
  tpose '[Pose(Point(0 0), 0)@2026-01-01,
          Pose(Point(10 20), 1.5707963267948966)@2026-01-02]'));
-- [POINT(1 0)@2026-01-01, POINT(10 21)@2026-01-02]

Transformaciones de marco entre SRID

La función transform(pose, srid) lleva los valores de pose de un SRID a otro. El flujo de trabajo n.º 6 del plan de GeoPose temporal amplía el comportamiento preexistente de solo posición con la corrección de orientación necesaria cuando el marco de origen y el de destino tienen bases distintas en el punto de la pose. La versión v1 implementa el caso canónico de OGC GeoPose —WGS-84 geográfico (EPSG:4326) ↔ WGS-84 ECEF (EPSG:4978)— utilizando la base estándar Este-Norte-Arriba en el punto geográfico como pivote de rotación. Para los pares de SRID cuya corrección de orientación aún no está definida, transform emite un NOTICE y deja pasar la orientación sin cambios.

Un viaje de ida y vuelta a través de ECEF y de regreso aterriza exactamente en la pose de entrada:

SELECT asEWKT(round(
  transform(transform(pose 'SRID=4326;Pose(Point(8 47 0), 1, 0, 0, 0)', 4978),
            4326), 6));
-- SRID=4326;Pose(POINT Z (8 47 0),1,0,0,0)

-- At the equator-meridian (lat=lon=0), the body identity quaternion in
-- the ECEF basis becomes the canonical ENU->ECEF rotation:
SELECT asEWKT(round(
  transform(pose 'SRID=4326;Pose(Point(0 0 0), 1, 0, 0, 0)', 4978), 6));
-- SRID=4978;Pose(POINT Z (6378137 0 0),0.5,-0.5,-0.5,-0.5)

La implementación también corrige un error preexistente de solo posición en el que transform no actualizaba el campo SRID del resultado, de modo que la pose devuelta ahora lleva el SRID de destino como se espera.

E/S JSON temporal

  • Convierte una pose temporal hacia o desde una envoltura JSON TemporalGeoPose. Cada carga útil por instante es un documento GeoPose de clase Basic estrictamente válido según OGC más un miembro validTime; la envoltura registra la clase de conformidad, la interpolación y (para secuencias y conjuntos de secuencias) la inclusión de los límites del período. Un consumidor GeoPose ajeno a MEOS puede iterar sobre instants[] (o cada sequences[].instants[]) y consumir cada elemento como un documento GeoPose estático.

    asGeoPose(tpose,conformance int4=0,maxdecimaldigits int4=-1) → text

    tposeFromGeoPose(text) → tpose

    La forma de la envoltura es

    {
      "type":          "TemporalGeoPose",
      "version":       "1.0",
      "conformance":   "Basic-Quaternion" | "Basic-YPR",
      "interpolation": "None" | "Discrete" | "Step" | "Linear",
      "instants":      [...]                  // for TInstant + TSequence
      "lower_inc":     true|false,            // for TSequence only
      "upper_inc":     true|false,            // for TSequence only
      "sequences":     [{...}, ...]           // for TSequenceSet only
    }
    
    SELECT asGeoPose(tpose '[Pose(Point(8 47), 0)@2026-01-01,
                             Pose(Point(9 48), 0.5)@2026-01-02]',
                     1, 4);
    -- {"type":"TemporalGeoPose","version":"1.0","conformance":"Basic-YPR",
    --  "interpolation":"Linear","lower_inc":true,"upper_inc":true,
    --  "instants":[
    --    {"position":{"lat":47,"lon":8,"h":0},
    --     "angles":{"yaw":0,"pitch":0,"roll":0},
    --     "validTime":"2026-01-01 00:00:00+01"},
    --    {"position":{"lat":48,"lon":9,"h":0},
    --     "angles":{"yaw":28.65,"pitch":0,"roll":0},
    --     "validTime":"2026-01-02 00:00:00+01"}]}
    

Velocidad y velocidad angular

  • Devuelve la velocidad de una pose temporal como un flotante temporal: la magnitud de la velocidad de la componente de posición (distancia recorrida por unidad de tiempo). La orientación no forma parte de este escalar; para la velocidad angular véase angularSpeed.

    speed(tpose) → tfloat

    SELECT asText(speed(tpose '[Pose(Point(0 0), 0)@2000-01-01, Pose(Point(1 1), 0.5)@2000-01-02]'));
    -- Interp=Step;[1.6368e-5@2000-01-01, 1.6368e-5@2000-01-02]
    -- (sqrt(2) units / 86400 seconds — units depend on the SRID's CRS)
    
  • Devuelve la velocidad angular de una pose temporal como un flotante temporal con interpolación por pasos (radianes por unidad de tiempo). Para las poses 2D es el delta theta del arco más corto por segmento dividido por la duración del segmento; para las poses 3D es el ángulo de arco de SLERP 2 · acos(|q1 · q2|) dividido por la duración del segmento. SLERP tiene por construcción velocidad angular constante a lo largo de un segmento, por lo que el resultado es constante a trozos.

    angularSpeed(tpose) → tfloat

    -- 90-degree yaw rotation over one day -> pi/2 rad / 86400 s
    SELECT asText(angularSpeed(tpose
      '[Pose(Point(0 0 0), 1, 0, 0, 0)@2000-01-01,
        Pose(Point(0 0 0), 0.7071067811865476, 0, 0, 0.7071067811865475)@2000-01-02]'));
    -- Interp=Step;[1.8181e-5@2000-01-01, 1.8181e-5@2000-01-02]