aa8a0ba3a86ff5dbbdfcd68c72a5e70e1c52e877..1292adc7aafa34a7c93c80390826bdc5b6d05cbf
2022-06-27 wu_xinjun
add replay_to func for task
1292ad 对比 | 目录
2022-06-24 wu_xinjun
add taskuuid
74c96c 对比 | 目录
2022-06-21 wu_xinjun
optimize for env setting via venv
65d1e4 对比 | 目录
2022-06-21 wu_xinjun
optimize for routing key
ee0fcc 对比 | 目录
2022-06-20 wu_xinjun
get pointclouds from client
6b37ae 对比 | 目录
2022-06-16 wu_xinjun
udp_get rebuild
14cc8f 对比 | 目录
2022-06-16 wu_xinjun
dust cleaner installed!
503678 对比 | 目录
2022-06-15 wu_xinjun
client enhanced&camera contorller
0dc337 对比 | 目录
2022-06-14 wu_xinjun
server enhanced!
d8e5c7 对比 | 目录
2022-06-10 wu_xinjun
-_-
baee79 对比 | 目录
2022-06-07 wu_xinjun
Merge commit 'mqdev' into mqaddFeature
da6ff0 对比 | 目录
2022-03-24 wu_xinjun
Merge remote-tracking branch 'github/dev' into addFeature
5a4485 对比 | 目录
2022-03-23 wu_xinjun
add lfs file
022170 对比 | 目录
2022-03-23 wu_xinjun
Merge dev commit '28668532ed2f97a3883be7e68bced252bd1f99bf' into addFeature
563f77 对比 | 目录
2022-03-10 wuxinjun
del Microwave
c92270 对比 | 目录
2022-03-07 wu_xinjun
read change log and readme.md
e1f883 对比 | 目录
2022-03-07 wu_xinjun
temp
360ba8 对比 | 目录
2022-03-04 wu_xinjun
second commit
6d4be7 对比 | 目录
2022-03-04 wu_xinjun
temp commit
e839f2 对比 | 目录
2022-02-28 wu_xinjun
add slam
9678b9 对比 | 目录
2022-02-28 wu_xinjun
Merge commit 'f79b30a55db543bd1c7dd494a8c896df8841aa28' into addFeature
9411c4 对比 | 目录
41个文件已修改
4个文件已删除
105个文件已添加
3527 ■■■■■ 已修改文件
README.md 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/ExportEnv.bat 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/JustDoubleClickMe.bat 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/SettingEnv.bat 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/aerial.tar.gz 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/Babel-2.10.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/Flask-2.1.2-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/Jinja2-3.1.2-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/Pygments-2.12.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/Send2Trash-1.8.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/Werkzeug-2.1.2-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/anyio-3.6.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/argon2_cffi-21.3.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/asttokens-2.0.5-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/attrs-21.4.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/backcall-0.2.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/beautifulsoup4-4.11.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/bitarray-2.5.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/bleach-5.0.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/certifi-2022.6.15-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/cffi-1.15.0-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/charset_normalizer-2.0.12-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/click-8.1.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/colorama-0.4.5-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/debugpy-1.6.0-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/decorator-5.1.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/defusedxml-0.7.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/deprecation-2.1.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/entrypoints-0.4-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/executing-0.8.3-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/fastjsonschema-2.15.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/idna-3.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/importlib_metadata-4.11.4-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/ipykernel-6.15.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/ipython-8.4.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/ipython_genutils-0.2.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/ipywidgets-7.7.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/itsdangerous-2.1.2-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jedi-0.18.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/json5-0.9.8.tar.gz 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jsonschema-4.6.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyter_client-7.3.4-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyter_core-4.10.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyter_packaging-0.12.2-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyter_server-1.17.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyterlab-3.4.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyterlab_pygments-0.2.2-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyterlab_server-2.14.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/jupyterlab_widgets-1.1.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/matplotlib_inline-0.1.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/mistune-0.8.4-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/nbclassic-0.3.7-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/nbclient-0.6.4-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/nbconvert-6.5.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/nbformat-5.4.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/nest_asyncio-1.5.5-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/notebook-6.4.12-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/notebook_shim-0.1.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/numpy-1.23.0-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/open3d-0.14.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/opencv_python-4.6.0.66-cp36-abi3-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/packaging-21.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pandocfilters-1.5.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/parso-0.8.3-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pickleshare-0.7.5-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pika-1.2.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/prometheus_client-0.14.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/prompt_toolkit-3.0.29-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/protobuf-4.21.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/protoc_wheel_0-21.1-py2.py3-none-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/psutil-5.9.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pure_eval-0.2.2-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pycparser-2.21-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pyparsing-3.0.9-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pyrsistent-0.18.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pyserial-3.5-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/python_dateutil-2.8.2-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pytz-2022.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pywin32-304-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pywinpty-2.0.5-cp39-none-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/pyzmq-23.2.0-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/requests-2.28.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/setuptools-62.6.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/six-1.16.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/sniffio-1.2.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/soupsieve-2.3.2.post1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/stack_data-0.3.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/terminado-0.15.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/tinycss2-1.1.1-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/tomlkit-0.11.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/tornado-6.1-cp39-cp39-win_amd64.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/tqdm-4.64.0-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/traitlets-5.3.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/urllib3-1.26.9-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/wcwidth-0.2.5-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/webencodings-0.5.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/websocket_client-1.3.3-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/wheel-0.37.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/widgetsnbextension-3.6.1-py2.py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
env/requirements/zipp-3.8.0-py3-none-any.whl 补丁 | 查看 | 原始文档 | blame | 历史
pipeline.pptx 补丁 | 查看 | 原始文档 | blame | 历史
requirements.txt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts/mqClient.py 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts/mqServer.py 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_Slam.bat 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_SlamAuto.bat 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_bin2ply.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_ply_show.bat 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_startClient.bat 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_startServer.bat 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_udp2bin.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_udp2ply.bat 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/TEST_udp_get.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/bin2ply.bat 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/ply_show.bat 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/startClient.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/startServer.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/udp2bin.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/udp2ply.bat 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scripts_launch/udp_get.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Server.py 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Server.py.backup 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/__init__.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/AcquisitionMain.py 711 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/AcquisitionMain.py.backup 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/CaptureThread.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/ControllThread.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/DustCleanerThread.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/MessageQueueThread.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/MessageThreads.py 496 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/Microwave.py 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/__init__.py 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/devices.py 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/__init__.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/demo/AutoGetUDP.bat 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/demo/AutoGetUDPtest.bat 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/demo/AutoSendAndGetTest.bat 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/demo/AutoSendUDPtest.bat 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/deviceTools.py 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/parsers.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/microwave/servers.py 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/protos/aerial.proto 383 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/protos/compile.bat 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/requirements.yaml 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/slam/__init__.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/__init__.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/slam.py 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/tools.py 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -1,18 +1,34 @@
# 华能煤堆实时三维重建采集端和服务端
## 运行环境
## TODO
1. Python版本:3.9
2. 第三方包:flask pika protobuf
1. 根据proto数据结构,重新优化src\engine\MessageThreads.py的相关内容;
2. 采集端:修改src\engine\devices.py内的相机的数据采集线程;
3. 服务端:增加图像数据的消息解析;
4. src\engine\MessageThreads.py内添加数据发送和接收线程。
## 创建环境
Just click ```JustDoubleClickMe.bat``` file to auto setiing the env, which is located in the ```env``` folder.
## MQ keys
## 运行采集端
🎈Given that the name parameters of one couple of the server and client is set to as below shown:
🚩server name : `server0`
🚩client name : `bunker0.block0.device0`
Double click to run  ```startClient.bat```
## 运行服务端
1. Server:
    > Binding keys for receive messages from clients are shown below:
    >> `server0.logs.test0`
    >> `server0.images.test0`
    >> `server0.plys.test0`
Double click to run  ```startServer.bat```
    > Routing keys for send commands to the client are shown below:
    >> `bunker0.block0.device0`
2. Client:
    > Binding keys for receive commands from the server are shown below:
    >> `bunker0.block0.device0`
    > Routing keys for send messages to the server are shown below:
    >> `server0.logs.test0`
    >> `server0.images.test0`
    >> `server0.plys.test0`
env/ExportEnv.bat
File was deleted
env/JustDoubleClickMe.bat
File was deleted
env/SettingEnv.bat
@@ -2,31 +2,26 @@
@REM change to the filepath
cd %~dp0
@REM echo change to path: %cd%
if exist ../../aerial_deploy (
    echo the folder aerial_deploy is exited, removing it ...
    rmdir /S /Q "../../aerial_deploy"
    echo remove done!
)
cd ..
git lfs install
git lfs pull
@REM create the virtual env for this project
@REM please make sure your machine have installed a
@REM python with global env variable or select it by yourself.
cd %~dp0
mkdir "../../aerial_deploy"
python -m venv "../.env"
echo setting the env ...
tar -xzf "./aerial.tar.gz" -C "../../aerial_deploy"
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
if not exist ".env" (
    mklink /j ".env" "../aerial_deploy/")
@REM install some packages
python -m pip install --no-index -f "requirements" -r "../requirements.txt"
echo #####################################################################
python -c "import cv2, pika, flask; print('Hello World! The env is ready!')"
cd %~dp0
call "../src/protos/compile.bat"
echo ALL DONE!
echo =========== ALL DONE ================
echo Press any key to exit this windiow.
pause
env/aerial.tar.gz
File was deleted
env/requirements/Babel-2.10.3-py3-none-any.whl
Binary files differ
env/requirements/Flask-2.1.2-py3-none-any.whl
Binary files differ
env/requirements/Jinja2-3.1.2-py3-none-any.whl
Binary files differ
env/requirements/MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/Pygments-2.12.0-py3-none-any.whl
Binary files differ
env/requirements/Send2Trash-1.8.0-py3-none-any.whl
Binary files differ
env/requirements/Werkzeug-2.1.2-py3-none-any.whl
Binary files differ
env/requirements/anyio-3.6.1-py3-none-any.whl
Binary files differ
env/requirements/argon2_cffi-21.3.0-py3-none-any.whl
Binary files differ
env/requirements/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl
Binary files differ
env/requirements/asttokens-2.0.5-py2.py3-none-any.whl
Binary files differ
env/requirements/attrs-21.4.0-py2.py3-none-any.whl
Binary files differ
env/requirements/backcall-0.2.0-py2.py3-none-any.whl
Binary files differ
env/requirements/beautifulsoup4-4.11.1-py3-none-any.whl
Binary files differ
env/requirements/bitarray-2.5.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/bleach-5.0.0-py3-none-any.whl
Binary files differ
env/requirements/certifi-2022.6.15-py3-none-any.whl
Binary files differ
env/requirements/cffi-1.15.0-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/charset_normalizer-2.0.12-py3-none-any.whl
Binary files differ
env/requirements/click-8.1.3-py3-none-any.whl
Binary files differ
env/requirements/colorama-0.4.5-py2.py3-none-any.whl
Binary files differ
env/requirements/debugpy-1.6.0-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/decorator-5.1.1-py3-none-any.whl
Binary files differ
env/requirements/defusedxml-0.7.1-py2.py3-none-any.whl
Binary files differ
env/requirements/deprecation-2.1.0-py2.py3-none-any.whl
Binary files differ
env/requirements/entrypoints-0.4-py3-none-any.whl
Binary files differ
env/requirements/executing-0.8.3-py2.py3-none-any.whl
Binary files differ
env/requirements/fastjsonschema-2.15.3-py3-none-any.whl
Binary files differ
env/requirements/idna-3.3-py3-none-any.whl
Binary files differ
env/requirements/importlib_metadata-4.11.4-py3-none-any.whl
Binary files differ
env/requirements/ipykernel-6.15.0-py3-none-any.whl
Binary files differ
env/requirements/ipython-8.4.0-py3-none-any.whl
Binary files differ
env/requirements/ipython_genutils-0.2.0-py2.py3-none-any.whl
Binary files differ
env/requirements/ipywidgets-7.7.1-py2.py3-none-any.whl
Binary files differ
env/requirements/itsdangerous-2.1.2-py3-none-any.whl
Binary files differ
env/requirements/jedi-0.18.1-py2.py3-none-any.whl
Binary files differ
env/requirements/json5-0.9.8.tar.gz
New file
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0fa6e4d3ef062f93ba9cf2a9103fe8e68c7917dfa33519ae3ac8c7e48e3c84ff
size 22562
env/requirements/jsonschema-4.6.0-py3-none-any.whl
Binary files differ
env/requirements/jupyter_client-7.3.4-py3-none-any.whl
Binary files differ
env/requirements/jupyter_core-4.10.0-py3-none-any.whl
Binary files differ
env/requirements/jupyter_packaging-0.12.2-py3-none-any.whl
Binary files differ
env/requirements/jupyter_server-1.17.1-py3-none-any.whl
Binary files differ
env/requirements/jupyterlab-3.4.3-py3-none-any.whl
Binary files differ
env/requirements/jupyterlab_pygments-0.2.2-py2.py3-none-any.whl
Binary files differ
env/requirements/jupyterlab_server-2.14.0-py3-none-any.whl
Binary files differ
env/requirements/jupyterlab_widgets-1.1.1-py3-none-any.whl
Binary files differ
env/requirements/matplotlib_inline-0.1.3-py3-none-any.whl
Binary files differ
env/requirements/mistune-0.8.4-py2.py3-none-any.whl
Binary files differ
env/requirements/nbclassic-0.3.7-py3-none-any.whl
Binary files differ
env/requirements/nbclient-0.6.4-py3-none-any.whl
Binary files differ
env/requirements/nbconvert-6.5.0-py3-none-any.whl
Binary files differ
env/requirements/nbformat-5.4.0-py3-none-any.whl
Binary files differ
env/requirements/nest_asyncio-1.5.5-py3-none-any.whl
Binary files differ
env/requirements/notebook-6.4.12-py3-none-any.whl
Binary files differ
env/requirements/notebook_shim-0.1.0-py3-none-any.whl
Binary files differ
env/requirements/numpy-1.23.0-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/open3d-0.14.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/opencv_python-4.6.0.66-cp36-abi3-win_amd64.whl
Binary files differ
env/requirements/packaging-21.3-py3-none-any.whl
Binary files differ
env/requirements/pandocfilters-1.5.0-py2.py3-none-any.whl
Binary files differ
env/requirements/parso-0.8.3-py2.py3-none-any.whl
Binary files differ
env/requirements/pickleshare-0.7.5-py2.py3-none-any.whl
Binary files differ
env/requirements/pika-1.2.1-py2.py3-none-any.whl
Binary files differ
env/requirements/prometheus_client-0.14.1-py3-none-any.whl
Binary files differ
env/requirements/prompt_toolkit-3.0.29-py3-none-any.whl
Binary files differ
env/requirements/protobuf-4.21.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/protoc_wheel_0-21.1-py2.py3-none-win_amd64.whl
Binary files differ
env/requirements/psutil-5.9.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/pure_eval-0.2.2-py3-none-any.whl
Binary files differ
env/requirements/pycparser-2.21-py2.py3-none-any.whl
Binary files differ
env/requirements/pyparsing-3.0.9-py3-none-any.whl
Binary files differ
env/requirements/pyrsistent-0.18.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/pyserial-3.5-py2.py3-none-any.whl
Binary files differ
env/requirements/python_dateutil-2.8.2-py2.py3-none-any.whl
Binary files differ
env/requirements/pytz-2022.1-py2.py3-none-any.whl
Binary files differ
env/requirements/pywin32-304-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/pywinpty-2.0.5-cp39-none-win_amd64.whl
Binary files differ
env/requirements/pyzmq-23.2.0-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/requests-2.28.0-py3-none-any.whl
Binary files differ
env/requirements/setuptools-62.6.0-py3-none-any.whl
Binary files differ
env/requirements/six-1.16.0-py2.py3-none-any.whl
Binary files differ
env/requirements/sniffio-1.2.0-py3-none-any.whl
Binary files differ
env/requirements/soupsieve-2.3.2.post1-py3-none-any.whl
Binary files differ
env/requirements/stack_data-0.3.0-py3-none-any.whl
Binary files differ
env/requirements/terminado-0.15.0-py3-none-any.whl
Binary files differ
env/requirements/tinycss2-1.1.1-py3-none-any.whl
Binary files differ
env/requirements/tomlkit-0.11.0-py3-none-any.whl
Binary files differ
env/requirements/tornado-6.1-cp39-cp39-win_amd64.whl
Binary files differ
env/requirements/tqdm-4.64.0-py2.py3-none-any.whl
Binary files differ
env/requirements/traitlets-5.3.0-py3-none-any.whl
Binary files differ
env/requirements/urllib3-1.26.9-py2.py3-none-any.whl
Binary files differ
env/requirements/wcwidth-0.2.5-py2.py3-none-any.whl
Binary files differ
env/requirements/webencodings-0.5.1-py2.py3-none-any.whl
Binary files differ
env/requirements/websocket_client-1.3.3-py3-none-any.whl
Binary files differ
env/requirements/wheel-0.37.1-py2.py3-none-any.whl
Binary files differ
env/requirements/widgetsnbextension-3.6.1-py2.py3-none-any.whl
Binary files differ
env/requirements/zipp-3.8.0-py3-none-any.whl
Binary files differ
pipeline.pptx
Binary files differ
requirements.txt
New file
@@ -0,0 +1,10 @@
numpy==1.23.0
Flask==2.1.2
pika==1.2.1
protobuf==4.21.1
tqdm==4.64.0
opencv-python==4.6.0.66
pyserial==3.5
bitarray==2.5.1
protoc-wheel-0==21.1
open3d==0.14.1
scripts/mqClient.py
@@ -8,7 +8,7 @@
from src.engine.AcquisitionMain import AcquisitionMain
from src.engine.AcquisitionMain import Config
# from src.engine.AcquisitionMain import Config
def quit(signum, frame):
    print('You choose to stop me.')
