Need to get mean and max values with this script - python

I'm having a few problems.
First, given wind speeds seem to be low, especially compared to other weather stations reporting close by (apparently there are lots of enthusiasts in my area). Just watching the trees, flag, bushes, small animals flying across my yard, I can tell 1.6mph is a wee bit low. Everything tested fine inside, and when I run the test script outside its picking up the signal as it spins.
the 2nd problem is it always reports the "mean" and "max" speeds as exactly the same. I've tried to adjust the intervals, but no matter what length of time I put in, they always report as the same numbers.
from gpiozero import Button
import requests
import time
import math
import statistics
import database
wind_count = 0
radius_cm = 9.0
wind_interval = 5
ADJUSTMENT = 1.18
interval = 60
gust = 0
def spin():
global wind_count
wind_count = wind_count + 1
def calculate_speed(time_sec):
global wind_count
global gust
circumference_cm = (2 * math.pi) * radius_cm
rotations = wind_count / 2.0
dist_cm = circumference_cm * rotations
dist_km = (circumference_cm * rotations) / 100000
dist_mi = dist_km * 0.621371
mi_per_sec = dist_mi / time_sec
mi_per_hour = mi_per_sec * 3600
return mi_per_hour * ADJUSTMENT
def reset_wind():
global wind_count
wind_count = 0
def reset_gust():
global gust
gust = 0
wind_speed_sensor = Button(16)
wind_speed_sensor.when_activated = spin
while True:
print("Starting Weather Sensor Read Loop...")
start_time = time.time()
while time.time() - start_time <= interval:
print("Start timed loop...")
wind_start_time = time.time()
reset_wind()
reset_gust()
store_speeds = []
time.sleep(wind_interval)
final_speed = calculate_speed(wind_interval)
store_speeds.append(final_speed)
wind_gust_speed = (max(store_speeds))
wind_speed = (statistics.mean(store_speeds))
print(wind_average, wind_speed)
When I comment out "store_speeds = [ ]" the first loop the speeds are reported the same, every loop after I get a "max" reading thats "different" than the mean. This still troubles me, because why on the first loop are they the same? Am I wrong for thinking with the wind_interval set at 5, and the interval set to 60, that its taking 5 second samples over a 60 second period, giving me 12 sample to get the mean and max from?
My goal is every time it reports, I get a mean and max for that "loop" if possible, and not a mean/max over the time the script stays running before its interrupted/stopped.

