Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ target/
.idea/

*~
.DS_Store
*.DS_Store*

# DOC
qsr_lib/docs/_build/
Expand Down
1 change: 1 addition & 0 deletions qsr_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ if (CATKIN_ENABLE_TESTING)
add_rostest(tests/qtcbs_tester.test)
add_rostest(tests/qtccs_tester.test)
add_rostest(tests/qtcbcs_tester.test)
add_rostest(tests/ra_tester.test)
add_rostest(tests/rcc2_tester.test)
add_rostest(tests/rcc3_tester.test)
add_rostest(tests/rcc8_tester.test)
Expand Down
4 changes: 2 additions & 2 deletions qsr_lib/scripts/example_extended.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def pretty_print_world_qsr_trace(which_qsr, qsrlib_response_message):


if __name__ == "__main__":
options = ["rcc2", "rcc3", "rcc8", "cardir", "qtcbs", "qtccs", "qtcbcs", "argd", "argprobd", "mos", "multiple"]
options = sorted(QSRlib().qsrs_registry.keys()) + ["multiple"]
multiple = options[:]; multiple.remove("multiple"); multiple.remove("argd"); multiple.remove("argprobd")

parser = argparse.ArgumentParser()
Expand All @@ -50,7 +50,7 @@ def pretty_print_world_qsr_trace(which_qsr, qsrlib_response_message):

dynamic_args = {}

if which_qsr == "rcc3" or which_qsr == "rcc2":
if which_qsr in ["rcc2", "rcc3", "ra"]:
dynamic_args = {which_qsr: {"quantisation_factor": args.quantisation_factor}}
o1 = [Object_State(name="o1", timestamp=0, x=1., y=1., xsize=5., ysize=8.),
Object_State(name="o1", timestamp=1, x=1., y=2., xsize=5., ysize=8.),
Expand Down
4 changes: 3 additions & 1 deletion qsr_lib/src/qsrlib_qsrs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from qsr_arg_prob_relations_distance import QSR_Arg_Prob_Relations_Distance
from qsr_moving_or_stationary import QSR_Moving_or_Stationary
from qsr_new_mwe import QSR_MWE
from qsr_ra import QSR_RA

# register new qsrs by class name below
qsrs_registry = (QSR_RCC2,
Expand All @@ -21,4 +22,5 @@
QSR_Arg_Relations_Distance,
QSR_Arg_Prob_Relations_Distance,
QSR_Moving_or_Stationary,
QSR_MWE)
QSR_MWE,
QSR_RA)
1 change: 1 addition & 0 deletions qsr_lib/src/qsrlib_qsrs/qsr_abstractclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class QSR_Abstractclass(object):
def __init__(self):
"""Constructor."""
self._dtype_map = {"points": self._return_points,
"bounding_boxes": self._return_bounding_boxes_2d, # todo this is to handle 2D/3D and needs its own function
"bounding_boxes_2d": self._return_bounding_boxes_2d}
"""dict: Mapping of _dtype to methods."""

Expand Down
79 changes: 79 additions & 0 deletions qsr_lib/src/qsrlib_qsrs/qsr_ra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, division
from numpy import isnan
from qsrlib_qsrs.qsr_dyadic_abstractclass import QSR_Dyadic_1t_Abstractclass


class QSR_RA(QSR_Dyadic_1t_Abstractclass):
"""Regional Algebra.

Members:
* _unique_id: "ra"
* _all_possible_relations: ("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "=")
* _dtype: "bounding_boxes"

Some explanation about the QSR. Maybe a reference if it exists.
"""

_unique_id = "ra"
"""str: Unique identifier name of the QSR."""