@@ -20,16 +20,14 @@
        print("EXAMPLE: Client.py 172.17.17.206 chai password123 aerial_rpc pod1 http://172.17.17.206/api 192.168.2.65")
        exit(1)
    if len(sys.argv) != 8:
    if len(sys.argv) != 6:
        help()
    try:
        MQhost = str(sys.argv[1])
        MQuser = str(sys.argv[2])
        MQpassword = str(sys.argv[3])
        QUEUEname = str(sys.argv[4])
        DEVICEname = str(sys.argv[5])
        SERVERhost = str(sys.argv[6])
        MICROWAVEhost = str(sys.argv[7])
        DEVICEname = str(sys.argv[4])
        MICROWAVEhost = str(sys.argv[5])
    except Exception as e:
        print(e)
@@ -40,15 +38,13 @@
    signal.signal(signal.SIGTERM, quit)
    # client = AcquisitionMain('192.168.3.54', 'chai',
    #                       'password123', 'aerial_rpc', 'pod1', 'http://192.168.3.54:5000/api', 10)
    config_dir = os.path.join(__file__, "..",  "../src/config.json" )
    config_path = os.path.abspath(config_dir)
    config = Config(config_path)
    # config_dir = os.path.join(__file__, "..",  "../src/config.json" )
    # config_path = os.path.abspath(config_dir)
    # config = Config(config_path)
    client = AcquisitionMain(MQhost,
                             MQuser,
                             MQpassword, 
                             QUEUEname,
                             DEVICEname, 
                             SERVERhost,
                             MICROWAVEhost, # udp server host, 192.168.2.65 for production
                             config)
                            )
    client.start()
scripts/mqServer.py
@@ -8,26 +8,31 @@
from src.Server import MyServer
if __name__ == "__main__":
    def help():
        print("Usage: Server.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [WEBport] [SAVEfolder]")
        print("EXAMPLE: Server.py localhost chai password123 aerial_rpc 5000 ./Images")
        exit(1)
    if len(sys.argv) != 7:
    if len(sys.argv) != 8:
        help()
    try:
        MQhost = str(sys.argv[1])
        MQuser = str(sys.argv[2])
        MQpassword = str(sys.argv[3])
        QUEUEname = str(sys.argv[4])
        WEBhost = str(sys.argv[4])
        WEBport = int(sys.argv[5])
        SAVEfolder = str(sys.argv[6])
        save_folder = SAVEfolder
        save_folder = str(sys.argv[6])
        server_name = str(sys.argv[7])
    except Exception as e:
        print(e)
        help()
    server = MyServer(host=MQhost, user=MQuser, password=MQpassword, queue=QUEUEname, port=WEBport, SAVEfolder=save_folder)
    server = MyServer(MQhost=MQhost,
                    MQuser=MQuser,
                    MQpassword=MQpassword,
                    WEBhost=WEBhost,
                    WEBport=WEBport,
                    save_folder=save_folder,
                    server_name=server_name)
    server.run_all()
