Skip to content

Commit

Permalink
Update farm_ng_amiga examples/tutorial (#190)
Browse files Browse the repository at this point in the history
* update camera client

* update the calibration readme

* update camera settings example

* add the camera to pointcloud example

* minor updates to the file readers

* add service client tutorial

* remove people detection

* add the service_counter tutorial

* add the service propagation example

* Update motor state stream example

* Add vehicle twist example

* Formatting & some typos

* Rename so examples are all README (helps w/ links)

* Update examples sidebar

---------

Co-authored-by: Kyle Coble <[email protected]>
  • Loading branch information
edgarriba and Hackerman342 authored Sep 27, 2023
1 parent 75c75c7 commit e8322f5
Show file tree
Hide file tree
Showing 16 changed files with 1,246 additions and 312 deletions.
100 changes: 100 additions & 0 deletions website/docs/examples/camera_calibration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
id: camera-calibration
title: Camera Calibration
---

## Camera Calibration

The requirements to run this example are to have a
[**farm-ng brain**](/docs/brain/) running Oak cameras and that
your PC is on the same local network as the brain.

### 1. Install the [farm-ng Brain ADK package](/docs/brain/brain-install)

### 2. Setup

:::tip

It is recommended to also install these dependencies and run the
example in the brain ADK virtual environment.

:::

Create first a virtual environment

```bash
python3 -m venv venv
source venv/bin/activate
```

```bash
# assuming you're already in the amiga-dev-kit/ directory
cd farm-ng-amiga/py/examples/camera_calibration
```

### 3. Install the example's dependencies

```bash
pip3 install -r requirements.txt
```

### 4. Execute the Python script

```bash
python3 main.py --service-config service_config.json
```

:::info
By default, the camera address is assumed top be `localhost`.
:::

### 5. Customize run

```bash
# usage: amiga-camera-calibration [-h] --service-config SERVICE_CONFIG
#
# optional arguments:
# -h, --help show this help message and exit
# --service-config SERVICE_CONFIG
# The camera config.
```

### 6. Code overview

In this example we use the `EventClient` with the `request_reply`
method to receive the camera camera calibration.
The `request_reply` method is a coroutine that returns a `Future` object.
The `Future` object is used to retrieve the result of the request.

The path to the calibration service is `/calibration` and the request message is `Empty`.
The response message is `OakCalibration`, which is automatically decoded by the `request_reply`
method using the `decode=True` argument.

```python
async def main(service_config_path: Path) -> None:
"""Request the camera calibration from the camera service.
Args:
service_config_path (Path): The path to the camera service config.
"""
# create a client to the camera service
config: EventServiceConfig = proto_from_json_file(service_config_path, EventServiceConfig())

# get the calibration message
calibration: oak_pb2.OakCalibration =
await EventClient(config).request_reply("/calibration", Empty(), decode=True)
print(calibration)


if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="amiga-camera-calibration")
parser.add_argument("--service-config", type=Path, required=True, help="The camera config.")
args = parser.parse_args()

asyncio.run(main(args.service_config))
```

:::tip
We highly recommend to have some basic knowledge about
[**`asyncio`**](https://docs.python.org/3/library/asyncio.html).
:::
74 changes: 0 additions & 74 deletions website/docs/examples/camera_calibration/camera-calibration.md

This file was deleted.

83 changes: 31 additions & 52 deletions website/docs/examples/camera_client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pip3 install -r requirements.txt
### 3. Execute the Python script

```bash
python3 main.py --port 50051
python3 main.py --service-config service_config.json
```

:::info
Expand All @@ -55,78 +55,57 @@ the `WifiClient` (coming soon)
```bash
python3 main.py --help

# usage: amiga-camera-app [-h] --port PORT [--address ADDRESS]
#[--stream-every-n STREAM_EVERY_N]

# usage: amiga-camera-stream [-h] --service-config SERVICE_CONFIG
#
# optional arguments:
# -h, --help show this help message and exit
# --port PORT The camera port.
# --address ADDRESS The camera address
# --stream-every-n STREAM_EVERY_N
# Streaming frequency
# --service-config SERVICE_CONFIG
# The camera config.
```

Usage example:

```bash
python3 main.py --address 192.168.1.93 --port 50051
```
To customize the run, you need to update the `service_config.json`
by modifying the `host` and `port` fields.

### 5. Code overview

Basic structure to consume from the camera client in an async
fashion.
In this example we use the `EventClient` with the `subscribe` method to receive the camera stream.

```python
from farm_ng.oak.client import OakCameraClient,
OakCameraClientConfig
from farm_ng.oak import oak_pb2

async def main(address: str, port: int, stream_every_n: int) ->
None:
async def main(service_config_path: Path) -> None:
"""Run the camera service client.
# configure the camera client
config = OakCameraClientConfig(address=address, port=port)
client = OakCameraClient(config)
Args:
service_config_path (Path): The path to the camera service config.
"""
# create a client to the camera service
config: EventServiceConfig = proto_from_json_file(service_config_path, EventServiceConfig())

# get the streaming object
response_stream = client.stream_frames(every_n=stream_every_n)
# instantiate the image decoder
image_decoder = ImageDecoder()

# start the streaming service
await client.connect_to_service()
async for event, message in EventClient(config).subscribe(config.subscriptions[0], decode=True):
print(f"Timestamps: {event.timestamps[-2]}")
print(f"Meta: {message.meta}")
print("###################\n")

while True:
# query the service state
state: oak_pb2.OakServiceState = await client.get_state()
# cast image data bytes to numpy and decode
image = np.from_dlpack(image_decoder.decode(message.image_data))

if state.value != oak_pb2.OakServiceState.RUNNING:
print("Camera is not streaming!")
continue
# visualize the image
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
cv2.imshow("image", image)
cv2.waitKey(1)

response: oak_pb2.StreamFramesReply = await
response_stream.read()
if response and response.status == oak_pb2.ReplyStatus.OK:
# get the sync frame
frame: oak_pb2.OakSyncFrame = response.frame
print(f"Got frame: {frame.sequence_num}")
print(f"Device info: {frame.device_info}")
print("#################################\n")

if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="amiga-camera-app")
parser.add_argument("--port", type=int, required=True,
help="The camera port.")
parser.add_argument("--address", type=str,
default="localhost", help="The camera address")
parser.add_argument("--stream-every-n", type=int, default=4,
help="Streaming frequency")
parser = argparse.ArgumentParser(prog="amiga-camera-stream")
parser.add_argument("--service-config", type=Path, required=True, help="The camera config.")
args = parser.parse_args()

asyncio.run(main(args.address, args.port, args.
stream_every_n))
asyncio.run(main(args.service_config))
```

:::tip
We highgly recommend to have some basic knowledge about
We highly recommend to have some basic knowledge about
[**`asyncio`**](https://docs.python.org/3/library/asyncio.html).
:::
Loading

0 comments on commit e8322f5

Please sign in to comment.