Skip to content

Module for processing geometry models using concepts from comp-rob2b and ones introduced for use by the SECORO group.

Classes:

Functions:

FrameModel

FrameModel(frame_id, graph)

Bases: ModelBase

Model object for a Frame

Attributes:

  • origin (URIRef) –

    URI for origin Point of the Frame

Parameters:

  • frame_id (URIRef) –

    URI of the frame in the graph

  • graph (Graph) –

    RDF graph for loading attributes

Source code in src/rdf_utils/models/geometry.py
69
70
71
72
73
74
75
76
def __init__(self, frame_id: URIRef, graph: Graph) -> None:
    super().__init__(node_id=frame_id, graph=graph)

    origin_id = graph.value(subject=self.id, predicate=URI_GEOM_PRED_ORIGIN)
    assert origin_id is not None and isinstance(
        origin_id, URIRef
    ), f"Frame '{self.id}' does not have a valid 'origin' property: {origin_id}"
    self.origin = origin_id

PoseCoordModel

PoseCoordModel(coord_id, graph)

Bases: ModelBase

Model object for a PoseCoordinate

Attributes:

  • pose (URIRef) –

    URI of Pose of the coordinate

  • of (FrameModel) –

    the pose's target frame

  • wrt (FrameModel) –

    the pose's reference frame

  • as_seen_by (URIRef) –

    the coordinate's reference frame

Parameters:

  • coord_id (URIRef) –

    URI of the PoseCoordinate in the graph

  • graph (Graph) –

    RDF graph for loading attributes

Source code in src/rdf_utils/models/geometry.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def __init__(self, coord_id: URIRef, graph: Graph) -> None:
    super().__init__(node_id=coord_id, graph=graph)

    assert URI_GEOM_TYPE_POSE_COORD in self.types, f"'{self.id}' is not a PoseCoordinate"

    seen_by_id = graph.value(subject=self.id, predicate=URI_GEOM_PRED_SEEN_BY)
    assert seen_by_id is not None and isinstance(
        seen_by_id, URIRef
    ), f"PoseCoordinate '{self.id}' does not have a valid 'as-seen-by' property: {seen_by_id}"
    self.as_seen_by = seen_by_id

    assert URI_GEOM_TYPE_POSE_REF in self.types, f"'{self.id}' is not a PoseReference"
    pose_id = graph.value(subject=self.id, predicate=URI_GEOM_PRED_OF_POSE)
    assert pose_id is not None and isinstance(
        pose_id, URIRef
    ), f"PoseCoordinate '{self.id}' does not have a valid 'of-pose' property: {pose_id}"
    self.pose = pose_id

    of_id = graph.value(subject=self.pose, predicate=URI_GEOM_PRED_OF)
    assert of_id is not None and isinstance(
        of_id, URIRef
    ), f"Pose '{self.pose}' does not have a valid 'of' property: {of_id}"
    self.of = FrameModel(frame_id=of_id, graph=graph)

    wrt_id = graph.value(subject=self.pose, predicate=URI_GEOM_PRED_WRT)
    assert wrt_id is not None and isinstance(
        wrt_id, URIRef
    ), f"Pose '{self.pose}' does not have a valid 'with-respect-to' property: {wrt_id}"
    self.wrt = FrameModel(frame_id=wrt_id, graph=graph)

PositionCoordModel

PositionCoordModel(coord_id, graph)

Bases: ModelBase

Model object for a PoseCoordinate

Attributes:

  • position (URIRef) –

    URI of Position of the coordinate

  • of (URIRef) –

    URI of the position's target Point

  • wrt (URIRef) –

    URI of the position's reference Point

  • as_seen_by (URIRef) –

    the coordinate's reference frame

Parameters:

  • coord_id (URIRef) –

    URI of the PositionCoordinate in the graph

  • graph (Graph) –

    RDF graph for loading attributes

