Improvement
This commit is contained in:
commit
afd1a37c0c
58
.gitigore
Normal file
58
.gitigore
Normal file
@ -0,0 +1,58 @@
|
||||
# Python cache files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
|
||||
# IDEs and editors
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
*pyc
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# Pytest
|
||||
.cache
|
||||
*.cover
|
||||
*.log
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
|
||||
# MyPy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution files
|
||||
*.egg
|
||||
*.egg-info/
|
||||
MANIFEST
|
||||
|
||||
# Other files
|
||||
*.DS_Store
|
||||
*.pdb
|
||||
*.pyo
|
||||
*.pyd
|
||||
*.db
|
||||
*.sqlite3
|
373
LICENSE
Normal file
373
LICENSE
Normal file
@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
2
README.md
Normal file
2
README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# AiraPulsar 飞行控制系统
|
||||
AiraPulsar (空中脉冲星, 简称 APSR) 是一套基于 WebSocket 的三点架构的轻量级网络飞行控制系统
|
4
comet/README.md
Normal file
4
comet/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Comet - 飞行器侧载端
|
||||
Comet(彗星) 是 AiraPulsar 飞行控制系统的飞行器侧载端
|
||||
|
||||
Comet(飞行器) 通过 Moon(中继服务器) 进行通讯, 接受来自 Pulsar(控制器) 的指令
|
213
comet/agent_logs.log
Normal file
213
comet/agent_logs.log
Normal file
@ -0,0 +1,213 @@
|
||||
2025-03-07T08:56:35.501146+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:56:35.501324+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:56:35.501414+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:57:13.903527+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:57:13.903678+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:57:13.903742+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:58:55.379859+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:58:55.380016+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:58:55.380084+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:59:05.381232+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:59:05.381387+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:59:05.381444+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T08:59:52.906831+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T08:59:52.906996+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T08:59:52.907060+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:41.008959+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:41.008959+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:41.009179+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:41.009179+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:41.009279+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:41.009279+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:44.632829+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:44.632829+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:00:44.633010+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:44.633010+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:00:44.633098+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:00:44.633098+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:01:31.329481+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:01:31.329481+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:01:31.329691+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:01:31.329691+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:01:31.329762+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:01:31.329762+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:18.294306+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:18.294306+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:18.294467+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:18.294467+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:18.294542+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:18.294542+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:49.424696+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:49.424696+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:02:49.424863+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:49.424863+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:02:49.424947+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:02:49.424947+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:12.117053+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:12.117053+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:12.117278+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:12.117278+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:12.117377+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:12.117377+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:43.470032+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:43.470032+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:03:43.470267+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:43.470267+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:03:43.470342+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:03:43.470342+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:11:06.876601+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:11:06.876601+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:11:06.876858+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:11:06.876858+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:11:06.876965+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:11:06.876965+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:12:16.848236+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:12:16.848236+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:12:16.848397+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:12:16.848397+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:12:16.848476+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:12:16.848476+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:10.751685+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:10.751685+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:10.751843+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:10.751843+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:10.751912+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:10.751912+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:20.013536+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:20.013536+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:20.013686+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:20.013686+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:20.013757+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:20.013757+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:39.079365+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:39.079365+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:19:39.079590+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:39.079590+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:19:39.079663+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:19:39.079663+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:13.855104+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:13.855104+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:13.855261+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:13.855261+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:13.855328+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:13.855328+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:22.574788+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:22.574788+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:20:22.574961+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:22.574961+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:20:22.575035+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:20:22.575035+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:26:57.804810+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:26:57.804810+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:26:57.804965+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:26:57.804965+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:26:57.805033+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:26:57.805033+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:26.670684+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:26.670684+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:26.670920+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:26.670920+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:26.671025+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:26.671025+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:26.674242+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:28:26.674242+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:28:35.156211+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:35.156211+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:28:35.156372+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:35.156372+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:28:35.156458+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:35.156458+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:28:35.159041+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:28:35.159041+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:29:25.100332+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:29:25.100332+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:29:25.100478+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:29:25.100478+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:29:25.100548+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:29:25.100548+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:29:25.102459+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:29:25.102459+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:30:13.965473+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:30:13.965473+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:30:13.965675+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:30:13.965675+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:30:13.965765+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:30:13.965765+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:30:13.967862+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:30:13.967862+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:20.560819+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:20.560819+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:20.561346+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:20.561346+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:20.561512+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:20.561512+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:20.564821+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:20.564821+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:41.871167+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:41.871167+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T09:31:41.871318+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:41.871318+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T09:31:41.871391+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:41.871391+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T09:31:41.873516+0800 - INFO - 成功建立连接
|
||||
2025-03-07T09:31:41.873516+0800 - INFO - 成功建立连接
|
||||
2025-03-07T10:02:22.246919+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T10:02:22.246919+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T10:02:22.247153+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T10:02:22.247153+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T10:02:22.247261+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T10:02:22.247261+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T10:02:22.247736+0800 - INFO - 等待连接成功
|
||||
2025-03-07T10:02:22.247736+0800 - INFO - 等待连接成功
|
||||
2025-03-07T10:02:22.249670+0800 - INFO - 成功建立连接
|
||||
2025-03-07T10:02:22.249670+0800 - INFO - 成功建立连接
|
||||
2025-03-07T10:02:22.347928+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T10:02:22.347928+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:55:55.862879+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:55:55.862879+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:55:55.863020+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:55:55.863020+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:55:55.863103+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:55:55.863103+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:55:55.863455+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:55:55.863455+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:55:55.865329+0800 - INFO - 成功建立连接, 单向延迟 7.05718994140625e-05ms
|
||||
2025-03-07T15:55:55.865329+0800 - INFO - 成功建立连接, 单向延迟 7.05718994140625e-05ms
|
||||
2025-03-07T15:55:55.963668+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:55:55.963668+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:29.263974+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:29.263974+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:29.264145+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:29.264145+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:29.264238+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:29.264238+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:29.264733+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:29.264733+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:29.266574+0800 - INFO - 成功建立连接, 单向延迟 0ms
|
||||
2025-03-07T15:56:29.266574+0800 - INFO - 成功建立连接, 单向延迟 0ms
|
||||
2025-03-07T15:56:29.364981+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:29.364981+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:47.266556+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:47.266556+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T15:56:47.266726+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:47.266726+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T15:56:47.266820+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:47.266820+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T15:56:47.267230+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:47.267230+0800 - INFO - 等待连接成功
|
||||
2025-03-07T15:56:47.269156+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T15:56:47.269156+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T15:56:47.367454+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T15:56:47.367454+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T17:45:08.362971+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T17:45:08.362971+0800 - INFO - 初始化代理对象
|
||||
2025-03-07T17:45:08.363174+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T17:45:08.363174+0800 - INFO - 卫星地址: ws://127.0.0.1:8765
|
||||
2025-03-07T17:45:08.363287+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T17:45:08.363287+0800 - INFO - 代理对象代号: comet
|
||||
2025-03-07T17:45:08.363894+0800 - INFO - 等待连接成功
|
||||
2025-03-07T17:45:08.363894+0800 - INFO - 等待连接成功
|
||||
2025-03-07T17:45:08.365733+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T17:45:08.365733+0800 - INFO - 成功建立连接, 单向延迟 0.1ms
|
||||
2025-03-07T17:45:08.464116+0800 - INFO - 连接成功, 取消阻塞
|
||||
2025-03-07T17:45:08.464116+0800 - INFO - 连接成功, 取消阻塞
|
19
comet/comet.py
Normal file
19
comet/comet.py
Normal file
@ -0,0 +1,19 @@
|
||||
from lib import agency
|
||||
import yaml
|
||||
import time
|
||||
moon_addr = None
|
||||
moon_port = None
|
||||
|
||||
with open('comet_config.yaml', 'r') as config_file:
|
||||
config = yaml.safe_load(config_file)
|
||||
moon_addr = config.get("moon_addr", "127.0.0.1")
|
||||
port = config.get("moon_port", 8765)
|
||||
|
||||
agent = None
|
||||
|
||||
def handler(data: dict):
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
agent = agency.Agent(name="comet", addr=moon_addr, handler=handler)
|
||||
agent.runasthread()
|
1
comet/comet_config.yaml
Normal file
1
comet/comet_config.yaml
Normal file
@ -0,0 +1 @@
|
||||
moon_addr: "ws://127.0.0.1:8765"
|
33
comet/hal/bus/interface.py
Normal file
33
comet/hal/bus/interface.py
Normal file
@ -0,0 +1,33 @@
|
||||
class Motor(object):
|
||||
angle = None
|
||||
def __init__(self, id):
|
||||
self.angle = 0 # mark
|
||||
self.id = id
|
||||
def get(self):
|
||||
return self.angle
|
||||
def turn(self, add_angle):
|
||||
self.angle += add_angle
|
||||
return self.angle
|
||||
class Engine(object):
|
||||
speed = None
|
||||
def __init__(self, id):
|
||||
self.speed = 0 # Mark
|
||||
self.id = id
|
||||
def get(self):
|
||||
return self.speed
|
||||
def tune(self, new_speed):
|
||||
self.speed = new_speed
|
||||
return self.speed
|
||||
|
||||
class Battery:
|
||||
def get():
|
||||
power_left = 0.9
|
||||
return power_left
|
||||
def stat():
|
||||
status = "Unplugged"
|
||||
return status
|
||||
|
||||
class Network:
|
||||
def stat():
|
||||
delay = 0.2 # ms
|
||||
return delay # or -1 (unreachable)
|
202
comet/hal/tuner.py
Normal file
202
comet/hal/tuner.py
Normal file
@ -0,0 +1,202 @@
|
||||
"""
|
||||
filename: tuner.py
|
||||
"""
|
||||
from bus import interface
|
||||
import threading
|
||||
class Surface(object):
|
||||
motor = None
|
||||
name = None
|
||||
curr_angle = None
|
||||
id = None
|
||||
type_ = "surface"
|
||||
def __init__(self, name, id):
|
||||
self.motor = interface.Motor(id)
|
||||
self.curr_angle = self.motor.get()
|
||||
self.name = name
|
||||
self.id = id
|
||||
print("初始化操纵面 {}, 硬件代号绑定为 {}".format(name, id))
|
||||
def add_angle(self, angle):
|
||||
self.motor.turn(angle)
|
||||
self.curr_angle = self.motor.get();
|
||||
#print("将 {} 的角度加成 {} 度".format(self.name, angle))
|
||||
def set_angle(self, angle):
|
||||
angle_turn = angle - self.motor.get()
|
||||
self.motor.turn(angle_turn)
|
||||
self.curr_angle = self.motor.get()
|
||||
#print("将 {} 的角度设置为 {} 度".format(self.name, angle))
|
||||
def get_angle(self):
|
||||
self.curr_angle = self.motor.get()
|
||||
#print("{} 当前角度为 {} 度".format(self.name, self.curr_angle))
|
||||
return self.curr_angle
|
||||
def status(self):
|
||||
return {"type":"Surface", "name":self.name, "angle":self.curr_angle}
|
||||
def selfchk(self):
|
||||
print("开始自检操纵面 {}".format(self.name))
|
||||
self.add_angle(30)
|
||||
self.add_angle(-60)
|
||||
self.set_angle(0)
|
||||
|
||||
class Engine(object):
|
||||
engine = None
|
||||
curr_speed = None
|
||||
id = None
|
||||
name = None
|
||||
type_ = "engine"
|
||||
def __init__(self, name, id):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.engine = interface.Engine(id)
|
||||
self.curr_speed = self.engine.get()
|
||||
print("初始化引擎 {}, 硬件代号绑定为 {}".format(name, id))
|
||||
def set_speed(self, new_speed):
|
||||
self.engine.tune(new_speed)
|
||||
self.curr_speed = self.engine.get()
|
||||
##print("将 {} 的转速调谐为 {} RPM".format(self.name, new_speed))
|
||||
def add_speed(self, add_speed):
|
||||
self.engine.tune(self.curr_speed + add_speed)
|
||||
self.curr_speed = self.engine.get()
|
||||
##print("将 {} 的转速加成 {} RPM".format(self.name, add_speed))
|
||||
def get_speed(self):
|
||||
##print("{} 当前转速为 {} RPM".format(self.name, self.curr_speed))
|
||||
self.curr_speed = self.engine.get()
|
||||
return self.curr_speed
|
||||
def status(self):
|
||||
##print(self.curr_speed)
|
||||
return {"type":"Engine", "name":self.name, "speed":self.get_speed()}
|
||||
def selfchk(self):
|
||||
print("开始自检引擎 {}".format(self.name))
|
||||
self.add_speed(3)
|
||||
self.add_speed(-6)
|
||||
self.set_speed(0)
|
||||
self.curr_speed = self.engine.get()
|
||||
|
||||
|
||||
class Sensor:
|
||||
data = dict()
|
||||
data["speed"] = 0
|
||||
data["battery"] = 0
|
||||
data["xangle"] = 0
|
||||
data["yangle"] = 0
|
||||
data["zangle"] = 0
|
||||
data["sign"] = 0
|
||||
data["cpuload"] = 0
|
||||
data["memload"] = 0
|
||||
data["memsum"] = 0
|
||||
data["torch"] = 0
|
||||
data["acc"] = 0
|
||||
is_torch_on = 0
|
||||
|
||||
@staticmethod
|
||||
def speed():
|
||||
Sensor.data["speed"] = 99
|
||||
return Sensor.data["speed"]
|
||||
|
||||
@staticmethod
|
||||
def battery():
|
||||
Sensor.data["battery"] = 0.8
|
||||
return Sensor.data["battery"]
|
||||
|
||||
@staticmethod
|
||||
def xangle():
|
||||
Sensor.data["xangle"] = 201
|
||||
return Sensor.data["xangle"]
|
||||
|
||||
@staticmethod
|
||||
def yangle():
|
||||
Sensor.data["yangle"] = 108
|
||||
return Sensor.data["yangle"]
|
||||
|
||||
@staticmethod
|
||||
def zangle():
|
||||
Sensor.data["zangle"] = 0
|
||||
return Sensor.data["zangle"]
|
||||
|
||||
@staticmethod
|
||||
def sign():
|
||||
Sensor.data["sign"] = 322
|
||||
return Sensor.data["sign"]
|
||||
|
||||
@staticmethod
|
||||
def cpuload():
|
||||
Sensor.data["cpuload"] = 0.12
|
||||
return Sensor.data["cpuload"]
|
||||
|
||||
@staticmethod
|
||||
def memload():
|
||||
Sensor.data["memload"] = 0.88
|
||||
return Sensor.data["memload"]
|
||||
|
||||
@staticmethod
|
||||
def memsum():
|
||||
Sensor.data["memsum"] = 2048
|
||||
return Sensor.data["memsum"]
|
||||
|
||||
@staticmethod
|
||||
def torch():
|
||||
Sensor.data["torch"] = Sensor.is_torch_on
|
||||
return Sensor.data["torch"]
|
||||
|
||||
@staticmethod
|
||||
def torchon():
|
||||
Sensor.is_torch_on = 1
|
||||
|
||||
@staticmethod
|
||||
def acc():
|
||||
Sensor.data["acc"] = 3
|
||||
return Sensor.data["acc"]
|
||||
|
||||
@staticmethod
|
||||
def net_delay():
|
||||
Sensor.data["net_delay"] = 300
|
||||
return Sensor.data["net_delay"]
|
||||
|
||||
@staticmethod
|
||||
def refresh():
|
||||
Sensor.speed()
|
||||
Sensor.battery()
|
||||
Sensor.xangle()
|
||||
Sensor.yangle()
|
||||
Sensor.zangle()
|
||||
Sensor.sign()
|
||||
Sensor.cpuload()
|
||||
Sensor.memload()
|
||||
Sensor.memsum()
|
||||
Sensor.torch()
|
||||
Sensor.acc()
|
||||
Sensor.net_delay()
|
||||
|
||||
@staticmethod
|
||||
def stat():
|
||||
#Sensor.refresh()
|
||||
return Sensor.data
|
||||
|
||||
def pseudo_gui():
|
||||
import tkinter as tk
|
||||
def update_label(key, value):
|
||||
labels[key].config(text=f"{key}: {value}")
|
||||
def update():
|
||||
while 1:
|
||||
for key in Sensor.data.keys():
|
||||
Sensor.data[key] = sliders[key].get()
|
||||
root = tk.Tk()
|
||||
root.title("DEBUGGING CONSOLE")
|
||||
|
||||
labels = {}
|
||||
sliders = {}
|
||||
|
||||
# 自动布局
|
||||
for key in Sensor.data.keys():
|
||||
# 创建标签
|
||||
label = tk.Label(root, text=f"{key}: {Sensor.data[key]}")
|
||||
label.pack()
|
||||
labels[key] = label
|
||||
|
||||
# 创建滑块
|
||||
slider = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, command=lambda value, k=key: update_label(k, value))
|
||||
slider.pack()
|
||||
sliders[key] = slider
|
||||
|
||||
up = threading.Thread(target=update, name='Update')
|
||||
up.start()
|
||||
root.mainloop()
|
||||
up.join()
|
36
comet/model_cfg/jf_17_pm/hardware.yaml
Normal file
36
comet/model_cfg/jf_17_pm/hardware.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
surface:
|
||||
-
|
||||
id: al
|
||||
attr: "a"
|
||||
side: "l"
|
||||
desc: 左副翼
|
||||
-
|
||||
id: ar
|
||||
attr: "a"
|
||||
side: "r"
|
||||
desc: 右副翼
|
||||
-
|
||||
id: fl
|
||||
attr: "f"
|
||||
side: "l"
|
||||
desc: 左襟翼
|
||||
-
|
||||
id: fr
|
||||
attr: "f"
|
||||
side: "r"
|
||||
desc: 右襟翼
|
||||
-
|
||||
id: r
|
||||
attr: "h"
|
||||
side: "n"
|
||||
desc: 方向舵
|
||||
-
|
||||
id: e
|
||||
attr: "i"
|
||||
side: "n"
|
||||
desc: 升降舵
|
||||
engine:
|
||||
-
|
||||
id: eng_1
|
||||
desc: "主引擎"
|
||||
vector: False
|
3
comet/model_cfg/jf_17_pm/index.yaml
Normal file
3
comet/model_cfg/jf_17_pm/index.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
name: "jf_17_pm"
|
||||
desc: "枭龙 单引擎单垂尾常规布局航模 螺旋桨驱动 尺寸修改型"
|
||||
view: ./src/view.png
|
BIN
comet/model_cfg/jf_17_pm/reference/3view.png
Normal file
BIN
comet/model_cfg/jf_17_pm/reference/3view.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
BIN
comet/model_cfg/jf_17_pm/reference/image.png
Normal file
BIN
comet/model_cfg/jf_17_pm/reference/image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 692 KiB |
BIN
comet/model_cfg/jf_17_pm/reference/logo.png
Normal file
BIN
comet/model_cfg/jf_17_pm/reference/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
BIN
comet/model_cfg/jf_17_pm/src/view.bmp
Normal file
BIN
comet/model_cfg/jf_17_pm/src/view.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
BIN
comet/model_cfg/jf_17_pm/src/view.png
Normal file
BIN
comet/model_cfg/jf_17_pm/src/view.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
98
lib/agency.py
Normal file
98
lib/agency.py
Normal file
@ -0,0 +1,98 @@
|
||||
"""
|
||||
filename: agency.py
|
||||
description: WebSocket network agency for AiraPulsar components.
|
||||
This module serves as a universal client module for Moons,
|
||||
facilitating communication between Pulsar/Comet and Moons.
|
||||
"""
|
||||
import websocket
|
||||
import json
|
||||
from loguru import logger
|
||||
import threading
|
||||
import time
|
||||
|
||||
# 配置日志
|
||||
logger.add("agent_logs.log", rotation="1 MB", level="INFO", format="{time} - {level} - {message}")
|
||||
|
||||
class Agent(object):
|
||||
"""
|
||||
handler: function which processes args
|
||||
receiver: sendto
|
||||
emitter: sendfrom
|
||||
content: original string data
|
||||
data: formatted json data -> dict
|
||||
"""
|
||||
wsapp = None
|
||||
is_connected = 0
|
||||
def __init__(self, name, addr, handler):
|
||||
logger.add("agent_logs.log", rotation="1 MB", level="INFO", format="{time} - {level} - {message}")
|
||||
logger.info("初始化代理对象")
|
||||
logger.info(f"卫星地址: {addr}")
|
||||
logger.info(f"代理对象代号: {name}")
|
||||
self.name = name
|
||||
self.addr = addr
|
||||
self.handler = handler
|
||||
self.wsapp = websocket.WebSocketApp(
|
||||
f"{addr}",
|
||||
on_open=self.__on_open,
|
||||
on_message=self.__on_message,
|
||||
on_close=self.__on_close
|
||||
)
|
||||
|
||||
def __dumper(self, receiver: str, content: dict):
|
||||
msg = {
|
||||
"id": self.name,
|
||||
"receiver": receiver,
|
||||
"content": content
|
||||
}
|
||||
return msg
|
||||
|
||||
def __loader(self, received_data: str):
|
||||
try:
|
||||
data = json.loads(received_data)
|
||||
content = data["content"]
|
||||
emitter = data["emitter"]
|
||||
return {"content": content, "emitter": emitter}
|
||||
except json.JSONDecodeError:
|
||||
logger.error("接收到的消息不是有效的 JSON 格式")
|
||||
return {"content": None, "emitter": None}
|
||||
|
||||
def __on_open(self, wsapp):
|
||||
start_time = time.time()
|
||||
self.send(receiver="auth", data="auth")
|
||||
self.is_connected = True
|
||||
end_time = time.time()
|
||||
delta = end_time - start_time
|
||||
logger.info(f"成功建立连接, 单向延迟 {round(delta*10000)/10}ms")
|
||||
|
||||
def __on_message(self, wsapp, message):
|
||||
loaded_data = self.__loader(message)
|
||||
if loaded_data["emitter"] is not None and loaded_data["content"] is not None:
|
||||
self.handler(emitter=loaded_data["emitter"],
|
||||
content=loaded_data["content"])
|
||||
|
||||
def __on_close(self, wsapp):
|
||||
self.is_connected = False
|
||||
logger.info("WebSocket 连接已关闭")
|
||||
|
||||
def send(self, receiver: str, data):
|
||||
if isinstance(data, dict):
|
||||
self.wsapp.send(
|
||||
json.dumps(self.__dumper(receiver, data))
|
||||
)
|
||||
elif isinstance(data, str):
|
||||
self.wsapp.send(
|
||||
json.dumps(self.__dumper(receiver, data))
|
||||
)
|
||||
else:
|
||||
logger.warning("数据类型不支持")
|
||||
|
||||
def run(self):
|
||||
self.wsapp.run_forever()
|
||||
|
||||
def runasthread(self):
|
||||
thread = threading.Thread(target=self.wsapp.run_forever)
|
||||
thread.start()
|
||||
logger.info("等待连接成功")
|
||||
while self.is_connected == 0:
|
||||
time.sleep(0.1)
|
||||
logger.info("连接成功, 取消阻塞")
|
13
moon/README.md
Normal file
13
moon/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Moon - 中继服务器
|
||||
Moon(卫星) 是 AiraPulsar 飞行控制系统的中继服务器
|
||||
|
||||
Comet(飞行器) 与 Pulsar(控制器) 通过 Moon(中继服务器) 进行通讯
|
||||
|
||||
这样做的好处:
|
||||
- 无需设置第三方内网穿透
|
||||
- 轻松查阅连接日志
|
||||
- 可扩展至多端远程架构
|
||||
- 仅需一个地址即可完成通讯
|
||||
- 便于第三方介入
|
||||
|
||||
建议将 Moon 部署至公网环境服务器中
|
119
moon/logs.log
Normal file
119
moon/logs.log
Normal file
@ -0,0 +1,119 @@
|
||||
2025-03-07T08:44:59.049714+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T08:54:33.168394+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T08:56:35.504311+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T08:57:12.572151+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T08:57:13.906086+0800 - INFO - 新客户端连接: 2
|
||||
2025-03-07T08:57:18.478193+0800 - INFO - 客户端断开连接: 2
|
||||
2025-03-07T08:58:55.383088+0800 - INFO - 新客户端连接: 3
|
||||
2025-03-07T08:59:04.634280+0800 - INFO - 客户端断开连接: 3
|
||||
2025-03-07T08:59:05.383848+0800 - INFO - 新客户端连接: 4
|
||||
2025-03-07T08:59:51.560133+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T08:59:52.909275+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T08:59:55.915998+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:00:43.283319+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:00:44.635715+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:01:29.896734+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:01:31.332525+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:02:17.026957+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:02:18.296634+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:02:48.143588+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:02:49.427049+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:03:10.834981+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:03:12.119704+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:03:12.119986+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:03:12.120071+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:03:42.168476+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:03:43.472305+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:03:43.472547+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:11:05.352860+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:11:06.882419+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:11:06.882773+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:12:14.693477+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:12:16.851004+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:12:16.851656+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:09.007145+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:19:10.754140+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:19:10.754434+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:18.493238+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:19:20.016578+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:19:20.016862+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:37.700993+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:19:39.081530+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:19:39.081796+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:19:43.080448+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:19:43.080720+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:20:12.487057+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:20:13.857585+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:20:13.857880+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:20:14.799728+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:20:17.208026+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:20:22.577076+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:20:22.577489+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:20:23.575751+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:20:23.576044+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:26:56.246176+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:26:57.807128+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:26:57.807419+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:26:58.805874+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:26:58.806066+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:28:25.117434+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:28:26.673876+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:28:26.674262+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:28:27.671936+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:28:27.672177+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:28:29.778081+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:28:33.464911+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:28:35.158721+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:28:35.159064+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:28:36.157310+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:28:36.157514+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:29:18.205614+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:29:22.053522+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:29:25.102228+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:29:25.102476+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:29:26.101162+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": "hi"}
|
||||
2025-03-07T09:29:26.101351+0800 - ERROR - 无法解码 JSON 消息
|
||||
2025-03-07T09:30:12.603632+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:30:13.967524+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:30:13.967874+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:30:14.966548+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": {"hi": "hi"}}
|
||||
2025-03-07T09:30:14.966787+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T09:31:19.129916+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:31:20.564382+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:31:20.564841+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:31:21.562523+0800 - INFO - 处理信息: {"id": "comet", "receiver": "1", "content": {"hi": "hi"}}
|
||||
2025-03-07T09:31:21.562718+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T09:31:31.503846+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T09:31:41.873175+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T09:31:41.873532+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T09:31:42.872072+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T09:31:42.872284+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T09:31:42.872356+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T10:02:07.173456+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T10:02:22.249420+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T10:02:22.249683+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T10:02:22.348277+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T10:02:22.348428+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T10:02:22.348504+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:55:54.389580+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T15:55:55.865014+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T15:55:55.865334+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T15:55:55.964049+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T15:55:55.964208+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:55:55.964276+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:55:58.304575+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T15:56:27.769208+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T15:56:29.266347+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T15:56:29.266586+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T15:56:29.365433+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T15:56:29.365581+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:56:29.365643+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:56:45.972404+0800 - INFO - 启动"卫星"中继服务器: ws://0.0.0.0:8765
|
||||
2025-03-07T15:56:47.268864+0800 - INFO - 新客户端连接: 1
|
||||
2025-03-07T15:56:47.269164+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
||||
2025-03-07T15:56:47.367838+0800 - INFO - 处理信息: {"id": "comet", "receiver": "*", "content": {"hi": "hi"}}
|
||||
2025-03-07T15:56:47.367979+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T15:56:47.368041+0800 - WARNING - 无法发送至端点
|
||||
2025-03-07T17:45:07.183410+0800 - INFO - 客户端断开连接: 1
|
||||
2025-03-07T17:45:08.365484+0800 - INFO - 新客户端连接: 2
|
||||
2025-03-07T17:45:08.365737+0800 - INFO - 处理信息: {"id": "comet", "receiver": "auth", "content": "auth"}
|
79
moon/moon.py
Normal file
79
moon/moon.py
Normal file
@ -0,0 +1,79 @@
|
||||
import json
|
||||
from loguru import logger
|
||||
import yaml
|
||||
from websocket_server import WebsocketServer
|
||||
import os
|
||||
|
||||
# 设置当前工作目录
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# 配置日志
|
||||
logger.add("logs.log", rotation="1 MB", level="INFO", format="{time} - {level} - {message}")
|
||||
|
||||
moon_addr = None
|
||||
port = None
|
||||
|
||||
with open('moon_config.yaml', 'r') as config_file:
|
||||
config = yaml.safe_load(config_file)
|
||||
moon_addr = config.get("addr", "127.0.0.1")
|
||||
port = config.get("port", 8765)
|
||||
|
||||
clients = dict() # id -> name
|
||||
clients_rev = dict() # name -> id
|
||||
clients_connection = dict() # id -> client obj
|
||||
|
||||
def new_client(client, server):
|
||||
clients_connection[client["id"]] = client
|
||||
logger.info(f"新客户端连接: {client['id']}")
|
||||
|
||||
def client_left(client, server):
|
||||
logger.info(f"客户端断开连接: {client['id']}")
|
||||
# 连接关闭时从集合中移除
|
||||
if client in clients.values():
|
||||
clients.pop(clients_rev[client['id']])
|
||||
clients_rev.pop(client['id'])
|
||||
|
||||
def message_received(client, server, message):
|
||||
logger.info(f"处理信息: {message}")
|
||||
try:
|
||||
msg = json.loads(message)
|
||||
clients[msg["id"]] = client['id']
|
||||
clients_rev[client['id']] = msg["id"]
|
||||
|
||||
if msg["receiver"] == "auth":
|
||||
return
|
||||
|
||||
if msg["receiver"] == "*":
|
||||
try:
|
||||
for i in clients_rev.values():
|
||||
content = msg["content"]
|
||||
content["emitter"] = msg["id"]
|
||||
server.send_message(
|
||||
clients_connection[i],
|
||||
json.dumps(content))
|
||||
except KeyError:
|
||||
logger.warning("无法发送至端点")
|
||||
|
||||
try:
|
||||
content = msg["content"]
|
||||
content["emitter"] = msg["id"]
|
||||
server.send_message(
|
||||
clients_connection[clients[msg["receiver"]]],
|
||||
json.dumps(content))
|
||||
except KeyError:
|
||||
logger.warning("无法发送至端点")
|
||||
except json.JSONDecodeError:
|
||||
logger.error("无法解码 JSON 消息")
|
||||
|
||||
def main():
|
||||
global moon_addr
|
||||
global port
|
||||
server = WebsocketServer(host=moon_addr, port=port)
|
||||
server.set_fn_new_client(new_client)
|
||||
server.set_fn_client_left(client_left)
|
||||
server.set_fn_message_received(message_received)
|
||||
logger.info(f'启动"卫星"中继服务器: ws://{moon_addr}:{port}')
|
||||
server.run_forever()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
2
moon/moon_config.yaml
Normal file
2
moon/moon_config.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
addr: 0.0.0.0
|
||||
port: 8765
|
59
pulsar/1.py
Normal file
59
pulsar/1.py
Normal file
@ -0,0 +1,59 @@
|
||||
import pygame
|
||||
import sys
|
||||
|
||||
# 初始化 Pygame
|
||||
pygame.init()
|
||||
|
||||
# 设置窗口大小
|
||||
width, height = 800, 600
|
||||
screen = pygame.display.set_mode((width, height))
|
||||
pygame.display.set_caption("Pygame Draw Example")
|
||||
|
||||
# 定义颜色
|
||||
BLACK = (0, 0, 0)
|
||||
WHITE = (255, 255, 255)
|
||||
RED = (255, 0, 0)
|
||||
GREEN = (0, 255, 0)
|
||||
BLUE = (0, 0, 255)
|
||||
YELLOW = (255, 255, 0)
|
||||
|
||||
# 主循环
|
||||
running = True
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
# 填充背景
|
||||
screen.fill(WHITE)
|
||||
|
||||
# 绘制线条
|
||||
pygame.draw.line(screen, RED, (50, 50), (200, 50), 5)
|
||||
pygame.draw.aaline(screen, BLUE, (50, 100), (200, 100))
|
||||
|
||||
# 绘制矩形
|
||||
pygame.draw.rect(screen, GREEN, (50, 150, 150, 100), 0) # 填充矩形
|
||||
pygame.draw.rect(screen, BLACK, (250, 150, 150, 100), 5) # 边框矩形
|
||||
|
||||
# 绘制圆形
|
||||
pygame.draw.circle(screen, YELLOW, (400, 200), 50, 0) # 填充圆形
|
||||
pygame.draw.circle(screen, BLACK, (500, 200), 50, 5) # 边框圆形
|
||||
|
||||
# 绘制椭圆
|
||||
pygame.draw.ellipse(screen, BLUE, (50, 300, 200, 100), 0) # 填充椭圆
|
||||
pygame.draw.ellipse(screen, BLACK, (300, 300, 200, 100), 5) # 边框椭圆
|
||||
|
||||
# 绘制多边形
|
||||
points = [(600, 400), (700, 300), (800, 400), (700, 500)]
|
||||
pygame.draw.polygon(screen, GREEN, points, 0) # 填充多边形
|
||||
pygame.draw.polygon(screen, BLACK, points, 5) # 边框多边形
|
||||
|
||||
# 绘制弧
|
||||
pygame.draw.arc(screen, RED, (50, 450, 200, 100), 0, 3.14, 5) # 弧
|
||||
|
||||
# 更新显示
|
||||
pygame.display.flip()
|
||||
|
||||
# 退出 Pygame
|
||||
pygame.quit()
|
||||
sys.exit()
|
4
pulsar/README.md
Normal file
4
pulsar/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Pulsar - 控制器侧载端
|
||||
Pulsar(脉冲星) 是 AiraPulsar 飞行控制系统的控制器侧载端, 项目亦由此而得名
|
||||
|
||||
Pulsar(控制器) 通过 Moon(中继服务器) 进行通讯, 给 Comet(飞行器) 发送指令
|
43
pulsar/graph.py
Normal file
43
pulsar/graph.py
Normal file
@ -0,0 +1,43 @@
|
||||
import pygame
|
||||
|
||||
class Graph:
|
||||
def rect(frame, position: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.rect(frame.surface, color=color, rect=(position[0], position[1], size[0], size[1]), width=width)
|
||||
|
||||
def line(frame, start_pos: tuple, end_pos: tuple, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.aaline(frame.surface, color, start_pos, end_pos)
|
||||
|
||||
def circle(frame, center: tuple, radius: int, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.circle(frame.surface, color, center, radius, width)
|
||||
|
||||
def ellipse(frame, rect: tuple, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.ellipse(frame.surface, color, rect, width)
|
||||
|
||||
def polygon(frame, pointlist: list, color: tuple = (255, 255, 255), width: int = 0):
|
||||
pygame.draw.polygon(frame.surface, color, pointlist, width)
|
||||
|
||||
def arc(frame, rect: tuple, color: tuple = (255, 255, 255), start_angle: float = 0, stop_angle: float = 3.14, width: int = 1):
|
||||
pygame.draw.arc(frame.surface, color, rect, start_angle, stop_angle, width)
|
||||
|
||||
def points(frame, pos: tuple, color: tuple = (255, 255, 255)):
|
||||
pygame.draw.point(frame.surface, color, pos)
|
||||
|
||||
def lines(frame, pointlist: list, color: tuple = (255, 255, 255), closed: bool = False):
|
||||
pygame.draw.aalines(frame.surface, color, closed, pointlist)
|
||||
|
||||
class Frame(object):
|
||||
name = None
|
||||
size = None
|
||||
surface = None
|
||||
is_hide = False
|
||||
def __init__(self, name: str, size: tuple):
|
||||
self.name = name
|
||||
self.surface = pygame.Surface(size, flags=pygame.HWSURFACE)
|
||||
print("初始化子模块")
|
||||
def show(self, window, position: tuple):
|
||||
if not self.is_hide:
|
||||
window.blit(self.surface, position)
|
||||
def set_visible(self, newstat=True):
|
||||
self.is_hide = newstat
|
||||
def set_position(self, newposition):
|
||||
self.position = newposition
|
1
pulsar/lib
Symbolic link
1
pulsar/lib
Symbolic link
@ -0,0 +1 @@
|
||||
../lib
|
3
testfield/README.md
Normal file
3
testfield/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# 实验与参考用代码
|
||||
仅作技术分析验证与历史留存, 若要修改此项目代码, 不必处理此文件夹
|
||||
若你要使用此软件, 可以克隆后直接将 testfield 文件夹删除
|
2
testfield/network/README.md
Normal file
2
testfield/network/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Sin 波形传输 [成功]
|
||||
基于 websocket 的通讯功能模型测试
|
70
testfield/network/sin_comet.py
Normal file
70
testfield/network/sin_comet.py
Normal file
@ -0,0 +1,70 @@
|
||||
import pygame
|
||||
import sys
|
||||
import threading
|
||||
import math
|
||||
import websocket
|
||||
import json
|
||||
import time
|
||||
sin_remote = 0
|
||||
th1 = None
|
||||
th2 = None
|
||||
moon_addr = "127.0.0.1"
|
||||
def on_open(wsapp):
|
||||
print("打开新连接")
|
||||
print("准备待命")
|
||||
message = {
|
||||
"id": "comet",
|
||||
"sendto": "auth",
|
||||
"content": "none"
|
||||
}
|
||||
wsapp.send(json.dumps(message))
|
||||
|
||||
def on_message(wsapp, message):
|
||||
global sin_remote
|
||||
print(f"接收到消息: {message}")
|
||||
if message == "-3":
|
||||
th1.start()
|
||||
sin_remote = float(message)
|
||||
|
||||
def on_close(wsapp):
|
||||
print("on_close")
|
||||
|
||||
def inet():
|
||||
global sin_remote
|
||||
wsapp = websocket.WebSocketApp(f"ws://{moon_addr}:8765",
|
||||
on_open=on_open,
|
||||
on_message=on_message,
|
||||
on_close=on_close)
|
||||
wsapp.run_forever()
|
||||
|
||||
def grap():
|
||||
pygame.init()
|
||||
width, height = 628, 600
|
||||
screen = pygame.display.set_mode((width, height))
|
||||
pygame.display.set_caption("TEST")
|
||||
LOCAL_COLOR = (255, 255, 255, 64)
|
||||
REMOTE_COLOR = [(0, 0, 255, 128), (255, 0, 0, 128)]
|
||||
frequency = 0.01 # 波动频率
|
||||
amplitude = 100 # 波动幅度
|
||||
x = round(time.time()*1000)
|
||||
while True:
|
||||
x = round(time.time()*1000)
|
||||
x = x % 628
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
|
||||
#pygame.draw.rect(screen, (0, 0, 0), (x, 0, 5, height)) # 扫描线
|
||||
y = height // 2 + amplitude * math.sin((x * frequency))
|
||||
y_remote = height // 2 + amplitude * sin_remote
|
||||
pygame.draw.rect(screen, (round(time.time()*1000+120)%256,round(time.time()*1000)%256,round(time.time()*1000+60)%256), (x, int(y_remote), 4, 4)) # 远程波形
|
||||
pygame.draw.rect(screen, LOCAL_COLOR, (x, int(y), 2, 2)) # 本地波形
|
||||
pygame.display.flip()
|
||||
pygame.time.delay(10)
|
||||
|
||||
if __name__ == "__main__":
|
||||
th1 = threading.Thread(target=grap)
|
||||
th2 = threading.Thread(target=inet)
|
||||
# 启动线程
|
||||
th2.start()
|
44
testfield/network/sin_moon.py
Normal file
44
testfield/network/sin_moon.py
Normal file
@ -0,0 +1,44 @@
|
||||
import json
|
||||
from websocket_server import WebsocketServer
|
||||
moon_addr = "127.0.0.1"
|
||||
clients = dict() # id -> name
|
||||
clients_rev = dict() # name -> id
|
||||
clients_connection = dict() # id -> client obj
|
||||
|
||||
def new_client(client, server):
|
||||
clients_connection[client["id"]] = client
|
||||
print(f"新客户端连接: {client['id']}")
|
||||
|
||||
def client_left(client, server):
|
||||
print(f"客户端断开连接: {client['id']}")
|
||||
# 连接关闭时从集合中移除
|
||||
if client in clients.values():
|
||||
clients.pop(clients_rev[client['id']])
|
||||
clients_rev.pop(client['id'])
|
||||
|
||||
def message_received(client, server, message):
|
||||
print(f"处理信息: {message}")
|
||||
try:
|
||||
msg = json.loads(message)
|
||||
clients[msg["id"]] = client['id']
|
||||
clients_rev[client['id']] = msg["id"]
|
||||
if msg["sendto"] == "auth":
|
||||
return
|
||||
try:
|
||||
server.send_message(clients_connection[clients[msg["sendto"]]], msg["content"])
|
||||
except KeyError:
|
||||
print("无法发送至端点")
|
||||
except json.JSONDecodeError:
|
||||
print("无法解码 JSON 消息")
|
||||
|
||||
def main():
|
||||
server = WebsocketServer(host=f'{moon_addr}', port=8765)
|
||||
server.set_fn_new_client(new_client)
|
||||
server.set_fn_client_left(client_left)
|
||||
server.set_fn_message_received(message_received)
|
||||
|
||||
print(f'启动"卫星"中继服务器: ws://{moon_addr}:8765')
|
||||
server.run_forever()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
34
testfield/network/sin_pulsar.py
Normal file
34
testfield/network/sin_pulsar.py
Normal file
@ -0,0 +1,34 @@
|
||||
import websocket
|
||||
import threading
|
||||
import math
|
||||
import json
|
||||
import time
|
||||
moon_addr = "127.0.0.1"
|
||||
def on_open(wsapp):
|
||||
print("打开新的连接")
|
||||
input("回车以启动同步: ")
|
||||
message = {
|
||||
"id": "pulsar",
|
||||
"sendto": "comet",
|
||||
"content": "-3"
|
||||
}
|
||||
wsapp.send(json.dumps(message))
|
||||
x = round(time.time()*1000)
|
||||
while 1:
|
||||
x = round(time.time()*1000)
|
||||
x = x % 628
|
||||
message["content"] = str(math.sin(x*0.01))
|
||||
wsapp.send(json.dumps(message))
|
||||
time.sleep(0.01)
|
||||
|
||||
def on_message(wsapp, message):
|
||||
print("on_message:", message)
|
||||
|
||||
def on_close(wsapp):
|
||||
print("on_close")
|
||||
|
||||
wsapp = websocket.WebSocketApp(f"ws://{moon_addr}:8765",
|
||||
on_open=on_open,
|
||||
on_message=on_message,
|
||||
on_close=on_close)
|
||||
wsapp.run_forever()
|
2
testfield/visual/README.md
Normal file
2
testfield/visual/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# 总览测试
|
||||
基于 bmp 的通讯功能模型测试
|
63
testfield/visual/main.py
Normal file
63
testfield/visual/main.py
Normal file
@ -0,0 +1,63 @@
|
||||
from PIL import Image
|
||||
import pygame
|
||||
import sys
|
||||
import time
|
||||
|
||||
colorzone = dict()
|
||||
|
||||
def img():
|
||||
# 打开 BMP 文件
|
||||
bmp_image = Image.open('view.bmp')
|
||||
|
||||
# 获取图像的基本信息
|
||||
width, height = bmp_image.size
|
||||
mode = bmp_image.mode
|
||||
|
||||
print(f"图像宽度: {width}, 高度: {height}, 模式: {mode}")
|
||||
|
||||
# 读取图像数据
|
||||
pixel_data = bmp_image.load() # 获取像素数据
|
||||
|
||||
# 遍历每个像素并打印其 RGB 值
|
||||
minleft = 0x3f3f3f3f
|
||||
mintop = 0x3f3f3f3f
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
minleft = min(minleft, x)
|
||||
mintop = min(mintop, y)
|
||||
r, g, b = pixel_data[x, y] # 获取每个像素的 RGB 值
|
||||
if r == 255 and b == 255 and g == 255:
|
||||
pass
|
||||
else:
|
||||
if (r,g,b) in colorzone:
|
||||
colorzone[(r,g,b)].append(((x//8)*4,(y//8)*4))
|
||||
else:
|
||||
colorzone[(r,g,b)] = list()
|
||||
colorzone[(r,g,b)].append((x//8*4,y//8*4))
|
||||
#print(f"像素 ({x}, {y}): R={r}, G={g}, B={b}")
|
||||
|
||||
colorzone[(255,255,255)] = colorzone[(0,0,0)]
|
||||
# 关闭图像
|
||||
bmp_image.close()
|
||||
|
||||
def grap():
|
||||
pygame.init()
|
||||
width, height = 800, 1000
|
||||
screen = pygame.display.set_mode((width, height))
|
||||
pygame.display.set_caption("TEST")
|
||||
global colorzone
|
||||
while True:
|
||||
for i in colorzone.keys():
|
||||
for j in colorzone[i]:
|
||||
if i != (255,255,255):
|
||||
pygame.draw.rect(screen, i, (j[0], j[1], 2, 2)) # 远程波形
|
||||
else:
|
||||
pygame.draw.rect(screen, i, (j[0], j[1], 1, 1)) # 远程波形
|
||||
pygame.display.flip()
|
||||
pygame.time.delay(10)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("START")
|
||||
img()
|
||||
print("LOADED")
|
||||
grap()
|
BIN
testfield/visual/view.bmp
Normal file
BIN
testfield/visual/view.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
17
testfield/visual/viewcfg.yaml
Normal file
17
testfield/visual/viewcfg.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
# 机体: Fuselage -> fuse
|
||||
# 副翼: Aileron -> aile
|
||||
# 襟翼: Flap -> flap
|
||||
# 发动机: Engine -> eng
|
||||
# 控制器: Controller -> ctrl
|
||||
# 方向舵: Rudder -> rud
|
||||
# 俯仰舵: Elevator -> elev
|
||||
marking:
|
||||
|
||||
color_config:
|
||||
fuselage: (255,255,255)
|
||||
aileron: ()
|
||||
flap:
|
||||
engine:
|
||||
controller: (255,255,255)
|
||||
rudder:
|
||||
elevator:
|
Loading…
x
Reference in New Issue
Block a user