wu_xinjun
2022-02-21 877d5c2499ceb567b8f5d7c00e7fd59b11458782
Merge commit '8c2322adaed3d4374a7524bdb9ae8fb27f74fe7f'
11个文件已删除
101 文件已重命名
52个文件已添加
4个文件已修改
3628 ■■■■ 已修改文件
.gitignore 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/launch.json 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/settings.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_bin2ply.bat 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_ply_show .bat 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_startClient.bat 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_startServer.bat 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_udp2bin.bat 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_udp2ply.bat 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TEST_udp_get.bat 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin2ply.BAT 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/ExportEnv.bat 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/JustDoubleClickMe.bat 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env/SettingEnv.bat 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ply_show.bat 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/compile.bat 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/CameraTest/CameraTest.py 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/CameraTest/Images/.gitignore 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Client.py 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Client/AerialClient.py 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Client/Client.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Client/MicroWaveParser.py 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/__init__.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/components.py 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/constants.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/AutoGetUDP.bat 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/AutoGetUDPtest.bat 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/AutoSendAndGetTest.bat 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/AutoSendUDPtest.bat 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/MicroWave2Ply.py 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/MicroWaveReceiverTest.py 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/MicroWaveUDPServerTest.py 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet0.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet1.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet10.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet11.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet12.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet13.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet14.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet15.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet16.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet17.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet18.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet19.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet2.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet20.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet21.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet22.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet23.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet24.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet25.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet26.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet27.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet28.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet29.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet3.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet30.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet31.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet32.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet33.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet34.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet35.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet36.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet37.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet38.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet39.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet4.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet40.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet41.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet42.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet43.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet44.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet45.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet46.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet47.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet48.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet49.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet5.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet50.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet51.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet52.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet53.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet54.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet55.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet56.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet57.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet58.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet59.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet6.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet60.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet61.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet62.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet63.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet64.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet65.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet66.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet67.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet68.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet69.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet7.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet70.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet71.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet72.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet73.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet74.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet75.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet76.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet77.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet78.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet79.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet8.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet80.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet81.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet82.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet83.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet84.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet85.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet86.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet87.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet88.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet89.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet9.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet90.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet91.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet92.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet93.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet94.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet95.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet96.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet97.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet98.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/demoData/packet99.udp 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/polty.ipynb 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/udp_test_get.py 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/demo/udp_test_send.py 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/parsers.py 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Microwave/servers.py 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Server.py 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Server/Server.py 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config.json 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/AcquisitionMain.py 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/CaptureThread.py 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/ControllThread.py 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/DeviceManager.py 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/DustCleaner.py 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/DustCleanerThread.py 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/MessageQueueThread.py 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/MicroWaveUDPThread.py 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/engine/__init__.py 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/protos/aerial.proto 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/protos/compile.bat 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/requirements.yaml 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udp_test/ParserTest.py 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udp_test/parser.py 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udp_test/send.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udp_test/udp.py 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/__init__.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/bin2ply.py 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/plot_ply.py 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/tools.py 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/udp2bin.py 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/udp_get.py 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
startClient.bat 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
startServer.bat 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
udp2bin.bat 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
udp2ply.bat 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
udp_get.bat 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -1,142 +1,22 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# cache
**/__pycache__/
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
/*.udp
.vs
# proto
src/protos/aerial_pb2.py
# env
env/aerial_deploy
env/*.gz
# demodata
src/microwave/demo/saveUdPData/
# data & image & microwave
Data
Images
Microwaves
Manual_Microwave*
# log
*.log
.vscode/launch.json
@@ -5,34 +5,86 @@
    "version": "0.2.0",
    "configurations": [
        {
            "name": "udp server test",
            "name": "Client_local",
            "type": "python",
            "request": "launch",
            "program": "src/udp_test/udp.py",
            "program": "${workspaceFolder}/src/Client.py",
            "args": [
                "localhost",
                "chai",
                "password123",
                "aerial_rpc",
                "pod1",
                "http://localhost/api",
                "localhost"
            ],
            "console": "integratedTerminal"
        },
        {
            "name": "Python: 当前文件",
            "name": "Client_production",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "program": "${workspaceFolder}/src/Client.py",
            "args": [
                "172.17.17.206",
                "chai",
                "password123",
                "aerial_rpc",
                "pod1",
                "http://172.17.17.206/api",
                "192.168.2.65"
            ],
            "console": "integratedTerminal"
        },
        {
            "name": "Python: Flask-Server",
            "name": "Server_local",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/src/Server/Server.py",
            "console": "integratedTerminal",
            "cwd": "${workspaceFolder}/src/Server"
            "program": "${workspaceFolder}/src/Server.py",
            "args": [
                "localhost",
                "chai",
                "password123",
                "aerial_rpc",
                "5000",
                "./Images"
            ],
            "console": "integratedTerminal"
        },
        {
            "name": "Python: parser",
            "name": "Server_production",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/src/Client/ParserTest.py",
            "console": "integratedTerminal",
            "cwd": "${workspaceFolder}/src/Client"
            "program": "${workspaceFolder}/src/Server.py",
            "args": [
                "172.17.17.206",
                "chai",
                "password123",
                "aerial_rpc",
                "5000",
                "./Images"
            ],
            "console": "integratedTerminal"
        },
        {
            "name": "udp2bin",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/src/utils/udp2bin.py",
            "args": [
                "./Manual_Microwave/pod1-2022-02-21-15-34-45/"
            ],
            "console": "integratedTerminal"
        },
        {
            "name": "bin2ply",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/src/utils/bin2ply.py",
            "args": [
                "./Manual_Microwave/pod1-2022-02-21-15-34-45/"
            ],
            "console": "integratedTerminal"
        }
    ]
}
.vscode/settings.json
@@ -7,5 +7,13 @@
            "--proto_path=${workspaceRoot}/proto",
            "--python_out=${workspaceRoot}/src/protos"
        ]
    }
    },
    "python":{
    },
    "jupyter.kernels.filter": [
        {
            "type": "jupyterKernelspec",
            "path": "${workspaceFolder}/env/aerial_deploy/python.exe"
        }
    ]
}
README.md
@@ -7,25 +7,12 @@
## 创建环境
```
    conda create -n aerial python=3.9
    conda install --name aerial flask pika protobuf requests
    conda activate aerial
    pip install pika opencv-contrib-python
Just click ```JustDoubleClickMe.bat``` file to auto setiing the env, which is located in the ```env``` folder.
## 运行采集端
```
## 运行采集端
```
    cd src/Client
    python Client.py
```
Double click to run  ```startClient.bat```
## 运行服务端
```
    cd src/Server
    python Server.py
```
Double click to run  ```startServer.bat```
TEST_bin2ply.bat
New file
@@ -0,0 +1,19 @@
@echo off
@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%
)
set BINfolder=./Manual_Microwave_test/pod1-2022-02-21-15-34-45/
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./src/utils/bin2ply.py %BINfolder%
pause
TEST_ply_show .bat
New file
@@ -0,0 +1,18 @@
@echo off
@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%
)
set PLYfile=./Manual_Microwave_test/pod1-2022-02-21-15-34-45/2522.ply
@REM -------------- Usage: plot_ply.py [PLYfile]"
%aerialpython% ./src/utils/plot_ply.py %PLYfile%
pause
TEST_startClient.bat
New file
@@ -0,0 +1,30 @@
@echo off
@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%
)
set MQhost=localhost
set MQuser=chai
set MQpassword=password123
set QUEUEname=aerial_rpc
set DEVICEname=pod1
set SERVERhost=http://localhost/api
set MICROWAVEhost=localhost
set LOGfile=ClientTEST.log
@REM Launch the Client
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%
echo Client.py has been terminited.
pause
TEST_startServer.bat
New file
@@ -0,0 +1,31 @@
@echo off
@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%
)
set MQhost=localhost
set MQuser=chai
set MQpassword=password123
set QUEUEname=aerial_rpc
set WEBport=5000
set SAVEfolder=./ImagesTEST
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% ./src/Server.py %MQhost% %MQuser% %MQpassword% %QUEUEname% %WEBport% %SAVEfolder% >> %LOGfile%
echo Server.py has been terminited.
pause
TEST_udp2bin.bat
New file
@@ -0,0 +1,19 @@
@echo off
@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%
)
set UDPfolder=./Manual_Microwave_test/pod1-2022-02-21-15-34-45/
@REM ---------------Usage: udp2bin.py [UDPfolder]
%aerialpython% ./src/utils/udp2bin.py %UDPfolder%
pause
TEST_udp2ply.bat
New file
@@ -0,0 +1,21 @@
@echo off
@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%
)
set UDPfolder=./Manual_Microwave_test/pod1-2022-02-21-15-34-45/
@REM ---------------Usage: udp2bin.py [UDPfolder]
%aerialpython% ./src/utils/udp2bin.py %UDPfolder%
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./src/utils/bin2ply.py %UDPfolder%
pause
TEST_udp_get.bat
New file
@@ -0,0 +1,21 @@
@echo off
@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%
)
set MICROWAVEhost=172.17.17.206
SET PACKETthreshold=100
SET DEVICEname=pod1
SET SAVEfolder=./Manual_Microwave_test
@REM ---------------Usage: udp_get.py [MICROWAVEhost] [PACKETthreshold] [DEVICEname] [SAVEfolder]
%aerialpython% ./src/utils/udp_get.py %MICROWAVEhost% %PACKETthreshold% %DEVICEname% %SAVEfolder%
pause
bin2ply.BAT
New file
@@ -0,0 +1,19 @@
@echo off
@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 please the folder path of the bin files.
@REM set BINfolder=./Manual_Microwave/pod1-2012-12-12-12-12-12/
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./src/utils/bin2ply.py %BINfolder%
pause
env/ExportEnv.bat
New file
@@ -0,0 +1,10 @@
@echo off
@REM change to the filepath
cd %~dp0
echo change to path: %cd%
echo Exporting env ...
conda pack -o aerial.tar.gz
echo Done!
env/JustDoubleClickMe.bat
New file
@@ -0,0 +1,14 @@
@echo off
cd %~dp0
echo ========== Setting Env ==============
call SettingEnv.bat
echo setting done!
echo ========== Testing Env ==============
echo test it with hello word...
set aerialpython=%cd%/aerial_deploy/python.exe
%aerialpython% -c "import cv2, pika, flask, pika; print('hello world!')"
echo =========== ALL DONE ================
echo Press any key to exit this windiow.
pause
env/SettingEnv.bat
New file
@@ -0,0 +1,19 @@
@echo off
@REM change to the filepath
cd %~dp0
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!
)
mkdir aerial_deploy
echo setting the env ...
tar -xzf ./aerial.tar.gz -C %cd%/aerial_deploy
echo ALL DONE!
ply_show.bat
New file
@@ -0,0 +1,19 @@
@echo off
@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 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% ./src/utils/plot_ply.py %PLYfile%
pause
proto/compile.bat
File was deleted
src/CameraTest/CameraTest.py
File was deleted
src/CameraTest/Images/.gitignore
File was deleted
src/Client.py
New file
@@ -0,0 +1,52 @@
import signal
import os, sys
batfile_dir = os.path.join(__file__, "..", "protos/compile.bat" )
batfile_path = os.path.abspath(batfile_dir)
os.system(batfile_path)
from engine.AcquisitionMain import AcquisitionMain
from engine.AcquisitionMain import Config
def quit(signum, frame):
    print('You choose to stop me.')
    sys.exit()
if __name__ == '__main__':
    def help():
        print("Usage: Client.py [MQhost] [MQuser] [MQpassword] [QUEUEname] [DEVICEname] [SERVERhost] [MICROWAVEhost]")
        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:
        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])
    except Exception as e:
        print(e)
        help()
    print("Start AcquisitionMain")
    signal.signal(signal.SIGINT, quit)
    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__, "..", "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()
src/Client/AerialClient.py
File was deleted
src/Client/Client.py
File was deleted
src/Client/MicroWaveParser.py
File was deleted
src/Microwave/__init__.py
New file
@@ -0,0 +1,4 @@
from .components import *
from  .constants import *
from  .parsers import *
from  .servers import *
src/Microwave/components.py
New file
@@ -0,0 +1,172 @@
from ctypes import Structure, c_ubyte, c_uint16, c_uint32, c_int16
from bitarray import bitarray, util
import math
"""
    UDP packets 0  --> ... --> UDP packets n
Handshake --> HeaderBlock --> DetectionBlock --> TrackerBlock --> FooterBlock
"""
class Handshake(Structure):
    """
    Handshake structure, 24 bytes
    """
    _pack_ = 1
    _fields_ = [
        ('Magic', c_ubyte*8),
        ('FrameDataLength', c_uint32),
        ('Reserved', c_ubyte * 12)
        ]
class HeaderBlock(Structure):
    """
    Header structure, 48 bytes
    """
    _pack_ = 1
    _fields_ = [
        ('Magic', c_ubyte * 8),             # [2 1 4 3 6 5 8 7]
        ('FrameNumber', c_uint32),          # frame number
        ('VersionNumber', c_uint32),        # Version number, uint32_t format: MMddhhmm
        ('NumberOfDetection', c_uint16),    # Number of Detection in the frame
        ('NumberOfTrack', c_uint16),        # Number of Detection in the frame
        ('HostSpeed', c_uint16),            # divide by 100 to get ego speed in m/s (e.g. 6453 = 64.53 m/s, e.g. -2456 = -24.56 m/s)
        ('HostAngle', c_uint16),            # divide by 100 to get host angle in degree. Clockwise rotation corresponds to positive rotation.(e.g. 1400 = 14 deg)
        ('Reserved', c_ubyte * 8),
        ('RangeAccuracyIdx', c_uint16),     # divide by 10000 to get value in m
        ('DopplerAccuracyIdx', c_uint16),   # divide by 10000 to get value in m/s
        ('AzimuthAccuracyIdx', c_uint16),   # divide by 10000 to get value in degree
        ('ElevationAccuracyIdx', c_uint16), # divide by 10000 to get value in degree
        ('DspWorkload', c_ubyte),
        ('ARMWorkload', c_ubyte),
        ('Reserved2', c_ubyte * 6),
    ]
    def __new__(cls, buf):
        # new instance from buf
        return cls.from_buffer_copy(buf)
    def __init__(self, data):
        # claculate parameters
        self.RangeAccuracy = self.RangeAccuracyIdx / 10000.0
        self.DopplerAccuracy = self.DopplerAccuracyIdx / 10000.0
        self.AzimuthAccuracy = self.AzimuthAccuracyIdx / 10000.0
        self.ElevationAccuracy = self.ElevationAccuracyIdx / 10000.0
class FooterBlock(Structure):
    """
    Footer structure, 32 bytes
    """
    _pack_ = 1
    _fields_ = [
        ('Reserved1', c_ubyte * 8),
        ('RangeAccuracyIdx', c_uint16),         # divide by 10000 to get value in m
        ('DopplerAccuracyIdx', c_uint16),       # divide by 10000 to get value in m
        ('AzimuthAccuracyIdx', c_uint16),       # divide by 10000 to get value in degree
        ('ElevationAccuracyIdx', c_uint16),     # divide by 10000 to get value in degree
        ('Reserved2', c_ubyte * 16),
    ]
    def __new__(cls, buf):
        # new instance from buf
        return cls.from_buffer_copy(buf)
    def __init__(self, data):
        # claculate parameters
        self.RangeAccuracy = self.RangeAccuracyIdx / 10000.0
        self.DopplerAccuracy = self.DopplerAccuracyIdx / 10000.0
        self.AzimuthAccuracy = self.AzimuthAccuracyIdx / 10000.0
        self.ElevationAccuracy = self.ElevationAccuracyIdx / 10000.0
class DetectionBlock:
    """
    Detection structure
    using bitarray parse structure because of ctypes can't parse compact bitfields
    """
    def __init__(self, header: HeaderBlock, footer: FooterBlock, data):
        buf = bytearray(data)
        buf.reverse()
        bits = bitarray()
        bits.frombytes(bytes(buf))
        # print(bits)
        # parse data structure
        self.Flag = bits[1]
        self.RangeIndex = util.ba2int(bits[54:64])
        self.DropplerIndex = util.ba2int(bits[45:54])
        if bits[44]:
            self.DropplerIndex -= 512
        self.AzimuthIndex = util.ba2int(bits[35:44])
        if bits[34]:
            self.AzimuthIndex -= 512
        self.BetaIndex = util.ba2int(bits[25:34])
        if bits[24]:
            self.BetaIndex -= 512
        self.PowerValue = util.ba2int(bits[8:24])
        if not self.Flag:
            # using header's parameters
            RangeAccuracy = header.RangeAccuracy
            DopplerAccuracy = header.DopplerAccuracy
            AzimuthAccuracy = header.AzimuthAccuracy
            ElevationAccuracy = header.ElevationAccuracy
        else:
            # using footer's parameters
            RangeAccuracy = footer.RangeAccuracy
            DopplerAccuracy = footer.DopplerAccuracy
            AzimuthAccuracy = footer.AzimuthAccuracy
            ElevationAccuracy = footer.ElevationAccuracy
        # claculation
        self.Power = self.PowerValue / 100.0
        self.Range = self.RangeIndex * RangeAccuracy
        self.Doppler = self.DropplerIndex * DopplerAccuracy
        self.Beta = self.BetaIndex * ElevationAccuracy
        self.Azimuth = self.AzimuthIndex * AzimuthAccuracy
        # degrees to radians
        alpha = math.radians(self.Azimuth)
        beta = math.radians(self.Beta)
        # XYZ: The XYZ coordinates can be retrieved using the following equation:
        # X = Range * Sin(Alpha) * Cos(Beta)
        # Y = Range * Sin(Beta)
        # Z = Range * Cos(Alpha) * Cos(Beta)
        # or
        # Z = sqrt(Range^2 - X^2 - Y^2)
        self.X = self.Range * math.sin(alpha) * math.cos(beta)
        self.Y = self.Range * math.sin(beta)
        self.Z = math.sqrt(self.Range * self.Range -
                           self.X * self.X - self.Y * self.Y)
class TrackerBlock(Structure):
    """
    Tracker structure
    """
    _pack_ = 1
    _fields_ = [
        ('TrackID', c_uint32),      # 0 to 4294967296 Track ID
        ('XPos', c_int16),          # -32768 to 32767, divide by 100 to get x in m (e.g. 6453 = 64.53 m, e.g.: -2456 = -24.56 m)
        ('YPos', c_int16),          # -32768 to 32767, divide by 100 to get y in m (e.g. 6453 = 64.53 m, e.g. -2456 = -24.56 m)
        ('ZPos', c_uint16),         # 0 to 65535, divide by 100 to get z in m (e.g. 12654 = 126.54 m)
        ('XDot', c_int16),          # -32768 to 32767, divide by 100 to get speed in the x direction in m/s (e.g. 6453 = 64.53 m/s, e.g. -2456 = -24.56 m/s)
        ('YDot', c_int16),          # -32768 to 32767, divide by 100 to get speed in the y direction in m/s (e.g. 6453 = 64.53 m/s, e.g. -2456 = -24.56 m/s)
        ('ZDot', c_int16),          # -32768 to 32767, divide by 100 to get speed in the z direction in m/s (e.g. 6453 = 64.53 m/s, e.g. -2456 = -24.56 m/s)
        ('Res1', c_uint16),
        ('Res2', c_uint16),
        ('Res3', c_uint16),
        ('Flag', c_uint16),         # 0 to 65535. 16 1-bit flags, the flag definitions are internal to Oculii.
                                    # Bit 3 – Bit 15 : Reserved
                                    # Bit 0, Bit 1, Bit 2 : Track Quality. Currently only values 1 and 2 are used. Filter to use only value ‘2’.
        ('Class', c_uint16),        # 0 to 5. Reserved for future.
                                    # 0: Unknown Class
                                    # 1: Pedestrian
                                    # 2: Motorcycle/Bike
                                    # 3: Vehicle and SUV
                                    # 4: Bus and Truck
                                    # 5: Background
        ('Conf', c_uint16),
        ('Res4', c_uint16),
        ('Res5', c_uint16),
    ]
src/Microwave/constants.py
New file
@@ -0,0 +1,2 @@
HAND_SHAKE_MAGIC = b"\x01\x09\x08\x09\x01\x00\x02\x02"
HEADER_MAGIC = b"\x02\x01\x04\x03\x06\x05\x08\x07"
src/Microwave/demo/AutoGetUDP.bat
New file
@@ -0,0 +1,22 @@
@echo off
@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%
)
echo All data will be save in '%cd%/saveUDPData/' folder
%aerialpython% udp_test_get.py microwave
echo =========== ALL DONE ================
echo Press any key to exit this windiow.
pause
src/Microwave/demo/AutoGetUDPtest.bat
New file
@@ -0,0 +1,22 @@
@echo off
@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%
)
echo All data will be saved in '%cd%/saveUDPData/' folder
%aerialpython% udp_test_get.py test
echo =========== ALL GET DONE ================
echo Press any key to exit this windiow.
pause
src/Microwave/demo/AutoSendAndGetTest.bat
New file
@@ -0,0 +1,16 @@
@echo off
@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%
)
start AutoGetUDPtest.bat
start AutoSendUDPtest.bat
src/Microwave/demo/AutoSendUDPtest.bat
New file
@@ -0,0 +1,22 @@
@echo off
@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%
)
echo All data saved in '%cd%/demoUDPData/' folder will be sent to 127.0.0.1:9911
%aerialpython% udp_test_send.py
echo =========== ALL SEND DONE ================
echo Press any key to exit this windiow.
pause
src/Microwave/demo/MicroWave2Ply.py
New file
@@ -0,0 +1,35 @@
import os
import sys
# add python path of microwave to sys.path
microwave_path = os.path.join(__file__, *(['..'] * 3))
microwave_path = os.path.abspath(microwave_path)
sys.path.insert(0, microwave_path)
from microwave.parsers import MicroWaveParser
if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('Usage: python MicroWave2Ply.py [filename.bin]')
        exit(1)
    filename = sys.argv[1]
    (fn, ext) = os.path.splitext(filename)
    with open(filename, "rb") as udp_file:
        buf = udp_file.read()
        point_cloud = MicroWaveParser.ParserFrame(buf)
        with open(fn + ".ply", "w") as f:
            f.write("ply\n")
            f.write("format ascii 1.0\n")
            f.write("comment MicroWave2Ply generated\n")
            f.write("element vertex %d\n" % len(point_cloud))
            f.write("property float x\n")
            f.write("property float y\n")
            f.write("property float z\n")
            f.write("element face 0\n")
            f.write("property list uchar int vertex_indices\n")
            f.write("end_header\n")
            for p in point_cloud:
                x, y, z = p
                f.write("{:.5f} {:.5f} {:.5f}\n".format(x, y, z))
            print("Done!")
src/Microwave/demo/MicroWaveReceiverTest.py
New file
@@ -0,0 +1,31 @@
import os
from sys import argv
import sys
# add python path of microwave to sys.path
microwave_path = os.path.join(__file__, *(['..'] * 3))
microwave_path = os.path.abspath(microwave_path)
sys.path.insert(0, microwave_path)
from microwave.servers import MicroWaveReceiver
if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('Usage: python MicroWaveReceiverTest.py [folder]')
        exit(1)
    folder = sys.argv[1]
    files = ["packet{}.udp".format(i) for i in range(100)]
    receiver = MicroWaveReceiver()
    for file in files:
        filename = os.path.join(folder, file)
        with open(filename, "rb") as f:
            data = f.read()
            receiver.AddBuf(data)
            if receiver.DataFrameReady:
                frame_number = receiver.Header.FrameNumber
                bin_name = os.path.join(folder, "{}.bin".format(frame_number))
                print("Frame {} ready".format(frame_number))
                with open(bin_name, "wb") as bin_file:
                    bin_file.write(receiver.DataFrame)
                    bin_file.close()
src/Microwave/demo/MicroWaveUDPServerTest.py
New file
@@ -0,0 +1,57 @@
import sys
import time
import os
from socketserver import BaseRequestHandler, UDPServer
# add python path of microwave to sys.path
microwave_path = os.path.join(__file__, *(['..'] * 3))
microwave_path = os.path.abspath(microwave_path)
sys.path.insert(0, microwave_path)
from microwave.servers import MicroWaveReceiver
class MicroWaveRequestHandlertest(BaseRequestHandler):
    def handle(self):
        # Get message and client socket
        buf, _ = self.request
        receiver = self.server.Receiver
        receiver.AddBuf(buf)
        if receiver.DataFrameReady:
            # data frame ready
            frame_number = receiver.Header.FrameNumber
            bin_name = os.path.join(self.server.OutputFolder, "{}.bin".format(frame_number))
            print("Frame {} ready".format(frame_number))
            with open(bin_name, "wb") as bin_file:
                bin_file.write(receiver.DataFrame)
class MicroWaveUDPServertest(UDPServer):
    def __init__(self, server_address, output_folder):
        super().__init__(server_address, MicroWaveRequestHandlertest)
        # create receiver instance
        self.Receiver = MicroWaveReceiver()
        self.OutputFolder = output_folder
if __name__ == '__main__':
    if len(sys.argv) == 2:
        output_folder = sys.argv[1]
    else:
        output_folder = '.'
    # host = '192.168.2.65'
    host = ''
    port = 9911
    server = MicroWaveUDPServertest((host, port), output_folder)
    server.packed_count = 0
    print(time.asctime(),'Server started on port', port)
    print('....')
    print('ctrl-c to quit server.')
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.server_close()
        print(time.asctime(),"Server Stopped")
    except:
        server.server_close()
        print(time.asctime(),"Server Stopped")
src/Microwave/demo/demoData/packet0.udp
Binary files differ
src/Microwave/demo/demoData/packet1.udp
Binary files differ
src/Microwave/demo/demoData/packet10.udp
Binary files differ
src/Microwave/demo/demoData/packet11.udp
Binary files differ
src/Microwave/demo/demoData/packet12.udp
Binary files differ
src/Microwave/demo/demoData/packet13.udp
Binary files differ
src/Microwave/demo/demoData/packet14.udp
Binary files differ
src/Microwave/demo/demoData/packet15.udp
Binary files differ
src/Microwave/demo/demoData/packet16.udp
Binary files differ
src/Microwave/demo/demoData/packet17.udp
Binary files differ
src/Microwave/demo/demoData/packet18.udp
Binary files differ
src/Microwave/demo/demoData/packet19.udp
Binary files differ
src/Microwave/demo/demoData/packet2.udp
Binary files differ
src/Microwave/demo/demoData/packet20.udp
Binary files differ
src/Microwave/demo/demoData/packet21.udp
Binary files differ
src/Microwave/demo/demoData/packet22.udp
Binary files differ
src/Microwave/demo/demoData/packet23.udp
Binary files differ
src/Microwave/demo/demoData/packet24.udp
Binary files differ
src/Microwave/demo/demoData/packet25.udp
Binary files differ
src/Microwave/demo/demoData/packet26.udp
Binary files differ
src/Microwave/demo/demoData/packet27.udp
Binary files differ
src/Microwave/demo/demoData/packet28.udp
Binary files differ
src/Microwave/demo/demoData/packet29.udp
Binary files differ
src/Microwave/demo/demoData/packet3.udp
Binary files differ
src/Microwave/demo/demoData/packet30.udp
Binary files differ
src/Microwave/demo/demoData/packet31.udp
Binary files differ
src/Microwave/demo/demoData/packet32.udp
Binary files differ
src/Microwave/demo/demoData/packet33.udp
Binary files differ
src/Microwave/demo/demoData/packet34.udp
Binary files differ
src/Microwave/demo/demoData/packet35.udp
Binary files differ
src/Microwave/demo/demoData/packet36.udp
Binary files differ
src/Microwave/demo/demoData/packet37.udp
Binary files differ
src/Microwave/demo/demoData/packet38.udp
Binary files differ
src/Microwave/demo/demoData/packet39.udp
Binary files differ
src/Microwave/demo/demoData/packet4.udp
Binary files differ
src/Microwave/demo/demoData/packet40.udp
Binary files differ
src/Microwave/demo/demoData/packet41.udp
Binary files differ
src/Microwave/demo/demoData/packet42.udp
Binary files differ
src/Microwave/demo/demoData/packet43.udp
Binary files differ
src/Microwave/demo/demoData/packet44.udp
Binary files differ
src/Microwave/demo/demoData/packet45.udp
Binary files differ
src/Microwave/demo/demoData/packet46.udp
Binary files differ
src/Microwave/demo/demoData/packet47.udp
Binary files differ
src/Microwave/demo/demoData/packet48.udp
Binary files differ
src/Microwave/demo/demoData/packet49.udp
Binary files differ
src/Microwave/demo/demoData/packet5.udp
Binary files differ
src/Microwave/demo/demoData/packet50.udp
Binary files differ
src/Microwave/demo/demoData/packet51.udp
Binary files differ
src/Microwave/demo/demoData/packet52.udp
Binary files differ
src/Microwave/demo/demoData/packet53.udp
Binary files differ
src/Microwave/demo/demoData/packet54.udp
Binary files differ
src/Microwave/demo/demoData/packet55.udp
Binary files differ
src/Microwave/demo/demoData/packet56.udp
Binary files differ
src/Microwave/demo/demoData/packet57.udp
Binary files differ
src/Microwave/demo/demoData/packet58.udp
Binary files differ
src/Microwave/demo/demoData/packet59.udp
Binary files differ
src/Microwave/demo/demoData/packet6.udp
Binary files differ
src/Microwave/demo/demoData/packet60.udp
Binary files differ
src/Microwave/demo/demoData/packet61.udp
Binary files differ
src/Microwave/demo/demoData/packet62.udp
Binary files differ
src/Microwave/demo/demoData/packet63.udp
Binary files differ
src/Microwave/demo/demoData/packet64.udp
Binary files differ
src/Microwave/demo/demoData/packet65.udp
Binary files differ
src/Microwave/demo/demoData/packet66.udp
Binary files differ
src/Microwave/demo/demoData/packet67.udp
Binary files differ
src/Microwave/demo/demoData/packet68.udp
Binary files differ
src/Microwave/demo/demoData/packet69.udp
Binary files differ
src/Microwave/demo/demoData/packet7.udp
Binary files differ
src/Microwave/demo/demoData/packet70.udp
Binary files differ
src/Microwave/demo/demoData/packet71.udp
Binary files differ
src/Microwave/demo/demoData/packet72.udp
Binary files differ
src/Microwave/demo/demoData/packet73.udp
Binary files differ
src/Microwave/demo/demoData/packet74.udp
Binary files differ
src/Microwave/demo/demoData/packet75.udp
Binary files differ
src/Microwave/demo/demoData/packet76.udp
Binary files differ
src/Microwave/demo/demoData/packet77.udp
Binary files differ
src/Microwave/demo/demoData/packet78.udp
Binary files differ
src/Microwave/demo/demoData/packet79.udp
Binary files differ
src/Microwave/demo/demoData/packet8.udp
Binary files differ
src/Microwave/demo/demoData/packet80.udp
Binary files differ
src/Microwave/demo/demoData/packet81.udp
Binary files differ
src/Microwave/demo/demoData/packet82.udp
Binary files differ
src/Microwave/demo/demoData/packet83.udp
Binary files differ
src/Microwave/demo/demoData/packet84.udp
Binary files differ
src/Microwave/demo/demoData/packet85.udp
Binary files differ
src/Microwave/demo/demoData/packet86.udp
Binary files differ
src/Microwave/demo/demoData/packet87.udp
Binary files differ
src/Microwave/demo/demoData/packet88.udp
Binary files differ
src/Microwave/demo/demoData/packet89.udp
Binary files differ
src/Microwave/demo/demoData/packet9.udp
Binary files differ
src/Microwave/demo/demoData/packet90.udp
Binary files differ
src/Microwave/demo/demoData/packet91.udp
Binary files differ
src/Microwave/demo/demoData/packet92.udp
Binary files differ
src/Microwave/demo/demoData/packet93.udp
Binary files differ
src/Microwave/demo/demoData/packet94.udp
Binary files differ
src/Microwave/demo/demoData/packet95.udp
Binary files differ
src/Microwave/demo/demoData/packet96.udp
Binary files differ
src/Microwave/demo/demoData/packet97.udp
Binary files differ
src/Microwave/demo/demoData/packet98.udp
Binary files differ
src/Microwave/demo/demoData/packet99.udp
Binary files differ
src/Microwave/demo/polty.ipynb
New file
@@ -0,0 +1,64 @@
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Open3D WARNING] [ViewControl] SetViewPoint() failed because window height and width are not set.\n"
     ]
    }
   ],
   "source": [
    "import open3d as o3d\n",
    "# visualization of point clouds.\n",
    "# pcd = o3d.io.read_point_cloud('dense2_without_color.ply')\n",
    "# show = [pcd]\n",
    "pcd2522 = o3d.io.read_point_cloud('demoData/2522.ply')\n",
    "pcd2523 = o3d.io.read_point_cloud('demoData2523.ply')\n",
    "pcd2524 = o3d.io.read_point_cloud('demoData2524.ply')\n",
    "pcd2525 = o3d.io.read_point_cloud('demoData2525.ply')\n",
    "pcd2526 = o3d.io.read_point_cloud('demoData2526.ply')\n",
    "pcd2527 = o3d.io.read_point_cloud('demoData2527.ply')\n",
    "show = [pcd2522,pcd2523,pcd2524,pcd2525,pcd2526,pcd2527]\n",
    "o3d.visualization.draw_geometries(show)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "35e65690039548a4ed71bb11d5d15cea8607c9411f67738c48033f1deba4df50"
  },
  "kernelspec": {
   "display_name": "Python 3.9.10 ('huaneng_server')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
src/Microwave/demo/udp_test_get.py
New file
@@ -0,0 +1,63 @@
from socketserver import BaseRequestHandler, UDPServer
import time
import os, sys
cudir,_ = os.path.split(__file__)
file_folder = os.path.join(cudir,"saveUDPData")
if not os.path.exists(file_folder):
    os.makedirs(file_folder)
    print(f"make a new folder: {file_folder}")
packed_count = 0
class PointCloudUDPRequestHandler(BaseRequestHandler):
    def handle(self):
        global packed_count
        print(time.asctime(),' Got connection from {}, {}'.format(self.client_address, packed_count))
        # Get message and client socket
        msg, sock = self.request
        f = open('{}/packet{}.udp'.format(file_folder,packed_count), 'wb')
        f.write(msg)
        f.close()
        packed_count += 1
        if packed_count >= 1000000:
            UDPServer.server_close(server)
if __name__ == '__main__':
    def help():
        print("Usage: udp_test_get.py [host]. host can be 'test' or 'microwave' ")
        exit(1)
    if len(sys.argv) == 2:
        if sys.argv[1] == 'test':
            host = ''
        elif sys.argv[1] == 'microwave':
            host = '192.168.2.65'
        else:
            help()
    else:
        help()
    global server
    # host = ''
    # host = '192.168.2.65' # use this host to get the udp data from microwave device
    port = 9911
    server =UDPServer((host, port), PointCloudUDPRequestHandler)
    print(time.asctime(),'Server started on port', port)
    print('....')
    print('ctrl-c to quit server.')
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.server_close()
        print(time.asctime(),"Server Stopped")
    except:
        server.server_close()
        print(time.asctime(),"Server Stopped")
src/Microwave/demo/udp_test_send.py
New file
@@ -0,0 +1,21 @@
import time
import socket
import os, sys
cudir,_ = os.path.split(__file__)
file_folder = os.path.join(cudir,"demoData")
packed_count = 0
if __name__ == '__main__':
    files = ["packet{}.udp".format(i) for i in range(0, 100)]
    for file in files:
        with open(os.path.join(file_folder,file), "rb") as f:
            message = f.read()
            client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            client_socket.settimeout(1.0)
            addr = ("127.0.0.1", 9911)
            client_socket.sendto(message, addr)
            print (time.asctime(), f' Sending {file} to {addr} ...')
            time.sleep(0.1)
    print('Done!')
src/Microwave/parsers.py
New file
@@ -0,0 +1,23 @@
from .components import *
from .constants import *
from ctypes import sizeof, string_at
class MicroWaveParser:
    @classmethod
    def ParserFrame(cls, buffer: bytes) -> list:
        """
        解析完整的一帧数据,数据包括数据头,数据体,数据尾,返回点云数组
        """
        header = HeaderBlock(buffer[:sizeof(HeaderBlock)])
        if HEADER_MAGIC == string_at(header.Magic, 8):
            footer = FooterBlock(buffer[-sizeof(FooterBlock):])
            point_cloud = []
            for i in range(header.NumberOfDetection):
                detection = DetectionBlock(header, footer, buffer[i * 8 + sizeof(HeaderBlock): (i + 1) * 8 + sizeof(HeaderBlock)])
                point = (detection.X, detection.Y, detection.Z)
                point_cloud.append(point)
            return point_cloud
        else:
            return []
src/Microwave/servers.py
New file
@@ -0,0 +1,146 @@
import os, sys
from ctypes import sizeof, string_at
from socketserver import BaseRequestHandler, UDPServer
from .components import *
from .constants import *
# 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
UDP_STATE_IDLE = 0
UDP_STATE_HAND_SHAKE = 1
UDP_STATE_DATA = 2
UDP_STATE_FOOTER  = 3
class MicroWaveReceiver:
    """
    micro wave data receiver
    use AddBuf method add udp packet to receiver
    when DataFrameReady == True, you can get data frame
    """
    def __init__(self):
        self.state = UDP_STATE_IDLE
        self.PointCount = 0
        self.TrackCount = 0
        self.DataFrameReady = False
        self.DataFrame = None
        self.Header = None
        self.Footer = None
    def _receive_data(self, data) -> None:
        """
        receive data packet from udp
        """
        self.data_buf.extend(data)
        self.ReceivedDataLength += len(data)
        if self.ReceivedDataLength == self.DataLength:
            # if received data length equal expected data length
            # then we can get footer block
            self.state = UDP_STATE_FOOTER
        return
    def _receive_footer(self, data) -> None:
        # receive footer block
        self.footer_buf.extend(data)
        self.ReceivedFooterLength += len(data)
        if self.ReceivedFooterLength == sizeof(FooterBlock):
            self.Footer = FooterBlock.from_buffer_copy(self.footer_buf)
            # after received footer block, the data frame is ready
            self.DataFrameReady = True
            # reset state to idle, ready for next data frame
            self.state = UDP_STATE_IDLE
        return
    def AddBuf(self, buf: bytes) -> None:
        # add a udp packet to receiver
        buf_size = len(buf)
        if self.state == UDP_STATE_IDLE:
            if buf_size == sizeof(Handshake):
                handshake = Handshake.from_buffer_copy(buf)
                if HAND_SHAKE_MAGIC == string_at(handshake.Magic, 8):
                    self.DataFrameReady = False
                    self.state = UDP_STATE_HAND_SHAKE
                    self.DataFrame = None
                    self.Header = None
                    self.Footer = None
        elif self.state == UDP_STATE_HAND_SHAKE:
            # after received handshake packet, we can get header block
            self.Header = HeaderBlock.from_buffer_copy(buf[:sizeof(HeaderBlock)])
            if HEADER_MAGIC == string_at(self.Header.Magic, 8):
                self.DataFrame = bytearray(buf)
                N = self.Header.NumberOfDetection
                Nt = self.Header.NumberOfTrack
                self.PointCount = 0
                self.TrackCount = 0
                self.DataLength = N * 8 + Nt * sizeof(TrackerBlock)
                self.RemainLength = self.DataLength + sizeof(FooterBlock)
                self.data_buf = bytearray()
                self.footer_buf = bytearray()
                self.Points = []
                self.ReceivedDataLength = 0
                self.ReceivedFooterLength = 0
                # the next packet should be data block
                self.state = UDP_STATE_DATA
                header_size = sizeof(HeaderBlock)
                # 处理第一个数据包中的数据
                data_size = min(buf_size - header_size, self.DataLength)
                self._receive_data(buf[header_size: header_size + data_size])
                # 判断第一个数据包中是否包含Footer Block
                if (header_size + data_size) < buf_size:
                    self._receive_footer(buf[header_size + data_size])
        elif self.state == UDP_STATE_DATA:
            # receive data block
            self.DataFrame.extend(buf)
            remain_data_size = self.DataLength - self.ReceivedDataLength
            data_size = min(buf_size, remain_data_size)
            self._receive_data(buf[: data_size])
            if data_size < buf_size:
                self._receive_footer(buf[data_size: ])
        elif self.state == UDP_STATE_FOOTER:
            # receive footer block
            self.DataFrame.extend(buf)
            self._receive_footer(buf)
class MicroWaveRequestHandler(BaseRequestHandler):
    """
    micro wave udp request handler
    """
    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)
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
src/Server.py
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)
        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)
        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/Server/Server.py
File was deleted
src/config.json
New file
@@ -0,0 +1,82 @@
{
  "Device_name": "实时堆体识别",
  "Device_ID": "e8d28684-c908-457e-ade9-381451d26b0c",
  "Device_Network_para": {
    "Network_SSID": "thisisaWiFI",
    "Network_Password": "thisisaWiFIpassword",
    "Network_mode": "5g",
    "Network_MAC": "AA-BB-CC-DD-EE-FF",
    "Network_IP": "192.168.99.99"
  },
  "Captue_Image_para": {
    "brightness": 50,
    "contrast": 50,
    "hue": 50,
    "saturation": 50,
    "clarity": 50,
    "white_balance": 50,
    "frame_rate": 20,
    "capture_interval": 10,
    "dodec_type": "h264",
    "resolution": "4k",
    "IFrame_interval": 10,
    "overlap": 0.8,
    "level_angle": 2,
    "left_angle": -3,
    "right_angle": 1,
    "device_mid_x": 100,
    "device_mid_y": 50,
    "device_mid_z": 8000,
    "camera_1_x": -100,
    "camera_1_y": -100,
    "camera_1_z": -100,
    "camera_2_x": -100,
    "camera_2_y": -100,
    "camera_2_z": -100,
    "camera_3_x": -100,
    "camera_3_y": -100,
    "camera_3_z": -100,
    "camera_4_x": -100,
    "camera_4_y": -100,
    "camera_4_z": -100,
    "left_pupil_distance": 400,
    "right_pupil_distance": 800
  },
  "Millimeter_Wave_para": {
    "level_angle": 2,
    "left_angle": -3,
    "right_angle": 1,
    "MW_x": 100,
    "MW_y": 50,
    "MW_z": 8000,
    "MW_IP": "192.168.168.9",
    "MW_Port": 50055,
    "protocol": "tcp",
    "dest_IP": "192.168.168.100",
    "dest_port": 50056,
    "dest_protocol": "xieyi?TCP"
  },
  "Clean_Brush_para": {
    "clean_lens_start_angle": 10,
    "clean_lens_end_angle": 90,
    "clean_lens_num": 2,
    "clean_lens_period": 1200,
    "clean_self_start_angle": 10,
    "clean_self_end_angle": 55,
    "clean_self_num": 2,
    "clean_self_period": 2400
  },
  "High_Light_para": {
    "open_hour": 18,
    "open_minute": 30,
    "close_hour": 6,
    "close_minute": 30,
    "brightness": 30,
    "color": "white"
  },
  "AI_Algorithm_para": {
    "threshold": 99.6,
    "para_1": 100,
    "para_2": 1
  }
}
src/engine/AcquisitionMain.py
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("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
New file
@@ -0,0 +1,70 @@
import sys
import cv2              # NOQA: E402
import os
import numpy as np
import threading
import time
# 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
class CaptureThread(threading.Thread):
    """
    camera capture thread
    """
    def __init__(self, cameras, msg_queue, interval, image_quality = 95):
        """init the thread"""
        threading.Thread.__init__(self)
        self.cameras = cameras
        self.msg_queue = msg_queue
        self.interval = interval
        self.image_quality = image_quality
        self.is_stop = False
    def stop(self):
        """stop the thread"""
        self.is_stop = True
    def run(self):
        print("CaptureThread started")
        self.next_time = time.time() + self.interval
        while not self.is_stop:
            this_time = time.time()
            if this_time > self.next_time:
                data1 = pb.ImagesMessage()
                for i in range(len(self.cameras)):
                    _, frame = self.cameras[i].read()
                    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.image_quality]
                    _, encimg = cv2.imencode('.jpg', frame, encode_param)
                    if frame is not None:
                        np_array = np.asarray(encimg)  # frame 转换为numpy数组
                        byte_array = np_array.tobytes()  # numpy数组转换为byte数组
                        if i == 0:
                            data1.image1 = byte_array
                        elif i == 1:
                            data1.image2 = byte_array
                        elif i == 2:
                            data1.image3 = byte_array
                        elif i == 3:
                            data1.image4 = byte_array
                data1_str = data1.SerializeToString()
                # create protobuf message
                req = pb.RequestCommand()
                req.sys_command = pb.SysCommand.FIVE_G_COMMAND
                req.sub_command = pb.SubCommand.FIVE_G_SEND_IMAGE_SUB_COMMAND
                req.data1.length = len(data1_str)
                req.data1.data = data1_str
                # add message to queue
                self.msg_queue.put(req)
                self.next_time += self.interval
            time.sleep(0.1)
        for camera in self.cameras:
            camera.release()
        print("CaptureThread stopped")
src/engine/ControllThread.py
New file
@@ -0,0 +1,86 @@
import os, sys
import queue
import time
import pika
import threading
from .DustCleanerThread import DustCleanerThread
# 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
class ControllThread(threading.Thread):
    """
    controll thread
    accept controll message from rabbitmq
    """
    def __init__(self, host: str, user: str, password: str, callback_queue: str, config):
        threading.Thread.__init__(self)
        # setup dust cleaner command queue and thread
        self.config = config
        self._dust_cleaner_cmd_queue = queue.Queue()
        self._dust_cleaner_thread = DustCleanerThread(self._dust_cleaner_cmd_queue, self.config)
        self._dust_cleaner_thread.setDaemon(True)
        self._dust_cleaner_thread.start()
        self._init_callback(host, user, password, callback_queue)
    def _def_routes(self):
        """define controll message routes"""
        self.routes = {
            pb.ControlSysCommand.DUST_CLEANER_COMMAND: self._on_dust_cleaner_command,
        }
    def _on_dust_cleaner_command(self, msg: pb.ControllMessage):
        # add message to dust cleaner command queue
        self._dust_cleaner_cmd_queue.put(msg)
        return
    def _default(self, req: pb.ControllMessage):
        print('default controll handler')
        return
    def _init_callback(self, host: str, user: str, password: str, queue: str):
        """init rabbitmq channel"""
        credentials = pika.PlainCredentials(user, password)
        parameters = pika.ConnectionParameters(
            credentials=credentials, host=host)
        connection = pika.BlockingConnection(parameters)
        self._channel = connection.channel()
        self._channel.queue_declare(queue=queue, durable=False)
        self._channel.basic_qos(prefetch_count=1)
        self._channel.basic_consume(
            on_message_callback=self._on_callback_request, queue=queue)
    def _on_callback_request(self, ch, method, properties, body):
        print('callback received')
        msg = pb.ControllMessage()
        msg.ParseFromString(body)
        dispatcher = self.routes.get(msg.sys_command, self._default)
        dispatcher(msg)
        ch.basic_ack(delivery_tag=method.delivery_tag)
        return
    def stop(self):
        """stop controll thread"""
        self._channel.stop_consuming()
        self._dust_cleaner_thread.stop()
    def run(self):
        print("ControllThread started")
        self._channel.start_consuming()
if __name__ == "__main__":
    print("Begin CallbackThread Test")
    cb_thread = ControllThread("localhost", "chai", "password123", "pod1")
    cb_thread.start()
    time.sleep(3)
    cb_thread.stop()
src/engine/DeviceManager.py
New file
@@ -0,0 +1,40 @@
import datetime
import os
import pika
class DeviceManager:
    def __init__(self, host, user, password):
        self.host = host
        self.user = user
        self.password = password
        self._devices = {}
    def _create_controll_channel(self, device_id: str):
        credentials = pika.PlainCredentials(self.user, self.password)
        parameters = pika.ConnectionParameters(
            credentials=credentials, host=self.host)
        # 连接队列服务器
        connection = pika.BlockingConnection(parameters)
        channel = connection.channel()
        channel.queue_declare(queue=device_id + "_callback")
        return channel
    def get_device(self, device_id: str, save_folder: str):
        device = self._devices.get(device_id, None)
        if device is None:
            start = datetime.datetime.now()
            if not os.path.exists(save_folder):
                os.mkdir(save_folder)
            path = os,path.join(save_folder,f"{device_id}-{start.strftime('%Y-%m-%d-%H-%M-%S')}")
            if not os.path.exists(path):
                os.mkdir(path)
            device = dict(
                power_on=True,
                srart=start,
                path=path,
                images=0,
                micro_wave=0,
                controll_channel=self._create_controll_channel(device_id)
                )
            self._devices[device_id] = device
        return device
src/engine/DustCleaner.py
New file
@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
__author__ = 'wangzhibo 2022.01.20'
import serial
import serial.tools.list_ports
class DustCleaner():
    # 初始化
    def __init__(self, com, bps, timeout):
        self.port = com
        self.bps = bps
        self.timeout = timeout
        self.com_port = None
        self.Open()
    # 打印设备基本信息
    def Print_Name(self):
        print(self.com_port.name)  # 设备名字
        print(self.com_port.port)  # 读或者写端口
        print(self.com_port.baudrate)  # 波特率
        print(self.com_port.bytesize)  # 字节大小
        print(self.com_port.parity)  # 校验位
        print(self.com_port.stopbits)  # 停止位
        print(self.com_port.timeout)  # 读超时设置
        print(self.com_port.writeTimeout)  # 写超时
        print(self.com_port.xonxoff)  # 软件流控
        print(self.com_port.rtscts)  # 软件流控
        print(self.com_port.dsrdtr)  # 硬件流控
        print(self.com_port.interCharTimeout)  # 字符间隔超时
    # 打开串口
    def Open(self) -> bool:
        try:
            # 打开串口,并得到串口对象
            self.com_port = serial.Serial(self.port, self.bps, timeout=self.timeout)
            # 判断是否打开成功
            if (self.com_port.is_open):
                return True
            else:
                return False
        except Exception as _:
            return False
    # 关闭串口
    def Close(self) -> None:
        self.com_port.close()
        print(self.com_port.is_open)  # 检验串口是否打开
    # 打印可用串口列表
    @classmethod
    def Print_Used_Com():
        port_list = list(serial.tools.list_ports.comports())
        print(port_list)
    # 发数据
    def Send(self, data):
        if (not self.com_port is None) and self.com_port.is_open():
            self.com_port.write(data)
            self.Recive()
    def SendNoChecksum(self, data):
        checksum = 0
        array = bytearray(data)
        for i in array[:-1]:
            checksum += i
        checksum = checksum % 256
        array[-1] = checksum
        self.Send(bytes(array))
    def Send_onetime_clean_self(self):   # 发送函数
        self.Send(bytes([0x5A, 0x04, 0x70, 0xCE]))    # 用write函数向串口发送数据
    def Send_onetime_clean_camera(self):   # 发送函数
        self.Send(bytes([0x5A, 0x04, 0x71, 0xCF]))    # 用write函数向串口发送数据
    def Send_close_period_clean_self(self):
        self.Send(bytes([0x5A, 0x06, 0x74, 0x00, 0x00, 0xD4]))    # close self period clean
    def Send_close_period_clean_camera(self):
        self.Send(bytes([0x5A, 0x06, 0x75, 0x00, 0x00, 0xD5]))    # close self period clean
    def Send_period_clean_self(self, period: int):
        minute_H = period // 256
        minute_L = period % 256
        self.SendNoChecksum(bytes([0x5A, 0x06, 0x74, minute_H, minute_L, 0x00]))
    def Send_period_clean_camera(self, period: int):
        minute_H = period // 256
        minute_L = period % 256
        self.SendNoChecksum(bytes([0x5A, 0x06, 0x75, minute_H, minute_L, 0x00]))
    def Send_self_clean_params(self, start_angle: int, end_angle: int, num: int):
        self.SendNoChecksum(bytes([0x5A, 0x07, 0x72, start_angle, end_angle, num, 0x00]))
    def Send_camera_clean_params(self, start_angle: int, end_angle: int, num: int):
        self.SendNoChecksum(bytes([0x5A, 0x07, 0x73, start_angle, end_angle, num, 0x00]))
    def Recive(self):
        return self.main_engine.read_all()
if __name__ == '__main__':
    # DustCleaner.Print_Used_Com()
    cleaner = DustCleaner("com11", 115200, 1)
    if cleaner.Open():
        cleaner.Send_close_period_clean_camera()
        cleaner.Recive()
src/engine/DustCleanerThread.py
New file
@@ -0,0 +1,67 @@
import sys              # NOQA: E402
import os
import threading
import time
from .DustCleaner import DustCleaner
# 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
class DustCleanerThread (threading.Thread):
    """
    dust cleaner threads
    """
    def __init__(self, cmd_queue, config):
        threading.Thread.__init__(self)
        self.config = config
        self.cmd_queue = cmd_queue
        self.stop = False
        self.cleaner = DustCleaner("com11", 115200, 1)
        self._init_dust_cleaner()
    def _init_dust_cleaner(self):
        """init dust cleaner"""
        # send dust cleaner self clean command
        self.cleaner.Send_self_clean_params(
            self.config.clean_self_start_angle,
            self.config.clean_self_end_angle,
            self.config.clean_self_num)
        # send dust cleaner period clean self command
        self.cleaner.Send_period_clean_self(self.config.clean_self_period)
        # send dust cleaner camera clean command
        self.cleaner.Send_camera_clean_params(
            self.config.clean_lens_start_angle,
            self.config.clean_lens_end_angle,
            self.config.clean_lens_num)
        # send dust cleaner period clean camera command
        self.cleaner.Send_period_clean_camera(self.config.clean_lens_period)
    def run(self):
        print("DustCleanerThread started")
        while not self.stop:
            # check if there is a command in the queue
            if not self.cmd_queue.empty():
                cmd = self.cmd_queue.get()
                dust_cleaner_msg = pb.DustCleanerMessage()
                dust_cleaner_msg.ParseFromString(cmd.data1.data)
                if cmd.sub_command == pb.ControlSubCommand.DUST_CLEANER_ONETIME_CLEAN_SELF:
                    self.cleaner.Send_onetime_clean_self()
                elif cmd.sub_command == pb.ControlSubCommand.DUST_CLEANER_ONETIME_CLEAN_CAMERA:
                    self.cleaner.Send_onetime_clean_camera()
                elif cmd.sub_command == pb.ControlSubCommand.DUST_CLEANER_CLOSE_PERIOD_CLEAN_SELF:
                    self.cleaner.Send_close_period_clean_self()
                elif cmd.sub_command == pb.ControlSubCommand.DUST_CLEANER_CLOSE_PERIOD_CLEAN_CAMERA:
                    self.cleaner.Send_close_period_clean_camera()
                elif cmd.sub_command == pb.ControlSubCommand.DUST_CLEANER_PERIOD_CLEAN_SELF:
                    self.cleaner.Send_close_period_clean_self(dust_cleaner_msg.period)
                elif cmd.sub_command == pb.ControlSubCommand.DUST_CLEANER_PERIOD_CLEAN_CAMERA:
                    self.cleaner.Send_period_clean_camera(dust_cleaner_msg.period)
            time.sleep(0.1)
        print("DustCleanerThread stopped")
src/engine/MessageQueueThread.py
New file
@@ -0,0 +1,108 @@
import sys              # NOQA: E402
import os
import pika
import threading
from ctypes import sizeof
from .DeviceManager import DeviceManager
# 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 microwave.components import HeaderBlock
from protos import aerial_pb2 as pb
class MessageQueueThread(threading.Thread):
    def __init__(self,
                 host: str,
                 user: str,
                 password: str,
                 queue: str,
                 device_manager: DeviceManager):
        threading.Thread.__init__(self)
        self._device_manager = device_manager
        self._def_routes()
        self.message_received: int = 0
        credentials = pika.PlainCredentials(user, password)
        parameters = pika.ConnectionParameters(
            credentials=credentials, host=host)
        connection = pika.BlockingConnection(parameters)
        self._channel = connection.channel()
        self._channel.queue_declare(queue=queue, durable=True)
        self._channel.basic_qos(prefetch_count=1)
        self._channel.basic_consume(
            on_message_callback=self._on_request, queue=queue)
    def _def_routes(self):
        self._routes = {
            pb.SysCommand.FIVE_G_COMMAND: self._on_five_g_command,
            pb.SysCommand.MICRO_WAVE_COMMAND: self._on_micro_wave_command,
        }
    def _default(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        print('onknown command')
    def _write_image(self, device: dict, idx: int, image: bytes):
        if (image is None) | (len(image) == 0):
            return
        filename = f'{device["path"]}/{idx}-{device["images"]}.jpg'
        with open(filename, 'wb') as f:
            f.write(image)
            f.close()
    def _on_five_g_command(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        # print('five g command')
        if pb.SubCommand.FIVE_G_SEND_IMAGE_SUB_COMMAND == req.sub_command:
            print(
                f'send image sub command received, length={req.data1.length}')
            if req.data1.length > 0:
                device = self._device_manager.get_device(req.device_id)
                img_msg = pb.ImagesMessage()
                img_msg.ParseFromString(req.data1.data)
                # print(img_msg.image1)
                count = device["images"]
                self._write_image(device, 1, img_msg.image1)
                self._write_image(device, 2, img_msg.image2)
                self._write_image(device, 3, img_msg.image3)
                self._write_image(device, 4, img_msg.image4)
                self._write_image(device, 5, img_msg.image5)
                device['images'] += 1
    def _on_micro_wave_command(self, req: pb.RequestCommand, resp: pb.ResponseCommand):
        print('micro wave command')
        if pb.SubCommand.MICRO_WAVE_SUB_COMMAND == req.sub_command:
            print('micro wave sub command received')
            device = self._device_manager.get_device(req.device_id)
            micro_wave_msg = pb.MicroWaveMessage()
            micro_wave_msg.ParseFromString(req.data1.data)
            if (micro_wave_msg.length == len(micro_wave_msg.data)):
                header = HeaderBlock.from_buffer_copy(micro_wave_msg[:sizeof(HeaderBlock)])
                filename = f'{device["path"]}/{device["micro_wave"]}-{header.FrameNumber}.micro_wave'
                with open(filename, 'wb') as f:
                    f.write(micro_wave_msg.data)
                    f.close()
                device['micro_wave'] += 1
    def _on_request(self, ch, method, properties, body):
        req = pb.RequestCommand()
        req.ParseFromString(body)
        dispatcher = self._routes.get(req.sys_command, self._default)
        resp = pb.ResponseCommand()
        dispatcher(req, resp)
        resp.checksum = 12345
        resp.state = pb.ResponseState.SUCCESS
        if properties.reply_to != None:
            ch.basic_publish(exchange='',
                             routing_key=properties.reply_to,  # 收消息的队列
                             properties=pika.BasicProperties(
                                 correlation_id=properties.correlation_id),  # 返回消息的队列
                             body=resp.SerializeToString())  # 返回结果数据
        ch.basic_ack(delivery_tag=method.delivery_tag)  # 确保消息被 客户端接收
        self.message_received += 1
        return
    def run(self):
        print(' [*] RabbitMQ Server started. Waiting for messages.')
        self._channel.start_consuming()
src/engine/MicroWaveUDPThread.py
New file
@@ -0,0 +1,22 @@
import os, sys
import threading
# 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 microwave.servers import MicroWaveUDPServer
class MicroWaveUDPThread (threading.Thread):
    def __init__(self, server_address, msg_queue):
        threading.Thread.__init__(self)
        self.udp_server = MicroWaveUDPServer(server_address, msg_queue)
    def run(self):
        print("MicroWaveUDPThread started")
        self.udp_server.serve_forever()
    def stop(self):
        self.udp_server.server_close()
src/engine/__init__.py
New file
@@ -0,0 +1,8 @@
from .AcquisitionMain import *
from .CaptureThread import *
from .ControllThread import *
from .DeviceManager import *
from .DustCleaner import *
from .DustCleanerThread import *
from .MessageQueueThread import *
from .MicroWaveUDPThread import *
src/protos/aerial.proto
File was renamed from proto/aerial.proto
@@ -120,3 +120,34 @@
    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
New file
@@ -0,0 +1,11 @@
@echo off
@REM change to the filepath
cd %~dp0
echo change to path: %cd%
set protoc=%cd%/../../env/aerial_deploy/Library/bin/protoc.exe
%protoc% aerial.proto --python_out=%cd%
echo compile done!
src/requirements.yaml
New file
@@ -0,0 +1,149 @@
name: aerial
channels:
  - conda-forge
  - defaults
dependencies:
  - bitarray=2.3.6=py39hb82d6ee_0
  - bzip2=1.0.8=h8ffe710_4
  - ca-certificates=2021.10.8=h5b45459_0
  - click=8.0.3=py39hcbf5309_1
  - colorama=0.4.4=pyh9f0ad1d_0
  - flask=2.0.2=pyhd8ed1ab_0
  - freetype=2.10.4=h546665d_1
  - fribidi=1.0.10=h8d14728_0
  - itsdangerous=2.0.1=pyhd8ed1ab_0
  - jbig=2.1=h8d14728_2003
  - jinja2=3.0.3=pyhd8ed1ab_0
  - jpeg=9e=h8ffe710_0
  - lcms2=2.12=h2a16943_0
  - lerc=3.0=h0e60522_0
  - libdeflate=1.8=h8ffe710_0
  - libffi=3.4.2=h8ffe710_5
  - libimagequant=2.17.0=hcfcfb64_1
  - libpng=1.6.37=h1d00b33_2
  - libprotobuf=3.19.4=h7755175_0
  - libtiff=4.3.0=hd413186_2
  - libwebp=1.2.2=h57928b3_0
  - libwebp-base=1.2.2=h8ffe710_1
  - libxcb=1.13=hcd874cb_1004
  - libzlib=1.2.11=h8ffe710_1013
  - llvm-openmp=12.0.1=h2d74725_1
  - lz4-c=1.9.3=h8ffe710_1
  - m2w64-gcc-libgfortran=5.3.0=6
  - m2w64-gcc-libs=5.3.0=7
  - m2w64-gcc-libs-core=5.3.0=7
  - m2w64-gmp=6.1.0=2
  - m2w64-libwinpthread-git=5.0.0.4634.697f757=2
  - markupsafe=2.0.1=py39hb82d6ee_1
  - msys2-conda-epoch=20160418=1
  - openjpeg=2.4.0=hb211442_1
  - openssl=3.0.0=h8ffe710_2
  - pika=1.2.0=pyh44b312d_0
  - pillow=9.0.1=py39ha53f419_0
  - pip=22.0.3=pyhd8ed1ab_0
  - protobuf=3.19.4=py39h415ef7b_0
  - pthread-stubs=0.4=hcd874cb_1001
  - python=3.9.10=hcf16a7b_2_cpython
  - python_abi=3.9=2_cp39
  - setuptools=60.8.1=py39hcbf5309_0
  - six=1.16.0=pyh6c4a22f_0
  - sqlite=3.37.0=h8ffe710_0
  - tk=8.6.11=h8ffe710_1
  - tzdata=2021e=he74cb21_0
  - ucrt=10.0.20348.0=h57928b3_0
  - vc=14.2=hb210afc_6
  - vs2015_runtime=14.29.30037=h902a5da_6
  - werkzeug=2.0.3=pyhd8ed1ab_1
  - wheel=0.37.1=pyhd8ed1ab_0
  - xorg-libxau=1.0.9=hcd874cb_0
  - xorg-libxdmcp=1.1.3=hcd874cb_0
  - xz=5.2.5=h62dcd97_1
  - zlib=1.2.11=h8ffe710_1013
  - zstd=1.5.2=h6255e5f_0
  - pip:
    - anyio==3.5.0
    - argon2-cffi==21.3.0
    - argon2-cffi-bindings==21.2.0
    - asttokens==2.0.5
    - attrs==21.4.0
    - babel==2.9.1
    - backcall==0.2.0
    - black==22.1.0
    - bleach==4.1.0
    - certifi==2021.10.8
    - cffi==1.15.0
    - charset-normalizer==2.0.12
    - debugpy==1.5.1
    - decorator==5.1.1
    - defusedxml==0.7.1
    - deprecation==2.1.0
    - entrypoints==0.4
    - executing==0.8.2
    - future==0.18.2
    - idna==3.3
    - ipykernel==6.9.0
    - ipython==8.0.1
    - ipython-genutils==0.2.0
    - ipywidgets==7.6.5
    - iso8601==1.0.2
    - jedi==0.18.1
    - json5==0.9.6
    - jsonschema==4.4.0
    - jupyter-client==7.1.2
    - jupyter-core==4.9.1
    - jupyter-packaging==0.11.1
    - jupyter-server==1.13.5
    - jupyterlab==3.2.9
    - jupyterlab-pygments==0.1.2
    - jupyterlab-server==2.10.3
    - jupyterlab-widgets==1.0.2
    - matplotlib-inline==0.1.3
    - mistune==0.8.4
    - mypy-extensions==0.4.3
    - nbclassic==0.3.5
    - nbclient==0.5.10
    - nbconvert==6.4.2
    - nbformat==5.1.3
    - nest-asyncio==1.5.4
    - notebook==6.4.8
    - numpy==1.22.2
    - open3d==0.14.1
    - opencv-contrib-python==4.5.5.62
    - packaging==21.3
    - pandocfilters==1.5.0
    - parso==0.8.3
    - pathspec==0.9.0
    - pickleshare==0.7.5
    - platformdirs==2.5.0
    - prometheus-client==0.13.1
    - prompt-toolkit==3.0.28
    - pure-eval==0.2.2
    - pycparser==2.21
    - pygments==2.11.2
    - pyparsing==3.0.7
    - pyrsistent==0.18.1
    - pyserial==3.5
    - python-dateutil==2.8.2
    - pytz==2021.3
    - pywin32==303
    - pywinpty==1.1.6
    - pyyaml==6.0
    - pyzmq==22.3.0
    - requests==2.27.1
    - send2trash==1.8.0
    - serial==0.0.97
    - sniffio==1.2.0
    - stack-data==0.1.4
    - terminado==0.13.1
    - testpath==0.5.0
    - tomli==2.0.1
    - tomlkit==0.9.2
    - tornado==6.1
    - traitlets==5.1.1
    - typing-extensions==4.1.1
    - urllib3==1.26.8
    - wcwidth==0.2.5
    - webencodings==0.5.1
    - websocket-client==1.2.3
    - widgetsnbextension==3.5.2
prefix: C:\Users\wuxinjun\miniconda3\envs\aerial
src/udp_test/ParserTest.py
File was deleted
src/udp_test/parser.py
File was deleted
src/udp_test/send.py
File was deleted
src/udp_test/udp.py
File was deleted
src/utils/__init__.py
New file
@@ -0,0 +1 @@
from .tools import *
src/utils/bin2ply.py
New file
@@ -0,0 +1,54 @@
import os
import sys
import time
# 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 microwave.parsers import MicroWaveParser
from tools import file_fliter
if __name__ == "__main__":
    def help():
        print("Usage: bin2ply.py [BINfolder]")
        print("EXAMPLE: BIN2ply.py ./manual_ply/pod1-2012-12-12-12-12-12/")
        exit(1)
    if len(sys.argv) != 2:
        help()
    try:
        BINfolder = str(sys.argv[1])
        # example pod1-2022-02-21-13-25-03_packet125.udp --> 125
        sort_lambda = lambda x:int(x.split('.')[0])
        bin_files = file_fliter(BINfolder,'bin', sort_lambda)
    except Exception as e:
        print(e)
        help()
    for file in bin_files:
        filename = file
        (fn, ext) = os.path.splitext(filename)
        with open(os.path.join(BINfolder,file), "rb") as bin_file:
            buf = bin_file.read()
            point_cloud = MicroWaveParser.ParserFrame(buf)
            with open(os.path.join(BINfolder,fn +".ply"), "w") as f:
                f.write("ply\n")
                f.write("format ascii 1.0\n")
                f.write("comment MicroWave2Ply generated\n")
                f.write("element vertex %d\n" % len(point_cloud))
                f.write("property float x\n")
                f.write("property float y\n")
                f.write("property float z\n")
                f.write("element face 0\n")
                f.write("property list uchar int vertex_indices\n")
                f.write("end_header\n")
                n_p = 0
                for p in point_cloud:
                    x, y, z = p
                    f.write("{:.5f} {:.5f} {:.5f}\n".format(x, y, z))
                    n_p += 1
                print(time.asctime(),f"Frame {fn}.ply have been saved with {n_p} points!")
src/utils/plot_ply.py
New file
@@ -0,0 +1,23 @@
import open3d as o3d
import sys
if __name__ == "__main__":
    def help():
        print("Usage: plot_ply.py [PLYfile]")
        print("EXAMPLE: plot_ply ./Manual_Microwave/pod1-2022-02-21-15-34-45/2522.ply")
        exit(1)
    if len(sys.argv) != 2:
        help()
    try:
        PLYfile = str(sys.argv[1])
        pcd = o3d.io.read_point_cloud(PLYfile)
    except Exception as e:
        print(e)
        help()
    show = [pcd]
    o3d.visualization.draw_geometries(show)
src/utils/tools.py
New file
@@ -0,0 +1,17 @@
import os, sys
def file_fliter(folder:str, file_ext:str, sort_format):
    files_List = os.listdir(folder)
    target_files = []
    # flitered by file extention name
    for file in files_List:
        if file.split('.')[-1] == file_ext:
            target_files.append(file)
    # sort the list by the sort_format
    target_files.sort(key=sort_format)
    return target_files
src/utils/udp2bin.py
New file
@@ -0,0 +1,46 @@
import os
from sys import argv
import sys
import time
# 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 microwave.servers import MicroWaveReceiver
from tools import file_fliter
if __name__ == '__main__':
    def help():
        print("Usage: udp2bin.py [UDPfolder]")
        print("EXAMPLE: udp2bin.py ./manual_ply/pod1-2012-12-12-12-12-12/")
        exit(1)
    if len(sys.argv) != 2:
        help()
    try:
        UDPfolder = str(sys.argv[1])
        # example pod1-2022-02-21-13-25-03_packet125.udp --> 125
        sort_lambda = lambda x:int(x.split('packet')[1][:-4])
        udp_files = file_fliter(UDPfolder,'udp', sort_lambda)
    except Exception as e:
        print(e)
        help()
    receiver = MicroWaveReceiver()
    for file in udp_files:
        filename = os.path.join(UDPfolder, file)
        with open(filename, "rb") as f:
            data = f.read()
            receiver.AddBuf(data)
            if receiver.DataFrameReady:
                frame_number = receiver.Header.FrameNumber
                bin_name = os.path.join(UDPfolder, "{}.bin".format(frame_number))
                print(time.asctime(),"Frame {} ready".format(frame_number))
                with open(bin_name, "wb") as bin_file:
                    bin_file.write(receiver.DataFrame)
                    bin_file.close()
src/utils/udp_get.py
New file
@@ -0,0 +1,88 @@
import datetime
from pickle import GLOBAL
from socketserver import BaseRequestHandler, UDPServer
import time
import os, sys
# cudir,_ = os.path.split(__file__)
# file_folder = os.path.join(cudir,"saveUDPData")
# if not os.path.exists(file_folder):
#     os.makedirs(file_folder)
#     print(f"make a new folder: {file_folder}")
packed_count = 0
class PointCloudUDPRequestHandler(BaseRequestHandler):
    def handle(self):
        global packed_count
        global path
        if packed_count == 0:
            start = datetime.datetime.now()
            if not os.path.exists(save_folder):
                os.mkdir(save_folder)
            path = os.path.join(save_folder,f"{device_id}-{start.strftime('%Y-%m-%d-%H-%M-%S')}")
            if not os.path.exists(path):
                os.mkdir(path)
            path = os.path.abspath(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()
        packed_count += 1
        if packed_count >= packet_threshold:
            UDPServer.server_close(server)
if __name__ == '__main__':
    def help():
        print("Usage: udp_get.py [MICROWAVEhost] [PACKETthreshold] [DEVICEname] [SAVEfolder]")
        print("EXAMPLE: udp_get.py 192.168.2.65 1000 pod1 ./manual_ply")
        exit(1)
    if len(sys.argv) != 5:
        help()
    try:
        MICROWAVEhost = str(sys.argv[1])
        PACKETthreshold = int(sys.argv[2])
        DEVICEname = str(sys.argv[3])
        SAVEfolder = str(sys.argv[4])
        global packet_threshold
        packet_threshold = PACKETthreshold
        global device_id
        device_id = DEVICEname
        global save_folder
        save_folder = SAVEfolder
    except Exception as e:
        print(e)
        help()
    global server
    # host = ''
    # host = '192.168.2.65' # use this host to get the udp data from microwave device
    port = 9911
    server =UDPServer((MICROWAVEhost, port), PointCloudUDPRequestHandler)
    print(time.asctime(),'Server started on port', port)
    print('....')
    print('ctrl-c to quit server.')
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.server_close()
        print(time.asctime(),"Server Stopped")
    except:
        server.server_close()
        print(time.asctime(),"Server Stopped")
startClient.bat
New file
@@ -0,0 +1,30 @@
@echo off
@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%
)
set MQhost=172.17.17.206
set MQuser=chai
set MQpassword=password123
set QUEUEname=aerial_rpc
set DEVICEname=pod1
set SERVERhost=http://172.17.17.206/api
set MICROWAVEhost=192.168.2.65
set LOGfile=Client.log
@REM Launch the Client
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%
echo Client.py has been terminited.
pause
startServer.bat
New file
@@ -0,0 +1,30 @@
@echo off
@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%
)
set MQhost=172.17.17.206
set MQuser=chai
set MQpassword=password123
set QUEUEname=aerial_rpc
set WEBport=5000
set SAVEfolder=./Images
set LOGfile=Server.log
@REM Launch the Server
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%
echo Server.py has been terminited.
pause
udp2bin.bat
New file
@@ -0,0 +1,20 @@
@echo off
@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 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% ./src/utils/udp2bin.py %UDPfolder%
pause
udp2ply.bat
New file
@@ -0,0 +1,22 @@
@echo off
@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 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% ./src/utils/udp2bin.py %UDPfolder%
@REM ---------------Usage: bin2ply.py [BINfolder]
%aerialpython% ./src/utils/bin2ply.py %UDPfolder%
pause
udp_get.bat
New file
@@ -0,0 +1,21 @@
@echo off
@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%
)
set MICROWAVEhost=192.168.2.65
SET PACKETthreshold=1000
SET DEVICEname=pod1
SET SAVEfolder=./Manual_Microwave
@REM ---------------Usage: udp_get.py [MICROWAVEhost] [PACKETthreshold] [DEVICEname] [SAVEfolder]
%aerialpython% ./src/utils/udp_get.py %MICROWAVEhost% %PACKETthreshold% %DEVICEname% %SAVEfolder%
pause