Source code in src/rdf_utils/models/geometry.py
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
def __init__(self, coord_id: URIRef, graph: Graph) -> None:
    super().__init__(node_id=coord_id, graph=graph)

    assert (
        URI_GEOM_TYPE_POSITION_COORD in self.types
    ), f"'{self.id}' is not a PositionCoordinate"

    seen_by_id = graph.value(subject=self.id, predicate=URI_GEOM_PRED_SEEN_BY)
    assert (
        seen_by_id is not None and isinstance(seen_by_id, URIRef)
    ), f"PositionCoordinate '{self.id}' does not have a valid 'as-seen-by' property: {seen_by_id}"
    self.as_seen_by = seen_by_id

    assert URI_GEOM_TYPE_POSITION_REF in self.types, f"'{self.id}' is not a PositionReference"
    position_id = graph.value(subject=self.id, predicate=URI_GEOM_PRED_OF_POSITION)
    assert (
        position_id is not None and isinstance(position_id, URIRef)
    ), f"PositionCoordinate '{self.id}' does not have a valid 'of-position' property: {position_id}"
    self.position = position_id

    of_id = graph.value(subject=self.position, predicate=URI_GEOM_PRED_OF)
    assert of_id is not None and isinstance(
        of_id, URIRef
    ), f"Position '{self.position}' does not have a valid 'of' property: {of_id}"
    self.of = of_id

    wrt_id = graph.value(subject=self.position, predicate=URI_GEOM_PRED_WRT)
    assert wrt_id is not None and isinstance(
        wrt_id, URIRef
    ), f"Position '{self.position}' does not have a valid 'with-respect-to' property: {wrt_id}"
    self.wrt = wrt_id

get_coord_vectorxyz

get_coord_vectorxyz(coord_model, graph)

Extract coordinates for a VectorXYZ model.

Parameters:

  • coord_model (ModelBase) –

    coordinate model object

  • graph (Graph) –

    RDF graph to look for coordinate attributes

Returns:

Source code in src/rdf_utils/models/geometry.py
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
def get_coord_vectorxyz(coord_model: ModelBase, graph: Graph) -> tuple[float, float, float]:
    """Extract coordinates for a VectorXYZ model.

    Parameters:
        coord_model: coordinate model object
        graph: RDF graph to look for coordinate attributes

    Returns:
        tuple containing (x, y, z) coordinates
    """
    assert (
        URI_GEOM_TYPE_VECTOR_XYZ in coord_model.types
    ), f"Coordinate '{coord_model.id}' is not of type 'VectorXYZ'"

    x_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_X)
    assert isinstance(x_node, Literal) and isinstance(
        x_node.value, float
    ), f"Coordinate '{coord_model.id}' does not have a 'x' property of type float: {x_node}"

    y_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_Y)
    assert isinstance(y_node, Literal) and isinstance(
        y_node.value, float
    ), f"Coordinate '{coord_model.id}' does not have a 'y' property of type float: {y_node}"

    z_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_Z)
    assert isinstance(z_node, Literal) and isinstance(
        z_node.value, float
    ), f"Coordinate '{coord_model.id}' does not have a 'z' property of type float: {z_node}"

    return (x_node.value, y_node.value, z_node.value)

get_euler_angles_abg

get_euler_angles_abg(coord_model, graph)

Extract coordinates for a AnglesAlphaBetaGamma model.

Parameters:

  • coord_model (PoseCoordModel) –

    coordinate model object, currently only handle PoseCoordModel

  • graph (Graph) –

    RDF graph to look for coordinate attributes

Returns:

Source code in src/rdf_utils/models/geometry.py
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
def get_euler_angles_abg(
    coord_model: PoseCoordModel, graph: Graph
) -> tuple[str, bool, URIRef, tuple[float, float, float]]:
    """Extract coordinates for a AnglesAlphaBetaGamma model.

    Parameters:
        coord_model: coordinate model object, currently only handle PoseCoordModel
        graph: RDF graph to look for coordinate attributes

    Returns:
        tuple containing:
        - axes sequence of the Euler angles
        - whether the rotation is intrinsic
        - unit of the angle values (degrees or radians)
        - angle values
    """
    assert (
        URI_GEOM_TYPE_ANGLES_ABG in coord_model.types
    ), f"coord '{coord_model.id}' does not have type 'AnglesAlphaBetaGamma'"

    seq, is_intrinsic = get_euler_angles_params(coord_model=coord_model, graph=graph)

    a_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_ALPHA)
    assert isinstance(a_node, Literal) and isinstance(
        a_node.value, float
    ), f"Coordinate '{coord_model.id}' does not have a 'alpha' property of type float: {a_node}"

    b_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_BETA)
    assert isinstance(b_node, Literal) and isinstance(
        b_node.value, float
    ), f"Coordinate '{coord_model.id}' does not have a 'beta' property of type float: {b_node}"

    g_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_GAMMA)
    assert isinstance(g_node, Literal) and isinstance(
        g_node.value, float
    ), f"Coordinate '{coord_model.id}' does not have a 'gamma' property of type float: {g_node}"

    angle_unit = None
    for unit_node in graph.objects(subject=coord_model.id, predicate=URI_QUDT_PRED_UNIT):
        assert isinstance(
            unit_node, URIRef
        ), f"Coordinate '{coord_model.id}' does not ref a URI 'unit': {unit_node}"
        if unit_node != URI_QUDT_TYPE_DEG and unit_node != URI_QUDT_TYPE_RAD:
            continue
        angle_unit = unit_node
        break

    assert angle_unit is not None, f"Coordinate '{coord_model.id}' has invalid angle unit"

    return seq, is_intrinsic, angle_unit, (a_node.value, b_node.value, g_node.value)

