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 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
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