_all_possible_relations = ("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "=")
"""tuple: All possible relations of the QSR."""

_dtype = "bounding_boxes"
"""str: On what kind of data the QSR works with."""

_inverse_map = {"<": ">", "m": "mi", "o": "oi", "s": "si", "d": "di", "f": "fi",
">": "<", "mi": "m", "o1": "o", "si": "s", "di": "d", "fi": "f"}
"""dict: Inverse relations"""

def __init__(self):
"""Constructor.

:return:
"""
super(QSR_RA, self).__init__()

def _compute_qsr(self, bb1, bb2, qsr_params, **kwargs):
"""Compute QSR value.

:param bb1: First object's bounding box.
:type bb2: tuple or list
:param bb2: Second object's bounding box.
:type bb2: tuple or list
:param qsr_params: QSR specific parameters passed in `dynamic_args`.
:type qsr_params: dict
:param kwargs: Optional further arguments.
:return: The computed QSR value: two/three comma separated Allen relations for 2D/3D.
:rtype: str
"""
if len(bb1) == 4 and len(bb2) == 4: # 2D version
return ",".join([self.__allen((bb1[0], bb1[2]), (bb2[0], bb2[2])),
self.__allen((bb1[1], bb1[3]), (bb2[1], bb2[3]))])
elif len(bb1) == 6 and len(bb2) == 6: # 3D version
return ",".join([self.__allen((bb1[0], bb1[3]), (bb2[0], bb2[3])),
self.__allen((bb1[1], bb1[4]), (bb2[1], bb2[4])),
self.__allen((bb1[2], bb1[5]), (bb2[2], bb2[5]))])
else:
raise ValueError("bb1 and bb2 must have length of 4 (2D) or 6 (3D)")

def __allen(self, i1, i2):
if isnan(i1).any() or isnan(i2).any(): # nan values cause dragons
raise ValueError("illegal 'nan' values found")

if i1[1] < i2[0]:
return "<"
if i1[1] == i2[0]:
return "m"
if i1[0] < i2[0] < i1[1] and i2[0] < i1[1] < i2[1]:
return "o"
if i1[0] == i2[0] and i1[1] < i2[1]:
return "s"
if i2[0] < i1[0] < i2[1] and i2[0] < i1[1] < i2[1]:
return "d"
if i2[0] < i1[0] < i2[1] and i1[1] == i2[1]:
return "f"
if i1[0] == i2[0] and i1[1] == i2[1]:
return "="
return self._inverse_map[self.__allen(i2, i1)]
1 change: 1 addition & 0 deletions qsr_lib/tests/data/data1_ra_defaults.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["1.0,o1,o2,{'ra': '>,>'}", "1.0,o2,o1,{'ra': '<,<'}", "2.0,o1,o2,{'ra': '>,mi'}", "2.0,o2,o1,{'ra': '<,m'}", "3.0,o1,o2,{'ra': '>,oi'}", "3.0,o2,o1,{'ra': '<,o'}", "4.0,o1,o2,{'ra': '>,='}", "4.0,o2,o1,{'ra': '<,='}", "5.0,o1,o2,{'ra': '>,o'}", "5.0,o2,o1,{'ra': '<,oi'}", "6.0,o1,o2,{'ra': '>,m'}", "6.0,o2,o1,{'ra': '<,mi'}", "7.0,o1,o2,{'ra': '>,<'}", "7.0,o2,o1,{'ra': '<,>'}", "8.0,o1,o2,{'ra': 'mi,>'}", "8.0,o2,o1,{'ra': 'm,<'}", "9.0,o1,o2,{'ra': 'mi,mi'}", "9.0,o2,o1,{'ra': 'm,m'}", "10.0,o1,o2,{'ra': 'mi,oi'}", "10.0,o2,o1,{'ra': 'm,o'}", "11.0,o1,o2,{'ra': 'mi,='}", "11.0,o2,o1,{'ra': 'm,='}", "12.0,o1,o2,{'ra': 'mi,o'}", "12.0,o2,o1,{'ra': 'm,oi'}", "13.0,o1,o2,{'ra': 'mi,m'}", "13.0,o2,o1,{'ra': 'm,mi'}", "14.0,o1,o2,{'ra': 'mi,<'}", "14.0,o2,o1,{'ra': 'm,>'}", "15.0,o1,o2,{'ra': 'oi,>'}", "15.0,o2,o1,{'ra': 'o,<'}", "16.0,o1,o2,{'ra': 'oi,mi'}", "16.0,o2,o1,{'ra': 'o,m'}", "17.0,o1,o2,{'ra': 'oi,oi'}", "17.0,o2,o1,{'ra': 'o,o'}", "18.0,o1,o2,{'ra': 'oi,='}", "18.0,o2,o1,{'ra': 'o,='}", "19.0,o1,o2,{'ra': 'oi,o'}", "19.0,o2,o1,{'ra': 'o,oi'}", "20.0,o1,o2,{'ra': 'oi,m'}", "20.0,o2,o1,{'ra': 'o,mi'}", "21.0,o1,o2,{'ra': 'oi,<'}", "21.0,o2,o1,{'ra': 'o,>'}", "22.0,o1,o2,{'ra': '=,>'}", "22.0,o2,o1,{'ra': '=,<'}", "23.0,o1,o2,{'ra': '=,mi'}", "23.0,o2,o1,{'ra': '=,m'}", "24.0,o1,o2,{'ra': '=,oi'}", "24.0,o2,o1,{'ra': '=,o'}", "25.0,o1,o2,{'ra': '=,='}", "25.0,o2,o1,{'ra': '=,='}", "26.0,o1,o2,{'ra': '=,o'}", "26.0,o2,o1,{'ra': '=,oi'}", "27.0,o1,o2,{'ra': '=,m'}", "27.0,o2,o1,{'ra': '=,mi'}", "28.0,o1,o2,{'ra': '=,<'}", "28.0,o2,o1,{'ra': '=,>'}", "29.0,o1,o2,{'ra': 'o,>'}", "29.0,o2,o1,{'ra': 'oi,<'}", "30.0,o1,o2,{'ra': 'o,mi'}", "30.0,o2,o1,{'ra': 'oi,m'}", "31.0,o1,o2,{'ra': 'o,oi'}", "31.0,o2,o1,{'ra': 'oi,o'}", "32.0,o1,o2,{'ra': 'o,='}", "32.0,o2,o1,{'ra': 'oi,='}", "33.0,o1,o2,{'ra': 'o,o'}", "33.0,o2,o1,{'ra': 'oi,oi'}", "34.0,o1,o2,{'ra': 'o,m'}", "34.0,o2,o1,{'ra': 'oi,mi'}", "35.0,o1,o2,{'ra': 'o,<'}", "35.0,o2,o1,{'ra': 'oi,>'}", "36.0,o1,o2,{'ra': 'm,>'}", "36.0,o2,o1,{'ra': 'mi,<'}", "37.0,o1,o2,{'ra': 'm,mi'}", "37.0,o2,o1,{'ra': 'mi,m'}", "38.0,o1,o2,{'ra': 'm,oi'}", "38.0,o2,o1,{'ra': 'mi,o'}", "39.0,o1,o2,{'ra': 'm,='}", "39.0,o2,o1,{'ra': 'mi,='}", "40.0,o1,o2,{'ra': 'm,o'}", "40.0,o2,o1,{'ra': 'mi,oi'}", "41.0,o1,o2,{'ra': 'm,m'}", "41.0,o2,o1,{'ra': 'mi,mi'}", "42.0,o1,o2,{'ra': 'm,<'}", "42.0,o2,o1,{'ra': 'mi,>'}", "43.0,o1,o2,{'ra': '<,>'}", "43.0,o2,o1,{'ra': '>,<'}", "44.0,o1,o2,{'ra': '<,mi'}", "44.0,o2,o1,{'ra': '>,m'}", "45.0,o1,o2,{'ra': '<,oi'}", "45.0,o2,o1,{'ra': '>,o'}", "46.0,o1,o2,{'ra': '<,='}", "46.0,o2,o1,{'ra': '>,='}", "47.0,o1,o2,{'ra': '<,o'}", "47.0,o2,o1,{'ra': '>,oi'}", "48.0,o1,o2,{'ra': '<,m'}", "48.0,o2,o1,{'ra': '>,mi'}", "49.0,o1,o2,{'ra': '<,<'}", "49.0,o2,o1,{'ra': '>,>'}"]
1 change: 1 addition & 0 deletions qsr_lib/tests/data/data1_ra_qsrs_for_global_namespace.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["1.0,o2,o1,{'ra': '<,<'}", "2.0,o2,o1,{'ra': '<,m'}", "3.0,o2,o1,{'ra': '<,o'}", "4.0,o2,o1,{'ra': '<,='}", "5.0,o2,o1,{'ra': '<,oi'}", "6.0,o2,o1,{'ra': '<,mi'}", "7.0,o2,o1,{'ra': '<,>'}", "8.0,o2,o1,{'ra': 'm,<'}", "9.0,o2,o1,{'ra': 'm,m'}", "10.0,o2,o1,{'ra': 'm,o'}", "11.0,o2,o1,{'ra': 'm,='}", "12.0,o2,o1,{'ra': 'm,oi'}", "13.0,o2,o1,{'ra': 'm,mi'}", "14.0,o2,o1,{'ra': 'm,>'}", "15.0,o2,o1,{'ra': 'o,<'}", "16.0,o2,o1,{'ra': 'o,m'}", "17.0,o2,o1,{'ra': 'o,o'}", "18.0,o2,o1,{'ra': 'o,='}", "19.0,o2,o1,{'ra': 'o,oi'}", "20.0,o2,o1,{'ra': 'o,mi'}", "21.0,o2,o1,{'ra': 'o,>'}", "22.0,o2,o1,{'ra': '=,<'}", "23.0,o2,o1,{'ra': '=,m'}", "24.0,o2,o1,{'ra': '=,o'}", "25.0,o2,o1,{'ra': '=,='}", "26.0,o2,o1,{'ra': '=,oi'}", "27.0,o2,o1,{'ra': '=,mi'}", "28.0,o2,o1,{'ra': '=,>'}", "29.0,o2,o1,{'ra': 'oi,<'}", "30.0,o2,o1,{'ra': 'oi,m'}", "31.0,o2,o1,{'ra': 'oi,o'}", "32.0,o2,o1,{'ra': 'oi,='}", "33.0,o2,o1,{'ra': 'oi,oi'}", "34.0,o2,o1,{'ra': 'oi,mi'}", "35.0,o2,o1,{'ra': 'oi,>'}", "36.0,o2,o1,{'ra': 'mi,<'}", "37.0,o2,o1,{'ra': 'mi,m'}", "38.0,o2,o1,{'ra': 'mi,o'}", "39.0,o2,o1,{'ra': 'mi,='}", "40.0,o2,o1,{'ra': 'mi,oi'}", "41.0,o2,o1,{'ra': 'mi,mi'}", "42.0,o2,o1,{'ra': 'mi,>'}", "43.0,o2,o1,{'ra': '>,<'}", "44.0,o2,o1,{'ra': '>,m'}", "45.0,o2,o1,{'ra': '>,o'}", "46.0,o2,o1,{'ra': '>,='}", "47.0,o2,o1,{'ra': '>,oi'}", "48.0,o2,o1,{'ra': '>,mi'}", "49.0,o2,o1,{'ra': '>,>'}"]
1 change: 1 addition & 0 deletions qsr_lib/tests/data/data1_ra_qsrs_for_qsr_namespace.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["1.0,o1,o2,{'ra': '>,>'}", "2.0,o1,o2,{'ra': '>,mi'}", "3.0,o1,o2,{'ra': '>,oi'}", "4.0,o1,o2,{'ra': '>,='}", "5.0,o1,o2,{'ra': '>,o'}", "6.0,o1,o2,{'ra': '>,m'}", "7.0,o1,o2,{'ra': '>,<'}", "8.0,o1,o2,{'ra': 'mi,>'}", "9.0,o1,o2,{'ra': 'mi,mi'}", "10.0,o1,o2,{'ra': 'mi,oi'}", "11.0,o1,o2,{'ra': 'mi,='}", "12.0,o1,o2,{'ra': 'mi,o'}", "13.0,o1,o2,{'ra': 'mi,m'}", "14.0,o1,o2,{'ra': 'mi,<'}", "15.0,o1,o2,{'ra': 'oi,>'}", "16.0,o1,o2,{'ra': 'oi,mi'}", "17.0,o1,o2,{'ra': 'oi,oi'}", "18.0,o1,o2,{'ra': 'oi,='}", "19.0,o1,o2,{'ra': 'oi,o'}", "20.0,o1,o2,{'ra': 'oi,m'}", "21.0,o1,o2,{'ra': 'oi,<'}", "22.0,o1,o2,{'ra': '=,>'}", "23.0,o1,o2,{'ra': '=,mi'}", "24.0,o1,o2,{'ra': '=,oi'}", "25.0,o1,o2,{'ra': '=,='}", "26.0,o1,o2,{'ra': '=,o'}", "27.0,o1,o2,{'ra': '=,m'}", "28.0,o1,o2,{'ra': '=,<'}", "29.0,o1,o2,{'ra': 'o,>'}", "30.0,o1,o2,{'ra': 'o,mi'}", "31.0,o1,o2,{'ra': 'o,oi'}", "32.0,o1,o2,{'ra': 'o,='}", "33.0,o1,o2,{'ra': 'o,o'}", "34.0,o1,o2,{'ra': 'o,m'}", "35.0,o1,o2,{'ra': 'o,<'}", "36.0,o1,o2,{'ra': 'm,>'}", "37.0,o1,o2,{'ra': 'm,mi'}", "38.0,o1,o2,{'ra': 'm,oi'}", "39.0,o1,o2,{'ra': 'm,='}", "40.0,o1,o2,{'ra': 'm,o'}", "41.0,o1,o2,{'ra': 'm,m'}", "42.0,o1,o2,{'ra': 'm,<'}", "43.0,o1,o2,{'ra': '<,>'}", "44.0,o1,o2,{'ra': '<,mi'}", "45.0,o1,o2,{'ra': '<,oi'}", "46.0,o1,o2,{'ra': '<,='}", "47.0,o1,o2,{'ra': '<,o'}", "48.0,o1,o2,{'ra': '<,m'}", "49.0,o1,o2,{'ra': '<,<'}"]
1 change: 1 addition & 0 deletions qsr_lib/tests/data/data2_ra_defaults.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions qsr_lib/tests/data/data3_ra_defaults.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions qsr_lib/tests/data/data4_ra_defaults.txt

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions qsr_lib/tests/ra_tester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python
from __future__ import print_function, division
import sys
from abstractclass_unittest_dyadic import Abstractclass_Unittest_Dyadic


class RA_Test(Abstractclass_Unittest_Dyadic):
def __init__(self, *args):
super(RA_Test, self).__init__(*args)
self._unique_id = "ra"

def test_defaults(self):
self.assertItemsEqual(*self.defaults("data1", "data1_ra_defaults.txt"))

def test_qsrs_for_global_namespace(self):
self.assertItemsEqual(*self.qsrs_for_global_namespace("data1", "data1_ra_qsrs_for_global_namespace.txt"))

def test_qsrs_for_qsr_namespace(self):
self.assertItemsEqual(*self.qsrs_for_qsr_namespace("data1", "data1_ra_qsrs_for_qsr_namespace.txt"))
self.assertItemsEqual(*self.qsrs_for_qsr_namespace_over_global_namespace("data1",
"data1_ra_qsrs_for_qsr_namespace.txt"))

def test_with_bounding_boxes(self):
self.assertItemsEqual(*self.defaults("data2", "data2_ra_defaults.txt"))

def test_without_bounding_boxes(self):
self.assertItemsEqual(*self.defaults("data3", "data3_ra_defaults.txt"))

def test_floats(self):
self.assertItemsEqual(*self.defaults("data4", "data4_ra_defaults.txt"))


if __name__ == '__main__':
import rosunit
rosunit.unitrun("qsr_lib", "ra_test", RA_Test, sys.argv)
3 changes: 3 additions & 0 deletions qsr_lib/tests/ra_tester.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<launch>
<test test-name="ra_tester" pkg="qsr_lib" type="ra_tester.py" />
</launch>
2 changes: 1 addition & 1 deletion qsr_lib/tests/unittests_generate_ground_truth.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def pretty_print_world_qsr_trace(which_qsr, qsrlib_response_message):

#### dyadic (except argd and argprobd, see below for these two
# dynamic_args = {"for_all_qsrs": {"qsrs_for": [("o2", "o1")]}} # qsrs_for_global_namespace
# dynamic_args = {args.qsr: {"qsrs_for": [("o1", "o2")]}} # qsrs_for_qsr_namespace, qsrs_for_qsr_namespace_over_global_namespace
dynamic_args = {args.qsr: {"qsrs_for": [("o1", "o2")]}} # qsrs_for_qsr_namespace, qsrs_for_qsr_namespace_over_global_namespace
# dynamic_args = {args.qsr: {"qsrs_for": [("o1", "o2")], "quantisation_factor": 2.0}} # custom

#### qtcs special case
Expand Down