Here is the working and corrected code:
from gpiozero import Button
import time
import math
import statistics
wind_count = 0
radius_cm = 9.0
wind_interval = 5
interval = 30
CM_IN_A_KM = 100000.0
SECS_IN_AN_HOUR = 3600
ADJUSTMENT = 1.18
store_speeds = []
def reset_wind():
global wind_count
wind_count = 0
def spin():
global wind_count
wind_count = wind_count + 1
def calculate_speed(time_sec):
global wind_count
circumference_cm = (2 * math.pi) * radius_cm
rotations = wind_count / 2.0
dist_km = (circumference_cm * rotations) / CM_IN_A_KM
km_per_sec = dist_km / time_sec
km_per_hour = km_per_sec * SECS_IN_AN_HOUR
mi_per_hour = km_per_hour * 0.6214
return mi_per_hour * ADJUSTMENT
wind_speed_sensor = Button(16)
wind_speed_sensor.when_pressed = spin
while True:
store_speeds = []
for _ in range (interval//wind_interval):
reset_wind()
#reset_gust()
time.sleep(wind_interval) # counter is spinning in background
final_speed = calculate_speed(wind_interval)
store_speeds.append(final_speed)
wind_gust = max(store_speeds)
wind_speed = statistics.mean(store_speeds)
print(wind_speed, wind_gust)

Related

Move a stepper motor to an exact position

My setup: An Arduino that reads numbers from serial(steps), then it moves the stepper motor that many steps. It uses a4988 driver, a 12 volt power supply, 1.5 amp Nema 17. All of that is fine, my issue is on the Python side.
In Python, I have tried to create a function in a variety of ways.
I used tkinter to get the mouse position on the screen, it moves in the x axis rotating the stepper. The stepper has a flashlight just to shine it at anything I point at with my mouse.
Say there is a camera below the stepper, if I move my mouse over to an object it would move there, within a tolerance of 5 steps either way. +5, -5
The function I have tried to create should work like this.
while True:
#I change direction by writing 400, clockwise, or 401, anti clockwise to serial.
step(10)#move only 10 steps
step(10)#it should do nothing as it has already moved 10 steps.
step(15)#it should move 5 steps as it has moved 10 already
step(5)#change direction and move back 10 steps
I am somewhat decent at python(or so I think)
here is my most promising code so far:
#I have direction changes done by writing a 400 for clockwise or 401 for anti clockwise to serial.
import tkinter as tk
import serial
ser = serial.Serial("COM8", 9600)
root = tk.Tk()
wi = root.winfo_screenwidth() / 2
width = root.winfo_screenwidth()
hi = root.winfo_screenheight() / 2
height = root.winfo_screenheight()
sere = '\r\n'
sender = sere.encode('utf_8')
pps = height / 200
# p.p.s pixels per step divide that by the same thing to get correct.
#how many pixels are for 1 step
print(pps)
#number of pixels difference divided by pps to get steps, then round for ease of use
past = 0
print(height, width, wi) # height divided by pps should always = max steps in my case 200
def send(steps):
global past
global current
sere = '\r\n'
current = steps
neg = past - 5
pos = past + 5
if current != past:
if current > pos or current < neg:
if steps > 1:
sender = sere.encode('utf_8')
e = str(steps).encode('utf_8')
ser.write(e + sender)
past = steps
while True:
pos = root.winfo_pointerx() - wi
steps = round(pos / pps)
print(pos, steps) # shows cursor position
#direction code is not in here as I have no need for it atm.For one simple reason, IT DOESN'T WORK!
Please explain answers if possible, I am a long time lurker, and only made a account just now for this.Thank you all for any assistance.
Edit:
The question is how to make a function that moves a stepper motor to a certain number of steps.If you command it to do 10 steps twice, it only moves 10 steps.
step(10) stepper moves 10 steps, do it again the motor does nothing as it is already at 10 steps.
If I do step(15) it would only move another 5 as it is at 10 steps.
Edit2 Clarification:
By function I mean
def step(steps):
#logic that makes it work
For anyone else who has this problem and people seem to not help a ton, heres my new code to drive it,
past = 0
sender = sere.encode('utf_8')
dir1 = str(400).encode('utf_8')
dir2 = str(401).encode('utf_8')
def send(steps):
global past
global current
global sender
global dir1
global dir2
global stepstaken
sere = '\r\n'
current = steps
neg = past - 5 # tolerance both are unused atm
pos = past + 5 # tolerance
needed = current - past
print(needed, steps)
if current != past:
if needed > 0:
serialsteps = str(needed).encode('utf_8')
ser.write(dir1 + sender)
ser.write(serialsteps + sender)
if needed < 0:
needed = needed * -1
serialstepss = str(needed).encode('utf_8')
ser.write(dir2 + sender)
ser.write(serialstepss + sender)
past = steps
Here is my full code for mouse to stepper motor,
import tkinter as tk
root = tk.Tk()
import serial
import struct
import time
stepstaken = 0
ardunioport = "COM" + str(input("Ardunio Port Number:")) # port number only
ser = serial.Serial(ardunioport, 9600)
wi = root.winfo_screenwidth() / 2
width = root.winfo_screenwidth()
hi = root.winfo_screenheight() / 2
height = root.winfo_screenheight()
sere = '\r\n' #still don't understand why but it does not work without this.
sender = sere.encode('utf_8')
pps = width / 200 #how many pixels are in 1 step
past = 0
sender = sere.encode('utf_8')
dir1 = str(400).encode('utf_8')
dir2 = str(401).encode('utf_8')
def send(steps):
global past
global current
global sender
global dir1
global dir2
global stepstaken
#need overcome overstepping
sere = '\r\n'
current = steps
neg = past - 5 # tolerance
pos = past + 5 # tolerance
needed = current - past
print(needed, steps)
if current != past:
if needed > 0:
serialsteps = str(needed).encode('utf_8')
ser.write(dir1 + sender)
ser.write(serialsteps + sender)
if needed < 0:
needed = needed * -1
serialstepss = str(needed).encode('utf_8')
ser.write(dir2 + sender)
ser.write(serialstepss + sender)
past = steps
while True:
pos = root.winfo_pointerx() - wi
steps = round(pos / pps)
#print("Mouse Position " + str(pos) + " Steps Needed" + str(steps)) # shows cursor position
send(steps)
For me it goes to a Arduino, the Arduino is not programmed to accept negative numbers. Instead it removes the - sign, multiply negative by negative = positive. It sends the opposite direction code/number then the steps needed to get there. Good luck everyone. This code works for me, no promise it will work for you.If it does not I am sorry.

Python invalid pointer error after running for a few days

I have this script on a Raspberry Pi that runs forever and every minute will get data from my weather station and then post it to a JSON and database. The issue is that after a few days of running, the Python script stops running with the following error:
munmap_chunk(): invalid pointer
Aborted
Here is the code:
from gpiozero import Button
import bme280_sensor
import wind_direction_byo
import ds18b20_therm
import statistics
import time
import math
import json
import database
import gc
CM_IN_A_KM = 100000.0
SECS_IN_AN_HOUR = 3600
ADJUSTMENT = 1.18
BUCKET_SIZE = 0.2794
store_speeds = []
store_directions = []
wind_count = 0
rain_count = 0
radius_cm = 9.0
wind_interval = 5
interval = 60
db = database.weather_database()
def spin():
global wind_count
wind_count = wind_count + 1
# print("spin" + str(wind_count))
def calculate_speed(time_sec):
global wind_count
circumference_cm = (2 * math.pi) * radius_cm
rotations = wind_count / 2.0
dist_km = (circumference_cm * rotations) / CM_IN_A_KM
km_per_sec = dist_km / time_sec
km_per_hour = km_per_sec * SECS_IN_AN_HOUR
return km_per_hour * ADJUSTMENT
wind_speed_sensor = Button(5)
wind_speed_sensor.when_pressed = spin
def reset_wind():
global wind_count
wind_count = 0
def bucket_tipped():
global rain_count
rain_count = rain_count + 1
def reset_rainfall():
global rain_count
rain_count = 0
def updateJsonFile(wind_average, wind_speed, wind_gust, rainfall, humidity, pressure, ambient_temp, ground_temp):
jsonFile = open("/var/www/html/weatherdata.json", "r")
data = json.load(jsonFile)
jsonFile.close()
tmp = data["ambient_temp"]
data["ambient_temp"] = ambient_temp
data["humidity"] = humidity
data["pressure"] = pressure
data["ground_temp"] = ground_temp
data["rainfall"] = rainfall
data["wind_average"] = wind_average
data["wind_speed"] = wind_speed
data["wind_gust"] = wind_gust
data["timestamp"] = time.time()
jsonFile = open("/var/www/html/weatherdata.json", "w+")
jsonFile.write(json.dumps(data))
jsonFile.close()
rain_sensor = Button(6)
rain_sensor.when_pressed = bucket_tipped
temp_probe = ds18b20_therm.DS18B20()
while True:
start_time = time.time()
while time.time() - start_time <= interval:
wind_start_time = time.time()
reset_wind()
#time.sleep(wind_interval)
while time.time() - wind_start_time <= wind_interval:
store_directions.append(wind_direction_byo.get_value())
final_speed = calculate_speed(wind_interval)
store_speeds.append(final_speed)
wind_average = wind_direction_byo.get_average(store_directions)
wind_gust = max(store_speeds)
wind_speed = statistics.mean(store_speeds)
rainfall = rain_count * BUCKET_SIZE
reset_rainfall()
humidity, pressure, ambient_temp = bme280_sensor.read_all()
ground_temp = temp_probe.read_temp()
#print(wind_average, wind_speed, wind_gust, rainfall, humidity, pressure, ambient_temp, ground_temp)
updateJsonFile(wind_average, wind_speed, wind_gust, rainfall, humidity, pressure, ambient_temp, ground_temp)
db.insert(ambient_temp, ground_temp, 0, pressure, humidity, wind_average, wind_speed, wind_gust, rainfall)
store_speeds = []
store_directions = []
gc.collect()
Most of the code is taken from Raspberry Pi's Weather Station guide. My addition is the updateJsonFile function and some other little things to get that to work. The website doesn't mention this problem however there was other errors in the guide they didn't mention.
My guess is that it's running out of memory (despite the garbage collect) considering the timing of when the error happens. I'm going to investigate that but if anyone else has a solution, that would be great.

Parsing values in and out a def functions

I am having a bit of a struggle with parsing values between these def functions. The base code getSensorData() and main() works fine, values are read from the sensor and sent to thingspeak. However, I wanted to add a calculation function called calcDewPoint() to the original code to calculate dewpoint from the sensor values (RH, T) but it seems that the code gets stuck :/
Output from terminal when I run the code as is:
starting...
sense1
sense2
dewpoint1
gamma1
exiting.
Temperature/Humidity monitor using Raspberry Pi and DHT22. Data is displayed at thingspeak.com
Change list 02/06/2020
Add dewpoint calculations
import sys
import RPi.GPIO as GPIO
from time import sleep
import Adafruit_DHT
import urllib2
import math #(using numPy instead of math lib)
#import numPy as np
#import constant (Create a *.py file to be able to use constant accross multiple projects)
#Constant Variables - Magnus Parameters
m = 17.62 #Mass Constant (Water Vapour)
Tn = 243.12 #Tempreture Constant
Ah = 6.112 #hPa Pressure Constant
Ak = 0.611 #kPa Pressure Constant
K = 273.15 #Kelvin constant
Ta = 216.7 #Tempreture Constant
myAPI = 'FZZHL7N2R2AXXXXX'
def getSensorData():
print 'sense1'
RH, T = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 17)
print 'sense2'
return (str(RH), str(T))
def calcDewPoint(RH, T):
print 'dewpoint1'
Td = (K * gamma(RH, T)) / (m - gamma(RH, T))
print 'dewpoint2'
return str(Td)
def gamma(RH, T):
print 'gamma1'
g = math.log(RH/100.0) + ((m * T) / (c + T))
print 'gamma2'
return str(g)
def main():
print 'starting...'
baseURL = 'https://api.thingspeak.com/update?api_key=%s' % myAPI
while True:
try:
RH, T = getSensorData() #Call function to Read DHT22 sensor conencted to RaspberryPi
Td = calcDewPoint(RH, T) #Call function to calculate dewpoint
f = urllib2.urlopen(baseURL + "&field1=%s&field2=%s&field3=%s" % (RH, T, Td))
print f.read()
f.close()
sleep(60) #uploads DHT22 sensor values every 1 minutes
except:
print 'exiting.'
break
# call main
if __name__ == '__main__':
main()
Your variable c is not defined. When you call calcDewPoint, it then calls gamma, which tries to run your math expression. However, c does not exist at that point.
Everything is running smooth, Code works with the odd exception in the debugger,
File "/usr/lib/python3/dist-packages/thonny/backend.py", line 305, in _custom_import
module = self._original_import(*args, **kw)
ImportError: No module named 'urllib2'
but overall it functions well. We can close up the thread.
"""
dht22.py
Temperature/Humidity monitor using Raspberry Pi and DHT22.
Data is displayed at thingspeak.com
Original author: Mahesh Venkitachalam at electronut.in
Modified by Jacques Kleynhans 06062020
Return rounded string values
Created Temporary variables Hum and Tair
"""
#import sys
import math
#import RPi.GPIO as GPIO
from time import sleep
import Adafruit_DHT
import urllib2
#Constant Variables - Magnus Parameters Max 0.083 Tair Range -20C + 50C
m = 17.62 # g/mol Mass Constant (Water Vapour)
Tn = 240.7263 #Tempreture Constant
Ah = 6.116441 #hPa Pressure Constant
Ak = 0.611 #kPa Pressure Constant
K = 273.15 #Kelvin constant
Ta = 216.7 #Tempreture Constant
#constant for leaf Temperature
Tc = 2.0
myAPI = 'FZZHL7N2R2AXXXXX'
def getSensorData():
RH, T = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 17)
return (round(RH,3), round(T,3))
# Define functions to calculate dewpoint, return a rounded string)
def calcDewPoint(Hum,Tair):
#print('dewpoint1')
Td = (Tn * gamma(Hum,Tair)) / (m - gamma(Hum,Tair))
#print('dewpoint2')
return round(Td,3)
def gamma(Hum,Tair):
#print ('gamma1')
g = math.log(Hum/100.0) + ((m * Tair) / (Tn + Tair))
#print('gamma2')
return round(g,3)
# Define functions to calculate VPD, return a rounded integer)
#Vapor pressure deficit control strategies for plant production
#IFAC Control applications and Ergonomics in Agriculture, Athens, Greece, 1998
def satVaporPres(Tair):
es = 6.1078*math.exp((Tair*17.2694)/(Tair+237.3)) #mPa
return round(es,3)
def actVaporPres(Hum, es):
ea = (Hum/100)*es
return round(ea,3)
def leafEs(Tair):
leafTemp = Tair - Tc
les = 6.1078*math.exp((leafTemp*17.2694)/(leafTemp+237.3))
return round(les, 3)
#Partial pressure of water vapour Pw in the air surrounding the plant
def parPressureW(Hum, es, Tair):
Pw = Hum*es*Tair
return(Pw)
def VPD(les, ea): #VPD air / crop
VPD = (les - ea)/10
return round(VPD,3)
def main():
print('starting...')
baseURL = 'https://api.thingspeak.com/update?api_key=%s' % myAPI
while True:
try:
RH, T = getSensorData()
Hum = RH
Tair = T
Td = calcDewPoint(Hum,Tair)
es = satVaporPres(Tair)
ea = actVaporPres(Hum, es)
les = leafEs(Tair)
TempVPD = VPD(les,ea)
print(Hum, Tair, Td, TempVPD)
f = urllib2.urlopen(baseURL + "&field1=%s&field2=%s&field3=%s&field4=%s" % (RH, T, Td, TempVPD))
print f.read()
f.close()
sleep(60) #uploads DHT22 sensor values every 1 minutes
except:
print('exiting.')
break
# call main
if __name__ == '__main__':
main()

