Compare commits
443
Commits
master
..
1a4ba3b896
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a4ba3b896 | ||
|
|
cc56c9c0ef | ||
|
|
3292fd8a30 | ||
|
|
848a866491 | ||
|
|
465253434e | ||
|
|
b420396896 | ||
|
|
9af5f221e7 | ||
|
|
c7b13c1e66 | ||
|
|
26968a0cc2 | ||
|
|
3f6fc6b1e5 | ||
|
|
68ea437305 | ||
|
|
b16a91f3d4 | ||
|
|
65370b01a8 | ||
|
|
46ab42e8c0 | ||
|
|
aecc14dfc2 | ||
|
|
9f5b78f6ff | ||
|
|
fd249860de | ||
|
|
de05c6bcff | ||
|
|
615b8b3e89 | ||
|
|
52d9b0c9ef | ||
|
|
fdc6706dc1 | ||
|
|
276e953c4b | ||
|
|
84fd7aa6f4 | ||
|
|
f957cb8205 | ||
|
|
1c07896b2f | ||
|
|
13091317f3 | ||
|
|
f16890d5d3 | ||
|
|
4313143f18 | ||
|
|
8d3347dc2f | ||
|
|
6f9043a8e4 | ||
|
|
e5e0306ca4 | ||
|
|
b32d04c529 | ||
|
|
6508a0c246 | ||
|
|
2b421c6f6b | ||
|
|
a8c416eacc | ||
|
|
93bed7edc6 | ||
|
|
e2ebf32698 | ||
|
|
c74f9b1078 | ||
|
|
73e1d8825f | ||
|
|
708d8c5a71 | ||
|
|
36bd9ae674 | ||
|
|
b682bb8e19 | ||
|
|
d27a9d81a3 | ||
|
|
83c6621482 | ||
|
|
e75a1c983d | ||
|
|
aba81a02c1 | ||
|
|
12798c8588 | ||
|
|
22a375a2ee | ||
|
|
93757eeb2f | ||
|
|
1919e6291f | ||
|
|
5b076f81a8 | ||
|
|
0b0d9a837c | ||
|
|
16c746ad2d | ||
|
|
8830f7e2ef | ||
|
|
fcfcfe4c7c | ||
|
|
5172a24509 | ||
|
|
0764e76ddb | ||
|
|
cf470109e7 | ||
|
|
5cc6613a3e | ||
|
|
7a88ffbfa7 | ||
|
|
40fcbbf578 | ||
|
|
78f8edcecf | ||
|
|
df93fcbdc0 | ||
|
|
75bfa63a22 | ||
|
|
7dd9b5a490 | ||
|
|
1b111e5547 | ||
|
|
92c2947c95 | ||
|
|
af1032f8ca | ||
|
|
ac3c6e1715 | ||
|
|
d09aac119c | ||
|
|
38dfafc141 | ||
|
|
33a3bf1d68 | ||
|
|
3ced88ec84 | ||
|
|
499682c1f2 | ||
|
|
8bc2d51af0 | ||
|
|
e200898015 | ||
|
|
78e95f3650 | ||
|
|
5d38bdccda | ||
|
|
bc1deab1e9 | ||
|
|
b3525a8185 | ||
|
|
f55ad94ec6 | ||
|
|
e14084b13f | ||
|
|
105c8911ac | ||
|
|
3a6473f278 | ||
|
|
3c95662453 | ||
|
|
cd70b150b0 | ||
|
|
6fb91723bb | ||
|
|
cdb0d7de26 | ||
|
|
0c59db3d1c | ||
|
|
54915d6dc6 | ||
|
|
c8b632ea68 | ||
|
|
1e7bd49677 | ||
|
|
19264b0232 | ||
|
|
efc02342e6 | ||
|
|
0e142f4e66 | ||
|
|
ceffff46b8 | ||
|
|
c2cec9b95d | ||
|
|
07a301bc84 | ||
|
|
e1bc98509d | ||
|
|
de5cf41385 | ||
|
|
763bae7791 | ||
|
|
6e2f471b5a | ||
|
|
b04f2ad8e2 | ||
|
|
54a05bf06e | ||
|
|
ce9329f20e | ||
|
|
2f22bd0316 | ||
|
|
227c1988f7 | ||
|
|
edbb314ca6 | ||
|
|
55598ae10a | ||
|
|
e7af22b776 | ||
|
|
e2cfa3aa20 | ||
|
|
23764e4a36 | ||
|
|
c64b4cfb43 | ||
|
|
316a067f56 | ||
|
|
47d918d633 | ||
|
|
621676c85e | ||
|
|
5d4d762b9b | ||
|
|
c9e0eef4b8 | ||
|
|
9ef2705543 | ||
|
|
017199f318 | ||
|
|
7136a33f63 | ||
|
|
2c0db0169c | ||
|
|
14a63d584d | ||
|
|
52b93fd4da | ||
|
|
af008e165c | ||
|
|
eceac6ca6d | ||
|
|
f7a3c0ec27 | ||
|
|
39a449d818 | ||
|
|
e7bebcb07b | ||
|
|
4c4f7c8af4 | ||
|
|
8020d862e3 | ||
|
|
5046eb26dd | ||
|
|
7a64390310 | ||
|
|
4b7c4ff93f | ||
|
|
ec7ac820cd | ||
|
|
a7ada08b15 | ||
|
|
57a07815a2 | ||
|
|
cda6ab93a0 | ||
|
|
edeeb9463f | ||
|
|
3d04e90d37 | ||
|
|
96b8da01da | ||
|
|
894809401c | ||
|
|
8c368adf02 | ||
|
|
d4dc5812a6 | ||
|
|
05671eb309 | ||
|
|
ca27877268 | ||
|
|
781be047fa | ||
|
|
bcc7aa2869 | ||
|
|
13026df615 | ||
|
|
cba8a071bc | ||
|
|
a4287d64a3 | ||
|
|
e7e4a9950b | ||
|
|
60e8be3ba5 | ||
|
|
129e31b7a2 | ||
|
|
9c3dfbbbbf | ||
|
|
82e3148975 | ||
|
|
d374248ca5 | ||
|
|
7bf1646d1e | ||
|
|
a02d71eb93 | ||
|
|
810701ef1f | ||
|
|
b2b64ca5c2 | ||
|
|
bcd8cd35a5 | ||
|
|
a7a1fb61b4 | ||
|
|
ff5b584d9c | ||
|
|
bfc1fedbde | ||
|
|
af52445efa | ||
|
|
449873950c | ||
|
|
022d98be9c | ||
|
|
318088797d | ||
|
|
6c88f3a9cc | ||
|
|
3e1c20ba08 | ||
|
|
14defb2e10 | ||
|
|
91a8020659 | ||
|
|
c474a182ea | ||
|
|
09ee7127dc | ||
|
|
8e2620dae0 | ||
|
|
1b360d8c89 | ||
|
|
e4f6e8b2b8 | ||
|
|
8e392679c1 | ||
|
|
0e7d01edbd | ||
|
|
8f3e4250fe | ||
|
|
db25d6553a | ||
|
|
86d63d4460 | ||
|
|
50518c5035 | ||
|
|
d75a8bb2b2 | ||
|
|
927b11e2bf | ||
|
|
3f618711bd | ||
|
|
5c2d042211 | ||
|
|
1a9279e152 | ||
|
|
a356870ac1 | ||
|
|
457983cff0 | ||
|
|
34622c5efe | ||
|
|
7f5d34a405 | ||
|
|
3fa3669f34 | ||
|
|
901c49017b | ||
|
|
17c73e06f3 | ||
|
|
2c1bb808fd | ||
|
|
34f1a2c15b | ||
|
|
e8c53a6fed | ||
|
|
8589485e8f | ||
|
|
ff77541f12 | ||
|
|
33e7a0b919 | ||
|
|
1d60de2ec8 | ||
|
|
e892f998d4 | ||
|
|
f9d3ecfbdc | ||
|
|
3603732b51 | ||
|
|
337338f5c8 | ||
|
|
894ef7f081 | ||
|
|
c27fabee9b | ||
|
|
b20b01d770 | ||
|
|
0348ba0da9 | ||
|
|
26d36c7dd8 | ||
|
|
0e84e0abe5 | ||
|
|
789eb7434b | ||
|
|
502a1996b4 | ||
|
|
0656f81f0b | ||
|
|
14cc8a79e4 | ||
|
|
88156ae02d | ||
|
|
f2a8564cae | ||
|
|
57eac1e589 | ||
|
|
be956d5d4f | ||
|
|
1a3d79334f | ||
|
|
a02d2768f5 | ||
|
|
51a4bcb237 | ||
|
|
7193f5796e | ||
|
|
a26271b4c9 | ||
|
|
3048518868 | ||
|
|
a605bbafaf | ||
|
|
f87cc98664 | ||
|
|
3d1e5e27fc | ||
|
|
c360292302 | ||
|
|
3fd79a43ec | ||
|
|
58a928b4a1 | ||
|
|
3037f62d96 | ||
|
|
8a5e6179f4 | ||
|
|
5d3c948219 | ||
|
|
9812e9bcde | ||
|
|
4583d9c6b8 | ||
|
|
588b4b29f0 | ||
|
|
7662dabc77 | ||
|
|
561b5899d3 | ||
|
|
856eeacf6b | ||
|
|
9414bbf1d2 | ||
|
|
47d07157cd | ||
|
|
dd4484d205 | ||
|
|
3454dd6e82 | ||
|
|
ca92c0ca48 | ||
|
|
385844c14f | ||
|
|
e7bcc797af | ||
|
|
1baf80741f | ||
|
|
93b35031e6 | ||
|
|
38188a1e45 | ||
|
|
88193364fa | ||
|
|
df51b1c47b | ||
|
|
883b441ee1 | ||
|
|
541bdb52dc | ||
|
|
d97bd08048 | ||
|
|
50e48f437a | ||
|
|
c2bcd0d0ce | ||
|
|
305d6b9fae | ||
|
|
d09d246467 | ||
|
|
8af65974f7 | ||
|
|
7bd64ec88e | ||
|
|
0c6d0cf2c5 | ||
|
|
6851b406c3 | ||
|
|
394849b642 | ||
|
|
5f217d62ee | ||
|
|
3744d262a4 | ||
|
|
e5642e505f | ||
|
|
a316b71311 | ||
|
|
bab537caca | ||
|
|
11847a31d0 | ||
|
|
87b985ba95 | ||
|
|
77e00a61cd | ||
|
|
b5351677fe | ||
|
|
49da5b8ef5 | ||
|
|
742ea6d617 | ||
|
|
22f39e6523 | ||
|
|
a28eb8d69f | ||
|
|
5aa0faec1e | ||
|
|
b29b03b5f5 | ||
|
|
09230ea09f | ||
|
|
93b3ad36e9 | ||
|
|
d8534ee312 | ||
|
|
0112032a1e | ||
|
|
cca6126d2c | ||
|
|
ad0ac8ac90 | ||
|
|
d481f98640 | ||
|
|
7cfd9f70f2 | ||
|
|
c486309ff2 | ||
|
|
b0a1756cc9 | ||
|
|
4a0fad6dee | ||
|
|
5668320faf | ||
|
|
f1ab1a7118 | ||
|
|
6c0f1985ba | ||
|
|
17f700caee | ||
|
|
59d708acd7 | ||
|
|
999d73da21 | ||
|
|
27063979a3 | ||
|
|
a71066166a | ||
|
|
7df142a508 | ||
|
|
c3132a6aad | ||
|
|
4d6be4de65 | ||
|
|
8c3a1e8ccf | ||
|
|
3d604121fe | ||
|
|
83ca3b65f9 | ||
|
|
6269b56e06 | ||
|
|
92c210458a | ||
|
|
d496697297 | ||
|
|
44aba9ba2a | ||
|
|
8e10d22da4 | ||
|
|
8258e663b6 | ||
|
|
c3e81029e8 | ||
|
|
2c04933596 | ||
|
|
567641b3cf | ||
|
|
352a86eac1 | ||
|
|
acc3c11151 | ||
|
|
801d49565c | ||
|
|
4bf4183e43 | ||
|
|
c9ee7d8eb9 | ||
|
|
21079fdc85 | ||
|
|
553e431989 | ||
|
|
48ffc8c5f4 | ||
|
|
55bbdcacde | ||
|
|
2292603d6d | ||
|
|
788f1e460c | ||
|
|
0b825533c8 | ||
|
|
4467ebcd1b | ||
|
|
e5f8657ed6 | ||
|
|
6763d5d29d | ||
|
|
60b64d988b | ||
|
|
e6df3e487e | ||
|
|
9a37a0a0f0 | ||
|
|
5992430f1c | ||
|
|
b407486fcc | ||
|
|
5858c62bb5 | ||
|
|
e760e2f579 | ||
|
|
402f6a2b6a | ||
|
|
601b9cf0c2 | ||
|
|
1bdc4a03b1 | ||
|
|
e87e5c1118 | ||
|
|
25a94a3b1a | ||
|
|
26050ae306 | ||
|
|
a6188b8bdf | ||
|
|
e1e63f7dde | ||
|
|
d0a310b881 | ||
|
|
4ca00d7369 | ||
|
|
aedd240b34 | ||
|
|
f248f68e82 | ||
|
|
1d60c29789 | ||
|
|
a9bae06334 | ||
|
|
aca385f5b0 | ||
|
|
f4f657c701 | ||
|
|
8a26705d7a | ||
|
|
766131ecfe | ||
|
|
b1f5478eb9 | ||
|
|
78c7a9ef40 | ||
|
|
8457f3ac8f | ||
|
|
65c9d11296 | ||
|
|
db3808bd09 | ||
|
|
4c32a4fcb4 | ||
|
|
f82931da06 | ||
|
|
c3dc17bca0 | ||
|
|
c53d0ee4df | ||
|
|
299750d47e | ||
|
|
8375e95360 | ||
|
|
8625c80c71 | ||
|
|
5a4a6336cc | ||
|
|
b12e6f33d9 | ||
|
|
e0af5124a7 | ||
|
|
b526fdcd60 | ||
|
|
a7fef5ba7d | ||
|
|
58f9cec145 | ||
|
|
e812db544c | ||
|
|
17d87ef422 | ||
|
|
246f7a22cd | ||
|
|
90fc510a21 | ||
|
|
b03528530c | ||
|
|
21feba0141 | ||
|
|
937c23f2be | ||
|
|
b53c68bb7a | ||
|
|
f312acddc8 | ||
|
|
5012ad8ad7 | ||
|
|
bee5b3a67d | ||
|
|
578b390b72 | ||
|
|
9640f03e2e | ||
|
|
536d3d731c | ||
|
|
93d0994725 | ||
|
|
118769b2c5 | ||
|
|
147356b1ae | ||
|
|
e06c9c2979 | ||
|
|
9eed4f8a21 | ||
|
|
0a83d5e7fb | ||
|
|
cf6fc30a19 | ||
|
|
7bc4e5acb8 | ||
|
|
836d80e9b6 | ||
|
|
1f8b6a7826 | ||
|
|
8f5b49859c | ||
|
|
d79593d1da | ||
|
|
b78fd06342 | ||
|
|
400c15dd7d | ||
|
|
db64d2e2c0 | ||
|
|
c5b4af9657 | ||
|
|
1514939a58 | ||
|
|
f2e21205f0 | ||
|
|
0d49699b16 | ||
|
|
4795ec01e4 | ||
|
|
ab96e2cf41 | ||
|
|
4da41acc2c | ||
|
|
788f06d011 | ||
|
|
94f7f78bba | ||
|
|
f5331b9e47 | ||
|
|
79509ac6d4 | ||
|
|
e76cd3c238 | ||
|
|
5e870a1760 | ||
|
|
458a13746d | ||
|
|
32d53914d9 | ||
|
|
4baedab71e | ||
|
|
0a63e9f9df | ||
|
|
0f4ee99f05 | ||
|
|
ae849589eb | ||
|
|
a5ecfe614b | ||
|
|
7ffc0536cb | ||
|
|
6fe2baa57a | ||
|
|
16cfe7aceb | ||
|
|
239692a729 | ||
|
|
d920ea0690 | ||
|
|
cd33393885 | ||
|
|
37321cc36d | ||
|
|
052f533912 | ||
|
|
52256e07da | ||
|
|
77d3f76e60 | ||
|
|
87d3ac8c82 | ||
|
|
8a95de44f9 | ||
|
|
4d4daa5180 | ||
|
|
3bd0b81836 | ||
|
|
fd6701a0e6 | ||
|
|
a0968f46bc | ||
|
|
2fcedb0223 | ||
|
|
84de8fb2a0 | ||
|
|
6370d24f99 | ||
|
|
790c0a2188 | ||
|
|
d6f4f8cb54 |
@@ -0,0 +1,37 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: Build PC Client on Linux
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install PySide6 psutil pyinstaller
|
||||
- name: PyInstaller
|
||||
run: |
|
||||
cd ./software/pc
|
||||
pyinstaller hexapod.spec
|
||||
cp mainwindow.ui ./dist/hexapod/
|
||||
- name: Archive built module
|
||||
uses: actions/upload-artifact@v2
|
||||
if: success()
|
||||
with:
|
||||
name: hexapod_linux
|
||||
path: ./software/pc/dist/hexapod
|
||||
@@ -0,0 +1,37 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: Build PC Client on Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install PySide6 psutil pyinstaller
|
||||
- name: PyInstaller
|
||||
run: |
|
||||
cd software\pc
|
||||
pyinstaller hexapod.spec
|
||||
copy mainwindow.ui .\dist\hexapod\
|
||||
- name: Archive built module
|
||||
uses: actions/upload-artifact@v2
|
||||
if: success()
|
||||
with:
|
||||
name: hexapod_windows
|
||||
path: .\software\pc\dist\hexapod
|
||||
@@ -25,8 +25,6 @@ The table below shows the difference between this project and the original one.
|
||||
|
||||
https://user-images.githubusercontent.com/471808/148647807-02e3e901-6181-4473-8ac4-3b5998fa8d17.mp4
|
||||
|
||||
https://user-images.githubusercontent.com/471808/158099495-1caeb903-a2e6-4e8d-9f13-54728d7d255a.mp4
|
||||
|
||||
## Software
|
||||
|
||||
### Raspberry Pi
|
||||
|
||||
Binary file not shown.
-123
@@ -1,123 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
@@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+1
-1
@@ -7,13 +7,13 @@
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="Embedded JDK" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.6.21" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+1
-4
@@ -29,13 +29,10 @@
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="SuppressKotlinCodeStyleNotification">
|
||||
<option name="disableForAll" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -4,12 +4,12 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk 32
|
||||
compileSdk 31
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.rookiedev.hexapod"
|
||||
minSdk 30
|
||||
targetSdk 32
|
||||
targetSdk 31
|
||||
versionCode 3
|
||||
versionName "1.2"
|
||||
|
||||
@@ -29,14 +29,13 @@ android {
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
namespace 'com.rookiedev.hexapod'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'com.google.android.material:material:1.6.0'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.rookiedev.hexapod">
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
|
||||
@@ -13,19 +13,18 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_paired_devices"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/black"
|
||||
android:padding="24dp"
|
||||
android:text="Select a Device"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:textColor="@color/white"
|
||||
android:visibility="visible" />
|
||||
android:text="Select a Device"
|
||||
android:visibility="visible"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
@@ -37,9 +36,8 @@
|
||||
android:id="@+id/paired_devices"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/black"
|
||||
android:listSelector="@color/grey_800"
|
||||
android:stackFromBottom="false" />
|
||||
android:stackFromBottom="false"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider1"
|
||||
@@ -51,13 +49,14 @@
|
||||
android:id="@+id/cancel_picker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="24dp"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
android:gravity="center_horizontal"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:padding="24dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:text="Cancel"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
android:visibility="visible" />
|
||||
android:visibility="visible"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -18,12 +18,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:elevation="8dp"
|
||||
android:forceDarkAllowed="false"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
android:paddingEnd="16dp"
|
||||
android:elevation="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/hexapod_logo"
|
||||
@@ -51,16 +50,12 @@
|
||||
android:id="@+id/wifi_tab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:forceDarkAllowed="false"
|
||||
android:text="WiFi" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/bluetooth_tab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:forceDarkAllowed="false"
|
||||
android:text="Bluetooth" />
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
@@ -83,8 +78,6 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/grey_500"
|
||||
android:forceDarkAllowed="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
@@ -92,10 +85,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@color/grey_500"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:visibility="visible"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/port_input_layout"
|
||||
@@ -107,23 +99,20 @@
|
||||
android:id="@+id/ip_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/grey_500"
|
||||
android:digits="0123456789."
|
||||
android:forceDarkAllowed="false"
|
||||
android:backgroundTint="@color/grey_100"
|
||||
android:hint="IP"
|
||||
android:inputType="number|numberDecimal"
|
||||
android:text="192.168.1.127"
|
||||
android:textColor="@android:color/primary_text_light" />
|
||||
android:text="192.168.1.127" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/port_input_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@color/grey_500"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:visibility="visible"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/paired_devices"
|
||||
@@ -135,12 +124,10 @@
|
||||
android:id="@+id/port_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/grey_500"
|
||||
android:forceDarkAllowed="false"
|
||||
android:backgroundTint="@color/grey_100"
|
||||
android:hint="Port"
|
||||
android:inputType="number"
|
||||
android:text="1234"
|
||||
android:textColor="@android:color/primary_text_light" />
|
||||
android:text="1234" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/grey_500"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:forceDarkAllowed="false"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
@@ -17,17 +16,17 @@
|
||||
android:layout_height="64dp"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textView_device_name"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textView_device_name"
|
||||
app:srcCompat="@drawable/ic_baseline_bluetooth_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_device_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textAppearance="?attr/textAppearanceBody1"
|
||||
android:text="TextView"
|
||||
app:layout_constraintBottom_toTopOf="@+id/textView_device_mac"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@@ -37,8 +36,8 @@
|
||||
android:id="@+id/textView_device_mac"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
android:textAppearance="?attr/textAppearanceCaption"
|
||||
android:text="TextView"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView_device_name" />
|
||||
|
||||
@@ -5,8 +5,8 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
|
||||
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Wed Feb 09 11:03:31 EST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
## This file must *NOT* be checked into Version Control Systems,
|
||||
## This file is automatically generated by Android Studio.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file should *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
#
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
#Fri Oct 21 23:04:27 CDT 2022
|
||||
sdk.dir=/home/cole/Android/Sdk
|
||||
sdk.dir=C\:\\Users\\rooki\\AppData\\Local\\Android\\Sdk
|
||||
@@ -1,206 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# MODIFIED to use pololu motor drivers, but compatible with adafruit_servokit driver layout
|
||||
# by Amelia Deck
|
||||
# Based on adafruit_motor.py as well
|
||||
|
||||
"""
|
||||
`adafruit_servokit`
|
||||
====================================================
|
||||
|
||||
CircuitPython helper library for the PWM/Servo FeatherWing, Shield and Pi HAT and Bonnet kits.
|
||||
|
||||
* Author(s): Kattni Rembor
|
||||
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
**Hardware:**
|
||||
|
||||
* `8-Channel PWM or Servo FeatherWing <https://www.adafruit.com/product/2928>`_
|
||||
* `Adafruit 16-Channel 12-bit PWM/Servo Shield <https://www.adafruit.com/product/1411>`_
|
||||
* `Adafruit 16-Channel PWM/Servo HAT for Raspberry Pi <https://www.adafruit.com/product/2327>`_
|
||||
* `Adafruit 16-Channel PWM/Servo Bonnet for Raspberry Pi <https://www.adafruit.com/product/3416>`_
|
||||
|
||||
**Software and Dependencies:**
|
||||
|
||||
* Adafruit CircuitPython firmware for the supported boards:
|
||||
https://github.com/adafruit/circuitpython/releases
|
||||
|
||||
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
|
||||
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
|
||||
* Adafruit's PCA9685 library: https://github.com/adafruit/Adafruit_CircuitPython_PCA9685
|
||||
* Adafruit's Motor library: https://github.com/adafruit/Adafruit_CircuitPython_Motor
|
||||
|
||||
"""
|
||||
|
||||
#import board
|
||||
#from adafruit_pca9685 import PCA9685
|
||||
|
||||
try:
|
||||
from typing import Optional
|
||||
import maestro
|
||||
import time
|
||||
#from busio import I2C
|
||||
#from adafruit_motor.servo import Servo, ContinuousServo
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
__version__ = "0.0.0+auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ServoKit.git"
|
||||
|
||||
pca = None
|
||||
|
||||
class ServoKit:
|
||||
"""Class representing an Adafruit PWM/Servo FeatherWing, Shield or Pi HAT and Bonnet kits.
|
||||
|
||||
Automatically uses the I2C bus on a Feather, Metro or Raspberry Pi.
|
||||
|
||||
Initialise the PCA9685 chip at ``address``.
|
||||
|
||||
The internal reference clock is 25MHz but may vary slightly with environmental conditions and
|
||||
manufacturing variances. Providing a more precise ``reference_clock_speed`` can improve the
|
||||
accuracy of the frequency and duty_cycle computations. See the ``calibration.py`` example in
|
||||
the `PCA9685 GitHub repo <https://github.com/adafruit/Adafruit_CircuitPython_PCA9685>`_ for
|
||||
how to derive this value by measuring the resulting pulse widths.
|
||||
|
||||
:param int channels: The number of servo channels available. Must be 8 or 16. The FeatherWing
|
||||
has 8 channels. The Shield, HAT, and Bonnet have 16 channels.
|
||||
:param ~I2C i2c: The I2C bus to use. If not provided, it will use generate the default I2C
|
||||
bus singleton ``busio.I2C()`` and use that.
|
||||
:param int address: The I2C address of the PCA9685. Default address is ``0x40``.
|
||||
:param int reference_clock_speed: The frequency of the internal reference clock in Hertz.
|
||||
Default reference clock speed is ``25000000``.
|
||||
:param int frequency: The overall PWM frequency of the PCA9685 in Hertz.
|
||||
Default frequency is ``50``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
channels: int,
|
||||
#i2c: Optional[I2C] = None,
|
||||
address: str = "/dev/ttyACM0",
|
||||
reference_clock_speed: int = 25000000,
|
||||
frequency: int = 50 # actually, device ID over serial pololu protocol. using existing var names for full compatibility!
|
||||
) -> None:
|
||||
if channels not in [6, 12, 18, 24]:
|
||||
raise ValueError("servo_channels must be 6, 12, 18, 24!")
|
||||
self._items = [None] * channels
|
||||
self._channels = channels
|
||||
#if i2c is None:
|
||||
# i2c = board.I2C()
|
||||
#self._pca = PCA9685(
|
||||
# i2c, address=address, reference_clock_speed=reference_clock_speed
|
||||
#)
|
||||
#self._pca.frequency = frequency
|
||||
global pca
|
||||
self._pca = maestro.Controller(ttyStr=address,device=frequency)
|
||||
pca = self._pca
|
||||
self._servo = _Servo(self)
|
||||
|
||||
@property
|
||||
def servo(self) -> "_Servo":
|
||||
""":class:`~adafruit_motor.servo.Servo` controls for standard servos.
|
||||
|
||||
This FeatherWing example rotates a servo on channel ``0`` to ``180`` degrees for one second,
|
||||
and then returns it to ``0`` degrees.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import time
|
||||
from adafruit_servokit import ServoKit
|
||||
|
||||
kit = ServoKit(channels=8)
|
||||
|
||||
kit.servo[0].angle = 180
|
||||
time.sleep(1)
|
||||
kit.servo[0].angle = 0
|
||||
|
||||
"""
|
||||
return self._servo
|
||||
|
||||
|
||||
class _Servo:
|
||||
# pylint: disable=protected-access
|
||||
def __init__(self, kit: ServoKit) -> None:
|
||||
self.kit = kit
|
||||
|
||||
def __getitem__(self, servo_channel: int):
|
||||
#import adafruit_motor.servo # pylint: disable=import-outside-toplevel
|
||||
|
||||
num_channels = self.kit._channels
|
||||
if servo_channel >= num_channels or servo_channel < 0:
|
||||
raise ValueError("servo must be 0-{}!".format(num_channels - 1))
|
||||
servo = pololuservo(servo_channel)
|
||||
|
||||
return servo
|
||||
raise ValueError("Channel {} is already in use.".format(servo_channel))
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.kit._items)
|
||||
|
||||
class pololuservo:
|
||||
def __init__(self, ch, actuation_range: int = 180, min_pulse: int = 1600, max_pulse: int = 9900):
|
||||
self.ch = ch
|
||||
self.actuation_range = actuation_range
|
||||
self._min_duty = min_pulse
|
||||
self._max_duty = max_pulse
|
||||
self._duty_range = max_pulse - min_pulse
|
||||
self.duty_cycle = 0
|
||||
print("init servo", ch)
|
||||
pca.setAccel(ch, 15)
|
||||
pca.setTarget(ch, int((max_pulse-min_pulse)/2 + min_pulse)) # set midpoint
|
||||
time.sleep(0.1)
|
||||
pca.setAccel(ch, 0)
|
||||
|
||||
|
||||
@property
|
||||
def angle(self) -> Optional[float]:
|
||||
"""The servo angle in degrees. Must be in the range ``0`` to ``actuation_range``.
|
||||
Is None when servo is disabled."""
|
||||
if self.fraction is None: # special case for disabled servos
|
||||
return None
|
||||
return self.actuation_range * self.fraction
|
||||
|
||||
@angle.setter
|
||||
def angle(self, new_angle: Optional[float]) -> None:
|
||||
if new_angle is None: # disable the servo by sending 0 signal
|
||||
self.fraction = None
|
||||
return
|
||||
if new_angle < 0 or new_angle > self.actuation_range:
|
||||
raise ValueError("Angle out of range")
|
||||
self.fraction = new_angle / self.actuation_range
|
||||
|
||||
@property
|
||||
def fraction(self) -> Optional[float]:
|
||||
"""Pulse width expressed as fraction between 0.0 (`min_pulse`) and 1.0 (`max_pulse`).
|
||||
For conventional servos, corresponds to the servo position as a fraction
|
||||
of the actuation range. Is None when servo is diabled (pulsewidth of 0ms).
|
||||
"""
|
||||
if self.duty_cycle == 0: # Special case for disabled servos
|
||||
return None
|
||||
return (self.duty_cycle - self._min_duty) / self._duty_range
|
||||
|
||||
@fraction.setter
|
||||
def fraction(self, value: Optional[float]) -> None:
|
||||
if value is None:
|
||||
#self._pwm_out.duty_cycle = 0 # disable the motor
|
||||
|
||||
return
|
||||
if not 0.0 <= value <= 1.0:
|
||||
raise ValueError("Must be 0.0 to 1.0")
|
||||
#if self.ch > 2 and self.ch < 6:
|
||||
# valuetmp = 1.0 - value
|
||||
# self.duty_cycle = self._min_duty + int(valuetmp * self._duty_range)
|
||||
#else:
|
||||
self.duty_cycle = self._min_duty + int(value * self._duty_range)
|
||||
#print(self.ch)
|
||||
#if self.ch == 0:
|
||||
#print(value)
|
||||
pca.setTarget(self.ch,int(self.duty_cycle))
|
||||
time.sleep(0.002)
|
||||
#self._pwm_out.duty_cycle = duty_cycle
|
||||
@@ -49,9 +49,8 @@ class BluetoothServer(Thread):
|
||||
|
||||
self.cmd_queue = out_cmd_queue
|
||||
|
||||
with open('config.json', 'r') as read_file:
|
||||
with open('/home/pi/hexapod/software/raspberry pi/config.json', 'r') as read_file:
|
||||
self.config = json.load(read_file)
|
||||
try:
|
||||
|
||||
stream = os.popen('hciconfig hci0')
|
||||
output = stream.read()
|
||||
@@ -65,16 +64,13 @@ class BluetoothServer(Thread):
|
||||
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
|
||||
|
||||
self.signal = self.SIG_NORMAL
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.bt_socket.bind((self.mac, self.port))
|
||||
self.bt_socket.listen(1)
|
||||
print('TCP listening')
|
||||
except: # OSError as err:
|
||||
except OSError as err:
|
||||
# print('emit tcp server error')
|
||||
# self.status.emit(self.STOP, '')
|
||||
pass
|
||||
@@ -108,9 +104,6 @@ class BluetoothServer(Thread):
|
||||
break
|
||||
|
||||
finally:
|
||||
try:
|
||||
self.bt_socket.close()
|
||||
self.cmd_queue.put('standby:')
|
||||
print('exit')
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -38,39 +38,39 @@
|
||||
"movementInterval": 5,
|
||||
"movementSwitchDuration": 150,
|
||||
"leg0Offset": [
|
||||
10,
|
||||
10,
|
||||
30
|
||||
4.0,
|
||||
6.0,
|
||||
2
|
||||
],
|
||||
"leg0Scale": [
|
||||
1,
|
||||
-1,
|
||||
-1
|
||||
1,
|
||||
1
|
||||
],
|
||||
"leg1Offset": [
|
||||
15,
|
||||
-20,
|
||||
35
|
||||
-1.0,
|
||||
8,
|
||||
-6
|
||||
],
|
||||
"leg1Scale": [
|
||||
1,
|
||||
-1,
|
||||
-1
|
||||
1,
|
||||
1
|
||||
],
|
||||
"leg2Offset": [
|
||||
-3,
|
||||
10,
|
||||
20
|
||||
1.0,
|
||||
12.0,
|
||||
1.0
|
||||
],
|
||||
"leg2Scale": [
|
||||
1,
|
||||
-1,
|
||||
-1
|
||||
1,
|
||||
1
|
||||
],
|
||||
"leg3Offset": [
|
||||
7,
|
||||
15,
|
||||
-10
|
||||
-3,
|
||||
12.0,
|
||||
-6.0
|
||||
],
|
||||
"leg3Scale": [
|
||||
1,
|
||||
@@ -78,9 +78,9 @@
|
||||
1
|
||||
],
|
||||
"leg4Offset": [
|
||||
15,
|
||||
10,
|
||||
5
|
||||
-6,
|
||||
2,
|
||||
-6.0
|
||||
],
|
||||
"leg4Scale": [
|
||||
1,
|
||||
@@ -88,20 +88,13 @@
|
||||
1
|
||||
],
|
||||
"leg5Offset": [
|
||||
-7,
|
||||
10,
|
||||
-30
|
||||
0,
|
||||
4.0,
|
||||
-10
|
||||
],
|
||||
"leg5Scale": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"leg0Laser": 17,
|
||||
"leg1Laser": 27,
|
||||
"leg2Laser": 22,
|
||||
"leg3Laser": 10,
|
||||
"leg4Laser": 9,
|
||||
"leg5Laser": 11
|
||||
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!python
|
||||
#
|
||||
# 2021 - PRESENT Zhengyu Peng
|
||||
# Website: https://zpeng.me
|
||||
@@ -28,7 +28,6 @@
|
||||
# https://circuitpython.readthedocs.io/projects/servokit/en/latest/
|
||||
from audioop import reverse
|
||||
from adafruit_servokit import ServoKit
|
||||
import maestro
|
||||
|
||||
from leg import Leg
|
||||
|
||||
@@ -93,7 +92,7 @@ class Hexapod(Thread):
|
||||
|
||||
self.calibration_mode = False
|
||||
|
||||
with open('config.json', 'r') as read_file:
|
||||
with open('/home/pi/hexapod/software/raspberry pi/config.json', 'r') as read_file:
|
||||
self.config = json.load(read_file)
|
||||
|
||||
# legs' coordinates
|
||||
@@ -116,40 +115,40 @@ class Hexapod(Thread):
|
||||
self.mount_position[:, 1] = self.mount_y
|
||||
|
||||
# Objects
|
||||
self.pca_right = ServoKit(channels=18, address="/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.4:1.0", frequency=0x0c)
|
||||
self.pca_left = ServoKit(channels=18, address="/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3:1.0", frequency=0x0d)
|
||||
#self.pca_left = self.pca_right
|
||||
self.pca_right = ServoKit(channels=16, address=0x40, frequency=120)
|
||||
self.pca_left = ServoKit(channels=16, address=0x41, frequency=120)
|
||||
|
||||
self.legs = [
|
||||
# front right
|
||||
Leg(0,
|
||||
[self.pca_left.servo[0], self.pca_left.servo[1],
|
||||
self.pca_left.servo[2]],
|
||||
correction=self.config.get('leg0Offset', [0, 0, 0]), scale=self.config.get('leg0Scale', [1, 1, 1])),
|
||||
[self.pca_left.servo[15], self.pca_left.servo[14],
|
||||
self.pca_left.servo[13]],
|
||||
correction=self.config.get('leg0Offset', [0, 0, 0])),
|
||||
# center right
|
||||
Leg(1,
|
||||
[self.pca_left.servo[3], self.pca_left.servo[4],
|
||||
self.pca_left.servo[5]],
|
||||
correction=self.config.get('leg1Offset', [0, 0, 0]), scale=self.config.get('leg1Scale', [1, 1, 1])),
|
||||
[self.pca_left.servo[8], self.pca_left.servo[4],
|
||||
self.pca_left.servo[11]],
|
||||
correction=self.config.get('leg1Offset', [0, 0, 0])),
|
||||
# rear right
|
||||
Leg(2,
|
||||
[self.pca_left.servo[6], self.pca_left.servo[7],
|
||||
self.pca_left.servo[8]],
|
||||
correction=self.config.get('leg2Offset', [0, 0, 0]), scale=self.config.get('leg2Scale', [1, 1, 1])),
|
||||
[self.pca_left.servo[0], self.pca_left.servo[1],
|
||||
self.pca_left.servo[2]],
|
||||
correction=self.config.get('leg2Offset', [0, 0, 0])),
|
||||
# rear left
|
||||
Leg(3,
|
||||
[self.pca_right.servo[6], self.pca_right.servo[7],
|
||||
self.pca_right.servo[8]],
|
||||
correction=self.config.get('leg3Offset', [0, 0, 0]), scale=self.config.get('leg3Scale', [1, 1, 1])),
|
||||
[self.pca_right.servo[15], self.pca_right.servo[14],
|
||||
self.pca_right.servo[13]],
|
||||
correction=self.config.get('leg3Offset', [0, 0, 0])),
|
||||
# center left
|
||||
Leg(4,
|
||||
[self.pca_right.servo[3], self.pca_right.servo[4],
|
||||
self.pca_right.servo[5]],
|
||||
correction=self.config.get('leg4Offset', [0, 0, 0]), scale=self.config.get('leg4Scale', [1, 1, 1])),
|
||||
[self.pca_right.servo[7], self.pca_right.servo[11],
|
||||
self.pca_right.servo[6]],
|
||||
correction=self.config.get('leg4Offset', [0, 0, 0])),
|
||||
# front left
|
||||
Leg(5,
|
||||
[self.pca_right.servo[0], self.pca_right.servo[1],
|
||||
self.pca_right.servo[2]],
|
||||
correction=self.config.get('leg5Offset', [0, 0, 0]), scale=self.config.get('leg5Scale', [1, 1, 1]))]
|
||||
[self.pca_right.servo[0], self.pca_right.servo[2],
|
||||
self.pca_right.servo[5]],
|
||||
correction=self.config.get('leg5Offset', [0, 0, 0]))]
|
||||
|
||||
# self.leg_0.reset(True)
|
||||
# self.leg_1.reset(True)
|
||||
@@ -263,7 +262,7 @@ class Hexapod(Thread):
|
||||
|
||||
try:
|
||||
cmd_string = self.cmd_queue.get(block=False)
|
||||
print('interrupt')
|
||||
print('interrput')
|
||||
except Empty:
|
||||
# time.sleep(self.interval)
|
||||
pass
|
||||
@@ -300,6 +299,7 @@ class Hexapod(Thread):
|
||||
|
||||
angles[:, 1] = 90-((ar + a1) * 180 / np.pi)
|
||||
angles[:, 2] = (90 - ((a1 + a2) * 180 / np.pi))+90
|
||||
|
||||
return angles
|
||||
|
||||
def cmd_handler(self, cmd_string):
|
||||
@@ -350,8 +350,7 @@ class Hexapod(Thread):
|
||||
|
||||
def save_config(self):
|
||||
try:
|
||||
json.dump(self.config, open(
|
||||
'/home/amelia/hexapod/software/raspberry pi/config2.json', 'w+'), indent=4)
|
||||
json.dump(self.config, open('/home/pi/hexapod/software/raspberry pi/config.json', 'w+'), indent=4)
|
||||
except PermissionError as err:
|
||||
pass
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ class Leg:
|
||||
self.junction_servos = junction_servos
|
||||
self.correction = correction
|
||||
self.constraint = constraint
|
||||
self.scale = scale
|
||||
|
||||
def set_angle(self, junction, angle):
|
||||
set_angle = np.min(
|
||||
@@ -51,19 +50,8 @@ class Leg:
|
||||
self.junction_servos[junction].angle = angle
|
||||
|
||||
def move_junctions(self, angles):
|
||||
if self.scale[0] < 0:
|
||||
self.set_angle(0, self.constraint[0][1] + self.constraint[0][0] - angles[0])
|
||||
#print(self.scale, self.constraint[0][1] + self.constraint[0][0] - angles[0])
|
||||
else:
|
||||
self.set_angle(0, angles[0])
|
||||
#print(self.scale, angles[0])
|
||||
if self.scale[1] < 0:
|
||||
self.set_angle(1, self.constraint[1][1] + self.constraint[1][0] - angles[1])
|
||||
else:
|
||||
self.set_angle(1, angles[1])
|
||||
if self.scale[2] < 0:
|
||||
self.set_angle(2, self.constraint[2][1] + self.constraint[2][0] - angles[2])
|
||||
else:
|
||||
self.set_angle(2, angles[2])
|
||||
|
||||
def reset(self, calibrated=False):
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
import serial
|
||||
from sys import version_info
|
||||
|
||||
PY2 = version_info[0] == 2 #Running Python 2.x?
|
||||
|
||||
#
|
||||
#---------------------------
|
||||
# Maestro Servo Controller
|
||||
#---------------------------
|
||||
#
|
||||
# Support for the Pololu Maestro line of servo controllers
|
||||
#
|
||||
# Steven Jacobs -- Aug 2013
|
||||
# https://github.com/FRC4564/Maestro/
|
||||
#
|
||||
# These functions provide access to many of the Maestro's capabilities using the
|
||||
# Pololu serial protocol
|
||||
#
|
||||
class Controller:
|
||||
# When connected via USB, the Maestro creates two virtual serial ports
|
||||
# /dev/ttyACM0 for commands and /dev/ttyACM1 for communications.
|
||||
# Be sure the Maestro is configured for "USB Dual Port" serial mode.
|
||||
# "USB Chained Mode" may work as well, but hasn't been tested.
|
||||
#
|
||||
# Pololu protocol allows for multiple Maestros to be connected to a single
|
||||
# serial port. Each connected device is then indexed by number.
|
||||
# This device number defaults to 0x0C (or 12 in decimal), which this module
|
||||
# assumes. If two or more controllers are connected to different serial
|
||||
# ports, or you are using a Windows OS, you can provide the tty port. For
|
||||
# example, '/dev/ttyACM2' or for Windows, something like 'COM3'.
|
||||
def __init__(self,ttyStr='/dev/ttyACM0',device=0x0c):
|
||||
# Open the command port
|
||||
self.usb = serial.Serial(ttyStr)
|
||||
# Command lead-in and device number are sent for each Pololu serial command.
|
||||
self.PololuCmd = chr(0xaa) + chr(device)
|
||||
# Track target position for each servo. The function isMoving() will
|
||||
# use the Target vs Current servo position to determine if movement is
|
||||
# occuring. Upto 24 servos on a Maestro, (0-23). Targets start at 0.
|
||||
self.Targets = [0] * 24
|
||||
# Servo minimum and maximum targets can be restricted to protect components.
|
||||
self.Mins = [0] * 24
|
||||
self.Maxs = [0] * 24
|
||||
|
||||
# Cleanup by closing USB serial port
|
||||
def close(self):
|
||||
self.usb.close()
|
||||
|
||||
# Send a Pololu command out the serial port
|
||||
def sendCmd(self, cmd):
|
||||
cmdStr = self.PololuCmd + cmd
|
||||
if PY2:
|
||||
self.usb.write(cmdStr)
|
||||
else:
|
||||
self.usb.write(bytes(cmdStr,'latin-1'))
|
||||
|
||||
# Set channels min and max value range. Use this as a safety to protect
|
||||
# from accidentally moving outside known safe parameters. A setting of 0
|
||||
# allows unrestricted movement.
|
||||
#
|
||||
# ***Note that the Maestro itself is configured to limit the range of servo travel
|
||||
# which has precedence over these values. Use the Maestro Control Center to configure
|
||||
# ranges that are saved to the controller. Use setRange for software controllable ranges.
|
||||
def setRange(self, chan, min, max):
|
||||
self.Mins[chan] = min
|
||||
self.Maxs[chan] = max
|
||||
|
||||
# Return Minimum channel range value
|
||||
def getMin(self, chan):
|
||||
return self.Mins[chan]
|
||||
|
||||
# Return Maximum channel range value
|
||||
def getMax(self, chan):
|
||||
return self.Maxs[chan]
|
||||
|
||||
# Set channel to a specified target value. Servo will begin moving based
|
||||
# on Speed and Acceleration parameters previously set.
|
||||
# Target values will be constrained within Min and Max range, if set.
|
||||
# For servos, target represents the pulse width in of quarter-microseconds
|
||||
# Servo center is at 1500 microseconds, or 6000 quarter-microseconds
|
||||
# Typcially valid servo range is 3000 to 9000 quarter-microseconds
|
||||
# If channel is configured for digital output, values < 6000 = Low ouput
|
||||
def setTarget(self, chan, target):
|
||||
# if Min is defined and Target is below, force to Min
|
||||
if self.Mins[chan] > 0 and target < self.Mins[chan]:
|
||||
target = self.Mins[chan]
|
||||
# if Max is defined and Target is above, force to Max
|
||||
if self.Maxs[chan] > 0 and target > self.Maxs[chan]:
|
||||
target = self.Maxs[chan]
|
||||
#
|
||||
lsb = target & 0x7f #7 bits for least significant byte
|
||||
msb = (target >> 7) & 0x7f #shift 7 and take next 7 bits for msb
|
||||
cmd = chr(0x04) + chr(chan) + chr(lsb) + chr(msb)
|
||||
self.sendCmd(cmd)
|
||||
# Record Target value
|
||||
self.Targets[chan] = target
|
||||
|
||||
# Set speed of channel
|
||||
# Speed is measured as 0.25microseconds/10milliseconds
|
||||
# For the standard 1ms pulse width change to move a servo between extremes, a speed
|
||||
# of 1 will take 1 minute, and a speed of 60 would take 1 second.
|
||||
# Speed of 0 is unrestricted.
|
||||
def setSpeed(self, chan, speed):
|
||||
lsb = speed & 0x7f #7 bits for least significant byte
|
||||
msb = (speed >> 7) & 0x7f #shift 7 and take next 7 bits for msb
|
||||
cmd = chr(0x07) + chr(chan) + chr(lsb) + chr(msb)
|
||||
self.sendCmd(cmd)
|
||||
|
||||
# Set acceleration of channel
|
||||
# This provide soft starts and finishes when servo moves to target position.
|
||||
# Valid values are from 0 to 255. 0=unrestricted, 1 is slowest start.
|
||||
# A value of 1 will take the servo about 3s to move between 1ms to 2ms range.
|
||||
def setAccel(self, chan, accel):
|
||||
lsb = accel & 0x7f #7 bits for least significant byte
|
||||
msb = (accel >> 7) & 0x7f #shift 7 and take next 7 bits for msb
|
||||
cmd = chr(0x09) + chr(chan) + chr(lsb) + chr(msb)
|
||||
self.sendCmd(cmd)
|
||||
|
||||
# Get the current position of the device on the specified channel
|
||||
# The result is returned in a measure of quarter-microseconds, which mirrors
|
||||
# the Target parameter of setTarget.
|
||||
# This is not reading the true servo position, but the last target position sent
|
||||
# to the servo. If the Speed is set to below the top speed of the servo, then
|
||||
# the position result will align well with the acutal servo position, assuming
|
||||
# it is not stalled or slowed.
|
||||
def getPosition(self, chan):
|
||||
cmd = chr(0x10) + chr(chan)
|
||||
self.sendCmd(cmd)
|
||||
lsb = ord(self.usb.read())
|
||||
msb = ord(self.usb.read())
|
||||
return (msb << 8) + lsb
|
||||
|
||||
# Test to see if a servo has reached the set target position. This only provides
|
||||
# useful results if the Speed parameter is set slower than the maximum speed of
|
||||
# the servo. Servo range must be defined first using setRange. See setRange comment.
|
||||
#
|
||||
# ***Note if target position goes outside of Maestro's allowable range for the
|
||||
# channel, then the target can never be reached, so it will appear to always be
|
||||
# moving to the target.
|
||||
def isMoving(self, chan):
|
||||
if self.Targets[chan] > 0:
|
||||
if self.getPosition(chan) != self.Targets[chan]:
|
||||
return True
|
||||
return False
|
||||
|
||||
# Have all servo outputs reached their targets? This is useful only if Speed and/or
|
||||
# Acceleration have been set on one or more of the channels. Returns True or False.
|
||||
# Not available with Micro Maestro.
|
||||
def getMovingState(self):
|
||||
cmd = chr(0x13)
|
||||
self.sendCmd(cmd)
|
||||
if self.usb.read() == chr(0):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
# Run a Maestro Script subroutine in the currently active script. Scripts can
|
||||
# have multiple subroutines, which get numbered sequentially from 0 on up. Code your
|
||||
# Maestro subroutine to either infinitely loop, or just end (return is not valid).
|
||||
def runScriptSub(self, subNumber):
|
||||
cmd = chr(0x27) + chr(subNumber)
|
||||
# can pass a param with command 0x28
|
||||
# cmd = chr(0x28) + chr(subNumber) + chr(lsb) + chr(msb)
|
||||
self.sendCmd(cmd)
|
||||
|
||||
# Stop the current Maestro Script
|
||||
def stopScript(self):
|
||||
cmd = chr(0x24)
|
||||
self.sendCmd(cmd)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
pyserial
|
||||
numpy
|
||||
@@ -47,10 +47,10 @@ class TCPServer(Thread):
|
||||
|
||||
self.cmd_queue = out_cmd_queue
|
||||
|
||||
with open('config.json', 'r') as read_file:
|
||||
with open('/home/pi/hexapod/software/raspberry pi/config.json', 'r') as read_file:
|
||||
self.config = json.load(read_file)
|
||||
|
||||
self.ip = '0.0.0.0'
|
||||
self.ip = '192.168.1.127'
|
||||
self.port = 1234
|
||||
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import maestro
|
||||
servo = maestro.Controller()
|
||||
import time
|
||||
print("1")
|
||||
for i in range(18):
|
||||
|
||||
servo.setAccel(i,10) #set servo 0 acceleration to 4
|
||||
servo.setSpeed(i,50) #set speed of servo 1
|
||||
servo.setTarget(i,6000) #set servo to move to center position
|
||||
|
||||
time.sleep(1)
|
||||
#servo.setTarget(0,6000)
|
||||
#x = servo.getPosition(1) #get the current position of servo 1
|
||||
print("5")
|
||||
#servo.close()
|
||||
print("6")
|
||||
Reference in New Issue
Block a user