pyonics 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyonics/CHANGES.txt +0 -0
- pyonics/__init__.py +0 -0
- pyonics/main.py +71 -0
- pyonics/meta.yaml +33 -0
- pyonics/requirements.txt +0 -0
- pyonics/setup.py +25 -0
- pyonics/submodules/__init__.py +0 -0
- pyonics/submodules/apps/__init__.py +0 -0
- pyonics/submodules/apps/apps.py +240 -0
- pyonics/submodules/audio/__init__.py +0 -0
- pyonics/submodules/audio/recording.py +21 -0
- pyonics/submodules/control/__init__.py +0 -0
- pyonics/submodules/control/control.py +359 -0
- pyonics/submodules/ui/__init__.py +0 -0
- pyonics/submodules/ui/interface.py +398 -0
- pyonics/submodules/ui/mfcc.conf +10 -0
- pyonics/submodules/ui/model.conf +10 -0
- pyonics/submodules/ui/system_strings.py +33 -0
- pyonics/submodules/ui/zira_us.reg +0 -0
- pyonics/submodules/video/__init__.py +0 -0
- pyonics/submodules/video/video.py +64 -0
- pyonics-0.0.1.dist-info/METADATA +40 -0
- pyonics-0.0.1.dist-info/RECORD +25 -0
- pyonics-0.0.1.dist-info/WHEEL +4 -0
- pyonics-0.0.1.dist-info/licenses/LICENSE +674 -0
pyonics/CHANGES.txt
ADDED
|
File without changes
|
pyonics/__init__.py
ADDED
|
File without changes
|
pyonics/main.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# For building powered human augmentations.
|
|
2
|
+
|
|
3
|
+
# -*- coding: utf-8 -*-
|
|
4
|
+
"""
|
|
5
|
+
Created on Tue Oct 11 21:55:28 2022
|
|
6
|
+
===============
|
|
7
|
+
Document Comments:
|
|
8
|
+
10.11.22
|
|
9
|
+
2218h
|
|
10
|
+
I think the index should be separate from the time values. Physics should
|
|
11
|
+
be based on time independent of the index so that I can have a consistent
|
|
12
|
+
indexing scheme regardless of the time resolution of the data.
|
|
13
|
+
|
|
14
|
+
11.3.22
|
|
15
|
+
0944h
|
|
16
|
+
Interface is mostly done. Needs the graph to actually be updating inside
|
|
17
|
+
the desktopGUI but otherwise the front end is ready for a presentation. Adding
|
|
18
|
+
the fractional calculus functionality will be next.
|
|
19
|
+
|
|
20
|
+
12.2.22
|
|
21
|
+
2021h
|
|
22
|
+
Trying to refactor into smaller pieces.
|
|
23
|
+
|
|
24
|
+
11.23.23
|
|
25
|
+
0145h
|
|
26
|
+
Lots of progress been made.
|
|
27
|
+
===============
|
|
28
|
+
LIBRARY IMPORTS
|
|
29
|
+
===============
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
# Local Submodules
|
|
33
|
+
|
|
34
|
+
import submodules.ui.interface as interface
|
|
35
|
+
|
|
36
|
+
# External Libraries
|
|
37
|
+
|
|
38
|
+
import pandas as pd
|
|
39
|
+
import matplotlib.pyplot as plt
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
CONFIG
|
|
43
|
+
"""
|
|
44
|
+
# pandas options
|
|
45
|
+
pd.options.display.width = 0
|
|
46
|
+
pd.set_option("display.max_columns", None)
|
|
47
|
+
pd.set_option("display.max_rows", None)
|
|
48
|
+
pd.set_option("display.width", None)
|
|
49
|
+
pd.set_option("display.max_colwidth", None)
|
|
50
|
+
|
|
51
|
+
# pyplot options
|
|
52
|
+
plt.ion()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
CLASS DEFINITIONS
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
FUNCTION DEFINITIONS
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main(ui_type="AR"):
|
|
65
|
+
if ui_type == "AR":
|
|
66
|
+
ui = interface.AugmentOverlayTkUI()
|
|
67
|
+
else:
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
main()
|
pyonics/meta.yaml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package:
|
|
2
|
+
name: pyonics
|
|
3
|
+
version: "0.1.0"
|
|
4
|
+
|
|
5
|
+
source:
|
|
6
|
+
path: .
|
|
7
|
+
|
|
8
|
+
build:
|
|
9
|
+
number: 1
|
|
10
|
+
script: python -m pip install --no-deps --ignore-installed .
|
|
11
|
+
|
|
12
|
+
requirements:
|
|
13
|
+
build:
|
|
14
|
+
- "python"
|
|
15
|
+
- "setuptools"
|
|
16
|
+
- "klampt"
|
|
17
|
+
- "numpy"
|
|
18
|
+
- "matplotlib"
|
|
19
|
+
- "matplotlib.pyplot"
|
|
20
|
+
- "pandas"
|
|
21
|
+
|
|
22
|
+
run:
|
|
23
|
+
- "python"
|
|
24
|
+
- "klampt"
|
|
25
|
+
- "numpy"
|
|
26
|
+
- "matplotlib"
|
|
27
|
+
- "matplotlib.pyplot"
|
|
28
|
+
- "pandas"
|
|
29
|
+
# Add any runtime dependencies here
|
|
30
|
+
|
|
31
|
+
about:
|
|
32
|
+
home: https://github.com/pyromakesmusic/MATH4157/pyonics
|
|
33
|
+
license: LicenseName # Replace with your license
|
pyonics/requirements.txt
ADDED
|
File without changes
|
pyonics/setup.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
import klampt
|
|
3
|
+
import numpy
|
|
4
|
+
import matplotlib
|
|
5
|
+
import matplotlib.pyplot
|
|
6
|
+
import pandas
|
|
7
|
+
import submodules.apps
|
|
8
|
+
import submodules.video
|
|
9
|
+
import submodules.audio
|
|
10
|
+
import submodules.control
|
|
11
|
+
import submodules.ui
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
setup(
|
|
15
|
+
name='pyonics',
|
|
16
|
+
version='0.1.0',
|
|
17
|
+
packages=find_packages(),
|
|
18
|
+
install_requires=[klampt,
|
|
19
|
+
numpy,
|
|
20
|
+
matplotlib,
|
|
21
|
+
pandas
|
|
22
|
+
|
|
23
|
+
# List your dependencies here
|
|
24
|
+
],
|
|
25
|
+
)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import asyncio # Needs asynchronous functionality
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import gpsd # GPS library
|
|
4
|
+
# import cv2 # CameraWidget library
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
import asyncio
|
|
7
|
+
# Klamp't imports
|
|
8
|
+
|
|
9
|
+
import klampt
|
|
10
|
+
import klampt.model.coordinates
|
|
11
|
+
import klampt.model.collide
|
|
12
|
+
import klampt.model.contact
|
|
13
|
+
import klampt.plan.robotplanning
|
|
14
|
+
import klampt.plan.robotcspace
|
|
15
|
+
import klampt.plan.cspace
|
|
16
|
+
import klampt.plan.rigidobjectcspace
|
|
17
|
+
|
|
18
|
+
# Each app should be its own class
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
CLASSES
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# HUD Widgets
|
|
25
|
+
class Map(klampt.vis.glcommon.GLProgram):
|
|
26
|
+
def __init__(self, widget=None):
|
|
27
|
+
self.world = klampt.WorldModel()
|
|
28
|
+
self.frenet = klampt.model.coordinates.Frame("frenet frame", self.world)
|
|
29
|
+
self.latitude = None
|
|
30
|
+
self.longitude = None
|
|
31
|
+
self.altitude = None
|
|
32
|
+
|
|
33
|
+
self.bearing = "east"
|
|
34
|
+
self.widget = widget
|
|
35
|
+
self.get_gps_data()
|
|
36
|
+
klampt.vis.glprogram.GLProgram.__init__(self)
|
|
37
|
+
|
|
38
|
+
async def surrounding_geometry(self):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_gps_data(self):
|
|
43
|
+
# Connect to the local gpsd service (default host and port)
|
|
44
|
+
try:
|
|
45
|
+
gpsd.connect()
|
|
46
|
+
# Get the GPS data
|
|
47
|
+
packet = gpsd.get_current()
|
|
48
|
+
# Check if the data is valid
|
|
49
|
+
if packet.mode >= 2:
|
|
50
|
+
self.latitude = packet.lat
|
|
51
|
+
self.longitude = packet.lon
|
|
52
|
+
self.altitude = packet.alt
|
|
53
|
+
|
|
54
|
+
return (f"Latitude: {self.latitude},\n Longitude: {self.longitude},\n Altitude: {self.altitude}")
|
|
55
|
+
else:
|
|
56
|
+
return ("No GPS fix")
|
|
57
|
+
except ConnectionRefusedError:
|
|
58
|
+
|
|
59
|
+
return("GPS Fix failed")
|
|
60
|
+
|
|
61
|
+
def update(self, bearing):
|
|
62
|
+
gpsd.connect()
|
|
63
|
+
# Get the GPS data
|
|
64
|
+
packet = gpsd.get_current()
|
|
65
|
+
# Check if the data is valid
|
|
66
|
+
if packet.mode >= 2:
|
|
67
|
+
self.latitude = packet.lat
|
|
68
|
+
self.longitude = packet.lon
|
|
69
|
+
self.altitude = packet.alt
|
|
70
|
+
|
|
71
|
+
self.bearing = bearing
|
|
72
|
+
|
|
73
|
+
def set_widget(self, widget):
|
|
74
|
+
self.widget = widget
|
|
75
|
+
|
|
76
|
+
class Clock():
|
|
77
|
+
def __init__(self, widget=None, widget_type=None):
|
|
78
|
+
# Adds a clock
|
|
79
|
+
self.time = datetime.now().strftime("%H:%M:%S")
|
|
80
|
+
self.widget = widget
|
|
81
|
+
self.widget_type = widget_type
|
|
82
|
+
def update(self):
|
|
83
|
+
self.time = datetime.now().strftime("%H:%M:%S")
|
|
84
|
+
return self.time
|
|
85
|
+
|
|
86
|
+
def set_widget(self, widget, widget_type):
|
|
87
|
+
self.widget = widget
|
|
88
|
+
self.widget_type = widget_type
|
|
89
|
+
|
|
90
|
+
class DateWidget:
|
|
91
|
+
def __init__(self):
|
|
92
|
+
# Adds a clock
|
|
93
|
+
self.date = datetime.now().strftime("%Y.%m.%d")
|
|
94
|
+
self.display = None
|
|
95
|
+
def update(self):
|
|
96
|
+
self.date = datetime.now().strftime("%Y.%m.%d")
|
|
97
|
+
return self.date
|
|
98
|
+
|
|
99
|
+
class TextWidget:
|
|
100
|
+
def __init__(self):
|
|
101
|
+
# Adds a clock
|
|
102
|
+
self.text = "widget text"
|
|
103
|
+
def update(self, text):
|
|
104
|
+
self.text = text
|
|
105
|
+
return self.text
|
|
106
|
+
|
|
107
|
+
# class CameraWidget(klampt.vis.glcommon.GLProgram):
|
|
108
|
+
# def __init__(self, i):
|
|
109
|
+
# klampt.vis.glcommon.GLProgram.__init__(self)
|
|
110
|
+
# # Launches with an index of a particular camera
|
|
111
|
+
# self.camera = None
|
|
112
|
+
# self.state = "minimized" # Can also be "fullscreen", "windowed", "closed"
|
|
113
|
+
#
|
|
114
|
+
# self.ret = None
|
|
115
|
+
# self.frame = None
|
|
116
|
+
# self.shutdown_flag = False
|
|
117
|
+
#
|
|
118
|
+
#
|
|
119
|
+
#
|
|
120
|
+
#
|
|
121
|
+
# def cam_launch(self, index):
|
|
122
|
+
# # Start the camera
|
|
123
|
+
# try:
|
|
124
|
+
# self.camera = cv2.VideoCapture(index)
|
|
125
|
+
# except:
|
|
126
|
+
# "Error: Exception launching camera input."
|
|
127
|
+
#
|
|
128
|
+
# while not self.shutdown_flag:
|
|
129
|
+
# asyncio.run(self.cam_loop())
|
|
130
|
+
#
|
|
131
|
+
# def cam_loop_synchronous(self):
|
|
132
|
+
# self.ret, self.frame = self.camera.read()
|
|
133
|
+
#
|
|
134
|
+
# # Check if the frame was read successfully
|
|
135
|
+
# if not self.ret:
|
|
136
|
+
# print("Error: Could not read frame.")
|
|
137
|
+
#
|
|
138
|
+
# # Display the frame
|
|
139
|
+
# cv2.imshow('Webcam', self.frame)
|
|
140
|
+
# return self.frame
|
|
141
|
+
#
|
|
142
|
+
# async def cam_loop(self):
|
|
143
|
+
# self.ret, self.frame = self.camera.read()
|
|
144
|
+
#
|
|
145
|
+
# # Check if the frame was read successfully
|
|
146
|
+
# if not self.ret:
|
|
147
|
+
# print("Error: Could not read frame.")
|
|
148
|
+
#
|
|
149
|
+
#
|
|
150
|
+
# # Display the frame
|
|
151
|
+
# cv2.imshow('Webcam', self.frame)
|
|
152
|
+
# return self.frame
|
|
153
|
+
#
|
|
154
|
+
# def cam_shutdown(self):
|
|
155
|
+
# # Break the loop if the user presses the 'q' key
|
|
156
|
+
# if cv2.waitKey(1) & 0xFF == ord('q'):
|
|
157
|
+
# self.shutdown_flag = True
|
|
158
|
+
|
|
159
|
+
# Desktop Applications
|
|
160
|
+
|
|
161
|
+
"""
|
|
162
|
+
Simulation
|
|
163
|
+
"""
|
|
164
|
+
class Sim(klampt.sim.simulation.SimpleSimulator):
|
|
165
|
+
"""
|
|
166
|
+
This is a class for Simulations. It will contain the substepping logic where forces are applied to simulated objects.
|
|
167
|
+
"""
|
|
168
|
+
def __init__(self, wm, robot, timestep, collisions=True): # Setting collisions to True for testing ONLY
|
|
169
|
+
klampt.sim.simulation.SimpleSimulator.__init__(self, wm)
|
|
170
|
+
self.world = wm
|
|
171
|
+
self.dt = timestep
|
|
172
|
+
|
|
173
|
+
self.robotmodel = robot
|
|
174
|
+
self.link_transforms_start = [self.robotmodel.link(x).getTransform() for x in range(self.robotmodel.numLinks())]
|
|
175
|
+
self.link_transforms_end = None
|
|
176
|
+
self.link_transforms_diff = None
|
|
177
|
+
|
|
178
|
+
if collisions:
|
|
179
|
+
self.collider = klampt.model.collide.WorldCollider(self.world)
|
|
180
|
+
self.planner = klampt.plan
|
|
181
|
+
else:
|
|
182
|
+
self.collider = None
|
|
183
|
+
|
|
184
|
+
async def pressures_to_forces(self, muscle_objects, pressures, force_multiplier):
|
|
185
|
+
force_list = [] # Makes a new empty list... of tuples? Needs link number, force, and transform
|
|
186
|
+
i = 0
|
|
187
|
+
try:
|
|
188
|
+
for muscle in muscle_objects:
|
|
189
|
+
triplet_a, triplet_b = muscle.update_muscle(pressures[i]) # Updates muscles w/ OSC argument
|
|
190
|
+
force_list.append(triplet_a)
|
|
191
|
+
force_list.append(triplet_b)
|
|
192
|
+
i += 1
|
|
193
|
+
except IndexError:
|
|
194
|
+
force_list.append([0,0,0])
|
|
195
|
+
force_list.append([0,0,0])
|
|
196
|
+
force_series = pd.Series(force_list)
|
|
197
|
+
return force_series * force_multiplier
|
|
198
|
+
|
|
199
|
+
async def simLoop(self, force_list):
|
|
200
|
+
"""
|
|
201
|
+
robot: A RobotModel.
|
|
202
|
+
force_list: Not sure what data structure, maybe a dataframe? name of muscle as index, with force and transform
|
|
203
|
+
|
|
204
|
+
Should possibly return a list of new transforms to be used for calculating stuff in the next time step.
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
self.link_transforms_start = [self.robotmodel.link(x).getTransform() for x in range(self.robotmodel.numLinks())]
|
|
208
|
+
"""
|
|
209
|
+
Below is where we apply each force in the simulation.
|
|
210
|
+
"""
|
|
211
|
+
for force in force_list:
|
|
212
|
+
link = self.body(self.robotmodel.link(force[0])) # From the force info, gets the link to apply force
|
|
213
|
+
force_vector = force[1] # Gets the force vector
|
|
214
|
+
transform = force[2] # Gets the transform at which to apply force
|
|
215
|
+
link.applyForceAtLocalPoint(force_vector, transform) # Applys the force
|
|
216
|
+
|
|
217
|
+
self.simulate(self.dt)
|
|
218
|
+
self.updateWorld()
|
|
219
|
+
if self.collider:
|
|
220
|
+
pass
|
|
221
|
+
#klampt.model.contact.world_contact_map(self.world, padding=0.1, kFriction=1, collider=self.collider)
|
|
222
|
+
#print(self.collider.collisions())
|
|
223
|
+
"""
|
|
224
|
+
Maybe here is where we have to get the updated link transforms and return them as "sensor" feedback.
|
|
225
|
+
"""
|
|
226
|
+
self.link_transforms_end = [self.robotmodel.link(x).getTransform() for x in range(self.robotmodel.numLinks())]
|
|
227
|
+
|
|
228
|
+
self.link_transforms_diff = [klampt.math.se3.error(self.link_transforms_start[x], self.link_transforms_end[x])
|
|
229
|
+
for x in range(len(self.link_transforms_start))] # Takes the Lie derivative from start -> end
|
|
230
|
+
return self.link_transforms_end # I don't even know if we need to use this, depends on if we pass by ref or var
|
|
231
|
+
|
|
232
|
+
async def configure_sim(self):
|
|
233
|
+
"""
|
|
234
|
+
Sets up the simulation to do whatever I want it to do.
|
|
235
|
+
"""
|
|
236
|
+
self.setSetting("boundaryLayerCollisions", "1")
|
|
237
|
+
self.setSetting("rigidObjectCollisions", "1")
|
|
238
|
+
self.setSetting("robotSelfCollisions", "1")
|
|
239
|
+
self.setSetting("robotRobotCollisions", "1")
|
|
240
|
+
self.setSetting("instabilityPostCorrectionEnergy", "0.01")
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import pyaudio
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
CHUNK = 2**5
|
|
5
|
+
RATE = 44100
|
|
6
|
+
LEN = 10
|
|
7
|
+
|
|
8
|
+
p = pyaudio.PyAudio()
|
|
9
|
+
|
|
10
|
+
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK)
|
|
11
|
+
player = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, output=True, frames_per_buffer=CHUNK)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
for i in range(int(LEN*RATE/CHUNK)): #go for a LEN seconds
|
|
15
|
+
data = np.fromstring(stream.read(CHUNK),dtype=np.int16)
|
|
16
|
+
player.write(data,CHUNK)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
stream.stop_stream()
|
|
20
|
+
stream.close()
|
|
21
|
+
p.terminate()
|
|
File without changes
|