Earth&Moon orbit system. My data is wrong

There is my code. I fixed it like this:
# Take 3 digits for significant figures in this code
import numpy as np
from math import *
from astropy.constants import *
import matplotlib.pyplot as plt
import time
start_time = time.time()
"""
G = Gravitational constant
g0 = Standard acceleration of gravity ( 9.8 m/s2)
M_sun = Solar mass
M_earth = Earth mass
R_sun = Solar darius
R_earth = Earth equatorial radius
au = Astronomical unit
Astropy.constants doesn't have any parameter of moon.
So I bring the data from wikipedia(https://en.wikipedia.org/wiki/Moon)
"""
M_moon = 7.342E22
R_moon = 1.737E6
M_earth = M_earth.value
R_earth = R_earth.value
G = G.value
perigee, apogee = 3.626E8, 4.054E8
position_E = np.array([0,0])
position_M = np.array([(perigee+apogee)/2.,0])
position_com = (M_earth*position_E+M_moon*position_M)/(M_earth+M_moon)
rel_pE = position_E - position_com
rel_pM = position_M - position_com
F = G*M_moon*M_earth/(position_M[0]**2)
p_E = {"x":rel_pE[0], "y":rel_pE[1],"v_x":0, "v_y":(float(F*rel_pE[0])/M_earth)**.5}
p_M = {"x":rel_pM[0], "y":rel_pM[1],"v_x":0, "v_y":(float(F*rel_pM[0])/M_moon)**.5}
print(p_E, p_M)
t = range(0,365)
data_E , data_M = [], []
def s(initial_velocity, acceleration, time):
result = initial_velocity*time + 0.5*acceleration*time**2
return result
def v(initial_velocity, acceleration, time):
result = initial_velocity + acceleration*time
return result
dist = float(sqrt((p_E["x"]-p_M['x'])**2 + (p_E["y"]-p_M["y"])**2))
xE=[]
yE=[]
xM=[]
yM=[]
data_E, data_M = [None]*len(t), [None]*len(t)
for i in range(1,366):
data_E[i-1] = p_E
data_M[i-1] = p_M
dist = ((p_E["x"]-p_M["x"])**2 + (p_E["y"]-p_M["y"])**2)**0.5
Fg = G*M_moon*M_earth/(dist**2)
theta_E = np.arctan(p_E["y"]/p_E["x"])
theta_M = theta_E + np.pi #np.arctan(data_M[i-1]["y"]/data_M[i-1]["x"])
Fx_E = Fg*np.cos(theta_E)
Fy_E = Fg*np.sin(theta_E)
Fx_M = Fg*np.cos(theta_M)
Fy_M = Fg*np.sin(theta_M)
a_E = Fg/M_earth
a_M = Fg/M_moon
v_E = (p_E["v_x"]**2+p_E["v_y"]**2)**.5
v_M = (p_M["v_x"]**2+p_M["v_y"]**2)**.5
p_E["v_x"] = v(p_E["v_x"], Fx_E/M_earth, 24*3600)
p_E["v_y"] = v(p_E["v_y"], Fy_E/M_earth, 24*3600)
p_E["x"] += s(p_E['v_x'], Fx_E/M_earth, 24*3600)
p_E["y"] += s(p_E['v_y'], Fy_E/M_earth, 24*3600)
p_M["v_x"] = v(p_M["v_x"], Fx_M/M_moon, 24*3600)
p_M["v_y"] = v(p_M["v_y"], Fy_M/M_moon, 24*3600)
p_M["x"] += s(p_M['v_x'], Fx_M/M_moon, 24*3600)
p_M["y"] += s(p_M['v_y'], Fy_M/M_moon, 24*3600)
for i in range(0,len(t)):
xE += data_E[i]["x"]
yE += data_E[i]["y"]
xM += data_M[i]["x"]
yM += data_M[i]["y"]
print("\n Run time \n --- %d seconds ---" %(time.time()-start_time))
after run this code i tried to print data_E and data_M.
Then I can get data but there is no difference. All of the data is the same.
But when I printed data step by step, it totally different.
I have wrong data problem and increase distance problem. Please help me this problem..
The code exits near line 45, where you are trying to assign p_E by pulling the square root of a negative number on the right hand side (as you've moved the [0] coordinate of the Earth to negative values while shifting Earth and Moon into the coordinate system of their center of mass). In line 45, the value of F*rel_pE[0]/M_earth is negative. So the code never reaches the end of the program using python 2.7.14. That bug needs to be solved before trying to discuss any further aspects.

Perspective projection and rotation in python

I've tried searching but none of the other questions seem to be like mine. I'm more or less experimenting with perspective projection and rotation in python, and have run into a snag. I'm sure my projection equations are accurate, as well as my rotation equations; however, when I run it, the rotation starts normal, but begins to swirl inwards until the vector is in the same position as the Z axis (the axis I am rotating over).
''' Imports '''
from tkinter import Tk, Canvas, TclError
from threading import Thread
from math import cos, sin, radians, ceil
from time import sleep
''' Points class '''
class pPoint:
def __init__(self, fPoint, wWC, wHC):
self.X = 0
self.Y = 0
self.Z = 0
self.xP = 0
self.yP = 0
self.fPoint = fPoint
self.wWC = wWC
self.wHC = wHC
def pProject(self):
self.xP = (self.fPoint * (self.X + self.wWC)) / (self.fPoint + self.Z)
self.yP = (self.fPoint * (self.Y + self.wHC)) / (self.fPoint + self.Z)
''' Main class '''
class Main:
def __init__(self):
''' Declarations '''
self.wWidth = 640
self.wHeight = 480
self.fPoint = 256
''' Generated declarations '''
self.wWC = self.wWidth / 2
self.wHC = self.wHeight / 2
''' Misc declarations '''
self.gWin = Tk()
self.vPoint = pPoint(self.fPoint, self.wWC, self.wHC)
self.vPoint.X = 50
self.vPoint.Y = 60
self.vPoint.Z = -25
self.vPoint.pProject()
self.ang = 0
def initWindow(self):
self.gWin.minsize(self.wWidth, self.wHeight)
self.gWin.maxsize(self.wWidth, self.wHeight)
''' Create canvas '''
self.gCan = Canvas(self.gWin, width = self.wWidth, height = self.wHeight, background = "black")
self.gCan.pack()
def setAxis(self):
''' Create axis points '''
self.pXax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pXbx = pPoint(self.fPoint, self.wWC, self.wHC)
self.pYax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pYbx = pPoint(self.fPoint, self.wWC, self.wHC)
self.pZax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pZbx = pPoint(self.fPoint, self.wWC, self.wHC)
''' Set axis points '''
self.pXax.X = -(self.wWC)
self.pXax.Y = 0
self.pXax.Z = 1
self.pXbx.X = self.wWC
self.pXbx.Y = 0
self.pXbx.Z = 1
self.pYax.X = 0
self.pYax.Y = -(self.wHC)
self.pYax.Z = 1
self.pYbx.X = 0
self.pYbx.Y = self.wHC
self.pYbx.Z = 1
self.pZax.X = 0
self.pZax.Y = 0
self.pZax.Z = -(self.fPoint) / 2
self.pZbx.X = 0
self.pZbx.Y = 0
self.pZbx.Z = (self.fPoint * self.wWC) - self.fPoint
def projAxis(self):
''' Project the axis '''
self.pXax.pProject()
self.pXbx.pProject()
self.pYax.pProject()
self.pYbx.pProject()
self.pZax.pProject()
self.pZbx.pProject()
def drawAxis(self):
''' Draw the axis '''
self.gCan.create_line(self.pXax.xP, self.pXax.yP, self.pXbx.xP, self.pXbx.yP, fill = "white")
self.gCan.create_line(self.pYax.xP, self.pYax.yP, self.pYbx.xP, self.pYbx.yP, fill = "white")
self.gCan.create_line(self.pZax.xP, self.pZax.yP, self.pZbx.xP, self.pZbx.yP, fill = "white")
def prePaint(self):
self.vA = self.gCan.create_line(self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP, fill = "red")
def paintCanvas(self):
try:
while True:
self.ang += 1
if self.ang >= 361:
self.ang = 0
self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))) - (self.vPoint.Y * sin(radians(self.ang)))
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))) + (self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()
self.gCan.coords(self.vA, self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP)
self.gWin.update_idletasks()
self.gWin.update()
sleep(0.1)
except TclError:
pass
mMain = Main()
mMain.initWindow()
mMain.setAxis()
mMain.projAxis()
mMain.drawAxis()
mMain.prePaint()
mMain.paintCanvas()
Thank you for any input :)
EDIT: Sorry, I just realized I forgot to put my question. I just want to know why it is gravitating inward, and not just rotating "normally"?
This section is wrong:
self.ang += 1
if self.ang >= 361:
self.ang = 0
self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))
- self.vPoint.Y * sin(radians(self.ang)))
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))
+ self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()
For two reasons:
self.ang will take integers in the open range [0 - 360], which means the angle 360 (== 0) is repeated.
In each iteration, you rotate the point from the previous iteration by the angle. As a result, your first frame is at 1 degree, your second at 1+2 = 3, the third at 1 + 2 + 3... You should either be:
rotating the point from the previous iteration by a constant angle each time (1°). This suffers from the problem mentioned in my comment
rotating the initial point by the current angle of rotation each time
Not actualy related to your problem, but I strongly suggest you to use Numpy to perform geometric transformations, specially if it involves 3D points.
Below, I post a sample snippet, I hope it helps:
import numpy
from math import radians, cos, sin
## suppose you have a Nx3 cloudpoint (it might even be a single row of x,y,z coordinates)
cloudpoint = give_me_a_cloudpoint()
## this will be a rotation around Y azis:
yrot = radians(some_angle_in_degrees)
## let's create a rotation matrix using a numpy array
yrotmatrix = numpy.array([[cos(yrot), 0, -sin(yrot)],
[0, 1, 0],
[sin(yrot), 0, cos(yrot)]], dtype=float)
## apply the rotation via dot multiplication
rotatedcloud = numpy.dot(yrotmatrix, pointcloud.T).T # .T means transposition

Categories