Generate random movement for a point in 3D space - matlab

I want to simulate a point that moves with random vibration around a mean position (let's say around the position [X, Y, Z] = [0,0,0]). The first solution that I found is to sum a couple of sinusoids for each axis based on the following equation:
<img src="https://latex.codecogs.com/gif.latex?\sum_{i&space;=&space;1}^n&space;A_i&space;\sin(\omega_i&space;t&plus;\phi)" title="\sum_{i = 1}^n A_i \sin(\omega_i t+\phi)" />
where A_i is a normal random amplitude, and omega_i is a normal random frequency. I have not tested the phase yet, so I leave it to zero for now. I generated figures of the expect normal distribution and equation results with the following approach. I tried multiple values of N and I'm not sure that the equation is giving a normally distributed results. Is my approach correct? Is there a better way to generate random vibration?

For such a task, you may find useful Perlin Noise or even Fractal Brownian Motion noise. See this implementation in JavaScript:
class Utils {
static Lerp(a, b, t) {
return (1 - t) * a + t * b;
}
static Fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
}
class Noise {
constructor() {
this.p = [];
this.permutationTable = [];
this.grad3 = [[1, 1, 0], [-1, 1, 0], [1, -1, 0],
[-1, -1, 0], [1, 0, 1], [-1, 0, 1],
[1, 0, -1], [-1, 0, -1], [0, 1, 1],
[0, -1, 1], [0, 1, -1], [0, -1, -1]];
for (let i = 0; i < 256; i++)
this.p[i] = Math.floor(Math.random() * 256);
for (let i = 0; i < 512; i++)
this.permutationTable[i] = this.p[i & 255];
}
PerlinDot(g, x, y, z) {
return g[0] * x + g[1] * y + g[2] * z;
}
PerlinNoise(x, y, z) {
let a = Math.floor(x);
let b = Math.floor(y);
let c = Math.floor(z);
x = x - a;
y = y - b;
z = z - c;
a &= 255;
b &= 255;
c &= 255;
let gi000 = this.permutationTable[a + this.permutationTable[b + this.permutationTable[c]]] % 12;
let gi001 = this.permutationTable[a + this.permutationTable[b + this.permutationTable[c + 1]]] % 12;
let gi010 = this.permutationTable[a + this.permutationTable[b + 1 + this.permutationTable[c]]] % 12;
let gi011 = this.permutationTable[a + this.permutationTable[b + 1 + this.permutationTable[c + 1]]] % 12;
let gi100 = this.permutationTable[a + 1 + this.permutationTable[b + this.permutationTable[c]]] % 12;
let gi101 = this.permutationTable[a + 1 + this.permutationTable[b + this.permutationTable[c + 1]]] % 12;
let gi110 = this.permutationTable[a + 1 + this.permutationTable[b + 1 + this.permutationTable[c]]] % 12;
let gi111 = this.permutationTable[a + 1 + this.permutationTable[b + 1 + this.permutationTable[c + 1]]] % 12;
let n000 = this.PerlinDot(this.grad3[gi000], x, y, z);
let n100 = this.PerlinDot(this.grad3[gi100], x - 1, y, z);
let n010 = this.PerlinDot(this.grad3[gi010], x, y - 1, z);
let n110 = this.PerlinDot(this.grad3[gi110], x - 1, y - 1, z);
let n001 = this.PerlinDot(this.grad3[gi001], x, y, z - 1);
let n101 = this.PerlinDot(this.grad3[gi101], x - 1, y, z - 1);
let n011 = this.PerlinDot(this.grad3[gi011], x, y - 1, z - 1);
let n111 = this.PerlinDot(this.grad3[gi111], x - 1, y - 1, z - 1);
let u = Utils.Fade(x);
let v = Utils.Fade(y);
let w = Utils.Fade(z);
let nx00 = Utils.Lerp(n000, n100, u);
let nx01 = Utils.Lerp(n001, n101, u);
let nx10 = Utils.Lerp(n010, n110, u);
let nx11 = Utils.Lerp(n011, n111, u);
let nxy0 = Utils.Lerp(nx00, nx10, v);
let nxy1 = Utils.Lerp(nx01, nx11, v);
return Utils.Lerp(nxy0, nxy1, w);
}
FractalBrownianMotion(x, y, z, octaves, persistence) {
let total = 0;
let frequency = 1;
let amplitude = 1;
let maxValue = 0;
for(let i = 0; i < octaves; i++) {
total = this.PerlinNoise(x * frequency, y * frequency, z * frequency) * amplitude;
maxValue += amplitude;
amplitude *= persistence;
frequency *= 2;
}
return total / maxValue;
}
}
With Fractal Brownian Motion can have huge control about the randomness of distribution. You can set the scale, initial offset and its increment for each axis, octaves, and persistence. You can generate as many positions you like by incrementing the offsets, like this:
const NUMBER_OF_POSITIONS = 1000;
const X_OFFSET = 0;
const Y_OFFSET = 0;
const Z_OFFSET = 0;
const X_SCALE = 0.01;
const Y_SCALE = 0.01;
const Z_SCALE = 0.01;
const OCTAVES = 8;
const PERSISTENCE = 2;
const T_INCREMENT = 0.1;
const U_INCREMENT = 0.01;
const V_INCREMENT = 1;
let noise = new Noise();
let positions = [];
let i = 0, t = 0, u = 0, v = 0;
while(i <= NUMBER_OF_POSITIONS) {
let position = {x:0, y:0, z:0};
position.x = noise.FractalBrownianMotion((X_OFFSET + t) * X_SCALE, (Y_OFFSET + t) * Y_SCALE, (Z_OFFSET + t) * Z_SCALE, OCTAVES, PERSISTENCE);
position.y = noise.FractalBrownianMotion((X_OFFSET + u) * X_SCALE, (Y_OFFSET + u) * Y_SCALE, (Z_OFFSET + u) * Z_SCALE, OCTAVES, PERSISTENCE);
position.z = noise.FractalBrownianMotion((X_OFFSET + v) * X_SCALE, (Y_OFFSET + v) * Y_SCALE, (Z_OFFSET + v) * Z_SCALE, OCTAVES, PERSISTENCE);
positions.push(position);
t += T_INCREMENT;
u += U_INCREMENT;
v += V_INCREMENT;
i++;
}
Positions you get with these options would look similar to these:
...
501: {x: 0.0037344935483775883, y: 0.1477509219864437, z: 0.2434570202517206}
502: {x: -0.008955635460317357, y: 0.14436114483299245, z: -0.20921147024725012}
503: {x: -0.06021806450587406, y: 0.14101769272762685, z: 0.17093922757597568}
504: {x: -0.05796055906294283, y: 0.13772732578136435, z: 0.0018755951606465138}
505: {x: 0.02243901814464688, y: 0.13448621540816477, z: 0.013341084536334057}
506: {x: 0.05074194554980439, y: 0.1312810723109357, z: 0.15821600463130164}
507: {x: 0.011075140752144507, y: 0.12809058766450473, z: 0.04006055269090941}
508: {x: -0.0000031848272303249632, y: 0.12488712875549206, z: -0.003957905411646261}
509: {x: -0.0029798194097060307, y: 0.12163862278870072, z: -0.1988934273517602}
510: {x: -0.008762098499026483, y: 0.11831055728747841, z: 0.02222898347134993}
511: {x: 0.01980289423585394, y: 0.11486802263767962, z: -0.0792283303765883}
512: {x: 0.0776034130079849, y: 0.11127772191732693, z: -0.14141576745502138}
513: {x: 0.08695806478169149, y: 0.10750987521108693, z: 0.049654228704645}
514: {x: 0.036915612100698, y: 0.10353995005320946, z: 0.00033977899920740567}
515: {x: 0.0025923223158845687, y: 0.09935015632822117, z: -0.00952549797548823}
516: {x: 0.0015456084571764527, y: 0.09493065267319889, z: 0.12609905321632175}
517: {x: 0.0582996941155056, y: 0.09028042189611517, z: -0.27532974820612816}
518: {x: 0.19186052966982514, y: 0.08540778482478142, z: -0.00035058098387404606}
519: {x: 0.27063961068049447, y: 0.08033053495775729, z: -0.07737309686568927}
520: {x: 0.20318957178662056, y: 0.07507568989311474, z: -0.14633819135757353}
...
Note: for efficiency, it's a good idea generate all positions only once into an array of positions like in this example, and then in some animation loop just assigning positions to your point from this array one by one.
Bonus: Here you can see how those values affect the distribution of multiple points by playing around with real-time response control panel:
https://marianpekar.github.io/fbm-space/
References:
https://en.wikipedia.org/wiki/Fractional_Brownian_motion
https://en.wikipedia.org/wiki/Perlin_noise

Related

Generate random Gaussian noise MTLTexture or MTLBuffer of size (width, height)

I am writing a real-time video filter application and for one of the algorithms I want to try out, I need to generate a random, gaussian univariate distributed buffer (or texture) based on the input source.
Coming from a Python background, the following few lines are running in about 0.15s (which is not real-time worthy but a lot faster than the Swift code I tried below):
h = 1170
w = 2532
with Timer():
noise = np.random.normal(size=w * h * 3)
plt.imshow(noise.reshape(w,h,3))
plt.show()
My Swift code try:
private func generateNoiseTextureBuffer(width: Int, height: Int) -> [Float] {
let w = Float(width)
let h = Float(height)
var noiseData = [Float](repeating: 0, count: width * height * 4)
for xi in (0 ..< width) {
for yi in (0 ..< height) {
let index = yi * width + xi
let x = Float(xi)
let y = Float(yi)
let random = GKRandomSource()
let gaussianGenerator = GKGaussianDistribution(randomSource: random, mean: 0.0, deviation: 1.0)
let randX = gaussianGenerator.nextUniform()
let randY = gaussianGenerator.nextUniform()
let scale = sqrt(2.0 * min(w, h) * (2.0 / Float.pi))
let rx = floor(max(min(x + scale * randX, w - 1.0), 0.0))
let ry = floor(max(min(y + scale * randY, h - 1.0), 0.0))
noiseData[index * 4 + 0] = rx + 0.5
noiseData[index * 4 + 1] = ry + 0.5
noiseData[index * 4 + 2] = 1
noiseData[index * 4 + 3] = 1
}
}
return noiseData
}
...
let noiseData = self.generateNoiseTextureBuffer(width: context.sourceColorTexture.width, height: context.sourceColorTexture.height)
let noiseDataSize = noiseData.count * MemoryLayout.size(ofValue: noiseData[0])
self.noiseBuffer = device.makeBuffer(bytes: noiseData, length: noiseDataSize)
How can I accomplish this fast and easily in Swift?

How to move PointCloud to coordinates center?

I have a PointCloud which have points with position(x, y, z) and color(r, g, b)
But points lays in big distance from coordinates canter:
Question is: what algorithm can be used to place all points to coordinates center? My guess is to create translation matrix and multiply all pointCloud points to it, but I can't determine what this matrix should contain
Just found an answer. Need to find center of mass of PointCloud with something like this:
var summX: Float = 0
var summY: Float = 0
var summZ: Float = 0
for point in points {
summX += point.x
summY += point.y
summZ += point.z
}
let middleX = summX / Float(points.count)
let middleY = summY / Float(points.count)
let middleZ = summZ / Float(points.count)
let centerOfMass = Float3(x: middleX, y: middleY, z: middleZ)
Then create translation matrix
And finally multiply all points to this matrix
let translationMatrix = float4x4(simd_float4(x: 1, y: 0, z: 0, w: -centerOfMass.x),
simd_float4(x: 0, y: 1, z: 0, w: -centerOfMass.y),
simd_float4(x: 0, y: 0, z: 1, w: -centerOfMass.z),
simd_float4(x: 0, y: 0, z: 0, w: 1))
let translatedPoints = points.map { point in
return point * translationMatrix
}

How to fix incorrect energy conservation problem in mass-spring-system simulation using RK4 method

I am making a simulation where you create different balls of certain mass, connected by springs which you can define (in the program below all springs have natural length L and spring constant k). How I do it is I created a function accel(b,BALLS), (note b is the specific ball and BALLS are all of the ball objects in various stages of update) which gets me acceleration on this one ball from calculating all the forces acting on it (tensions from ball the springs connected to it and gravity) and I would think this function is definitely correct and problems lie elsewhere in the while loop. I then use the RK4 method described on this website: http://spiff.rit.edu/richmond/nbody/OrbitRungeKutta4.pdf in the while loop to update velocity and position of each ball. To test my understanding of the method I first made a simulation where only two balls and one spring is involved on Desmos: https://www.desmos.com/calculator/4ag5gkerag
I allowed for energy display and saw that indeed RK4 is much better than Euler method. Now I made it in python in the hope that it should work with arbitrary config of balls and springs, but energy isn't even conserved when I have two balls and one spring! I couldn't see what I did differently, at least when two balls on involved. And when I introduce a third ball and a second spring to the system, energy increases by the hundreds every second. This is my first time coding a simulation with RK4, and I expect you guys can find mistakes in it. I have an idea that maybe the problem is caused by because there are multiple bodies and difficulties arises when I update their kas or kvs at the same time but then again I can't spot any difference between what this code is doing when simulating two balls and my method used in the Desmos file. Here is my code in python:
import pygame
import sys
import math
import numpy as np
pygame.init()
width = 1200
height = 900
SCREEN = pygame.display.set_mode((width, height))
font = pygame.font.Font(None, 25)
TIME = pygame.time.Clock()
dampwall = 1
dt = 0.003
g = 20
k=10
L=200
def dist(a, b):
return math.sqrt((a[0] - b[0])*(a[0] - b[0]) + (a[1] - b[1])*(a[1] - b[1]))
def mag(a):
return dist(a, [0, 0])
def dp(a, b):
return a[0]*b[0]+a[1]*b[1]
def norm(a):
return list(np.array(a)/mag(a))
def reflect(a, b):
return norm([2*a[1]*b[0]*b[1]+a[0]*(b[0]**2 - b[1]**2), 2*a[0]*b[0]*b[1]+a[1]*(-b[0]**2 + b[1]**2)])
class ball:
def __init__(self, x, y, vx, vy, mass,spr,index,ka,kv):
self.r = [x, y]
self.v = [vx, vy]
self.radius = 5
self.mass = mass
self.spr=spr
self.index = index
self.ka=ka
self.kv=kv
def detectbounce(self,width,height):
if self.r[0] + self.radius > width/2 and self.r[0]+self.v[0] > self.r[0] or self.r[0] - self.radius < -width/2 and self.r[0]+self.v[0] < self.r[0] or self.r[1] + self.radius > height/2 and self.r[1]+self.v[1] > self.r[1] or self.r[1] - self.radius < -height/2 and self.r[1]+self.v[1] < self.r[1]:
return True
def bounce_walls(self, width, height):
if self.r[0] + self.radius > width/2 and self.r[0]+self.v[0] > self.r[0]:
self.v[0] *= -dampwall
if self.r[0] - self.radius < -width/2 and self.r[0]+self.v[0] < self.r[0]:
self.v[0] *= -dampwall
if self.r[1] + self.radius > height/2 and self.r[1]+self.v[1] > self.r[1]:
self.v[1] *= -dampwall
if self.r[1] - self.radius < -height/2 and self.r[1]+self.v[1] < self.r[1]:
self.v[1] *= -dampwall
def update_r(self,v, h):
self.r[0] += v[0] * h
self.r[1] += v[1] * h
def un_update_r(self,v, h):
self.r[0] += -v[0] * h
self.r[1] += -v[1] * h
def KE(self):
return 0.5 * self.mass * mag(self.v)**2
def GPE(self):
return self.mass * g * (-self.r[1] + height)
def draw(self, screen, width, height):
pygame.draw.circle(screen, (0, 0, 255), (self.r[0] +
width / 2, self.r[1] + height / 2), self.radius)
#(self, x, y, vx, vy, mass,spr,index,ka,kv):
# balls = [ball(1, 19, 0, 0,5,[1],0,[0,0,0,0],[0,0,0,0]), ball(250, 20, 0,0,1,[0],1,[0,0,0,0],[0,0,0,0])]
# springs = [[0, 1]]
balls = [ball(1, 19, 0, 0,5,[1,3],0,[0,0,0,0],[0,0,0,0]), ball(250, 20, 0,0,2,[0,2,3],1,[0,0,0,0],[0,0,0,0]),ball(450, 0, 0,0,2,[1,3],1,[0,0,0,0],[0,0,0,0]),ball(250, -60, 0,0,2,[0,1,2],1,[0,0,0,0],[0,0,0,0])]
springs = [[0, 1],[1,2],[0,3],[1,3],[2,3]]
def accel(b,BALLS):
A=[0,g]
for i in range(0,len(b.spr)):
ball1=b
ball2=BALLS[b.spr[i]]
r1 = norm(list(np.array(ball2.r) - np.array(ball1.r)))
lnow = dist(ball1.r, ball2.r)
force = k * (lnow - L)
A[0]+=force/ball1.mass*r1[0]
A[1]+=force/ball1.mass*r1[1]
return A
initE=0
while True:
TIME.tick(200)
SCREEN.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#compute k1a and k1v for all balls
for ball in balls:
ball.ka[0]=accel(ball,balls)
ball.kv[0]=ball.v
#create newb1 based on 'updated' position of all balls with their own k1v
newb=[]
for ball in balls:
ball.update_r(ball.kv[0], dt/2)
newb.append(ball)
ball.un_update_r(ball.kv[0], dt/2)
#compute k2a and k2v for all balls based on newb1
for ball in balls:
ball.update_r(ball.kv[0], dt/2)
ball.ka[1]=accel(ball,newb)
ball.un_update_r(ball.kv[0], dt/2)
ball.kv[1]=[ball.v[0]+0.5*dt*ball.ka[0][0],ball.v[1]+0.5*dt*ball.ka[0][1]]
#create newb2 based on 'updated' position of all balls with their own k2v
newb=[]
for ball in balls:
ball.update_r(ball.kv[1], dt/2)
newb.append(ball)
ball.un_update_r(ball.kv[1], dt/2)
#compute k3a and k3v for all balls
for ball in balls:
ball.update_r(ball.kv[1], dt/2)
ball.ka[2]=accel(ball,newb)
ball.un_update_r(ball.kv[1], dt/2)
ball.kv[2]=[ball.v[0]+0.5*dt*ball.ka[1][0],ball.v[1]+0.5*dt*ball.ka[1][1]]
newb=[]
for ball in balls:
ball.update_r(ball.kv[2], dt)
newb.append(ball)
ball.un_update_r(ball.kv[2], dt)
#compute k4a and k4v for all balls
for ball in balls:
ball.update_r(ball.kv[2], dt)
ball.ka[3]=accel(ball,newb)
ball.un_update_r(ball.kv[2], dt)
ball.kv[3]=[ball.v[0]+dt*ball.ka[2][0],ball.v[1]+dt*ball.ka[2][1]]
#final stage of update
for ball in balls:
if ball.detectbounce(width,height)==True:
ball.bounce_walls(width, height)
else:
ball.v=[ball.v[0]+dt*(ball.ka[0][0]+2*ball.ka[1][0]+2*ball.ka[2][0]+ball.ka[3][0])/6, ball.v[1]+dt*(ball.ka[0][1]+2*ball.ka[1][1]+2*ball.ka[2][1]+ball.ka[3][1])/6]
ball.r=[ball.r[0]+dt*(ball.kv[0][0]+2*ball.kv[1][0]+2*ball.kv[2][0]+ball.kv[3][0])/6, ball.r[1]+dt*(ball.kv[0][1]+2*ball.kv[1][1]+2*ball.kv[2][1]+ball.kv[3][1])/6]
for ball in balls:
ball.draw(SCREEN, width, height)
for i in range(0,len(ball.spr)):
ball1=ball
ball2=balls[ball.spr[i]]
pygame.draw.line(SCREEN, (0, 0, 155), (
ball1.r[0]+width/2, ball1.r[1]+height/2), (ball2.r[0]+width/2, ball2.r[1]+height/2))
#check for energy
KE = 0
EPE = 0
GPE = 0
for i in range(0, len(springs)):
EPE += 1/2 * k * \
(L - dist(balls[springs[i][0]].r,
balls[springs[i][1]].r))**2
for i in range(0, len(balls)):
KE += balls[i].KE()
GPE += balls[i].GPE()
if initE == 0:
initE += KE+EPE+GPE
text = font.render('init Energy: ' + str(round(initE,1))+' '+'KE: ' + str(round(KE, 1)) + ' '+'EPE: ' + str(round(EPE, 1))+' ' + 'GPE: ' + str(round(GPE, 1)) + ' ' + 'Total: ' + str(round(KE+EPE+GPE, 1)) + ' ' + 'Diff: ' + str(round((KE+EPE+GPE-initE), 1)),
True, (255, 255, 255))
textRect = text.get_rect()
textRect.center = (370, 70)
SCREEN.blit(text, textRect)
pygame.display.flip()
This is the edited, corrected by Lutz Lehmann and with some extra improvements:
import pygame
import sys
import math
import numpy as np
pygame.init()
width = 1200
height = 900
SCREEN = pygame.display.set_mode((width, height))
font = pygame.font.Font(None, 25)
TIME = pygame.time.Clock()
dampwall = 1
dt = 0.003
g = 5
k = 10
L = 200
digits = 6
def dist(a, b):
return math.sqrt((a[0] - b[0])*(a[0] - b[0]) + (a[1] - b[1])*(a[1] - b[1]))
def mag(a):
return dist(a, [0, 0])
def dp(a, b):
return a[0]*b[0]+a[1]*b[1]
def norm(a):
return list(np.array(a)/mag(a))
def reflect(a, b):
return norm([2*a[1]*b[0]*b[1]+a[0]*(b[0]**2 - b[1]**2), 2*a[0]*b[0]*b[1]+a[1]*(-b[0]**2 + b[1]**2)])
class Ball:
def __init__(self, x, y, vx, vy, mass, spr, index, ka, kv):
self.r = [x, y]
self.v = [vx, vy]
self.radius = 5
self.mass = mass
self.spr = spr
self.index = index
self.ka = ka
self.kv = kv
def copy(self):
return Ball(self.r[0], self.r[1], self.v[0], self.v[1], self.mass, self.spr, self.index, self.ka, self.kv)
def detectbounce(self, width, height):
if self.r[0] + self.radius > width/2 and self.r[0]+self.v[0] > self.r[0] or self.r[0] - self.radius < -width/2 and self.r[0]+self.v[0] < self.r[0] or self.r[1] + self.radius > height/2 and self.r[1]+self.v[1] > self.r[1] or self.r[1] - self.radius < -height/2 and self.r[1]+self.v[1] < self.r[1]:
return True
def bounce_walls(self, width, height):
if self.r[0] + self.radius > width/2 and self.r[0]+self.v[0] > self.r[0]:
self.v[0] *= -dampwall
if self.r[0] - self.radius < -width/2 and self.r[0]+self.v[0] < self.r[0]:
self.v[0] *= -dampwall
if self.r[1] + self.radius > height/2 and self.r[1]+self.v[1] > self.r[1]:
self.v[1] *= -dampwall
if self.r[1] - self.radius < -height/2 and self.r[1]+self.v[1] < self.r[1]:
self.v[1] *= -dampwall
def update_r(self, v, h):
self.r[0] += v[0] * h
self.r[1] += v[1] * h
def un_update_r(self, v, h):
self.r[0] += -v[0] * h
self.r[1] += -v[1] * h
def KE(self):
return 0.5 * self.mass * mag(self.v)**2
def GPE(self):
return self.mass * g * (-self.r[1] + height)
def draw(self, screen, width, height):
pygame.draw.circle(screen, (0, 0, 255), (self.r[0] +
width / 2, self.r[1] + height / 2), self.radius)
# (self, x, y, vx, vy, mass,spr,index,ka,kv):
# balls = [Ball(1, 19, 0, 0, 1, [1], 0, [0, 0, 0, 0], [0, 0, 0, 0]),
# Ball(250, 20, 0, 0, 1, [0], 1, [0, 0, 0, 0], [0, 0, 0, 0])]
# springs = [[0, 1]]
balls = [Ball(1, 19, 0, 0,5,[1,3],0,[0,0,0,0],[0,0,0,0]), Ball(250, 20, 0,0,2,[0,2,3],1,[0,0,0,0],[0,0,0,0]),Ball(450, 0, 0,0,2,[1,3],1,[0,0,0,0],[0,0,0,0]),Ball(250, -60, 0,0,2,[0,1,2],1,[0,0,0,0],[0,0,0,0])]
# n=5
# resprings=[]
# for i in range(0,n):
# for j in range(0,n):
# if i==0 and j==0:
# resprings.append([1,2,n,n+1,2*n])
# if i==n and j==0:
# resprings.apend([n*(n-1)+1,n*(n-1)+2,n*(n-2),n*(n-3),n*(n-2)+1])
# if j==0 and i!=0 or i!=n:
# resprings.append([(i-1)*n+1,(i-1)*n+2,(i-2)*n,(i-2)*n+1,(i)*n,(i)*n+1])
def getsprings(B):
S=[]
for i in range(0,len(B)):
theball=B[i]
for j in range(len(theball.spr)):
spring=sorted([i,theball.spr[j]])
if spring not in S:
S.append(spring)
return S
springs = getsprings(balls)
def accel(b, BALLS):
A = [0, g]
for i in range(0, len(b.spr)):
ball1 = b
ball2 = BALLS[b.spr[i]]
r1 = norm(list(np.array(ball2.r) - np.array(ball1.r)))
lnow = dist(ball1.r, ball2.r)
force = k * (lnow - L)
A[0] += force/ball1.mass*r1[0]
A[1] += force/ball1.mass*r1[1]
return A
initE = 0
while True:
TIME.tick(200)
SCREEN.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
for ball in balls:
ball.bounce_walls(width, height)
# compute k1a and k1v for all balls
for ball in balls:
ball.ka[0] = accel(ball, balls)
ball.kv[0] = ball.v
# create newb1 based on 'updated' position of all balls with their own k1v
newb = []
for ball in balls:
ball.update_r(ball.kv[0], dt/2)
newb.append(ball.copy())
ball.un_update_r(ball.kv[0], dt/2)
# compute k2a and k2v for all balls based on newb1
for ball in balls:
ball.update_r(ball.kv[0], dt/2)
ball.ka[1] = accel(ball, newb)
ball.un_update_r(ball.kv[0], dt/2)
ball.kv[1] = [ball.v[0]+0.5*dt*ball.ka[0]
[0], ball.v[1]+0.5*dt*ball.ka[0][1]]
# create newb2 based on 'updated' position of all balls with their own k2v
newb = []
for ball in balls:
ball.update_r(ball.kv[1], dt/2)
newb.append(ball.copy())
ball.un_update_r(ball.kv[1], dt/2)
# compute k3a and k3v for all balls
for ball in balls:
ball.update_r(ball.kv[1], dt/2)
ball.ka[2] = accel(ball, newb)
ball.un_update_r(ball.kv[1], dt/2)
ball.kv[2] = [ball.v[0]+0.5*dt*ball.ka[1]
[0], ball.v[1]+0.5*dt*ball.ka[1][1]]
newb = []
for ball in balls:
ball.update_r(ball.kv[2], dt)
newb.append(ball.copy())
ball.un_update_r(ball.kv[2], dt)
# compute k4a and k4v for all balls
for ball in balls:
ball.update_r(ball.kv[2], dt)
ball.ka[3] = accel(ball, newb)
ball.un_update_r(ball.kv[2], dt)
ball.kv[3] = [ball.v[0]+dt*ball.ka[2][0], ball.v[1]+dt*ball.ka[2][1]]
# final stage of update
for ball in balls:
ball.v = [ball.v[0]+dt*(ball.ka[0][0]+2*ball.ka[1][0]+2*ball.ka[2][0]+ball.ka[3][0])/6,
ball.v[1]+dt*(ball.ka[0][1]+2*ball.ka[1][1]+2*ball.ka[2][1]+ball.ka[3][1])/6]
ball.r = [ball.r[0]+dt*(ball.kv[0][0]+2*ball.kv[1][0]+2*ball.kv[2][0]+ball.kv[3][0])/6,
ball.r[1]+dt*(ball.kv[0][1]+2*ball.kv[1][1]+2*ball.kv[2][1]+ball.kv[3][1])/6]
for ball in balls:
ball.draw(SCREEN, width, height)
for i in range(0, len(ball.spr)):
ball1 = ball
ball2 = balls[ball.spr[i]]
pygame.draw.line(SCREEN, (0, 0, 155), (
ball1.r[0]+width/2, ball1.r[1]+height/2), (ball2.r[0]+width/2, ball2.r[1]+height/2))
# check for energy
KE = 0
EPE = 0
GPE = 0
for i in range(0, len(springs)):
EPE += 1/2 * k * \
(L - dist(balls[springs[i][0]].r,
balls[springs[i][1]].r))**2
for i in range(0, len(balls)):
KE += balls[i].KE()
GPE += balls[i].GPE()
if initE == 0:
initE += KE+EPE+GPE
text1 = font.render(f"initial energy: {str(round(initE, digits))}", True, (255, 255, 255))
text2 = font.render(f"kinetic energy: {str(round(KE, digits))}", True, (255, 255, 255))
text3 = font.render(f"elastic potential energy: {str(round(EPE, digits))}", True, (255, 255, 255))
text4 = font.render(f"gravitational energy: {str(round(GPE, digits))}", True, (255, 255, 255))
text5 = font.render(f"total energy: {str(round(KE + EPE + GPE, digits))}", True, (255, 255, 255))
text6 = font.render(f"change in energy: {str(round(KE + EPE + GPE - initE, digits))}", True, (255, 255, 255))
SCREEN.blit(text1, (10, 10))
SCREEN.blit(text2, (10, 60))
SCREEN.blit(text3, (10, 110))
SCREEN.blit(text4, (10, 160))
SCREEN.blit(text5, (10, 210))
SCREEN.blit(text6, (10, 260))
pygame.display.flip()
The immediate error seems to be this
for ball in balls:
...
newb1.append(ball)
...
as ball is just a reference to the class ball instance, thus newb1 is a list of references to the objects in balls, it makes no difference if you manipulate the one or the other, it is always the same data records that get changed.
You need to apply a copy mechanism, as you have lists of lists, you need a deep copy, or a dedicated copy member method, else you just copy the array references in the ball instances, so you get different instances, but pointing to the same arrays.
It is probably not an error but still a bad idea to have the class name also as variable name in the same scope.

raspberry pi OSError; savedModel file does not exist at

This code does not have an error when running on a computer, but when I move all the files and run it on a Raspberry Pi, I get this error. Where and how to fix it?
OSError; savedModel file does not exist at: models/mask_detector.model/{saved_model.pbtxt|saved_model.pb}
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
import numpy as np
import cv2
facenet = cv2.dnn.readNet('models/deploy.prototxt', 'models/res10_300x300_ssd_iter_140000.caffemodel')
model = load_model('models/mask_detector.model')
cap = cv2.VideoCapture(0)
i = 0
while cap.isOpened():
ret, img = cap.read()
if not ret:
break
h, w = img.shape[:2]
blob = cv2.dnn.blobFromImage(img, scalefactor=1., size=(300, 300), mean=(104., 177., 123.))
facenet.setInput(blob)
dets = facenet.forward()
result_img = img.copy()
for i in range(dets.shape[2]):
confidence = dets[0, 0, i, 2]
if confidence < 0.5:
continue
x1 = int(dets[0, 0, i, 3] * w)
y1 = int(dets[0, 0, i, 4] * h)
x2 = int(dets[0, 0, i, 5] * w)
y2 = int(dets[0, 0, i, 6] * h)
face = img[y1:y2, x1:x2]
face_input = cv2.resize(face, dsize=(224, 224))
face_input = cv2.cvtColor(face_input, cv2.COLOR_BGR2RGB)
face_input = preprocess_input(face_input)
face_input = np.expand_dims(face_input, axis=0)
mask, nomask = model.predict(face_input).squeeze()
if mask > nomask:
color = (0, 255, 0)
label = 'Mask %d%%' % (mask * 100)
else:
color = (0, 0, 255)
label = 'No Mask %d%%' % (nomask * 100)
cv2.rectangle(result_img, pt1=(x1, y1), pt2=(x2, y2), thickness=2, color=color, lineType=cv2.LINE_AA)
cv2.putText(result_img, text=label, org=(x1, y1 - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.8,
color=color, thickness=2, lineType=cv2.LINE_AA)
cv2.imshow('img',result_img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

when rotation shape changed in metal

I just created a rectangle using four vertices in metal. I just need to rotate it. So I use a model metrics.Here is my vertex shader.
vertex VertexOutTexture vertex_shader_texture(const VertexInTexture vertices [[stage_in]],
constant ModelConstant &modelConstants[[buffer(1)]],
VertexOutTexture v;
v.position = modelConstants.modelMatrix*float4(vertices.position,1);
v.color = vertices.color;
v.textureCoordinates = vertices.textureCoordinates;
return v;
}
it rotate. But shape is changed. So I used projection transformation which converts the node’s coordinates from camera coordinates to normalized coordinates.
I create projrction matrix:
var sceneConstants = ScenceConstants()
set its value:
sceneConstants.projectionMatrix = matrix_float4x4(prespectiveDegreesFov:45, aspectRatio:Float(1.0),nearZ:0.1,farZ:100)
where init mathod is in math.h
init(prespectiveDegreesFov degreesFov:Float, aspectRatio:Float,nearZ:Float,farZ:Float){
let fov = radians(fromDegrees: degreesFov)
let y = 1/tan(fov*0.5)
let x = y/aspectRatio
let z1 = farZ/(nearZ - farZ)
let w = (z1*nearZ)
columns = (
float4(x, 0, 0, 0),
float4(0, y, 0, 0),
float4(0, 0, z1,-1),
float4(0, 0, w, 0)
)
}
send commands to GPU:
commandEncoder.setVertexBytes(&sceneConstants, length: MemoryLayout<ScenceConstants>.stride, index: 2)
change my vertex shader:
v.position = sceneConstants.projectionMatrix* modelConstants.modelMatrix*float4(vertices.position ,1 );
But it did not work.
before rotation:
after rotation:
I have atached math functions I am using below.
func radians(fromDegrees degrees:Float) ->Float{
return (degrees/100)*Float(Double.pi)
}
extension matrix_float4x4 {
init(prespectiveDegreesFov degreesFov:Float, aspectRatio:Float,nearZ:Float,farZ:Float){
let fov = radians(fromDegrees: degreesFov)
let y = 1/tan(fov*0.5)
let x = y/aspectRatio
let z1 = farZ/(nearZ - farZ)
let w = (z1*nearZ)
columns = (
float4(x, 0, 0, 0),
float4(0, y, 0, 0),
float4(0, 0, z1,-1),
float4(0, 0, w, 0)
)
}
mutating func scale(axis: float3){
var result = matrix_identity_float4x4
let x :Float = axis.x
let y :Float = axis.y
let z :Float = axis.z
result.columns = (
float4(x,0,0,0),
float4(0,y,0,0),
float4(0,0,z,0),
float4(0,0,0,1)
)
print("self:\(self)")
self = matrix_multiply(self, result)
}
mutating func translate(direction: float3){
var result = matrix_identity_float4x4
let x :Float = direction.x
let y :Float = direction.y
let z :Float = direction.z
result.columns = (
float4(1,0,0,0),
float4(0,1,0,0),
float4(0,0,1,0),
float4(x,y,z,1)
)
print("self:\(self)")
self = matrix_multiply(self, result)
}
mutating func rotate(angle: Float ,axis: float3){
var result = matrix_identity_float4x4
let x :Float = axis.x
let y :Float = axis.y
let z :Float = axis.z
let c: Float = cos(angle)
let s:Float = sin(angle)
let mc :Float = (1 - c)
let r1c1: Float = x * x * mc + c
let r2c1: Float = x * y * mc + z * s
let r3c1: Float = x * z * mc - y * s
let r4c1: Float = 0.0
let r1c2: Float = y * x * mc - z * s
let r2c2: Float = y * y * mc + c
let r3c2: Float = y * z * mc + x * s
let r4c2: Float = 0.0
let r1c3: Float = z * x * mc + y * s
let r2c3: Float = z * y * mc - x * s
let r3c3: Float = z * z * mc + c
let r4c3: Float = 0.0
let r1c4: Float = 0.0
let r2c4: Float = 0.0
let r3c4: Float = 0.0
let r4c4: Float = 1.0
result.columns = (
float4(r1c1,r2c1,r3c1,r4c1),
float4(r1c2,r2c2,r3c2,r4c2),
float4(r1c3,r2c3,r3c3,r4c3),
float4(r1c4,r2c4,r3c4,r4c4)
)
print("Result:\(result)")
self = matrix_multiply(self, result)
}
}
How can I fix this issue?Any suggestions please?