get_euler_angles_params

get_euler_angles_params(coord_model, graph)

Extract parameters for a EulerAngles model.

Parameters:

  • coord_model (PoseCoordModel) –

    coordinate model object, currently only handle PoseCoordModel

  • graph (Graph) –

    RDF graph to look for coordinate attributes

Returns:

  • tuple[str, bool]

    tuple containing axes sequence of the Euler angles and whether the rotation is intrinsic

Source code in src/rdf_utils/models/geometry.py
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
def get_euler_angles_params(coord_model: PoseCoordModel, graph: Graph) -> tuple[str, bool]:
    """Extract parameters for a EulerAngles model.

    Parameters:
        coord_model: coordinate model object, currently only handle PoseCoordModel
        graph: RDF graph to look for coordinate attributes

    Returns:
        tuple containing axes sequence of the Euler angles and whether the rotation is intrinsic
    """
    assert (
        URI_GEOM_TYPE_EULER_ANGLES in coord_model.types
    ), f"coord '{coord_model.id}' does not have type 'EulerAngles'"

    if URI_GEOM_TYPE_INTRINSIC in coord_model.types:
        is_intrinsic = True
    elif URI_GEOM_TYPE_EXTRINSIC in coord_model.types:
        is_intrinsic = False
    else:
        raise ConstraintViolation(
            domain="geometry",
            message=f"EulerAngles coord '{coord_model.id}' does not have 'Intrinsic' or 'Extrinsic' type",
        )

    seq_node = graph.value(subject=coord_model.id, predicate=URI_GEOM_PRED_AXES_SEQ)
    assert (
        isinstance(seq_node, Literal) and isinstance(seq_node.value, str)
    ), f"Coordinate '{coord_model.id}' does not have a 'axes-sequence' property of type str: {seq_node}"

    return seq_node.value, is_intrinsic

get_scipy_rotation

get_scipy_rotation(coord_model, graph)

Parse orientation coordinate in a graph into a SciPy Rotation.

Handles and convert different orientation coordinate types into a SciPy Rotation

Parameters:

  • coord_model (PoseCoordModel) –

    coordinate model object, currently only handle PoseCoordModel

  • graph (Graph) –

    RDF graph to look for coordinate attributes

Returns:

Source code in src/rdf_utils/models/geometry.py
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
def get_scipy_rotation(coord_model: PoseCoordModel, graph: Graph) -> Rotation:
    """Parse orientation coordinate in a graph into a SciPy Rotation.

    Handles and convert different orientation coordinate types into a
    [SciPy Rotation](scipy.spatial.transform.Rotation)

    Parameters:
        coord_model: coordinate model object, currently only handle PoseCoordModel
        graph: RDF graph to look for coordinate attributes

    Returns:
        Corresponding [SciPy Rotation](scipy.spatial.transform.Rotation)
    """
    if URI_GEOM_TYPE_ANGLES_ABG in coord_model.types:
        seq, is_intrinsic, unit, angles = get_euler_angles_abg(coord_model=coord_model, graph=graph)
        if is_intrinsic:
            seq = seq.upper()
        return Rotation.from_euler(seq=seq, angles=angles, degrees=(unit == URI_QUDT_TYPE_DEG))
    else:
        raise RuntimeError(
            f"unhandled orientation coordinate type for '{coord_model.id}', types: {coord_model.types}"
        )