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/148647807-02e3e901-6181-4473-8ac4-3b5998fa8d17.mp4
|
||||||
|
|
||||||
https://user-images.githubusercontent.com/471808/158099495-1caeb903-a2e6-4e8d-9f13-54728d7d255a.mp4
|
|
||||||
|
|
||||||
## Software
|
## Software
|
||||||
|
|
||||||
### Raspberry Pi
|
### 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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="17" />
|
<bytecodeTargetLevel target="11" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+1
-1
@@ -7,13 +7,13 @@
|
|||||||
<option name="testRunner" value="GRADLE" />
|
<option name="testRunner" value="GRADLE" />
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="Embedded JDK" />
|
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</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>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</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" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
<option name="id" value="Android" />
|
<option name="id" value="Android" />
|
||||||
</component>
|
</component>
|
||||||
<component name="SuppressKotlinCodeStyleNotification">
|
|
||||||
<option name="disableForAll" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
||||||
@@ -4,12 +4,12 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 32
|
compileSdk 31
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.rookiedev.hexapod"
|
applicationId "com.rookiedev.hexapod"
|
||||||
minSdk 30
|
minSdk 30
|
||||||
targetSdk 32
|
targetSdk 31
|
||||||
versionCode 3
|
versionCode 3
|
||||||
versionName "1.2"
|
versionName "1.2"
|
||||||
|
|
||||||
@@ -29,14 +29,13 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = '1.8'
|
||||||
}
|
}
|
||||||
namespace 'com.rookiedev.hexapod'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
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'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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_CONNECT" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
|||||||
@@ -13,19 +13,18 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/black"
|
android:orientation="vertical"
|
||||||
android:orientation="vertical">
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title_paired_devices"
|
android:id="@+id/title_paired_devices"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/black"
|
|
||||||
android:padding="24dp"
|
android:padding="24dp"
|
||||||
android:text="Select a Device"
|
|
||||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||||
android:textColor="@color/white"
|
android:text="Select a Device"
|
||||||
android:visibility="visible" />
|
android:visibility="visible"
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider"
|
||||||
@@ -37,9 +36,8 @@
|
|||||||
android:id="@+id/paired_devices"
|
android:id="@+id/paired_devices"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/black"
|
android:stackFromBottom="false"
|
||||||
android:listSelector="@color/grey_800"
|
/>
|
||||||
android:stackFromBottom="false" />
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider1"
|
android:id="@+id/divider1"
|
||||||
@@ -51,13 +49,14 @@
|
|||||||
android:id="@+id/cancel_picker"
|
android:id="@+id/cancel_picker"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:padding="24dp"
|
||||||
|
android:textAppearance="?attr/textAppearanceButton"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center_horizontal"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:padding="24dp"
|
|
||||||
android:text="Cancel"
|
android:text="Cancel"
|
||||||
android:textAppearance="?attr/textAppearanceButton"
|
android:visibility="visible"
|
||||||
android:visibility="visible" />
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -18,12 +18,11 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
android:elevation="8dp"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp">
|
android:paddingEnd="16dp"
|
||||||
|
android:elevation="8dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/hexapod_logo"
|
android:id="@+id/hexapod_logo"
|
||||||
@@ -51,16 +50,12 @@
|
|||||||
android:id="@+id/wifi_tab"
|
android:id="@+id/wifi_tab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:text="WiFi" />
|
android:text="WiFi" />
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabItem
|
<com.google.android.material.tabs.TabItem
|
||||||
android:id="@+id/bluetooth_tab"
|
android:id="@+id/bluetooth_tab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:text="Bluetooth" />
|
android:text="Bluetooth" />
|
||||||
|
|
||||||
</com.google.android.material.tabs.TabLayout>
|
</com.google.android.material.tabs.TabLayout>
|
||||||
@@ -83,8 +78,6 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
@@ -92,10 +85,9 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:errorEnabled="true"
|
app:errorEnabled="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/port_input_layout"
|
app:layout_constraintBottom_toTopOf="@id/port_input_layout"
|
||||||
@@ -107,23 +99,20 @@
|
|||||||
android:id="@+id/ip_input"
|
android:id="@+id/ip_input"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:digits="0123456789."
|
android:digits="0123456789."
|
||||||
android:forceDarkAllowed="false"
|
android:backgroundTint="@color/grey_100"
|
||||||
android:hint="IP"
|
android:hint="IP"
|
||||||
android:inputType="number|numberDecimal"
|
android:inputType="number|numberDecimal"
|
||||||
android:text="192.168.1.127"
|
android:text="192.168.1.127" />
|
||||||
android:textColor="@android:color/primary_text_light" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/port_input_layout"
|
android:id="@+id/port_input_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:errorEnabled="true"
|
app:errorEnabled="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/paired_devices"
|
app:layout_constraintBottom_toTopOf="@id/paired_devices"
|
||||||
@@ -135,12 +124,10 @@
|
|||||||
android:id="@+id/port_input"
|
android:id="@+id/port_input"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
android:backgroundTint="@color/grey_100"
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:hint="Port"
|
android:hint="Port"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:text="1234"
|
android:text="1234" />
|
||||||
android:textColor="@android:color/primary_text_light" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,9 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:forceDarkAllowed="false"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="16dp">
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
@@ -17,17 +16,17 @@
|
|||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/textView_device_name"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/textView_device_name"
|
||||||
app:srcCompat="@drawable/ic_baseline_bluetooth_24" />
|
app:srcCompat="@drawable/ic_baseline_bluetooth_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView_device_name"
|
android:id="@+id/textView_device_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="TextView"
|
|
||||||
android:textAppearance="?attr/textAppearanceBody1"
|
android:textAppearance="?attr/textAppearanceBody1"
|
||||||
|
android:text="TextView"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/textView_device_mac"
|
app:layout_constraintBottom_toTopOf="@+id/textView_device_mac"
|
||||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@@ -37,8 +36,8 @@
|
|||||||
android:id="@+id/textView_device_mac"
|
android:id="@+id/textView_device_mac"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="TextView"
|
|
||||||
android:textAppearance="?attr/textAppearanceCaption"
|
android:textAppearance="?attr/textAppearanceCaption"
|
||||||
|
android:text="TextView"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/textView_device_name" />
|
app:layout_constraintTop_toBottomOf="@+id/textView_device_name" />
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#Wed Feb 09 11:03:31 EST 2022
|
#Wed Feb 09 11:03:31 EST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
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
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
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.
|
# as it contains information specific to your local configuration.
|
||||||
#
|
#
|
||||||
# Location of the SDK. This is only used by Gradle.
|
# Location of the SDK. This is only used by Gradle.
|
||||||
# For customization when using a Version Control System, please read the
|
# For customization when using a Version Control System, please read the
|
||||||
# header note.
|
# header note.
|
||||||
#Fri Oct 21 23:04:27 CDT 2022
|
sdk.dir=C\:\\Users\\rooki\\AppData\\Local\\Android\\Sdk
|
||||||
sdk.dir=/home/cole/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
|
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.config = json.load(read_file)
|
||||||
try:
|
|
||||||
|
|
||||||
stream = os.popen('hciconfig hci0')
|
stream = os.popen('hciconfig hci0')
|
||||||
output = stream.read()
|
output = stream.read()
|
||||||
@@ -65,16 +64,13 @@ class BluetoothServer(Thread):
|
|||||||
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
|
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
|
||||||
|
|
||||||
self.signal = self.SIG_NORMAL
|
self.signal = self.SIG_NORMAL
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
self.bt_socket.bind((self.mac, self.port))
|
self.bt_socket.bind((self.mac, self.port))
|
||||||
self.bt_socket.listen(1)
|
self.bt_socket.listen(1)
|
||||||
print('TCP listening')
|
print('TCP listening')
|
||||||
except: # OSError as err:
|
except OSError as err:
|
||||||
# print('emit tcp server error')
|
# print('emit tcp server error')
|
||||||
# self.status.emit(self.STOP, '')
|
# self.status.emit(self.STOP, '')
|
||||||
pass
|
pass
|
||||||
@@ -108,9 +104,6 @@ class BluetoothServer(Thread):
|
|||||||
break
|
break
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
try:
|
|
||||||
self.bt_socket.close()
|
self.bt_socket.close()
|
||||||
self.cmd_queue.put('standby:')
|
self.cmd_queue.put('standby:')
|
||||||
print('exit')
|
print('exit')
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -38,39 +38,39 @@
|
|||||||
"movementInterval": 5,
|
"movementInterval": 5,
|
||||||
"movementSwitchDuration": 150,
|
"movementSwitchDuration": 150,
|
||||||
"leg0Offset": [
|
"leg0Offset": [
|
||||||
10,
|
4.0,
|
||||||
10,
|
6.0,
|
||||||
30
|
2
|
||||||
],
|
],
|
||||||
"leg0Scale": [
|
"leg0Scale": [
|
||||||
1,
|
1,
|
||||||
-1,
|
1,
|
||||||
-1
|
1
|
||||||
],
|
],
|
||||||
"leg1Offset": [
|
"leg1Offset": [
|
||||||
15,
|
-1.0,
|
||||||
-20,
|
8,
|
||||||
35
|
-6
|
||||||
],
|
],
|
||||||
"leg1Scale": [
|
"leg1Scale": [
|
||||||
1,
|
1,
|
||||||
-1,
|
1,
|
||||||
-1
|
1
|
||||||
],
|
],
|
||||||
"leg2Offset": [
|
"leg2Offset": [
|
||||||
-3,
|
1.0,
|
||||||
10,
|
12.0,
|
||||||
20
|
1.0
|
||||||
],
|
],
|
||||||
"leg2Scale": [
|
"leg2Scale": [
|
||||||
1,
|
1,
|
||||||
-1,
|
1,
|
||||||
-1
|
1
|
||||||
],
|
],
|
||||||
"leg3Offset": [
|
"leg3Offset": [
|
||||||
7,
|
-3,
|
||||||
15,
|
12.0,
|
||||||
-10
|
-6.0
|
||||||
],
|
],
|
||||||
"leg3Scale": [
|
"leg3Scale": [
|
||||||
1,
|
1,
|
||||||
@@ -78,9 +78,9 @@
|
|||||||
1
|
1
|
||||||
],
|
],
|
||||||
"leg4Offset": [
|
"leg4Offset": [
|
||||||
15,
|
-6,
|
||||||
10,
|
2,
|
||||||
5
|
-6.0
|
||||||
],
|
],
|
||||||
"leg4Scale": [
|
"leg4Scale": [
|
||||||
1,
|
1,
|
||||||
@@ -88,20 +88,13 @@
|
|||||||
1
|
1
|
||||||
],
|
],
|
||||||
"leg5Offset": [
|
"leg5Offset": [
|
||||||
-7,
|
0,
|
||||||
10,
|
4.0,
|
||||||
-30
|
-10
|
||||||
],
|
],
|
||||||
"leg5Scale": [
|
"leg5Scale": [
|
||||||
1,
|
1,
|
||||||
1,
|
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
|
# 2021 - PRESENT Zhengyu Peng
|
||||||
# Website: https://zpeng.me
|
# Website: https://zpeng.me
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
# https://circuitpython.readthedocs.io/projects/servokit/en/latest/
|
# https://circuitpython.readthedocs.io/projects/servokit/en/latest/
|
||||||
from audioop import reverse
|
from audioop import reverse
|
||||||
from adafruit_servokit import ServoKit
|
from adafruit_servokit import ServoKit
|
||||||
import maestro
|
|
||||||
|
|
||||||
from leg import Leg
|
from leg import Leg
|
||||||
|
|
||||||
@@ -93,7 +92,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
self.calibration_mode = False
|
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)
|
self.config = json.load(read_file)
|
||||||
|
|
||||||
# legs' coordinates
|
# legs' coordinates
|
||||||
@@ -116,40 +115,40 @@ class Hexapod(Thread):
|
|||||||
self.mount_position[:, 1] = self.mount_y
|
self.mount_position[:, 1] = self.mount_y
|
||||||
|
|
||||||
# Objects
|
# 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_right = ServoKit(channels=16, address=0x40, frequency=120)
|
||||||
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 = ServoKit(channels=16, address=0x41, frequency=120)
|
||||||
#self.pca_left = self.pca_right
|
|
||||||
self.legs = [
|
self.legs = [
|
||||||
# front right
|
# front right
|
||||||
Leg(0,
|
Leg(0,
|
||||||
[self.pca_left.servo[0], self.pca_left.servo[1],
|
[self.pca_left.servo[15], self.pca_left.servo[14],
|
||||||
self.pca_left.servo[2]],
|
self.pca_left.servo[13]],
|
||||||
correction=self.config.get('leg0Offset', [0, 0, 0]), scale=self.config.get('leg0Scale', [1, 1, 1])),
|
correction=self.config.get('leg0Offset', [0, 0, 0])),
|
||||||
# center right
|
# center right
|
||||||
Leg(1,
|
Leg(1,
|
||||||
[self.pca_left.servo[3], self.pca_left.servo[4],
|
[self.pca_left.servo[8], self.pca_left.servo[4],
|
||||||
self.pca_left.servo[5]],
|
self.pca_left.servo[11]],
|
||||||
correction=self.config.get('leg1Offset', [0, 0, 0]), scale=self.config.get('leg1Scale', [1, 1, 1])),
|
correction=self.config.get('leg1Offset', [0, 0, 0])),
|
||||||
# rear right
|
# rear right
|
||||||
Leg(2,
|
Leg(2,
|
||||||
[self.pca_left.servo[6], self.pca_left.servo[7],
|
[self.pca_left.servo[0], self.pca_left.servo[1],
|
||||||
self.pca_left.servo[8]],
|
self.pca_left.servo[2]],
|
||||||
correction=self.config.get('leg2Offset', [0, 0, 0]), scale=self.config.get('leg2Scale', [1, 1, 1])),
|
correction=self.config.get('leg2Offset', [0, 0, 0])),
|
||||||
# rear left
|
# rear left
|
||||||
Leg(3,
|
Leg(3,
|
||||||
[self.pca_right.servo[6], self.pca_right.servo[7],
|
[self.pca_right.servo[15], self.pca_right.servo[14],
|
||||||
self.pca_right.servo[8]],
|
self.pca_right.servo[13]],
|
||||||
correction=self.config.get('leg3Offset', [0, 0, 0]), scale=self.config.get('leg3Scale', [1, 1, 1])),
|
correction=self.config.get('leg3Offset', [0, 0, 0])),
|
||||||
# center left
|
# center left
|
||||||
Leg(4,
|
Leg(4,
|
||||||
[self.pca_right.servo[3], self.pca_right.servo[4],
|
[self.pca_right.servo[7], self.pca_right.servo[11],
|
||||||
self.pca_right.servo[5]],
|
self.pca_right.servo[6]],
|
||||||
correction=self.config.get('leg4Offset', [0, 0, 0]), scale=self.config.get('leg4Scale', [1, 1, 1])),
|
correction=self.config.get('leg4Offset', [0, 0, 0])),
|
||||||
# front left
|
# front left
|
||||||
Leg(5,
|
Leg(5,
|
||||||
[self.pca_right.servo[0], self.pca_right.servo[1],
|
[self.pca_right.servo[0], self.pca_right.servo[2],
|
||||||
self.pca_right.servo[2]],
|
self.pca_right.servo[5]],
|
||||||
correction=self.config.get('leg5Offset', [0, 0, 0]), scale=self.config.get('leg5Scale', [1, 1, 1]))]
|
correction=self.config.get('leg5Offset', [0, 0, 0]))]
|
||||||
|
|
||||||
# self.leg_0.reset(True)
|
# self.leg_0.reset(True)
|
||||||
# self.leg_1.reset(True)
|
# self.leg_1.reset(True)
|
||||||
@@ -263,7 +262,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
cmd_string = self.cmd_queue.get(block=False)
|
cmd_string = self.cmd_queue.get(block=False)
|
||||||
print('interrupt')
|
print('interrput')
|
||||||
except Empty:
|
except Empty:
|
||||||
# time.sleep(self.interval)
|
# time.sleep(self.interval)
|
||||||
pass
|
pass
|
||||||
@@ -300,6 +299,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
angles[:, 1] = 90-((ar + a1) * 180 / np.pi)
|
angles[:, 1] = 90-((ar + a1) * 180 / np.pi)
|
||||||
angles[:, 2] = (90 - ((a1 + a2) * 180 / np.pi))+90
|
angles[:, 2] = (90 - ((a1 + a2) * 180 / np.pi))+90
|
||||||
|
|
||||||
return angles
|
return angles
|
||||||
|
|
||||||
def cmd_handler(self, cmd_string):
|
def cmd_handler(self, cmd_string):
|
||||||
@@ -350,8 +350,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
def save_config(self):
|
def save_config(self):
|
||||||
try:
|
try:
|
||||||
json.dump(self.config, open(
|
json.dump(self.config, open('/home/pi/hexapod/software/raspberry pi/config.json', 'w+'), indent=4)
|
||||||
'/home/amelia/hexapod/software/raspberry pi/config2.json', 'w+'), indent=4)
|
|
||||||
except PermissionError as err:
|
except PermissionError as err:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -361,7 +360,7 @@ class Hexapod(Thread):
|
|||||||
try:
|
try:
|
||||||
cmd_string = self.cmd_queue.get(block=False)
|
cmd_string = self.cmd_queue.get(block=False)
|
||||||
except Empty:
|
except Empty:
|
||||||
#time.sleep(self.interval)
|
# time.sleep(self.interval)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.cmd_handler(cmd_string)
|
self.cmd_handler(cmd_string)
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ class Leg:
|
|||||||
self.junction_servos = junction_servos
|
self.junction_servos = junction_servos
|
||||||
self.correction = correction
|
self.correction = correction
|
||||||
self.constraint = constraint
|
self.constraint = constraint
|
||||||
self.scale = scale
|
|
||||||
|
|
||||||
def set_angle(self, junction, angle):
|
def set_angle(self, junction, angle):
|
||||||
set_angle = np.min(
|
set_angle = np.min(
|
||||||
@@ -51,19 +50,8 @@ class Leg:
|
|||||||
self.junction_servos[junction].angle = angle
|
self.junction_servos[junction].angle = angle
|
||||||
|
|
||||||
def move_junctions(self, angles):
|
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])
|
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])
|
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])
|
self.set_angle(2, angles[2])
|
||||||
|
|
||||||
def reset(self, calibrated=False):
|
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
|
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.config = json.load(read_file)
|
||||||
|
|
||||||
self.ip = '0.0.0.0'
|
self.ip = '192.168.1.127'
|
||||||
self.port = 1234
|
self.port = 1234
|
||||||
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
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