Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geo cord polygon query #320

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
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
28 changes: 26 additions & 2 deletions docker/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,25 @@ ENV FLATBUFFER_VER="2.0.0"
ENV GRPC_VER="1.35.0"
ENV PB_REL="https://github.com/protocolbuffers/protobuf/releases"
ENV PB_VER="21.12"
ENV PROJ_VER="9.4.0"
ENV GTEST_VER="1.12.0"
ENV DOX_REL="https://github.com/doxygen/doxygen/archive/refs/tags"
ENV DOX_VER="Release_1_9_3"
ENV CCACHE_VER="4.9.1"
ENV HADOLINT_VER="2.12.0"
ENV PIP3_VER="24.1.2"

# make custom installed libraries available to the system
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}/usr/local/lib"

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

#Install general required tools
# Install general required tools

# PROJ deps:
# - curl
# - libtiff5-dev
# - sqlite3
RUN apt-get -qq update && apt-get -qq install -y --no-install-recommends -y \
software-properties-common \
bash-completion \
Expand All @@ -37,7 +46,6 @@ RUN apt-get -qq update && apt-get -qq install -y --no-install-recommends -y \
vim \
build-essential \
pkg-config \
libproj-dev \
python3-catkin-tools \
python3-osrf-pycommon \
ros-noetic-vision-msgs \
Expand All @@ -47,6 +55,8 @@ RUN apt-get -qq update && apt-get -qq install -y --no-install-recommends -y \
bison \
libjsoncpp-dev \
libcurl4-openssl-dev \
sqlite3 \
libtiff5-dev \
&& rm -rf /var/lib/apt/lists/*


Expand Down Expand Up @@ -161,6 +171,20 @@ RUN wget --progress=dot:giga $PB_REL/download/v$PB_VER/protobuf-cpp-3.$PB_VER.zi
&& cd ../.. \
&& rm -rf protobuf-cpp-3.$PB_VER.zip protobuf-3.$PB_VER

####################################################
#Install PROJ
####################################################
RUN wget --progress=dot:giga https://download.osgeo.org/proj/proj-${PROJ_VER}.tar.gz \
&& tar -xf proj-${PROJ_VER}.tar.gz \
&& cd proj-${PROJ_VER} \
&& mkdir build \
&& cd build \
&& cmake .. \
&& cmake --build . \
&& cmake --build . --target install \
&& cd ../.. \
&& rm -r proj-${PROJ_VER}.tar.gz proj-${PROJ_VER}

####################################################
#Install GoogleTest
####################################################
Expand Down
81 changes: 81 additions & 0 deletions docs/mkdocs/tutorials/geodetic-projects-and-queries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Geodetic projects and querying within another spatial reference system

This tutorial features creating a project in a user-specified geographic
spatial reference system and
spatially querying SEEREP from another spatial reference system.

The transforms are implemented with the help of [PROJ](https://proj.org/en/stable/)s
C API.

## Creating geodetic projects

Source:
[examples/python/gRPC/meta/gRPC_fb_createGeodeticCoordProject.py](https://github.com/agri-gaia/seerep/blob/main/examples/python/gRPC/meta/gRPC_fb_createGeodeticCoordProject.py)

```python
--8<-- "https://raw.githubusercontent.com/agri-gaia/seerep/main/examples/python/gRPC/meta/gRPC_fb_createGeodeticCoordProject.py:15:28"
```

This function call creates a project in the reference system `EPSG:4326`
with its topocentric origin at `latitude=52.358199`, `longitude=8.279679`
and `altitude=4`.
With `latitude` and `longitude` in decimal degree and `altitude` in meters.
Altitude specifies the ellipsoidal height of the origin.
The `"2"` string here defines the name of the projects map frame.

**NOTE**: Currently only SRIDs(Spatial Reference System Identifiers)
with geographic coordinates are supported.
The coordinates defined by the SRID also have to be in latitude first
and longitude second order.

## Query with polygons defined in other spatial reference systems

Source: [examples/python/gRPC/images/gRPC_fb_queryImage.py](https://github.com/agri-gaia/seerep/blob/main/examples/python/gRPC/images/gRPC_fb_queryImages.py)

```python
--8<-- "https://raw.githubusercontent.com/agri-gaia/seerep/main/examples/python/gRPC/images/gRPC_fb_queryImages.py:146:169"
```

**NOTE**: This is not the full function definition.

This queries SEEREP from another SRID, in this case `"EPSG:3857"`, in which the
spatial polygon has to be defined in.
In this case every SRID supported by `PROJ` can be used, `x` is the first coordinate
and `y` the second.

According to the used SRID this can mean a different type of
coordinate. When using `"EPSG:4314"` for example `x` would be the `latitude` and
`y` the `longitude` in decimal degree (see [EPSG:4314](https://epsg.io/4314))
or when using `"EPSG:32632"` `x` would be `easting` and `y` would be `northing`
in meters (see [EPSG:32632](https://epsg.io/32632)).

The polygon will be transformed to the projects CRS (coordinate reference system)
and then projected to topocentric using `PROJ` in the backend.

**NOTE**: These transformations can have strong deviations or even use ballpark
transformations with even larger errors in the resulting positions depending on
the different SRIDs used.
For testing [https://epsg.io/](https://epsg.io/) can be used,
it uses `PROJ` in the backend as well.

## Transforms backend

For the first stage transform
(transforming coordinates to the projects coordinate reference system) the
[cs2cs](https://proj.org/en/stable/apps/cs2cs.html) [C API equivalent](https://proj.org/en/stable/development/reference/functions.html#c.proj_create_crs_to_crs)
is used. The following example essentially simulates that step.

```bash
cs2cs EPSG:4326 EPSG:3857 <<<"52.3588799817 8.2796787735 -100.0000000000"
```

In the second stage projection to topocentric a `PROJ` string, like in the
following [cct](https://proj.org/en/stable/apps/cct.html) pipeline, is used.

```bash
echo "8.2796787735 52.3588799817 -100.0000000000" | cct -d 10 +proj=pipeline
+step +proj=cart +step +proj=topocentric +lat_0=52.358199 +lon_0=8.279679 +h_0=0.000000
```

The source code for the transforms can be found [here](https://github.com/agri-gaia/seerep/blob/main/seerep_srv/seerep_core/src/core_project.cpp)
in the `transformToMapFrame` method.
17 changes: 12 additions & 5 deletions docs/mkdocs/tutorials/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ z-coordinate point and a height value. Queries are performed by forming an
encompassing axis aligned bounding box from the polygon. This can lead to an
AABB larger than the polygon and poses the potential problem of returning results
to the user which are not fully inside the query polygon. That problem is
resolved by providing a boolean variable called fullyEncapsulated`. If false,
resolved by providing a boolean variable called `fullyEncapsulated`. If false,
resultant polygons, which are partially inside the query polygon are also returned.

### A time interval (temporal query)
Expand All @@ -71,11 +71,18 @@ Only performs the query in these included projects specified by their uuids.

If the pixel data of the image should not be returned in order to save bandwith.

### InMapFrame
### CrsString

Whether the query is done in the map frame.
If not, the provided polygon for the spatial query will be transformed from the
geodesic coordinates of the project into the map frame beforehand.
Specifies where the query is done.
Valid values are `map`, `project` or any SRID from
[https://spatialreference.org/ref/](https://spatialreference.org/ref/).

If the query should be done from the origin of project (the map frame),
use `map` (default).
When querying in the same spatial reference system as specified in the project
use `project`.

Using the last option is explained in more detail [here](geodetic-projects-and-queries.md).

### Example code for querying images

Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs/tutorials/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ following topics are covered:

- Creating and retrieving projects
- Sending and querying images
- Projects and querying in other spatial reference systems
- Writing python examples
- Writing python integration tests

Expand Down
77 changes: 63 additions & 14 deletions examples/python/gRPC/images/gRPC_fb_queryImages.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
from seerep.util.fb_helper import (
create_label,
create_label_category,
createPoint2d,
createPolygon2D,
createQuery,
createRectangularPolygon2D,
createTimeInterval,
createTimeStamp,
getOrCreateProject,
Expand Down Expand Up @@ -78,25 +77,26 @@ def query_images(
]


if __name__ == "__main__":
def query_example():
fbb = flatbuffers.Builder()
grpc_channel = get_gRPC_channel()
project_uuid = getOrCreateProject(fbb, grpc_channel, "testproject")

# create the data for the query
scale = 100
vertices = [
createPoint2d(fbb, x * scale, y * scale)
for x, y in [(-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)]
]

polygon_2d = createPolygon2D(fbb, 700, -100, vertices)
polygon_2d = createRectangularPolygon2D(
fbb,
x=-100,
extent_x=200,
extent_y=200,
y=-100,
z=-100,
height=700,
)

time_min = createTimeStamp(fbb, 1610549273, 0)
time_max = createTimeStamp(fbb, 1938549273, 0)
time_interval = createTimeInterval(fbb, time_min, time_max)
time_interval = createTimeInterval(fbb, time_min, time_max) # noqa: F841

project_uuids = [project_uuid]
project_uuids = [project_uuid] # noqa: F841

labels = [
create_label(builder=fbb, label=label_str, label_id=i)
Expand All @@ -121,7 +121,6 @@ def query_images(
labels=labelsCategory,
withoutData=True,
fullyEncapsulated=False,
inMapFrame=True,
)

if matching_images is None or len(matching_images) == 0:
Expand All @@ -142,3 +141,53 @@ def query_images(
+ img.Labels(0).Labels(0).Label().decode("utf-8")
)
print("------------------------------------------------------------------")


def query_geodetic_example():
fbb = flatbuffers.Builder()
grpc_channel = get_gRPC_channel()
project_uuid = getOrCreateProject(fbb, grpc_channel, "geodeticProject")

polygon_epsg3857 = createRectangularPolygon2D(
fbb,
x=921689.630348,
y=6865153.476919,
extent_x=655,
extent_y=655,
z=0,
height=100,
)

matching_images = query_images(
fbb,
grpc_channel,
project_uuid,
polygon2d=polygon_epsg3857,
withoutData=True,
fullyEncapsulated=False,
crsString="EPSG:3857",
)

if matching_images is None or len(matching_images) == 0:
print("No images matched the query.")
sys.exit()

print(f"Number of images matching the query: {len(matching_images)}")

for img in matching_images:
print(
"------------------------------------------------------------------"
)
print(f"Msg UUID: {img.Header().UuidMsgs().decode('utf-8')}")
print(f"Number of labels: {img.LabelsLength()}")
if img.LabelsLength() > 0:
print(
"First label: "
+ img.Labels(0).Labels(0).Label().decode("utf-8")
)
print("------------------------------------------------------------------")


if __name__ == "__main__":
query_example()
# query_geodetic_example()
Loading
Loading