scripts_launch/TEST_Slam.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM set folder=T:\\Data\\projects\\huaneng\\00_Docs\\slamtest
@@ -43,9 +35,9 @@
if %choice% == y (
    %aerialpython% ./scripts/slamManualMode.py %folder% %alpha% %beta% %gamma% %savename%
    python ./scripts/slamManualMode.py %folder% %alpha% %beta% %gamma% %savename%
    @REM -------------- Usage: plot_ply.py [PLYfile]"
    %aerialpython% ./scripts/plot_ply.py %PLYfile%
    python ./scripts/plot_ply.py %PLYfile%
) else (
    echo you choose stop!
    exit
scripts_launch/TEST_SlamAuto.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM pre-defined parameters
@@ -64,9 +56,9 @@
if %choice% == y (
    %aerialpython% ./scripts/slamAutoMode.py %servo_path% %port% %speed% %degree_step% %time_delay% %alpha% %beta% %gamma% %microwaveHost% %udp_packets% %deviceName% %saveFolder%
    python ./scripts/slamAutoMode.py %servo_path% %port% %speed% %degree_step% %time_delay% %alpha% %beta% %gamma% %microwaveHost% %udp_packets% %deviceName% %saveFolder%
    @REM -------------- Usage: plot_ply.py [PLYfile]"
    %aerialpython% ./scripts/plot_ply.py %PLYfile%
    python ./scripts/plot_ply.py %PLYfile%
) else (
    echo you choose stop!
    exit
scripts_launch/TEST_bin2ply.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
echo [the folder example]: ./slamdata/
@@ -21,5 +13,5 @@
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./scripts/bin2ply.py %BINfolder%
python ./scripts/bin2ply.py %BINfolder%
pause
scripts_launch/TEST_ply_show.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
set PLYfile=./test60120.ply
scripts_launch/TEST_startClient.bat
@@ -2,25 +2,18 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
set MQhost=localhost
@REM set MQhost=localhost
set MQhost=47.92.33.19
set MQuser=chai
set MQpassword=password123
set QUEUEname=aerial_rpc
set DEVICEname=pod1
set DEVICEname=bunker0.block0.device0
set SERVERhost=http://192.168.1.224/api
set MICROWAVEhost=localhost
set LOGfile=ClientTEST.log
@@ -30,6 +23,6 @@
echo Client.py is running ...
@REM -------- Usage: Client.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [DEVICEname] [SERVERhost] [MICROWAVEhost]
@REM %aerialpython% ./src/Client.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %DEVICEname% %SERVERhost% %MICROWAVEhost% >> %LOGfile%
%aerialpython% ./scripts/mqClient.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %DEVICEname% %SERVERhost% %MICROWAVEhost%
python ./scripts/mqClient.py %MQhost% %MQuser% %MQpassword% %DEVICEname% %MICROWAVEhost%
echo Client.py has been terminited.
pause
scripts_launch/TEST_startServer.bat
@@ -2,35 +2,27 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM set MQhost=localhost
set MQhost=47.92.33.19
set MQuser=chai
set MQpassword=password123
set QUEUEname=aerial_rpc
set WEBhost=0.0.0.0
set WEBport=5000
set SAVEfolder=./ImagesTEST
set SAVEfolder=./data/server0/
set SERVERname=server0
set LOGfile=ServerTEST.log
@REM Launch the Server
@REM -------- Usage: Server.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [WEBport] [SAVEfolder]")
echo the log file will be saved in the [%LOGfile%] file
echo Server.py is running ...
@REM -------- Usage: Server.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [WEBport] [SAVEfolder]")
%aerialpython% ./scripts/mqServer.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %WEBport% %SAVEfolder%
python ./scripts/mqServer.py %MQhost% %MQuser% %MQpassword% %WEBhost% %WEBport% %SAVEfolder% %SERVERname%
echo Server.py has been terminited.
pause
scripts_launch/TEST_udp2bin.bat
@@ -2,23 +2,15 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
echo [the UDP folder example]: ./slamdata/60/
set /p UDPfolder=Please input the UDP folder:
@REM ---------------Usage: udp2bin.py [UDPfolder]
%aerialpython% ./scripts/udp2bin.py %UDPfolder%
python ./scripts/udp2bin.py %UDPfolder%
pause
scripts_launch/TEST_udp2ply.bat
@@ -2,25 +2,17 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
echo [the UDP folder example]: ./slamdata/60/
set /p UDPfolder=Please input the UDP folder:
@REM ---------------Usage: udp2bin.py [UDPfolder]
%aerialpython% ./scripts/udp2bin.py %UDPfolder%
python ./scripts/udp2bin.py %UDPfolder%
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./scripts/bin2ply.py %UDPfolder%
python ./scripts/bin2ply.py %UDPfolder%
pause
scripts_launch/TEST_udp_get.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
set MICROWAVEhost=192.168.2.65
@@ -29,5 +21,5 @@
set folder=./%SAVEfolder%/%SUBfolder%/
echo the udp data will be saved in folder %folder%
@REM ---------------Usage: udp_get.py [MICROWAVEhost] [PACKETthreshold] [DEVICEname] [SAVEfolder]
%aerialpython% ./scripts/udp_get.py %MICROWAVEhost% %PACKETthreshold% %DEVICEname% %SAVEfolder% %SUBfolder%
python ./scripts/udp_get.py %MICROWAVEhost% %PACKETthreshold% %DEVICEname% %SAVEfolder% %SUBfolder%
pause
scripts_launch/bin2ply.bat
@@ -2,23 +2,14 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM please the folder path of the bin files.
@REM set BINfolder=./Manual_Microwave/pod1-2012-12-12-12-12-12/
@REM add vitrual env python to the path
path ".env/Scripts/";%path%
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./scripts/bin2ply.py %BINfolder%
python ./scripts/bin2ply.py %BINfolder%
pause
scripts_launch/ply_show.bat
@@ -2,22 +2,11 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM please the folder path of the bin files.
@REM set PLYfile=./Manual_Microwave/pod1-2022-02-21-15-34-45/2522.ply
@REM -------------- Usage: plot_ply.py [PLYfile]"
%aerialpython% ./scripts/plot_ply.py %PLYfile%
python ./scripts/plot_ply.py %PLYfile%
pause
scripts_launch/startClient.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
set MQhost=172.17.17.206
@@ -29,6 +21,6 @@
echo the log file will be saved in the [%LOGfile%] file
echo Client.py is running ...
@REM -------- Usage: Client.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [DEVICEname] [SERVERhost] [MICROWAVEhost]
%aerialpython% ./src/Client.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %DEVICEname% %SERVERhost% %MICROWAVEhost% >> %LOGfile%
python ./src/Client.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %DEVICEname% %SERVERhost% %MICROWAVEhost% >> %LOGfile%
echo Client.py has been terminited.
pause 
scripts_launch/startServer.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
set MQhost=172.17.17.206
@@ -28,7 +20,7 @@
echo the log file will be saved in the [%LOGfile%] file
echo Server.py is running ...
@REM -------- Usage: Server.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [WEBport] [SAVEfolder]")
%aerialpython% ./src/Server.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %WEBport% %SAVEfolder% >> >> %LOGfile%
python ./src/Server.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %WEBport% %SAVEfolder% >> >> %LOGfile%
echo Server.py has been terminited.
pause
scripts_launch/udp2bin.bat
@@ -2,23 +2,15 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM please the folder path of the udp files.
@REM set UDPfolder=./Manual_Microwave/pod1-2012-12-12-12-12-12/
@REM ---------------Usage: udp2bin.py [UDPfolder]
%aerialpython% ./scripts/udp2bin.py %UDPfolder%
python ./scripts/udp2bin.py %UDPfolder%
pause
scripts_launch/udp2ply.bat
@@ -2,25 +2,17 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
@REM please the folder path of the udp files.
@REM set UDPfolder=./Manual_Microwave/pod1-2012-12-12-12-12-12/
@REM ---------------Usage: udp2bin.py [UDPfolder]
%aerialpython% ./scripts/udp2bin.py %UDPfolder%
python ./scripts/udp2bin.py %UDPfolder%
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./scripts/bin2ply.py %UDPfolder%
python ./scripts/bin2ply.py %UDPfolder%
pause
scripts_launch/udp_get.bat
@@ -2,18 +2,10 @@
@REM change to the filepath
cd %~dp0
@REM add vitrual env python to the path
path "%~dp0/../.env/Scripts/";%path%
cd ..
set aerialpython=%cd%/.env/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
cd %~dp0
cd ..
echo change to path: %cd%
set MICROWAVEhost=192.168.2.65
@@ -21,5 +13,5 @@
SET DEVICEname=pod1
SET SAVEfolder=./Manual_Microwave
@REM ---------------Usage: udp_get.py [MICROWAVEhost] [PACKETthreshold] [DEVICEname] [SAVEfolder]
%aerialpython% ./scripts/udp_get.py %MICROWAVEhost% %PACKETthreshold% %DEVICEname% %SAVEfolder%
python ./scripts/udp_get.py %MICROWAVEhost% %PACKETthreshold% %DEVICEname% %SAVEfolder%
pause
src/Server.py
@@ -1,89 +1,208 @@
import sys              # NOQA: E402    
import os
from flask import Flask, request
import pika
import uuid
import queue
from threading import Thread
from datetime import datetime
from .engine.DeviceManager import DeviceManager
from .engine.MessageQueueThread import MessageQueueThread
from .engine import MessageThreads as ths
from .protos import aerial_pb2 as pb
from .utils.tools import update_folder_for_today
class MyServer(Flask):
    def __init__(self, host, user, password, queue, port, SAVEfolder):
    def __init__(self,
                MQhost:str,
                MQuser:str,
                MQpassword:str,
                WEBhost:str,
                WEBport:int,
                save_folder:str,
                server_name:str
                ):
        Flask.__init__(self, __name__)
        self.host = host
        self.user = user
        self.password = password
        self.queue = queue
        self.port = port
        global save_folder
        save_folder = SAVEfolder
        self.MQhost = MQhost
        self.MQuser = MQuser
        self.MQpassword = MQpassword
        self.WEBhost = WEBhost
        self.WEBport = WEBport
        self.save_folder = save_folder
        self.server_name = server_name
        self.replay_host = "http://192.168.1.17:8001/admin/business/colletmeta/getDeviceMsg"
        today = datetime.now().strftime('%Y-%m-%d')
        today_folder = os.path.join(self.save_folder,today)
        self.today = {"today":today,
                    "today_folder":today_folder,
                    "sup_folder":self.save_folder,
                    "sub_folder": ""}
        self.task_uuid_folder = {"init":os.path.join(self.today["today_folder"],"init")}
        if not os.path.exists(self.task_uuid_folder["init"]):
            os.makedirs(self.task_uuid_folder["init"])
        self.route('/api', methods=['POST'])(self.api)
        self.route('/', methods=['GET'])(self.hello)
        self._def_routes()
        self._device_manager = DeviceManager(host, user, password)
        # self._def_routes()
    def _def_routes(self):
        self.routes = {
            pb.SysCommand.SYS_COMMAND: self._on_sys_command,
        }
        # queue
        self.LogsReceiver_queue = queue.Queue()
        self.ImagesReceiver_queue = queue.Queue()
        self.PlysReceiver_queue = queue.Queue()
    def _on_sys_command(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        if pb.SubCommand.POWER_ON_SUB_COMMAND == req.sub_command:
            print('power on message received')
            self._device_manager.get_device(req.device_id,save_folder)
        elif pb.SubCommand.POWER_OFF_SUB_COMMAND == req.sub_command:
            device = self._device_manager.get_device(req.device_id,save_folder)
            device['power_on'] = False
            print('power off message received')
        return
        self.CommandsSender_queue = queue.Queue()
    def _default(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        print('onknown command')
    def _connect_to_MQ(self):
        credentials = pika.PlainCredentials(self.MQuser, self.MQpassword)
        self.parameters = pika.ConnectionParameters(
            credentials=credentials, host=self.MQhost,heartbeat=0)
        # 连接队列服务器
        try:
            self.connection = pika.BlockingConnection(self.parameters)
            print(f"connected to MQ server: {self.MQhost} with user {self.MQuser}")
            self.connection.close()
        except Exception :
            print("Can't connecting to the MQ server")
            exit(1)
    def api(self):
        req = pb.RequestCommand()
        req.ParseFromString(request.data)
        dispatcher = self.routes.get(req.sys_command, self._default)
        resp = pb.ResponseCommand()
        dispatcher(req, resp)
        resp.checksum = 12345
        response = Flask.response_class(
            resp.SerializeToString(),
            mimetype='application/x-protobuf'
        )
        return response, 200
    def _receiver_Thread_Launcher(self):
        # launch logs receiver thread
        self.LogsReceiver_Thread = ths.receiverThread(
                                    MQparams=self.parameters,
                                    exchange_name='logs_topic',
                                    exchange_type='topic',
                                    MQqueue_name=f'{self.server_name}_logs_queue',
                                    binding_keys=[f'{self.server_name}.logs.test0'],
                                    message_queue=self.LogsReceiver_queue
                                    )
        self.LogsReceiver_Thread.setDaemon(True)
        self.LogsReceiver_Thread.setName("Thread-logsReceiver")
        self.LogsReceiver_Thread.start()
        # launch images receiver thread
        self.ImagesReceiver_Thread = ths.receiverThread(
                                    MQparams=self.parameters,
                                    exchange_name='images_topic',
                                    exchange_type='topic',
                                    MQqueue_name=f'{self.server_name}_images_queue',
                                    binding_keys=[f"{self.server_name}.images.test0"],
                                    message_queue=self.ImagesReceiver_queue
                                    )
        self.ImagesReceiver_Thread.setDaemon(True)
        self.ImagesReceiver_Thread.setName("Thread-imagesReceiver")
        self.ImagesReceiver_Thread.start()
        # launch plys receiver thread
        self.PlysReceiver_Thread = ths.receiverThread(
                                    MQparams=self.parameters,
                                    exchange_name='plys_topic',
                                    exchange_type='topic',
                                    MQqueue_name=f'{self.server_name}_plys_queue',
                                    binding_keys=[f'{self.server_name}.plys.test0'],
                                    message_queue=self.PlysReceiver_queue
                                    )
        self.PlysReceiver_Thread.setDaemon(True)
        self.PlysReceiver_Thread.setName("Thread-plysReceiver")
        self.PlysReceiver_Thread.start()
        # launch decode thread
        queue_list = [self.LogsReceiver_queue,self.ImagesReceiver_queue,self.PlysReceiver_queue]
        queue_tags = ["Logs", "Images", "Plys"]
        self.MsgDecoder_Thread = ths.decodeThread(
                                    queue_list= queue_list,
                                    queue_tags= queue_tags,
                                    task_folder= self.task_uuid_folder  ,
                                    replay_host=self.replay_host
                                    )
        self.MsgDecoder_Thread.setDaemon(True)
        self.MsgDecoder_Thread.setName("Thread-dataDecoder")
        self.MsgDecoder_Thread.start()
    def _sender_Thread_Launcher(self):
        # launcher commands sender thread
        self.CommandsSender_Thread = ths.senderThread(
                                    MQparams=self.parameters,
                                    exchange_name='commands_topic',
                                    exchange_type='topic',
                                    message_queue=self.CommandsSender_queue
                        )
        self.CommandsSender_Thread.setDaemon(True)
        self.CommandsSender_Thread.setName("Thread-commandsSender")
        self.CommandsSender_Thread.start()
    def hello(self):
        return 'Hello, This is acquisition demo API!'
    def run_rabbitmq(self, host: str, user: str, password: str, queue: str) -> None:
        self._message_queue_thread = MessageQueueThread(
            host, user, password, queue, self._device_manager, save_folder)
        self._message_queue_thread.start()
    def api(self):
        try:
            success, response_bytes = self.verify_commands(request.data)
        except:
            response_bytes = b'command error!'
        response = Flask.response_class(
            response_bytes,
            mimetype='application/x-bytes'
        )
        return response,200
    def verify_commands(self,input_command:bytes):
        # parse the command from bytes to the pb object
        req_command = pb.CommandMessage()
        req_command.ParseFromString(input_command)
        # extracting some info for use
        source = req_command.source
        # generatetime = req_command.generatetime
        # syscommand = req_command.syscommand
        # subcommand = req_command.subcommand
        targetclient = req_command.targetclient
        # returnserver = req_command.returnserver
        taskuuid = req_command.taskuuid
        update_folder_for_today(self.today)
        task_path = os.path.join(self.today["today_folder"],taskuuid)
        self.task_uuid_folder[taskuuid] = task_path
        if not os.path.exists(task_path):
            os.makedirs(task_path)
        curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
        print(f"[x] {curr_time}|(From {source}): task [{taskuuid}] received and sending it to [{targetclient}]." )
        self.CommandsSender_queue.put([targetclient,input_command])
        response_bytes = bytes(f"Receive command success! The data will be save in [{os.path.abspath(task_path)}]",\
                        encoding="utf8")
        return True, response_bytes
    def run_rabbitmq(self):
        self._connect_to_MQ()
        self._receiver_Thread_Launcher()
        self._sender_Thread_Launcher()
    def run_all(self):
        self.run_rabbitmq(self.host, self.user, self.password, self.queue)
        self.run(debug=False, host="0.0.0.0", port=self.port)
    def send_controll_message(self, device_id, msg):
        device = self._device_manager.get_device(device_id,save_folder)
        if device is None:
            channel = device.controll_channel
            channel.basic_publish(
                exchange='',
                routing_key='',
                body=msg.SerializeToString())
    def send_dust_cleaner_cmd(self, device_id, sub_cmd, period):
        msg = pb.ControllMessage()
        msg.sys_command = pb.ControlSysCommand.DUST_CLEANER_COMMAND
        msg.sub_command = sub_cmd
        data_msg = pb.DustCleanerMessage()
        data_msg.period = period
        data1_str = data_msg.SerializeToString()
        msg.data1.length = len(data1_str)
        msg.data1.data = data1_str
        self.run_rabbitmq()
        self.run(debug=False, host=self.WEBhost, port=self.WEBport)
src/Server.py.backup
New file
@@ -0,0 +1,115 @@
from posixpath import abspath
import sys              # NOQA: E402
import os
from flask import Flask, request
batfile_dir = os.path.join(__file__, "..", "protos/compile.bat" )
batfile_path = os.path.abspath(batfile_dir)
os.system(batfile_path)
from engine.DeviceManager import DeviceManager
from engine.MessageQueueThread import MessageQueueThread
from protos import aerial_pb2 as pb
class MyServer(Flask):
    def __init__(self, host, user, password, queue, port):
        Flask.__init__(self, __name__)
        self.host = host
        self.user = user
        self.password = password
        self.queue = queue
        self.port = port
        self.route('/api', methods=['POST'])(self.api)
        self.route('/', methods=['GET'])(self.hello)
        self._def_routes()
        self._device_manager = DeviceManager(host, user, password)
    def _def_routes(self):
        self.routes = {
            pb.SysCommand.SYS_COMMAND: self._on_sys_command,
        }
    def _on_sys_command(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        if pb.SubCommand.POWER_ON_SUB_COMMAND == req.sub_command:
            print('power on message received')
            self._device_manager.get_device(req.device_id,save_folder)
        elif pb.SubCommand.POWER_OFF_SUB_COMMAND == req.sub_command:
            device = self._device_manager.get_device(req.device_id,save_folder)
            device['power_on'] = False
            print('power off message received')
        return
    def _default(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        print('onknown command')
    def api(self):
        req = pb.RequestCommand()
        req.ParseFromString(request.data)
        dispatcher = self.routes.get(req.sys_command, self._default)
        resp = pb.ResponseCommand()
        dispatcher(req, resp)
        resp.checksum = 12345
        response = Flask.response_class(
            resp.SerializeToString(),
            mimetype='application/x-protobuf'
        )
        return response, 200
    def hello(self):
        return 'Hello, This is acquisition demo API!'
    def run_rabbitmq(self, host: str, user: str, password: str, queue: str) -> None:
        self._message_queue_thread = MessageQueueThread(
            host, user, password, queue, self._device_manager, save_folder)
        self._message_queue_thread.start()
    def run_all(self):
        self.run_rabbitmq(self.host, self.user, self.password, self.queue)
        self.run(debug=False, host="0.0.0.0", port=self.port)
    def send_controll_message(self, device_id, msg):
        device = self._device_manager.get_device(device_id,save_folder)
        if device is None:
            channel = device.controll_channel
            channel.basic_publish(
                exchange='',
                routing_key='',
                body=msg.SerializeToString())
    def send_dust_cleaner_cmd(self, device_id, sub_cmd, period):
        msg = pb.ControllMessage()
        msg.sys_command = pb.ControlSysCommand.DUST_CLEANER_COMMAND
        msg.sub_command = sub_cmd
        data_msg = pb.DustCleanerMessage()
        data_msg.period = period
        data1_str = data_msg.SerializeToString()
        msg.data1.length = len(data1_str)
        msg.data1.data = data1_str
if __name__ == "__main__":
    def help():
        print("Usage: Server.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [WEBport] [SAVEfolder]")
        print("EXAMPLE: Server.py localhost chai password123 aerial_rpc 5000 ./Images")
        exit(1)
    if len(sys.argv) != 7:
        help()
    try:
        MQhost = str(sys.argv[1])
        MQuser = str(sys.argv[2])
        MQpassword = str(sys.argv[3])
        QUEUEname = str(sys.argv[4])
        WEBport = int(sys.argv[5])
        SAVEfolder = str(sys.argv[6])
        global save_folder
        save_folder = SAVEfolder
    except Exception as e:
        print(e)
        help()
    server = MyServer(host="localhost", user='chai', password='password123', queue='aerial_rpc', port=5000)
    server.run_all()
src/__init__.py
@@ -1,5 +1,5 @@
from .engine import *
from .microwave import *
from .protos import *
from .slam import *
from .utils import *
# from .engine import *
# from .microwave import *
# from .protos import *
# from .slam import *
# from .utils import *
src/engine/AcquisitionMain.py
@@ -1,16 +1,15 @@
import sys              # NOQA: E402
import os
import cv2
import logging
import json
from time import sleep
import pika
import queue
import requests
import time
from datetime import datetime
from .CaptureThread import CaptureThread
from .ControllThread import ControllThread
from .MicroWaveUDPThread import MicroWaveUDPThread
# from .CaptureThread import CaptureThread
# from .ControllThread import ControllThread
# from .MicroWaveUDPThread import MicroWaveUDPThread
from . import MessageThreads as ths
from .devices import cameraController, dustCleanerController,microwaveController
# # add python path of src to sys.path
# src_path = os.path.join(__file__, *(['..'] * 2))
@@ -24,234 +23,484 @@
IMAGE_HEIGHT = 2880
CAMERA_COUNT = 4
class Config:
    """
    config class
    """
    def __init__(self, config_file: str):
        self.interval: float = 10
        self.resolution = '4k'
# class Config:
#     """
#     config class
#     """
#     def __init__(self, config_file: str):
#         self.interval: float = 10
#         self.resolution = '4k'
        self.clean_lens_start_angle = 10
        self.clean_lens_end_angle = 90
        self.clean_lens_num = 2
        self.clean_lens_period = 1200
        self.clean_self_start_angle = 10
        self.clean_self_end_angle = 55
        self.clean_self_num = 2
        self.clean_self_period = 240
#         self.clean_lens_start_angle = 10
#         self.clean_lens_end_angle = 90
#         self.clean_lens_num = 2
#         self.clean_lens_period = 1200
#         self.clean_self_start_angle = 10
#         self.clean_self_end_angle = 55
#         self.clean_self_num = 2
#         self.clean_self_period = 240
        # load config file
        with open(config_file, 'r') as f:
            self.config = json.load(f)
            self.device_id = self.config['Device_ID']
            self.interval = self.config['Captue_Image_para']['capture_interval']
            self.resolution = self.config['Captue_Image_para']['resolution']
#         # load config file
#         with open(config_file, 'r') as f:
#             self.config = json.load(f)
#             self.device_id = self.config['Device_ID']
#             self.interval = self.config['Captue_Image_para']['capture_interval']
#             self.resolution = self.config['Captue_Image_para']['resolution']
            Clean_Brush_para = self.config['Clean_Brush_para']
            self.clean_lens_start_angle = Clean_Brush_para['clean_lens_start_angle']
            self.clean_lens_end_angle = Clean_Brush_para['clean_lens_end_angle']
            self.clean_lens_num = Clean_Brush_para['clean_lens_num']
            self.clean_lens_period = Clean_Brush_para['clean_lens_period']
            self.clean_self_start_angle = Clean_Brush_para['clean_self_start_angle']
            self.clean_self_end_angle = Clean_Brush_para['clean_self_end_angle']
            self.clean_self_num = Clean_Brush_para['clean_self_num']
            self.clean_self_period = Clean_Brush_para['clean_self_period']
            f.close()
        return
#             Clean_Brush_para = self.config['Clean_Brush_para']
#             self.clean_lens_start_angle = Clean_Brush_para['clean_lens_start_angle']
#             self.clean_lens_end_angle = Clean_Brush_para['clean_lens_end_angle']
#             self.clean_lens_num = Clean_Brush_para['clean_lens_num']
#             self.clean_lens_period = Clean_Brush_para['clean_lens_period']
#             self.clean_self_start_angle = Clean_Brush_para['clean_self_start_angle']
#             self.clean_self_end_angle = Clean_Brush_para['clean_self_end_angle']
#             self.clean_self_num = Clean_Brush_para['clean_self_num']
#             self.clean_self_period = Clean_Brush_para['clean_self_period']
#             f.close()
#         return
class AcquisitionMain:
    """
    acquisition main class
    """
class AcquisitionMain (object):
    def __init__(self,
                 rabbitmq_host: str,
                 rabbitmq_user: str,
                 rabbitmq_password: str,
                 rabbitmq_queue: str,
                 device_id: str,
                 api_url: str,
                 udp_server_host: str,
                 config: Config) -> None:
        """
        init AcquisitionMain class
        Args:
            rabbitmq_host: rabbitmq server host
            rabbitmq_user: rabbitmq user
            rabbitmq_password: rabbitmq password
            rabbitmq_queue: rabbitmq upload queue
            device_id: device id
            api_url: server api url
            udp_server_host: udp server host for micro wave, localhost for testing or 192.168.2.65 for production
            config: config object
        """
        self.rabbitmq_host: str = rabbitmq_host
        self.udp_server_host: str = udp_server_host
        self.rabbitmq_user: str = rabbitmq_user
        self.rabbitmq_password: str = rabbitmq_password
        self.rabbitmq_queue: str = rabbitmq_queue
        self.device_id: str = device_id
        self.message_send: int = 0
        self.api_url: str = api_url
        self.config = config
        self.image_quality: float = 95
        self.cameras: list = []
        self.msg_queue = queue.Queue()
        # thread members
        self._controll_thread = None
        self._capture_thread = None
        self._udp_thread = None
                MQhost:str,
                MQuser:str,
                MQpassword:str,
                deviceID:str,
                MICROWAVEhost:str):
    def _start_udp_thread(self):
        """start udp thread"""
        if self._udp_thread is None:
            self._udp_thread = MicroWaveUDPThread((self.udp_server_host, 9911), self.msg_queue)
            self._udp_thread.setDaemon(True)
            self._udp_thread.start()
        # device ID
        self.device_id = deviceID
        # rabbit MQ
        self.MQhost = MQhost
        self.MQuser = MQuser
        self.MQpassword = MQpassword
        self.parameters = None
        # camera
        self.IMAGE_WIDTH = IMAGE_WIDTH
        self.IMAGE_HEIGHT = IMAGE_HEIGHT
        self.CAMERA_COUNT = CAMERA_COUNT
        # microwave
        self.MICROWAVEhost = MICROWAVEhost
        # self.MICROWAVEPort = MICROWAVEhost
        self.MICROWAVEport = 9911
    def _stop_udp_thread(self):
        """stop udp thread"""
        if not self._udp_thread is None:
            self._udp_thread.stop()
            self._udp_thread = None
    def _start_capture_thread(self):
        """start camera capture thread"""
        if self._capture_thread is None:
            self._open_cameras()
            if len(self.cameras) == 0:
                print("No camera available")
                return
            self._capture_thread = CaptureThread(
                self.cameras, self.msg_queue, self.config.interval, self.image_quality)
            self._capture_thread.setDaemon(True)
            self._capture_thread.start()
    def _stop_capture_thread(self):
        """stop camera capture thread"""
        if not self._capture_thread is None:
            self._capture_thread.stop()
            self._capture_thread = None
    def _start_controll_thread(self):
        """start controll thread"""
        if self._controll_thread is None:
            self._controll_thread = ControllThread(
                self.rabbitmq_host, self.rabbitmq_user, self.rabbitmq_password, self.device_id + "_callback",
                self.config)
            self._controll_thread.setDaemon(True)
            self._controll_thread.start()
    def _stop_controll_thread(self):
        """stop controll thread"""
        if not self._controll_thread is None:
            self._controll_thread.stop()
            self._controll_thread = None
    def _connect_message_queue(self) -> None:
        """connect message queue of rabbitmq"""
        credentials = pika.PlainCredentials(self.rabbitmq_user, self.rabbitmq_password)
        parameters = pika.ConnectionParameters(
            credentials=credentials, host=self.rabbitmq_host)
        # 连接队列服务器
        self._connection = pika.BlockingConnection(parameters)
        self.channel = self._connection.channel()
        self.channel.queue_declare(queue='', exclusive=True)
    def _close_message_queue(self) -> None:
        """close message queue of rabbitmq"""
        self._connection.close()
    def _set_logging(self):
        """set logging"""
        logging.basicConfig(level=logging.INFO,
                            format='%(asctime)s %(levelname)s %(message)s',
                            datefmt='%Y-%m-%d %H:%M:%S')
        self.logger = logging.getLogger(__name__)
    def _send_data(self, req: pb.RequestCommand) -> None:
        """send data to rabbitmq"""
        req.device_id = self.device_id
        body = req.SerializeToString()
        self.channel.basic_publish(
            exchange='',
            routing_key=self.rabbitmq_queue,
            body=body)
        self.message_send += 1
        return
    def _call(self, req: pb.RequestCommand, timeout: int = 10) -> pb.ResponseCommand:
        """call server api"""
        req.device_id = self.device_id
        self.response = None
        body = req.SerializeToString()
        response = requests.post(
            self.api_url,
            data=body,
            headers={'Content-Type': 'application/x-protobuf'},
            timeout=timeout)
        resp = pb.ResponseCommand()
        resp.ParseFromString(response.content)
        return resp
    def _send_power_on_message(self) -> pb.ResponseCommand:
        """send power on message"""
        print("send power on message")
        req = pb.RequestCommand()
        req.sys_command = pb.SysCommand.SYS_COMMAND
        req.sub_command = pb.SubCommand.POWER_ON_SUB_COMMAND
        return self._call(req)
    def _send_power_off_message(self) -> pb.ResponseCommand:
        """send power off message"""
        print("send power off message")
        req = pb.RequestCommand()
        req.sys_command = pb.SysCommand.SYS_COMMAND
        req.sub_command = pb.SubCommand.POWER_OFF_SUB_COMMAND
        return self._call(req)
    def _open_cameras(self):
        """
        Test the ports and returns a tuple with the available ports and the ones that are working.
        """
        self.cameras = []
        self.working_ports = []
        for dev_port in range(CAMERA_COUNT):
            camera = cv2.VideoCapture(dev_port, cv2.CAP_DSHOW)
            camera.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH)
            camera.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT)
            camera.set(cv2.CAP_PROP_FPS, 1)
            if camera.isOpened():
                is_reading, img = camera.read()
                w = camera.get(3)
                h = camera.get(4)
                if is_reading:
                    print("Port %s is working and reads images (%s x %s)" %
                          (dev_port, h, w))
                    self.working_ports.append(dev_port)
                    self.cameras.append(camera)
    def _main_loop(self):
        # main loop of the acquisition main program
        self._connect_message_queue()
        while True:
            try:
                if not self.msg_queue.empty():
                    msg = self.msg_queue.get()
                    self._send_data(msg)
                    print(time.asctime(), "send message")
                time.sleep(0.1)
            except Exception as e:
                break
        self._close_message_queue()
        self._stop_udp_thread()
        self._stop_capture_thread()
        self._stop_controll_thread()
        print("Stopped")
        # dust cleaner
        self.com = "COM11"
        self.bps = "115200"
        self.timeout = 1
        
    def start(self) -> None:
        """start all threads"""
        self._start_controll_thread()
        self._start_capture_thread()
        self._start_udp_thread()
        self._main_loop()
        # threads
        self.threads = []
        # queue
        self.CommandsReceiver_queue = queue.Queue()
        self.LogsSender_queue = queue.Queue()
        self.ImagesSender_queue = queue.Queue()
        self.PlysSender_queue = queue.Queue()
        # device
        self.cc = None # camera controller
        self.mc = None # microwave controller
        self.dc = None # dust cleaner controller
        self.rc = None # rotation device controler
        self.controller_dict = {
            "camera": self.cc,
            "microwave":self.mc,
            "dustcleaner":self.dc,
            "rotation": self.rc
        }
    def _connect_to_MQ(self):
        credentials = pika.PlainCredentials(self.MQuser, self.MQpassword)
        self.parameters = pika.ConnectionParameters(
            credentials=credentials, host=self.MQhost,heartbeat=0)
        # 连接队列服务器
        try:
            self.connection = pika.BlockingConnection(self.parameters)
            print(f"connected to MQ server: {self.MQhost} with user {self.MQuser}")
            self.connection.close()
        except Exception :
            print("Can't connecting to the MQ server")
            exit(1)
    def _receiver_Thread_Launcher(self):
        # launch a commands receiver thread
        self.CommandsReceiver_Thread = ths.receiverThread(
                                    MQparams=self.parameters,
                                    exchange_name='commands_topic',
                                    exchange_type='topic',
                                    MQqueue_name=f"{self.device_id}_commands_queue",
                                    binding_keys=[f"{self.device_id}"],
                                    message_queue=self.CommandsReceiver_queue
                                    )
        self.CommandsReceiver_Thread.setDaemon(True)
        self.CommandsReceiver_Thread.setName("Thread-commandsReceiver")
        self.CommandsReceiver_Thread.start()
        self.threads.append(self.CommandsReceiver_Thread)
    def _sender_Thread_Launcher(self):
        # launch a logs sender thread
        self.LogsSender_Thread = ths.senderThread(
                                MQparams=self.parameters,
                                exchange_name="logs_topic",
                                exchange_type="topic",
                                message_queue=self.LogsSender_queue
                        )
        self.LogsSender_Thread.setDaemon(True)
        self.LogsSender_Thread.setName("Thread-logsSender")
        self.LogsSender_Thread.start()
        self.threads.append(self.LogsSender_Thread)
        # launch a images sender thread
        self.ImagesSender_Thread = ths.senderThread(
                                MQparams=self.parameters,
                                exchange_name="images_topic",
                                exchange_type="topic",
                                message_queue=self.ImagesSender_queue
                        )
        self.ImagesSender_Thread.setDaemon(True)
        self.ImagesSender_Thread.setName("Thread-imageSender")
        self.ImagesSender_Thread.start()
        self.threads.append(self.ImagesSender_Thread)
        # launch a plys sender thread
        self.PlysSender_Thread = ths.senderThread(
                                MQparams=self.parameters,
                                exchange_name="plys_topic",
                                exchange_type="topic",
                                message_queue=self.PlysSender_queue
                        )
        self.PlysSender_Thread.setDaemon(True)
        self.PlysSender_Thread.setName("Thread-plysSender")
        self.PlysSender_Thread.start()
        self.threads.append(self.PlysSender_Thread)
    def _connect_device(self):
        # connect to cameras
        self.cc = cameraController(
                        IMAGE_WIDTH=self.IMAGE_WIDTH,
                        IMAGE_HEIGHT=self.IMAGE_HEIGHT,
                        CAMERA_COUNT=self.CAMERA_COUNT,
                        device_id=self.device_id,
                        logs_queue=self.LogsSender_queue,
                        images_queue=self.ImagesSender_queue,
                        init_binding_key=self.device_id,
                        init_routing_key="server0"
        )
        self.dc = dustCleanerController(
                    com = self.com,
                    bps = self.bps,
                    timeout=self.timeout,
                    logs_queue=self.LogsSender_queue,
                    device_id=self.device_id,
                    init_binding_key=self.device_id,
                    init_routing_key="server0"
                    )
        self.mc = microwaveController(
                    MicrowaveHost=self.MICROWAVEhost,
                    MicrowavePort=self.MICROWAVEport,
                    init_packet_threshold=100,
                    init_timeusage_threshold=0.2,
                    device_id=self.device_id,
                    logs_queue=self.LogsSender_queue,
                    plys_queue=self.PlysSender_queue,
                    init_binding_key=self.device_id,
                    init_routing_key="server0"
        )
    def command_control(self):
        while True:
            try:
                while not self.CommandsReceiver_queue.empty():
                    command_bytes= self.CommandsReceiver_queue.get()
                    # parse the command from bytes to the pb object
                    req_command = pb.CommandMessage()
                    req_command.ParseFromString(command_bytes)
                    # extracting some info for use
                    source = req_command.source
                    generatetime = req_command.generatetime
                    syscommand = req_command.syscommand
                    subcommand = req_command.subcommand
                    targetclient = req_command.targetclient
                    returnserver = req_command.returnserver
                    taskuuid = req_command.taskuuid
                    curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
                    print(f"[x] {curr_time}|(From {source}): task [{taskuuid}] received!" )
                    # command for camera
                    if syscommand == pb.SysCommand.CAMERA_COMMAND:
                        # capture image
                        if subcommand == pb.SubCommand.ONE_TIME_CAPTURE:
                            self.cc.capture(routing_key=returnserver,taskuuid=taskuuid)
                        # unknown command
                        else:
                            pass
                    # command for microwave device
                    elif syscommand == pb.SysCommand.MICROWAVE_COMMAND:
                        if subcommand == pb.SubCommand.ONE_CIRCLE_SCAN:
                            self.mc.scan(routing_key=returnserver,taskuuid=taskuuid)
                        # unknown command
                        else:
                            pass
                    # command for dust cleaner
                    elif syscommand == pb.Syscommand.DUSTCLEANER_COMMAND:
                        if subcommand == pb.SubCommand.ONE_CLEAN_SCAN:
                            self.dc.clean(routing_key=returnserver,taskuuid=taskuuid)
                        # unknown command
                        else:
                            pass
                    # unknown command
                    else:
                        pass
                else:
                    sleep(1)
            except:
                break
    def run_rabbitmq(self):
        self._connect_to_MQ()
        self._receiver_Thread_Launcher()
        self._sender_Thread_Launcher()
    def run_device(self):
        self._connect_device()
    def run_all(self):
        # connecting to MQ server,launching the message delivery queues
        self.run_rabbitmq()
        # connecting to devices and wrap data to the corressponding queue
        self.run_device()
        sleep(10)
        self.command_control()
    def stop_all(self):
        for t in self.threads:
            t.stop()
            print(f"stop {t.name}")
    def start(self):
        # try:
        #     self.run_all()
        #     print("[*] Client is runing ...")
        #     self.CommandsReceiver_Thread.join()
        # except Exception as e:
        #     print(e)
        #     print("running error, stop all threads")
        #     self.stop_all()
        # print("main thread end.")
        self.run_all()
        return 0
    # def _start_udp_thread(self):
    #     """start udp thread"""
    #     if self._udp_thread is None:
    #         self._udp_thread = MicroWaveUDPThread((self.udp_server_host, 9911), self.msg_queue)
    #         self._udp_thread.setDaemon(True)
    #         self._udp_thread.start()
    # def _stop_udp_thread(self):
    #     """stop udp thread"""
    #     if not self._udp_thread is None:
    #         self._udp_thread.stop()
    #         self._udp_thread = None
    # def _start_capture_thread(self):
    #     """start camera capture thread"""
    #     if self._capture_thread is None:
    #         self._open_cameras()
    #         if len(self.cameras) == 0:
    #             print("No camera available")
    #             return
    #         self._capture_thread = CaptureThread(
    #             self.cameras, self.msg_queue, self.config.interval, self.image_quality)
    #         self._capture_thread.setDaemon(True)
    #         self._capture_thread.start()
    # def _stop_capture_thread(self):
    #     """stop camera capture thread"""
    #     if not self._capture_thread is None:
    #         self._capture_thread.stop()
    #         self._capture_thread = None
    # def _start_controll_thread(self):
    #     """start controll thread"""
    #     if self._controll_thread is None:
    #         self._controll_thread = ControllThread(
    #             self.rabbitmq_host, self.rabbitmq_user, self.rabbitmq_password, self.device_id + "_callback",
    #             self.config)
    #         self._controll_thread.setDaemon(True)
    #         self._controll_thread.start()
    # def _stop_controll_thread(self):
    #     """stop controll thread"""
    #     if not self._controll_thread is None:
    #         self._controll_thread.stop()
    #         self._controll_thread = None
    # def _connect_message_queue(self) -> None:
    #     """connect message queue of rabbitmq"""
    #     credentials = pika.PlainCredentials(self.rabbitmq_user, self.rabbitmq_password)
    #     parameters = pika.ConnectionParameters(
    #         credentials=credentials, host=self.rabbitmq_host)
    #     # 连接队列服务器
    #     self._connection = pika.BlockingConnection(parameters)
    #     self.channel = self._connection.channel()
    #     self.channel.queue_declare(queue='', exclusive=True)
    # def _close_message_queue(self) -> None:
    #     """close message queue of rabbitmq"""
    #     self._connection.close()
    # def _set_logging(self):
    #     """set logging"""
    #     logging.basicConfig(level=logging.INFO,
    #                         format='%(asctime)s %(levelname)s %(message)s',
    #                         datefmt='%Y-%m-%d %H:%M:%S')
    #     self.logger = logging.getLogger(__name__)
    # def _send_data(self, req: pb.RequestCommand) -> None:
    #     """send data to rabbitmq"""
    #     req.device_id = self.device_id
    #     body = req.SerializeToString()
    #     self.channel.basic_publish(
    #         exchange='',
    #         routing_key=self.rabbitmq_queue,
    #         body=body)
    #     self.message_send += 1
    #     return
    # def _call(self, req: pb.RequestCommand, timeout: int = 10) -> pb.ResponseCommand:
    #     """call server api"""
    #     req.device_id = self.device_id
    #     self.response = None
    #     body = req.SerializeToString()
    #     response = requests.post(
    #         self.api_url,
    #         data=body,
    #         headers={'Content-Type': 'application/x-protobuf'},
    #         timeout=timeout)
    #     resp = pb.ResponseCommand()
    #     resp.ParseFromString(response.content)
    #     return resp
    # def _send_power_on_message(self) -> pb.ResponseCommand:
    #     """send power on message"""
    #     print("send power on message")
    #     req = pb.RequestCommand()
    #     req.sys_command = pb.SysCommand.SYS_COMMAND
    #     req.sub_command = pb.SubCommand.POWER_ON_SUB_COMMAND
    #     return self._call(req)
    # def _send_power_off_message(self) -> pb.ResponseCommand:
    #     """send power off message"""
    #     print("send power off message")
    #     req = pb.RequestCommand()
    #     req.sys_command = pb.SysCommand.SYS_COMMAND
    #     req.sub_command = pb.SubCommand.POWER_OFF_SUB_COMMAND
    #     return self._call(req)
    # def _open_cameras(self):
    #     """
    #     Test the ports and returns a tuple with the available ports and the ones that are working.
    #     """
    #     self.cameras = []
    #     self.working_ports = []
    #     for dev_port in range(CAMERA_COUNT):
    #         camera = cv2.VideoCapture(dev_port, cv2.CAP_DSHOW)
    #         camera.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH)
    #         camera.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT)
    #         camera.set(cv2.CAP_PROP_FPS, 1)
    #         if camera.isOpened():
    #             is_reading, img = camera.read()
    #             w = camera.get(3)
    #             h = camera.get(4)
    #             if is_reading:
    #                 print("Port %s is working and reads images (%s x %s)" %
    #                       (dev_port, h, w))
    #                 self.working_ports.append(dev_port)
    #                 self.cameras.append(camera)
    # def _main_loop(self):
    #     # main loop of the acquisition main program
    #     self._connect_message_queue()
    #     while True:
    #         try:
    #             if not self.msg_queue.empty():
    #                 msg = self.msg_queue.get()
    #                 self._send_data(msg)
    #                 print(time.asctime(), "send message")
    #             time.sleep(0.1)
    #         except Exception as e:
    #             break
    #     self._close_message_queue()
    #     self._stop_udp_thread()
    #     self._stop_capture_thread()
    #     self._stop_controll_thread()
    #     print("Stopped")
    # def start(self) -> None:
    #     """start all threads"""
    #     self._start_controll_thread()
    #     self._start_capture_thread()
    #     self._start_udp_thread()
    #     self._main_loop()
src/engine/AcquisitionMain.py.backup
New file
@@ -0,0 +1,257 @@
import sys              # NOQA: E402
import os
import cv2
import logging
import json
import pika
import queue
import requests
import time
from .CaptureThread import CaptureThread
from .ControllThread import ControllThread
from .MicroWaveUDPThread import MicroWaveUDPThread
# add python path of src to sys.path
src_path = os.path.join(__file__, *(['..'] * 2))
src_path = os.path.abspath(src_path)
sys.path.insert(0, src_path)
from protos import aerial_pb2 as pb
IMAGE_WIDTH = 3840
IMAGE_HEIGHT = 2880
CAMERA_COUNT = 4
class Config:
    """
    config class
    """
    def __init__(self, config_file: str):
        self.interval: float = 10
        self.resolution = '4k'
        self.clean_lens_start_angle = 10
        self.clean_lens_end_angle = 90
        self.clean_lens_num = 2
        self.clean_lens_period = 1200
        self.clean_self_start_angle = 10
        self.clean_self_end_angle = 55
        self.clean_self_num = 2
        self.clean_self_period = 240
        # load config file
        with open(config_file, 'r') as f:
            self.config = json.load(f)
            self.device_id = self.config['Device_ID']
            self.interval = self.config['Captue_Image_para']['capture_interval']
            self.resolution = self.config['Captue_Image_para']['resolution']
            Clean_Brush_para = self.config['Clean_Brush_para']
            self.clean_lens_start_angle = Clean_Brush_para['clean_lens_start_angle']
            self.clean_lens_end_angle = Clean_Brush_para['clean_lens_end_angle']
            self.clean_lens_num = Clean_Brush_para['clean_lens_num']
            self.clean_lens_period = Clean_Brush_para['clean_lens_period']
            self.clean_self_start_angle = Clean_Brush_para['clean_self_start_angle']
            self.clean_self_end_angle = Clean_Brush_para['clean_self_end_angle']
            self.clean_self_num = Clean_Brush_para['clean_self_num']
            self.clean_self_period = Clean_Brush_para['clean_self_period']
            f.close()
        return
class AcquisitionMain:
    """
    acquisition main class
    """
    def __init__(self,
                 rabbitmq_host: str,
                 rabbitmq_user: str,
                 rabbitmq_password: str,
                 rabbitmq_queue: str,
                 device_id: str,
                 api_url: str,
                 udp_server_host: str,
                 config: Config) -> None:
        """
        init AcquisitionMain class
        Args:
            rabbitmq_host: rabbitmq server host
            rabbitmq_user: rabbitmq user
            rabbitmq_password: rabbitmq password
            rabbitmq_queue: rabbitmq upload queue
            device_id: device id
            api_url: server api url
            udp_server_host: udp server host for micro wave, localhost for testing or 192.168.2.65 for production
            config: config object
        """
        self.rabbitmq_host: str = rabbitmq_host
        self.udp_server_host: str = udp_server_host
        self.rabbitmq_user: str = rabbitmq_user
        self.rabbitmq_password: str = rabbitmq_password
        self.rabbitmq_queue: str = rabbitmq_queue
        self.device_id: str = device_id
        self.message_send: int = 0
        self.api_url: str = api_url
        self.config = config
        self.image_quality: float = 95
        self.cameras: list = []
        self.msg_queue = queue.Queue()
        # thread members
        self._controll_thread = None
        self._capture_thread = None
        self._udp_thread = None
    def _start_udp_thread(self):
        """start udp thread"""
        if self._udp_thread is None:
            self._udp_thread = MicroWaveUDPThread((self.udp_server_host, 9911), self.msg_queue)
            self._udp_thread.setDaemon(True)
            self._udp_thread.start()
    def _stop_udp_thread(self):
        """stop udp thread"""
        if not self._udp_thread is None:
            self._udp_thread.stop()
            self._udp_thread = None
    def _start_capture_thread(self):
        """start camera capture thread"""
        if self._capture_thread is None:
            self._open_cameras()
            if len(self.cameras) == 0:
                print("No camera available")
                return
            self._capture_thread = CaptureThread(
                self.cameras, self.msg_queue, self.config.interval, self.image_quality)
            self._capture_thread.setDaemon(True)
            self._capture_thread.start()
    def _stop_capture_thread(self):
        """stop camera capture thread"""
        if not self._capture_thread is None:
            self._capture_thread.stop()
            self._capture_thread = None
    def _start_controll_thread(self):
        """start controll thread"""
        if self._controll_thread is None:
            self._controll_thread = ControllThread(
                self.rabbitmq_host, self.rabbitmq_user, self.rabbitmq_password, self.device_id + "_callback",
                self.config)
            self._controll_thread.setDaemon(True)
            self._controll_thread.start()
    def _stop_controll_thread(self):
        """stop controll thread"""
        if not self._controll_thread is None:
            self._controll_thread.stop()
            self._controll_thread = None
    def _connect_message_queue(self) -> None:
        """connect message queue of rabbitmq"""
        credentials = pika.PlainCredentials(self.rabbitmq_user, self.rabbitmq_password)
        parameters = pika.ConnectionParameters(
            credentials=credentials, host=self.rabbitmq_host)
        # 连接队列服务器
        self._connection = pika.BlockingConnection(parameters)
        self.channel = self._connection.channel()
        self.channel.queue_declare(queue='', exclusive=True)
    def _close_message_queue(self) -> None:
        """close message queue of rabbitmq"""
        self._connection.close()
    def _set_logging(self):
        """set logging"""
        logging.basicConfig(level=logging.INFO,
                            format='%(asctime)s %(levelname)s %(message)s',
                            datefmt='%Y-%m-%d %H:%M:%S')
        self.logger = logging.getLogger(__name__)
    def _send_data(self, req: pb.RequestCommand) -> None:
        """send data to rabbitmq"""
        req.device_id = self.device_id
        body = req.SerializeToString()
        self.channel.basic_publish(
            exchange='',
            routing_key=self.rabbitmq_queue,
            body=body)
        self.message_send += 1
        return
    def _call(self, req: pb.RequestCommand, timeout: int = 10) -> pb.ResponseCommand:
        """call server api"""
        req.device_id = self.device_id
        self.response = None
        body = req.SerializeToString()
        response = requests.post(
            self.api_url,
            data=body,
            headers={'Content-Type': 'application/x-protobuf'},
            timeout=timeout)
        resp = pb.ResponseCommand()
        resp.ParseFromString(response.content)
        return resp
    def _send_power_on_message(self) -> pb.ResponseCommand:
        """send power on message"""
        print("send power on message")
        req = pb.RequestCommand()
        req.sys_command = pb.SysCommand.SYS_COMMAND
        req.sub_command = pb.SubCommand.POWER_ON_SUB_COMMAND
        return self._call(req)
    def _send_power_off_message(self) -> pb.ResponseCommand:
        """send power off message"""
        print("send power off message")
        req = pb.RequestCommand()
        req.sys_command = pb.SysCommand.SYS_COMMAND
        req.sub_command = pb.SubCommand.POWER_OFF_SUB_COMMAND
        return self._call(req)
    def _open_cameras(self):
        """
        Test the ports and returns a tuple with the available ports and the ones that are working.
        """
        self.cameras = []
        self.working_ports = []
        for dev_port in range(CAMERA_COUNT):
            camera = cv2.VideoCapture(dev_port, cv2.CAP_DSHOW)
            camera.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH)
            camera.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT)
            camera.set(cv2.CAP_PROP_FPS, 1)
            if camera.isOpened():
                is_reading, img = camera.read()
                w = camera.get(3)
                h = camera.get(4)
                if is_reading:
                    print("Port %s is working and reads images (%s x %s)" %
                          (dev_port, h, w))
                    self.working_ports.append(dev_port)
                    self.cameras.append(camera)
    def _main_loop(self):
        # main loop of the acquisition main program
        self._connect_message_queue()
        while True:
            try:
                if not self.msg_queue.empty():
                    msg = self.msg_queue.get()
                    self._send_data(msg)
                    print(time.asctime(), "send message")
                time.sleep(0.1)
            except Exception as e:
                break
        self._close_message_queue()
        self._stop_udp_thread()
        self._stop_capture_thread()
        self._stop_controll_thread()
        print("Stopped")
    def start(self) -> None:
        """start all threads"""
        self._start_controll_thread()
        self._start_capture_thread()
        self._start_udp_thread()
        self._main_loop()
src/engine/CaptureThread.py
@@ -1,6 +1,4 @@
import sys
import cv2              # NOQA: E402
import os
import numpy as np
import threading
import time
src/engine/ControllThread.py
@@ -1,5 +1,3 @@
import os, sys
import queue
import time
import pika
src/engine/DustCleanerThread.py
@@ -1,5 +1,3 @@
import sys              # NOQA: E402
import os
import threading
import time
src/engine/MessageQueueThread.py
@@ -1,5 +1,3 @@
import sys              # NOQA: E402
import os
import pika
import threading
from ctypes import sizeof
src/engine/MessageThreads.py
New file
@@ -0,0 +1,496 @@
import os
import queue
import threading
import pika
import time
from datetime import datetime
from typing import List
import numpy as np
import cv2
import requests
# # add python path of src to sys.path
# src_path = os.path.join(__file__, *(['..'] * 2))
# src_path = os.path.abspath(src_path)
# sys.path.insert(0, src_path)
from ..protos import aerial_pb2 as pb
from ..utils.tools import write_ply
# class Message(object):
#     def __init__(self,sender_id,sender_key,body,routing_key):
#         self.sender_id = sender_id
#         self.sender_key = sender_key
#         self.body = body
#         self.routing_key = routing_key
class senderThread(threading.Thread):
    def  __init__(self,
                    MQparams: pika.ConnectionParameters,
                    exchange_name: str,
                    exchange_type:str,
                    # routing_key:str,
                    message_queue:queue.Queue,
                        ):
            super().__init__()
            self.MQparams = MQparams
            self.exchange_name = exchange_name
            self.exchange_type = exchange_type
            # self.routing_key = routing_key
            self.message_queue = message_queue
            # connect to RabbitMQ
            self.is_stop = False
            self.connection = pika.BlockingConnection(self.MQparams)
    def stop(self):
        """stop the thread"""
        self.is_stop = True
    #     self.connection.close()
    def run(self):
        while not self.is_stop:
            # declare a exchange
            channel = self.connection.channel()
            channel.exchange_declare(exchange=self.exchange_name,
                                    exchange_type=self.exchange_type)
            while True:
                try:
                    if not self.message_queue.empty() and not self.is_stop:
                        # decode the routing key and message body from tuple list
                        message = self.message_queue.get()
                        msg_routing_key = message[0]
                        msg_body = message[1]
                        if msg_body is not False:
                            # publish a PERSISTENT message
                            channel.basic_publish(
                            exchange = self.exchange_name,
                            routing_key = msg_routing_key,
                            body = msg_body,
                            properties=pika.BasicProperties(
                                delivery_mode=pika.spec.PERSISTENT_DELIVERY_MODE
                                    )
                            )
                            timestamp = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
                            caption = f"[x] {timestamp} | Sending message to [{msg_routing_key}]"
                            print(caption)
                    else:
                        time.sleep(1)
                except Exception as e:
                    print(e)
                    break
class receiverThread(threading.Thread):
    def  __init__(self,
                    MQparams: pika.ConnectionParameters,
                    exchange_name: str,
                    exchange_type:str,
                    MQqueue_name:str,
                    binding_keys:List[str],
                    message_queue:queue.Queue,
                        ):
            super().__init__()
            self.MQparams = MQparams
            self.exchange_name = exchange_name
            self.exchange_type = exchange_type
            self.MQqueue_name = MQqueue_name
            self.binding_keys = binding_keys
            self.message_queue = message_queue
            # connect to RabbitMQ
            self.is_stop = False
            self.connection = pika.BlockingConnection(self.MQparams)
    def stop(self):
        """stop the thread"""
        self.is_stop = True
    #     self.connection.close()
    def run(self):
        while not self.is_stop:
            # declare a exchange
            channel = self.connection.channel()
            channel.exchange_declare(exchange=self.exchange_name,
                                    exchange_type=self.exchange_type)
            # declare the queue and bind it with keys
            channel.queue_declare(queue=self.MQqueue_name, durable=True)
            for binding_key in self.binding_keys:
                channel.queue_bind(exchange=self.exchange_name, queue=self.MQqueue_name, routing_key=binding_key)
                print(f"[*] Using [{binding_key}] bind [{self.MQqueue_name}] on [{self.exchange_name}]")
            # consume the message
            channel.basic_qos(prefetch_count=1)
            channel.basic_consume(
                queue=self.MQqueue_name,
                on_message_callback=self.callback
            )
            channel.start_consuming()
    def callback(self,ch, method, properties, body):
        if self.is_stop:
            ch.close()
        if body is not False:
            self.message_queue.put(body)
        ch.basic_ack(delivery_tag = method.delivery_tag)
class decodeThread(threading.Thread):
    def __init__(self,
        queue_list:List[queue.Queue],
        queue_tags:List[str],
        task_folder:dict[str,str],
        replay_host:str):
        super().__init__()
        self.queue_list = queue_list
        self.queue_tags = queue_tags
        self.queue_num = 0
        self.task_folder = task_folder
        self.replay_host = replay_host
        self.is_stop = False
        assert len(self.queue_list) == len(self.queue_tags)
    def stop(self):
        """stop the thread"""
        self.is_stop = True
    def run(self) -> None:
        # # creating a path for saving data
        # time_tag = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
        # self.save_root_folder = os.path.join(self.task_folder,time_tag)
        # os.makedirs(self.save_root_folder)
        # self.logsmsg_folder = os.path.join(self.save_root_folder,"LogsMsg")
        # self.imagesmsg_folder = os.path.join(self.save_root_folder,"ImagesMsg")
        # self.plysmsg_folder = os.path.join(self.save_root_folder,"PlysMsg")
        # self.commandsmsg_folder = os.path.join(self.save_root_folder,"CommandsMsg")
        # sub_folder_list = [self.logsmsg_folder,self.imagesmsg_folder,
        #                 self.plysmsg_folder,self.commandsmsg_folder]
        # for folder in sub_folder_list:
        #     os.mkdir(folder)
        #     print(f"[NOTICE] Creating folder: {folder}")
        # process the queue list
        self.queue_num = len(self.queue_list)
        while self.queue_num:
            i = 0
            while True:
                # select a queue
                i_tag = i % self.queue_num
                queue = self.queue_list[i_tag]
                # make sure the queue is not empty
                while not queue.empty() and not self.is_stop:
                    # decode the msg using cooresponding method
                    queue_tag = self.queue_tags[i_tag]
                    decode_method = self.decode_select(queue_tag)
                    decode_method(queue)
                # next queue
                i += 1
    def decode_select(self,queue_tags:str):
        route_dic = {
            "Logs":self.decode_LogsMsg,
            "Images":self.decode_ImagesMsg,
            "Plys":self.decode_PlysMsg,
            "Commands":self.decode_CommandsMsg
        }
        return route_dic[queue_tags]
    def decode_LogsMsg(self,queue):
        nums_limit = 10
        count = 0
        while not queue.empty() and count < nums_limit:
            # extracting the msg from queue
            msg = queue.get()
            msg_pb = pb.LogsMessage()
            msg_pb.ParseFromString(msg)
            # process the msg
            msg_source = msg_pb.source
            msg_timestamp = msg_pb.timestamp
            msg_context = msg_pb.context
            taskuuid = msg_pb.taskuuid
            save_folder = self.task_folder[taskuuid]
            # save the raw pb msg
            # curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
            raw_file_name = os.path.join(save_folder,f"{msg_timestamp}-{msg_source}.LogsMsg")
            with open(raw_file_name, 'wb') as file:
                file.write(msg)
            # display the info to the console
            curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
            notice_str = f"[x] {curr_time}|(From {msg_source}): {msg_context}"
            print(notice_str)
            replay_to_(host = self.replay_host,
                        message=notice_str,
                        message_type="logs",
                        taskuuid=taskuuid)
            # next msg
            count += 1
    def decode_ImagesMsg(self,queue):
        while not queue.empty():
            # extracting the msg from queue
            msg = queue.get()
            msg_pb = pb.ImagesMessage()
            msg_pb.ParseFromString(msg)
            # process the msg
            msg_source = msg_pb.source
            msg_timestamp = msg_pb.timestamp
            taskuuid = msg_pb.taskuuid
            save_folder = self.task_folder[taskuuid]
            # save the raw pb msg
            # curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
            raw_file_name = os.path.join(save_folder,f"{msg_timestamp}-{msg_source}.ImagesMsg")
            with open(raw_file_name, 'wb') as file:
                file.write(msg)
            # process the images
            id = 0
            for image in msg_pb.Image:
                imagelegth = image.length
                image_byte = image.data
                # save the images
                if (image_byte is None) | (len(image_byte) != imagelegth ):
                    pass
                else:
                    filename = f"{msg_timestamp}-{msg_source}-image{id}.jpg"
                    filepath = os.path.join(save_folder,filename)
                    with open(filepath, 'wb') as f:
                        f.write(image_byte)
                    # display the info to the console
                    curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
                    notice_str = f"[x] {curr_time}|(From {msg_source}): image{id} saved!"
                    print(notice_str)
                    replay_to_(host = self.replay_host,
                                message=notice_str,
                                message_type="images",
                                taskuuid=taskuuid)
                # next image item
                id += 1
    def decode_PlysMsg(self,queue):
        while not queue.empty():
            # extracting the msg from queue
            msg = queue.get()
            msg_pb = pb.PlysMessage()
            msg_pb.ParseFromString(msg)
            # process the msg
            msg_source = msg_pb.source
            msg_timestamp = msg_pb.timestamp
            taskuuid = msg_pb.taskuuid
            save_folder = self.task_folder[taskuuid]
            # save the raw pb msg
            # curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
            raw_file_name = os.path.join(save_folder,f"{msg_timestamp}-{msg_source}.PlysMsg")
            with open(raw_file_name, 'wb') as file:
                file.write(msg)
            # process the muti ply data
            id = 0
            for ply in msg_pb.Plydata:
                data_legth = ply.length
                data_byte = ply.data
                rows = ply.rows
                cols = ply.cols
                order = ply.order
                dt = ply.dtype
                # save the pointcloud array data
                if (data_byte is None) | (len(data_byte) != data_legth):
                        pass
                else:
                    # frame the bytes to array
                    data_array = np.frombuffer(data_byte,dtype=dt)
                    data_array = data_array.reshape(rows,cols,order=order)
                    # save the data with .ply format
                    filename = f"{msg_timestamp}-{msg_source}-pointcloud{id}"
                    write_ply(data_array,save_folder,filename)
                    # display the info to the console
                    curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
                    notice_str = f"[x] {curr_time}|(From {msg_source}): ply{id} saved!"
                    print(notice_str)
                    replay_to_(host = self.replay_host,
                                message=notice_str,
                                message_type="plys",
                                taskuuid=taskuuid)
                # next ply item
                id += 1
    def decode_CommandsMsg(self,queue):
        raise NotImplementedError("NOT IMPLEMENT!")
def replay_to_(host:str,
            message:str,
            message_type:str,
            taskuuid:str,
            ):
    if taskuuid != "init":
        try:
            # target = host+taskuuid
            target = host
            print(f"Send message to [{target}]")
            payload = {"taskid":taskuuid, "messagetype":message_type, "message": message}
            r = requests.post(target,params = payload,timeout=3)
            print("send success!")
        except Exception as e:
            print(e)
            print("send error!")
            pass
def send_logs_tool(logs:List[str],
                logs_queue:queue.Queue,
                source:str,
                routing_key:str,
                taskuuid:str = "init"):
    for i, log in enumerate(logs):
        if log is not None:
            # constract a logs message
            logsMsg = pb.LogsMessage()
            logsMsg.source = source
            curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
            logsMsg.timestamp = curr_time
            logsMsg.context = log
            logsMsg.taskuuid = taskuuid
            # convert the proto object to string
            logsMsg_bytes = logsMsg.SerializeToString()
            # add logsmsg to queue
            logs_queue.put([routing_key,logsMsg_bytes])
def send_images_tool(images:List[np.array],
                    images_queue:queue.Queue,
                    source:str,
                    routing_key:str,
                    taskuuid:str = "init"):
    # constract a images message
    imagesMsg = pb.ImagesMessage()
    imagesMsg.source = source
    curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    imagesMsg.timestamp = curr_time
    imagesMsg.taskuuid = taskuuid
    for img in images:
        if img is not None:
            success,image_encoded = cv2.imencode(".jpg",img)
            if success:
                image_bytes = image_encoded.tobytes()
                image_length = len(image_bytes)
                # add the encoded image to msg
                image_item = imagesMsg.Image.add()
                image_item.length = image_length
                image_item.data = image_bytes
    # converting the pb image msg to bytes
    imageMsg_bytes = imagesMsg.SerializeToString()
    # add the imageMsg to the queue
    images_queue.put([routing_key,imageMsg_bytes])
def send_pointcloud_tool(pointclouds:queue.Queue,
                        plys_queue:queue.Queue,
                        source:str,
                        routing_key:str,
                        taskuuid:str = "init"):
    # constract a plys message
    plysMsg = pb.PlysMessage()
    plysMsg.source = source
    curr_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    plysMsg.timestamp = curr_time
    plysMsg.taskuuid = taskuuid
    empty = True
    run =True
    while run:
        while not pointclouds.empty():
            value = pointclouds.get()
            if value is not False:
                empty = False
                pointcloud = np.array(value)
                # get the attributes of the PointCloudItem
                rows = pointcloud.shape[0]
                cols = pointcloud.shape[1]
                order = "C"
                dtype = str(pointcloud.dtype)
                data = pointcloud.tobytes(order=order)
                length = len(data)
                # add the pointcloud to the msg
                item  = plysMsg.Plydata.add()
                item.length = length
                item.rows = rows
                item.cols = cols
                item.order = order
                item.dtype = dtype
                item.data = data
            else:
                if not empty:
                    # converting the pb ply msg to bytes
                    plysMsg_bytes = plysMsg.SerializeToString()
                    # add the plysMsg to the queue
                    plys_queue.put([routing_key,plysMsg_bytes])
                    # end the outer while loop and triminate this function
                else:
                    print("[x] NO pointcloud has been captured!")
                run = False
        else:
            time.sleep(3)
src/engine/Microwave.py
New file
@@ -0,0 +1,57 @@
import queue
from typing import Union
import threading
from .MessageThreads import send_logs_tool
from ..microwave.servers import MicroWaveUDPThread,UDP2PointcloudThread
class micorwaveMannager(object):
    def __init__(self,
            MicrowaveHost:str,
            MicrowavePort:int,
            ):
        # microwave
        self.MicrowaveHost = MicrowaveHost
        self.MicrowavePort = MicrowavePort
        # udp get
        self._udp_get_thread = None
        # self.packet_threshold = packet_threshold
        # self.timeusage_threshold = timeusage_threshold
        self.udp_queue = queue.Queue()
        self.udp_get_stop = threading.Event()
        self._udp_get_thread_name = "Thread-UDPGet"
        # udp to pointcloud
        self._udp2pointcloud_thread = None
        self.pointcloud_queue = queue.Queue()
        self._udp2pointcloud_thread_name = "Thread-UDP2PointCloud"
    def _udp_get_thread_launcher(self,
                    packet_threshold:Union[int, None],
                    timeusage_threshold:Union[int, None]):
        self.udp_get_stop.clear()
        self._udp_get_thread = MicroWaveUDPThread(MicrowaveHost=self.MicrowaveHost,
                            MicrowavePort=self.MicrowavePort,
                            udp_queue=self.udp_queue,
                            udp_get_stop=self.udp_get_stop,
                            packet_threshold=packet_threshold,
                            timeusage_threshold=timeusage_threshold)
        self._udp_get_thread.setDaemon(True)
        self._udp_get_thread.setName(self._udp_get_thread_name)
        self._udp_get_thread.start()
    def _udp2pointcloud_thread_launcher(self):
        self._udp2pointcloud_thread = UDP2PointcloudThread(
                                        udp_queue = self.udp_queue,
                                        pointcloud_queue=self.pointcloud_queue
                                        )
        self._udp2pointcloud_thread.setDaemon(True)
        self._udp2pointcloud_thread.setName(self._udp2pointcloud_thread_name)
        self._udp2pointcloud_thread.start()
src/engine/__init__.py
@@ -1,8 +1,10 @@
from .AcquisitionMain import *
from .CaptureThread import *
from .ControllThread import *
from .DeviceManager import *
from .DustCleaner import *
from .DustCleanerThread import *
from .MessageQueueThread import *
from .MicroWaveUDPThread import *
# from .AcquisitionMain import *
# from .CaptureThread import *
# from .ControllThread import *
# from .DeviceManager import *
# from .DustCleaner import *
# from .DustCleanerThread import *
# from .MessageQueueThread import *
# from .MicroWaveUDPThread import *
# from .MessageThreads import *
# from .devices import *
src/engine/devices.py
New file
@@ -0,0 +1,239 @@
import cv2
import time
from typing import List, Union
import queue
# # add python path of src to sys.path
# src_path = os.path.join(__file__, *(['..'] * 2))
# src_path = os.path.abspath(src_path)
# sys.path.insert(0, src_path)
from .DustCleaner import DustCleaner
from .Microwave import micorwaveMannager
from .MessageThreads import send_logs_tool, send_images_tool, send_pointcloud_tool
######################################### CAMERAS ############################################
class cameraController(object):
    def __init__(self,
            IMAGE_WIDTH:int,
            IMAGE_HEIGHT:int,
            CAMERA_COUNT:int,
            device_id:str,
            logs_queue:queue.Queue,
            images_queue:queue.Queue,
            init_routing_key:str,
            init_binding_key:str,
            init_taskuuid:str = "init"
            ):
        self.IMAGE_WIDTH = IMAGE_WIDTH
        self.IMAGE_HEIGHT = IMAGE_HEIGHT
        self.CAMERA_COUNT = CAMERA_COUNT
        self.device_id = device_id
        self.logs_queue = logs_queue
        self.images_queue = images_queue
        self.routing_key = init_routing_key
        self.init_routing_key = init_routing_key
        self.binding_key = init_binding_key
        self.init_taskuuid = init_taskuuid
        self.taskuuid = init_taskuuid
        self._check_cameras()
    def _check_cameras(self):
        self.cameras = []
        self.camera_work = []
        self.working_ports = []
        test_logs = []
        test_images = []
        # init the cameras
        for dev_port in range(self.CAMERA_COUNT):
            # set the props of the camera by cv2 lib
            camera = cv2.VideoCapture(dev_port, cv2.CAP_DSHOW)
            camera.set(cv2.CAP_PROP_FRAME_WIDTH, self.IMAGE_WIDTH)
            camera.set(cv2.CAP_PROP_FRAME_HEIGHT, self.IMAGE_HEIGHT)
            camera.set(cv2.CAP_PROP_FPS, 1)
            self.cameras.append(camera)
            self.camera_work.append(False)
        # test the cameras
        (test_logs, test_images) = self._capture_image(mode = "test")
        # generate the msg and put it to queues
        self._generate_msg(test_logs,test_images)
    def _generate_msg(self,logs:List[str],images:List):
        send_logs_tool(logs=logs,
                        logs_queue=self.logs_queue,
                        source=self.device_id,
                        routing_key=self.routing_key+".logs.test0",
                        taskuuid=self.taskuuid)
        send_images_tool(images=images,
                        images_queue=self.images_queue,
                        source=self.device_id,
                        routing_key=self.routing_key+".images.test0",
                        taskuuid=self.taskuuid)
    def _capture_image(self,mode:str = "capture"):
        """
        mode -> "test" or "capture"
        """
        TEST = False
        if mode == "test":
            TEST = True
        else:
            pass
        log_list = []
        image_list = []
        # iterate the cameras
        for dev_port, camera in enumerate(self.cameras):
            # init the flags
            is_reading = False
            log = None
            img = None
            if not TEST and self.camera_work[dev_port] is not True:
                pass
            else:
                # capture the image
                if camera.isOpened():
                    is_reading, img = camera.read()
                    w = camera.get(3)
                    h = camera.get(4)
                    if is_reading:
                        log = f"camera port {dev_port} is working and reads images ({h} x {w})"
                    else:
                        log = f"camera port {dev_port} can not work"
                else:
                    log = f"camera port {dev_port} can not found"
                # display
                print(f"{time.asctime()} | {log}")
            # add some tags for camera when test
            if TEST:
                self.working_ports.append(dev_port)
                if is_reading:
                    self.camera_work[dev_port] = True
            log_list.append(log)
            image_list.append(img)
        return log_list, image_list
    def capture(self,routing_key:str, taskuuid:str):
        self.routing_key = routing_key
        self.taskuuid = taskuuid
        (logs,images) = self._capture_image()
        # generate the msg and put it to queues
        self._generate_msg(logs,images)
        self.routing_key = self.init_routing_key
        self.taskuuid = self.init_taskuuid
######################################## MICROWAVE ###########################################
class microwaveController(micorwaveMannager):
    def __init__(self,
            MicrowaveHost: str,
            MicrowavePort: int,
            init_packet_threshold: Union[int, None],
            init_timeusage_threshold: Union[int, float, None],
            device_id:str,
            logs_queue:queue.Queue,
            plys_queue:queue.Queue,
            init_routing_key:str,
            init_binding_key:str,
            init_taskuuid:str = "init"
            ):
        super().__init__(MicrowaveHost, MicrowavePort)
        self.device_id = device_id
        self.plys_queue = plys_queue
        self.routing_key = init_routing_key
        self.init_routing_key = init_routing_key
        self.binding_key = init_binding_key
        self.init_taskuuid = init_taskuuid
        self.taskuuid = init_taskuuid
        # testing the device when instance the class
        self._get_pointcloud(init_packet_threshold,init_timeusage_threshold)
    def _get_pointcloud(self,
                    packet_threshold:Union[int, None],
                    timeusage_threshold:Union[int, None]):
        self._udp_get_thread_launcher(packet_threshold,timeusage_threshold)
        self._udp2pointcloud_thread_launcher()
        self._generate_msg()
    def _generate_msg(self):
        send_pointcloud_tool(pointclouds=self.pointcloud_queue,
                            plys_queue=self.plys_queue,
                            source=self.device_id,
                            routing_key=self.routing_key+".plys.test0",
                            taskuuid=self.taskuuid)
    def scan(self,routing_key:str,taskuuid:str):
        # self.routing_key = routing_key
        # self.taskuuid = self.init_taskuuid
        # self._generate_msg()
        raise NotImplementedError
####################################### DUST CLEANER #########################################
class dustCleanerController(DustCleaner):
    def __init__(self, com, bps, timeout, logs_queue, device_id,
                init_routing_key:str,
                init_binding_key:str,
                init_taskuuid:str = "init"):
        super().__init__(com, bps, timeout)
        self.logs_queue = logs_queue
        self.device_id = device_id
        self.routing_key = init_routing_key
        self.init_routing_key = init_routing_key
        self.binding_key = init_binding_key
        self.init_taskuuid = init_taskuuid
        self.taskuuid = init_taskuuid
        self._check_cleaner()
    def _check_cleaner(self):
        success = self.Open()
        log = "Unknown log."
        if success:
            log = f"The port [{self.port}] refered to the dust cleaner is open."
        else:
            log = f"The port [{self.port}] refered to the dust cleaner can not open."
        # display
        print(f"{time.asctime()} | {log}")
        send_logs_tool(logs=[log],
                        logs_queue=self.logs_queue,
                        source = self.device_id,
                        routing_key=self.routing_key+".logs.test0")
    def clean(self,routing_key:str,taskuuid:str):
        raise NotImplementedError
src/microwave/__init__.py
@@ -1,5 +1,5 @@
from .components import *
from  .constants import *
from  .parsers import *
from  .servers import *
from .deviceTools import *
# from .components import *
# from  .constants import *
# from  .parsers import *
# from  .servers import *
# from .deviceTools import *
src/microwave/demo/AutoGetUDP.bat
@@ -2,19 +2,10 @@
@REM change to the filepath
cd %~dp0
echo change to path: %cd%
@REM add vitrual env python to the path
path "%~dp0/../../../../.env/Scripts/";%path%
set aerialpython=%cd%/../../../env/aerial_deploy/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
echo All data will be save in '%cd%/saveUDPData/' folder
%aerialpython% udp_test_get.py microwave
python udp_test_get.py microwave
echo =========== ALL DONE ================
src/microwave/demo/AutoGetUDPtest.bat
@@ -2,19 +2,12 @@
@REM change to the filepath
cd %~dp0
echo change to path: %cd%
set aerialpython=%cd%/../../../env/aerial_deploy/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
@REM add vitrual env python to the path
path "%~dp0/../../../../.env/Scripts/";%path%
echo All data will be saved in '%cd%/saveUDPData/' folder
%aerialpython% udp_test_get.py test
python udp_test_get.py test
echo =========== ALL GET DONE ================
src/microwave/demo/AutoSendAndGetTest.bat
@@ -2,15 +2,9 @@
@REM change to the filepath
cd %~dp0
echo change to path: %cd%
set aerialpython=%cd%/../../../env/aerial_deploy/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
@REM add vitrual env python to the path
path "%~dp0/../../../../.env/Scripts/";%path%
start AutoGetUDPtest.bat 
start AutoSendUDPtest.bat
src/microwave/demo/AutoSendUDPtest.bat
@@ -2,19 +2,12 @@
@REM change to the filepath
cd %~dp0
echo change to path: %cd%
set aerialpython=%cd%/../../../env/aerial_deploy/python.exe
set envsetting=%cd%/env/SettingEnv.bat
@REM Setting the env
if not exist %aerialpython% (
    call %envsetting%
)
@REM add vitrual env python to the path
path "%~dp0/../../../../.env/Scripts/";%path%
echo All data saved in '%cd%/demoUDPData/' folder will be sent to 127.0.0.1:9911
%aerialpython% udp_test_send.py
python udp_test_send.py
echo =========== ALL SEND DONE ================
src/microwave/deviceTools.py
@@ -1,48 +1,25 @@
import datetime
import queue
from socketserver import BaseRequestHandler, UDPServer
import time
import os, sys
import open3d as o3d
from multiprocessing import  Pool
import numpy as np
import threading
from ..utils import file_fliter, write_ply
from .servers import MicroWaveReceiver
from ..utils.tools import file_fliter, write_ply
from .servers import MicroWaveReceiver,MicroWaveUDPThread
from .parsers import MicroWaveParser
# # add python path of src to sys.path
# src_path = os.path.join(__file__, *(['..'] * 2))
# src_path = os.path.abspath(src_path)
# sys.path.insert(1, src_path)
# udp_get
class PointCloudUDPRequestHandler(BaseRequestHandler):
    def handle(self):
        packet_threshold = self.server.packet_threshold
        packed_count = self.server.packed_count
        path = self.server.path
        print(time.asctime(),' Got connection from {}, {}'.format(self.client_address, packed_count))
        # Get message and client socket
        msg, sock = self.request
        time_tag = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
        f = open('{}/{}_packet{}.udp'.format(path,time_tag,packed_count), 'wb')
        f.write(msg)
        f.close()
        self.server.packed_count += 1
        self.server.udp_list.append(msg)
        if packed_count >= packet_threshold:
            UDPServer.server_close(self.server)
def udp_get_tool(microwaveHost,packetThreshold,deviceName,saveFolder,subFolder):
    # host = ''
    # host = '192.168.2.65' # use this host to get the udp data from microwave device
    port = 9911
    server =UDPServer((microwaveHost, port), PointCloudUDPRequestHandler)
    udp_queue = queue.Queue()
    udp_get_stop = threading.Event()
    if subFolder is not None:
        path = os.path.join(saveFolder,subFolder)
@@ -52,23 +29,42 @@
    if not os.path.exists(path):
        os.makedirs(path)
    server.path = os.path.abspath(path)
    server.packet_threshold = packetThreshold
    server.packed_count = 0
    server.udp_list = []
    udp_thread = MicroWaveUDPThread(MicrowaveHost=microwaveHost,
                                MicrowavePort=port,
                                udp_queue=udp_queue,
                                udp_get_stop=udp_get_stop,
                                packet_threshold=packetThreshold,
                                timeusage_threshold=None)
    udp_thread.setDaemon(True)
    udp_thread.setName("UDPGet_Thread")
    print(time.asctime(),'Server started on port', port)
    print('....')
    print('ctrl-c to quit server.')
    try:
        server.serve_forever()
        udp_thread.start()
        run = True
        while run:
            packed_count = 0
            while not udp_queue.empty():
                value = udp_queue.get()
                if value is not False:
                    time_tag = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
                    with ('{}/{}_packet{}.udp'.format(path,time_tag,packed_count), 'wb') as f:
                        f.write(udp_queue.get())
                        packed_count += 1
                else:
                    run = False
    except KeyboardInterrupt:
        server.server_close()
        udp_get_stop.set()
        print(time.asctime(),"Server Stopped")
    except:
        server.server_close()
        print(time.asctime(),"Server Stopped")
    return server.udp_list
        udp_get_stop.set()
        print(time.asctime(),"Server Stopped with unknown reasons")
# udp2bin
def udp2bin_tool(udp_folder_Or_list):
@@ -81,7 +77,7 @@
    else:
        UDPfolder = udp_folder_Or_list
        # example pod1-2022-02-21-13-25-03_packet125.udp --> 125
        sort_lambda = lambda x:int(x.split('packet')[1][:-4])
        sort_lambda = lambda x:int(x.split('packet')[-1][:-4])
        udp_files = file_fliter(UDPfolder,'udp', sort_lambda)
        Save = True
src/microwave/parsers.py
@@ -1,5 +1,3 @@
from tkinter import Frame
from .components import *
from .constants import *
from ctypes import sizeof, string_at
src/microwave/servers.py
@@ -1,10 +1,16 @@
import os, sys
from ctypes import sizeof, string_at
from socketserver import BaseRequestHandler, UDPServer
# from socketserver import _AddressType, _RequestType, BaseRequestHandler, BaseServer, UDPServer
from socketserver import BaseRequestHandler, BaseServer, UDPServer
import threading
from typing import Union
import warnings
import time
import queue
import numpy as np
from .components import *
from .constants import *
from ..protos import aerial_pb2 as pb
from .parsers import MicroWaveParser
@@ -97,6 +103,7 @@
        buf_size = len(buf)
        if buf_size == sizeof(Handshake):
            self._is_handshake(buf)
            return # there is only handshake(24 bytes) on it, end AddBuf func.
        if self.state == UDP_STATE_HAND_SHAKE:
            # after received handshake packet, we can get header block 
@@ -104,7 +111,7 @@
                # make sure to get a complete header
                result = self._get_header(buf)
            except Exception as e:
                warnings.warn(f"encounter an unknow error {e} when getting the header data in udp packets ...")
                warnings.warn(f"encounter an unknow error [{e}] when getting the header data in udp packets ...")
                result = False
            if not result:
@@ -135,38 +142,170 @@
            self.DataFrame.extend(bytes(buf))
            self._receive_footer(buf)
class UDP2PointcloudThread(threading.Thread):
    def __init__(self,
                udp_queue:queue.Queue,
                pointcloud_queue:queue.Queue,
                    ):
        self.udp_queue = udp_queue
        self.pointcloud_queue = pointcloud_queue
        super().__init__()
    def run(self):
        receiver = MicroWaveReceiver()
        print(time.asctime(),"DP2Pointcloud Thread is starting to decode the udp packets... ")
        run = True
        while run:
            while not self.udp_queue.empty():
                udp = self.udp_queue.get()
                if udp is not False:
                    receiver.AddBuf(udp)
                    if receiver.DataFrameReady:
                        buf = receiver.DataFrame
                        buf_data = MicroWaveParser.ParserFrame(buf)
                        for frame in buf_data:
                            Frame_id = frame[0]
                            FrameNumber = frame[1]
                            point_cloud = np.array(frame[2])
                            if len(point_cloud) == 0 :
                                print(f"Notice: Frame {FrameNumber} is empty!")
                            else:
                                print(time.asctime(),f"Frame {FrameNumber} ready")
                                self.pointcloud_queue.put(point_cloud)
                else:
                    run = False
                    self.pointcloud_queue.put(False)
        print(time.asctime(),"DP2Pointcloud Thread finshed to decode the udp packets... ")
class MicroWaveRequestHandler(BaseRequestHandler):
    """
    micro wave udp request handler
    """
    def __init__(self,
        request,
        client_address,
        server: BaseServer) -> None:
        super().__init__(request, client_address, server)
    def handle(self):
        # Get message and client socket
        buf, _ = self.request
        receiver = self.server.Receiver
        # add buffer to receiver
        receiver.AddBuf(buf)
        if receiver.DataFrameReady:
            # dataframe ready, add to udp_queue
            msg = pb.RequestCommand()
            msg.sys_command = pb.SysCommand.MICRO_WAVE_COMMAND
            msg.sub_command = pb.SubCommand.MICRO_WAVE_SUB_COMMAND
            data1 = pb.MicroWaveMessage()
            data1.length = len(receiver.DataFrame)
            data1.data = bytes(receiver.DataFrame)
            data1_str = data1.SerializeToString()
            msg.data1.length = len(data1_str)
            msg.data1.data = data1_str
            self.server.msg_queue.put(msg)
        if not self.server.udp_get_stop.isSet():
            buf, _ = self.request
            packed_count = self.server.packed_count
            print(f"{time.asctime()} | Got connection from {self.client_address}, {packed_count}")
            self.server.udp_queue.put(buf)
            self.server.packed_count += 1
        # else:
        #     UDPServer.server_close(self.server)
        #     self.server.udp_queue.put(False)
        #     print(f"{time.asctime()} | UDP-Get server is stopped by thresholds or keyborad interrupt.")
class MicroWaveUDPServer(UDPServer):
    """
    micro wave udp server
    """
    def __init__(self, server_address, msg_queue):
        super().__init__(server_address, MicroWaveRequestHandler)
        # create receiver instance
        self.Receiver = MicroWaveReceiver()
        self.msg_queue = msg_queue
    def __init__(self,
            server_address: tuple[str,int],
            RequestHandlerClass: MicroWaveRequestHandler,
            udp_queue:queue.Queue,
            udp_get_stop:threading.Event,
            packet_threshold:Union[int, None],
            timeusage_threshold:Union[int, None]
            ) -> None:
        self.server_address = server_address
        self.RequestHandlerClass = MicroWaveRequestHandler
        self.udp_queue = udp_queue
        self.udp_get_stop = udp_get_stop
        self.udp_get_stop.clear()
        self.packet_threshold = packet_threshold
        self.timeusage_threshold = timeusage_threshold # mins
        self.packed_count = 0
        super().__init__(server_address, RequestHandlerClass)
        print(f"[*] | Listening on address {server_address}")
        # record start time of the server
        if self.timeusage_threshold is not None:
            self.start_time = time.time()
    def service_actions(self) -> None:
        # check to stop the server via muti-thresdhold
        if self.packet_threshold is not None and \
                self.packed_count >= self.packet_threshold:
            self.udp_get_stop.set()
        if self.timeusage_threshold is not None:
            cur_time = time.time() # seconds
            time_usage = int(cur_time - self.start_time)
            if time_usage > 60*self.timeusage_threshold:
                self.udp_get_stop.set()
        if self.udp_get_stop.isSet():
            print(f"{time.asctime()} | UDP-Get server is stopped by thresholds or keyborad interrupt.")
            self.udp_queue.put(False)
            self._BaseServer__shutdown_request = True
            # self.__is_shut_down.set()
class MicroWaveUDPThread(threading.Thread):
    def __init__(self,
                MicrowaveHost:str,
                MicrowavePort:int,
                udp_queue:queue.Queue,
                udp_get_stop:threading.Event,
                packet_threshold:Union[int, None],
                timeusage_threshold:Union[int, None]
                ):
        super().__init__()
        self.MicrowaveHost = MicrowaveHost
        self.MicrowavePort = MicrowavePort
        self.udp_queue = udp_queue
        self.udp_get_stop = udp_get_stop
        self.packet_threshold = packet_threshold
        self.timeusage_threshold = timeusage_threshold
    def stop(self):
        """stop the server to stop the """
        self.udp_get_stop.set()
    def run(self):
        logs_list = []
        server = MicroWaveUDPServer(server_address=(self.MicrowaveHost,self.MicrowavePort),
                                    RequestHandlerClass=MicroWaveRequestHandler,
                                    udp_queue=self.udp_queue,
                                    udp_get_stop=self.udp_get_stop,
                                    packet_threshold=self.packet_threshold,
                                    timeusage_threshold=self.timeusage_threshold
                                    )
        try:
            print(time.asctime(),"UDP Getting Server is starting to capture the udp packet... ")
            server.serve_forever()
            print(time.asctime(),"UDP Getting Server finshed to capture the udp packet ")
        except Exception as e:
            print(e)
            server.server_close()
            self.udp_get_stop.set()
            print(time.asctime(),"[ERROR] UDP Getting Server Stopped with Unknown Reason!")
src/protos/aerial.proto
@@ -1,153 +1,294 @@
syntax = "proto3";
enum SysCommand {
  UNKOWN_COMMAND     = 0;   // 未知命令
  SYS_COMMAND        = 1;   // 系统命令
  SENSOR_COMMAND     = 2;   // 传感器命令
  FIVE_G_COMMAND     = 3;   // 通讯5G模块命令
  CAMERA_COMMAND     = 4;   // 摄像头参数命令
  IO_COMMAND         = 5;   // 外设IO口操作命令
  SYS_PARAMS_COMMAND = 6;   // 系统参数获取
  WIFI_COMMAND       = 7;   // 设备WIFI参数设置
  KERNEL_COMMAND     = 8;   // 核心计算参数设
  DEVICE_COMMAND     = 9;   // 工作设备参数设置
  MICRO_WAVE_COMMAND = 10;  // 毫米波
}
// enum SysCommand {
//   UNKOWN_COMMAND     = 0;   // 未知命令
//   SYS_COMMAND        = 1;   // 系统命令
//   SENSOR_COMMAND     = 2;   // 传感器命令
//   FIVE_G_COMMAND     = 3;   // 通讯5G模块命令
//   CAMERA_COMMAND     = 4;   // 摄像头参数命令
//   IO_COMMAND         = 5;   // 外设IO口操作命令
//   SYS_PARAMS_COMMAND = 6;   // 系统参数获取
//   WIFI_COMMAND       = 7;   // 设备WIFI参数设置
//   KERNEL_COMMAND     = 8;   // 核心计算参数设
//   DEVICE_COMMAND     = 9;   // 工作设备参数设置
//   MICRO_WAVE_COMMAND = 10;  // 毫米波
// }
enum SubCommand {
  option allow_alias = true;
// enum SubCommand {
//   option allow_alias = true;
   
  UNKOWN_SUB_COMMAND   = 0;                   // 未知子命令
//   UNKOWN_SUB_COMMAND   = 0;                   // 未知子命令
  // 系统命令
  POWER_ON_SUB_COMMAND = 1;                   // 开机
  POWER_OFF_SUB_COMMAND = 2;                  // 关机
//   // 系统命令
//   POWER_ON_SUB_COMMAND = 1;                   // 开机
//   POWER_OFF_SUB_COMMAND = 2;                  // 关机
  // 传感器命令
  SENSOR_INIT_SUB_COMMAND = 1;                // 传感器初始化
  SENSOR_REQURE_SUB_COMMAND = 2;              // 传感器参数获取
  RTK_SETTING_SUB_COMMAND = 3;                // RTK外设参数设置
  RTK_REQURE_SUB_COMMAND = 4;                 // RTK外设数据获取
//   // 传感器命令
//   SENSOR_INIT_SUB_COMMAND = 1;                // 传感器初始化
//   SENSOR_REQURE_SUB_COMMAND = 2;              // 传感器参数获取
//   RTK_SETTING_SUB_COMMAND = 3;                // RTK外设参数设置
//   RTK_REQURE_SUB_COMMAND = 4;                 // RTK外设数据获取
  // 通讯5G模块命令
  FIVE_G_INIT_SUB_COMMAND = 1;                // 5G模块参数初始化
  FIVE_G_SEND_IMAGE_SUB_COMMAND = 2;          // 5G通讯图像数据发送
  FIVE_G_REQURE_SUB_COMMAND = 3;              // 5G通讯接收
//   // 通讯5G模块命令
//   FIVE_G_INIT_SUB_COMMAND = 1;                // 5G模块参数初始化
//   FIVE_G_SEND_IMAGE_SUB_COMMAND = 2;          // 5G通讯图像数据发送
//   FIVE_G_REQURE_SUB_COMMAND = 3;              // 5G通讯接收
  // 摄像头参数命令
  CAMERA_NUMBER_SUB_COMMAND = 1;              // 设备摄像头个数
  CAMERA_RESOLUTION_SUB_COMMAND = 2;          // 设备摄像头工作分辨率
  CAMERA_FRAME_RATE_SUB_COMMAND = 3;          // 摄像头工作帧率
  CAMERA_OTHER_PARAMS_SUB_COMMAND = 4;        // 摄像头工作其他参数
//   // 摄像头参数命令
//   CAMERA_NUMBER_SUB_COMMAND = 1;              // 设备摄像头个数
//   CAMERA_RESOLUTION_SUB_COMMAND = 2;          // 设备摄像头工作分辨率
//   CAMERA_FRAME_RATE_SUB_COMMAND = 3;          // 摄像头工作帧率
//   CAMERA_OTHER_PARAMS_SUB_COMMAND = 4;        // 摄像头工作其他参数
  // 外设IO口操作命令
  CAMERA_DUST_REMOVAL_START_SUB_COMMAND = 1;  // 摄像头除尘启动
  CAMERA_CONTROL_START_SUB_COMMAND = 2;       // 外设控制数据启动(18路控制)
//   // 外设IO口操作命令
//   CAMERA_DUST_REMOVAL_START_SUB_COMMAND = 1;  // 摄像头除尘启动
//   CAMERA_CONTROL_START_SUB_COMMAND = 2;       // 外设控制数据启动(18路控制)
  // 系统参数获取
  CPU_FREQUENCY_SUB_COMMAND = 1;              // CPU主频工作数据
  CPU_KERNAL_TEMP_SUB_COMMAND = 2;            // CPU核心温度数据
  CPU_BETTERY_DATA_SUB_COMMAND = 3;           // 电池供电电量数据
//   // 系统参数获取
//   CPU_FREQUENCY_SUB_COMMAND = 1;              // CPU主频工作数据
//   CPU_KERNAL_TEMP_SUB_COMMAND = 2;            // CPU核心温度数据
//   CPU_BETTERY_DATA_SUB_COMMAND = 3;           // 电池供电电量数据
  // 设备WIFI参数设置
  WIFI_HOTSPOT_SETTING_SUB_COMMAND = 1;       // WIFI热点设置
  WIFI_HOTSPOT_START_STOP_SUB_COMMAND = 2;    // WIFI热点开启和关闭
//   // 设备WIFI参数设置
//   WIFI_HOTSPOT_SETTING_SUB_COMMAND = 1;       // WIFI热点设置
//   WIFI_HOTSPOT_START_STOP_SUB_COMMAND = 2;    // WIFI热点开启和关闭
  // 核心计算参数设置
  POINT_CLOUD_ACCURACY_SUB_COMMAND = 1;       // 点云计算精度
  SPLICING_PARAMS_SUB_COMMAND = 2;            // 拼接参数
  MAP_INTERFACE_PLATFORM_SUB_COMMAND = 3;     // 地图接口平台
  DATA_STORE_BACKUP_SUB_COMMAND = 4;          // 数据存储备份
//   // 核心计算参数设置
//   POINT_CLOUD_ACCURACY_SUB_COMMAND = 1;       // 点云计算精度
//   SPLICING_PARAMS_SUB_COMMAND = 2;            // 拼接参数
//   MAP_INTERFACE_PLATFORM_SUB_COMMAND = 3;     // 地图接口平台
//   DATA_STORE_BACKUP_SUB_COMMAND = 4;          // 数据存储备份
  // 工作设备参数设置
  SYSTEM_TIMER_SUB_COMMAND = 1;               // 系统工作定时
  SYSTEM_COORD_HEIGHT_SUB_COMMAND = 2;        // 工作区域坐标与高度
  TRIGGER_CONDITION_SUB_COMMAND = 3;          // 工作触发条件
  GRAVITY_FAILURE_SUB_COMMAND = 4;            // 重力加速度失效参数
  NINE_AXIS_FAILURE_SUB_COMMAND = 5;          // 九轴加速度失效参数
//   // 工作设备参数设置
//   SYSTEM_TIMER_SUB_COMMAND = 1;               // 系统工作定时
//   SYSTEM_COORD_HEIGHT_SUB_COMMAND = 2;        // 工作区域坐标与高度
//   TRIGGER_CONDITION_SUB_COMMAND = 3;          // 工作触发条件
//   GRAVITY_FAILURE_SUB_COMMAND = 4;            // 重力加速度失效参数
//   NINE_AXIS_FAILURE_SUB_COMMAND = 5;          // 九轴加速度失效参数
  // 毫米波
  MICRO_WAVE_SUB_COMMAND = 1;                 // 毫米波
//   // 毫米波
//   MICRO_WAVE_SUB_COMMAND = 1;                 // 毫米波
// }
// message DataField {
//   int32 length = 1;                           // 数据长度
//   bytes data = 2;                            // 数据内容
//   int32 checksum = 3;                        // 校验码
// }
// message CapturedData {
//   int64 capture_time = 1;                     // 采集时间
//   string capture_device =2;                   // 采集设备
//   int32 capture_port = 3;                     // 采集设备序号
//   DataField DataField = 4;
//   string data_type = 5;                         // 数据类型 image udp
// }
// message DataMessage{
//   int64 sending_time = 1;
//   string sending_device = 2;
//   string target_device = 3;
//   CapturedData CapturedData = 5;
// }
// message StateData {
//  int64 state_time = 1;
//  string state_device = 2;
//  DataField DataField = 4;
// }
// message StateMessage {
//   int64 sending_time = 1;
//   string sending_device = 2;
//   string target_device = 3;
//   CapturedData StatedData = 5;
// }
// message CommandData {
//   SysCommand SysCommand = 1;
//   SubCommand SubCommand = 2;
// }
// message CommandMessage {
//   int64 sending_time = 1;
//   string sending_device = 2;
//   string target_device = 3;
//   CommandData CommandData =4;
// }
enum SysCommand{
  UNKOWN_COMMAND     = 0;
  CAMERA_COMMAND     = 1;
  MICROWAVE_COMMAND   = 2;
  DUSTCLEANER_COMMAND   = 3;
}
message DataField {
  int32 length = 1;                           // 数据长度
  bytes data = 2;                            // 数据内容
  int32 checksum = 3;                        // 校验码
enum SubCommand{
  UNKOWN_SUBCOMMAND     = 0;
  // camera params
  ONE_TIME_CAPTURE      = 1;
  // microwave params
  ONE_CIRCLE_SCAN       = 2;
  // dust cleaner params
  ONE_CLEAN_SCAN        = 4;
}
message CommandMessage{
  string source = 1;
  string generatetime = 2;
  SysCommand syscommand = 3;
  SubCommand subcommand = 4;
  string targetclient = 5;
  string returnserver = 6;
  string taskuuid = 7;
}
message LogsMessage{
  string source = 1;
  string timestamp = 2;
  string context = 3;
  optional string taskuuid = 4;
}
message ImagesMessage
{
  bytes image1  = 1;
  bytes image2  = 2;
  bytes image3  = 3;
  bytes image4  = 4;
  bytes image5  = 5;
  string source = 1;
  string timestamp = 2;
  message ImageItems
  {
    int32 length = 1;                           // 数据长度
    bytes data = 2;                            // 数据内容
  }
  repeated ImageItems Image = 3;
  optional string taskuuid = 4;
}
message MicroWaveMessage
message PlysMessage
{
  int32 length = 1;                           // 数据长度
  bytes data = 2;                            // 数据内容
}
  string source = 1;
  string timestamp = 2;
message RequestCommand {
  int32 sync_word = 1;              // 同步字
  string device_id = 2;             // 设备ID
  SysCommand sys_command = 3;       // 命令1
  SubCommand sub_command = 4;       // 命令2
  DataField data1 = 5;              // 数据1
  DataField data2 = 6;              // 数据2
  int32 checksum = 7;               // 校验码
}
  message PointCloudItem
  {
    int32 length = 1;
    int32 rows = 2;
    int32 cols = 3;
    string order = 4;
    string dtype = 5;
    bytes data = 6;
  }
enum ResponseState
{
  SUCCESS = 0;                  // 成功
  FAILURE = 1;                  // 失败
  ABNORMAL = 2;                 // 异常
  INFICIENT_POWER = 3;          // 电量不足
  OTHER = 4;                    // 其他
}
  repeated PointCloudItem Plydata = 3;
  optional string taskuuid = 4;
message ResponseCommand
{
    string device_id = 1;        // 设备ID
    SysCommand sys_command = 2;  // 命令1
    SubCommand sub_command = 3;  // 命令2
    ResponseState state = 4;     // 响应状态
    int32 data_length = 5;       // 数据长度
    bytes data = 6;              // 数据
    int32 checksum = 7;          // 校验码
  // enum ref_system
  // {
  //   MICROWAVE_SYSTEM = 0;
  //   DEVICE_SYSTEM = 1;
  // }
  // ref_system reference = 4
}
// 服务端向采集端发送的主指令
enum ControlSysCommand {
  DUST_CLEANER_COMMAND = 0;
}
// 服务端向采集端发送的子命令
enum ControlSubCommand {
  // dust cleaner sub commands
  DUST_CLEANER_ONETIME_CLEAN_SELF         = 0;
  DUST_CLEANER_ONETIME_CLEAN_CAMERA       = 1;
  DUST_CLEANER_CLOSE_PERIOD_CLEAN_SELF    = 2;
  DUST_CLEANER_CLOSE_PERIOD_CLEAN_CAMERA  = 3;
  DUST_CLEANER_PERIOD_CLEAN_SELF          = 4;
  DUST_CLEANER_PERIOD_CLEAN_CAMERA        = 5;
}
// dust cleaner command message
message DustCleanerMessage  {
  uint32 period = 1;
}
// 控制上位机消息
message ControllMessage {
  int32 sync_word = 1;                // 同步字
  ControlSysCommand sys_command = 3;  // 主命令
  ControlSubCommand sub_command = 4;  // 子命令
  DataField data = 5;                 // 数据
  int32 checksum = 7;                 // 校验码
}
// message MicroWaveMessage
// {
//   int32 length = 1;                           // 数据长度
//   bytes data = 2;                            // 数据内容
// }
// message CommandRequest{
// }
// message StateMessage{
//   string message_type = 1;
//   int64 generate_time = 2;
//   string generate_device = 3;
//   string target_device = 4;
//   string message_uuid = 5;
//   string str_body = 6;
// }
// message RequestCommand {
//   int32 sync_word = 1;              // 同步字
//   string device_id = 2;             // 设备ID
//   SysCommand sys_command = 3;       // 命令1
//   SubCommand sub_command = 4;       // 命令2
//   DataField data1 = 5;              // 数据1
//   DataField data2 = 6;              // 数据2
//   int32 checksum = 7;               // 校验码
// }
// enum ResponseState
// {
//   SUCCESS = 0;                  // 成功
//   FAILURE = 1;                  // 失败
//   ABNORMAL = 2;                 // 异常
//   INFICIENT_POWER = 3;          // 电量不足
//   OTHER = 4;                    // 其他
// }
// message ResponseCommand
// {
//     string device_id = 1;        // 设备ID
//     SysCommand sys_command = 2;  // 命令1
//     SubCommand sub_command = 3;  // 命令2
//     ResponseState state = 4;     // 响应状态
//     int32 data_length = 5;       // 数据长度
//     bytes data = 6;              // 数据
//     int32 checksum = 7;          // 校验码
// }
// // 服务端向采集端发送的主指令
// enum ControlSysCommand {
//   DUST_CLEANER_COMMAND = 0;
// }
// // 服务端向采集端发送的子命令
// enum ControlSubCommand {
//   // dust cleaner sub commands
//   DUST_CLEANER_ONETIME_CLEAN_SELF         = 0;
//   DUST_CLEANER_ONETIME_CLEAN_CAMERA       = 1;
//   DUST_CLEANER_CLOSE_PERIOD_CLEAN_SELF    = 2;
//   DUST_CLEANER_CLOSE_PERIOD_CLEAN_CAMERA  = 3;
//   DUST_CLEANER_PERIOD_CLEAN_SELF          = 4;
//   DUST_CLEANER_PERIOD_CLEAN_CAMERA        = 5;
// }
// // dust cleaner command message
// message DustCleanerMessage  {
//   uint32 period = 1;
// }
// // 控制上位机消息
// message ControllMessage {
//   int32 sync_word = 1;                // 同步字
//   ControlSysCommand sys_command = 3;  // 主命令
//   ControlSubCommand sub_command = 4;  // 子命令
//   DataField data = 5;                 // 数据
//   int32 checksum = 7;                 // 校验码
// }
src/protos/compile.bat
@@ -3,8 +3,9 @@
@REM change to the filepath
cd %~dp0
set protoc=%cd%/../../.env/Library/bin/protoc.exe
path "%~dp0/../../.env/Scripts";%path%
@REM call "%cd%/../../.env/Scripts/activate.bat"
%protoc% aerial.proto --python_out=%cd%
python -m protoc aerial.proto --python_out=%cd%
echo protoc: aerial.proto compile done!
src/requirements.yaml
File was deleted
src/slam/__init__.py
@@ -1,3 +1,3 @@
from .core import *
from .manualMode import *
from .autoMode import *
# from .core import *
# from .manualMode import *
# from .autoMode import *
src/utils/__init__.py
@@ -1 +1 @@
from .tools import *
# from .tools import *
src/utils/slam.py
New file
@@ -0,0 +1,52 @@
import numpy as np
from .tools import read_ply
def get_rotation_matrix(angle:str):
    """generate a rotation matrix from the specific angel,
        the angle is the degree that coordinate system B rotated from coordinate A
        in direction from x to y  with z is the axis.
    Args:
        angle (str): the angle, value in [-360,360]
    Returns:
        rotation_matrix (np.array): the rotation matrix
    """
    if np.abs(float(angle))>360:
        raise ValueError(f"incorrect angle value: value in [-360,360] is excepted, but {angle} is offered.")
    angle_float = np.pi * float(angle) / 180
    rotation_matrix = np.array(
        [[np.cos(angle_float,), np.sin(angle_float), 0.],
        [-np.sin(angle_float), np.cos(angle_float), 0.],
        [0., 0., 1.]],
        dtype=np.float16
    )
    return rotation_matrix
def compose_ply(muti_ply_with_angle: list):
    ply_nums = len(muti_ply_with_angle)
    composed_ply_List = []
    for ply_with_angle in muti_ply_with_angle:
        angle = ply_with_angle[0]
        ply = ply_with_angle[1]
        if isinstance(ply,str):
            ply = read_ply(ply)
        rotation_matrix = get_rotation_matrix(angle)
        rotated_ply = np.matmul(rotation_matrix,ply)
        composed_ply_List.append(rotated_ply)
    composed_ply_array = np.array(composed_ply_List).reshape(-1,3)
    return composed_ply_array
if __name__ == "__main__":
    m = get_rotation_matrix('180')
    print(m)
src/utils/tools.py
@@ -1,8 +1,8 @@
from email import header
import os, sys
import numpy as np
import time
from tqdm import tqdm
from datetime import datetime
def file_fliter(folder:str, file_ext:str, sort_format = None):
@@ -76,10 +76,27 @@
                header="".join(header),
                comments="",
                fmt=fmt)
    print(f"{time.asctime()} {name}.ply have been saved with {n_p} points!")
    print(f"{time.asctime()} | {name}.ply have been saved with {n_p} points!")
def update_folder_for_today(folder_tree:dict[str,str]):
    """
    "sup_folder" + "today" +"sub_folder" >> "today_folder"
    """
    try:
        sup = folder_tree["sup_folder"]
        sub = folder_tree["sub_folder"]
        today = datetime.now().strftime('%Y-%m-%d')
        today_folder = os.path.join(sup,today,sub)
        folder_tree["today"] = today
        folder_tree["today_folder"] = today_folder
    except Exception as e:
        raise ValueError(f"{e}")
if __name__ == "__main__":
    ply_array = read_ply('src\\microwave\\demo\\demoData\\2522.ply')