Kivy animation rotation over 360 degrees - wind direction indicator - animation

I am learning every day and invest many hours in a simple looking project.
Now I am faced with the problem that kivy rotates backwards my windrose after input of values over 360 degree.
Example:
First input: 356 degree -> rotates forwards to next input 360 degree.
Third input: 10 degree -> rotates backwards from 360 degree all the way back to 10 degree instead of using the shortest way.
What can I do to teach kivy to rotate always the shortest way? Forward and backwards?
See the example picture here
import socket
from kivy.animation import Animation
from kivy.clock import Clock, mainthread
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.app import App
from kivy.config import Config
from kivy.core.window import Window
from kivy.properties import NumericProperty
Config.set('graphics', 'width', '600')
Config.set('graphics', 'height', '650')
Window.size = (550, 650)
Window.clearcolor = (0.219, 0.247, 0.282, 1)
icon = "meteo_icon.ico"
title = "AWOS 1.0 display"
UDP_IP = ""
UDP_PORT = 6999
sock=socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
class DirWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
KV = """
WindowManager:
DirWindow:
<DirWindow>:
angle: 0
name: 'AWOS_windrose'
Image:
source: 'rwy_pic.png'
size_hint: None, None
size: 400, 400
pos_hint: {'center_x': 0.5, 'center_y': 0.4}
canvas.before:
PushMatrix
Rotate:
angle: 110
axis: (0, 0, 1)
origin: (self.center_x, self.center_y , 0)
canvas.after:
PopMatrix
Image:
source: 'arrow_thin.png'
size_hint: None, None
size: 530, 530
pos_hint: {'center_x': 0.5, 'center_y': 0.4}
# apply rotation matrix to this Image
canvas.before:
PushMatrix
Rotate:
angle: root.angle
axis: (0, 0, 1)
origin: (self.center_x, self.center_y , 0)
canvas.after:
PopMatrix
Image:
source: 'wind_dial.png'
size_hint: None, None
size: 500, 500
pos_hint: {'center_x': 0.5, 'center_y': 0.4}
"""
class MyMainApp(App):
angle = NumericProperty(0)
def build(self):
self.title = 'AWOS 1.0 - Wind Display'
Clock.schedule_interval(self.animate_needle, 2) # start the animation in 2 seconds
return Builder.load_string(KV)
def animate_needle(self, dt):
data, addr = sock.recvfrom(1024)
wind_direction = (data.decode()[35:38])
#wind_speed = (data.decode()[26:30])
wind_control = (data.decode()[20:24])
a = "WIND"
if wind_control == a:
self.anim = Animation(angle=(-int(wind_direction)), duration=2)
self.anim.repeat = True
windrose = self.root.get_screen('AWOS_windrose')
self.anim.start(windrose)
print(wind_direction)
def on_angle(self, item, angle):
if angle == 360:
item.angle = 0

Related

Yaw rotation of gear object in vpython

I was wondering how to yaw gear object about Y-axis in vpython. I have been following some tutorials and I have managed to rotate the gear. The gear rotates about Z axis in vpython. I want the gear to remain rotating about Z axis but I would like to yaw the gear around Y-axis. When xxx.rotate(axis=vector(0,0,1), it works as it should do. As soon as I alter anything it goes crazy. I am not sure what xxx.rotate(origin) is meant to do. In my case, I have messed around with the origin vector but it doesn't make any sense to me. I am not sure if the origin vector expects parameter values in x,y,z or some other sequence. I hope I am making makes sense.
The code below is a working code and you can see what I am trying to do here. I have been debugging for a while so please ignore unnecessary comments.
'
# https://www.youtube.com/watch?v=0Sw8sxsN984
# https://www.youtube.com/watch?v=MJiVtz4Uj7M
from vpython import *
import numpy as np
axisOpac = 0.4
def makeAxes(length):
global axes
xaxis = arrow(pos=vector(0, 0, 0), axis=length*vector(1,0,0), shaftwidth = 0.1*(length), color=color.red, opacity = axisOpac)
negXaxis = xaxis.clone()
negXaxis.axis *= -1
yaxis = arrow(pos=vector(0, 0, 0), axis=length*vector(0,1,0), color=color.green, opacity = axisOpac)
negYaxis = yaxis.clone()
negYaxis.axis *= -1
zaxis = arrow(pos=vector(0, 0, 0), axis=length*vector(0,0,1), color=color.magenta, opacity = axisOpac)
negZaxis = zaxis.clone()
negZaxis.axis *= -1
fudge = 0.01*length
xlabel = label(text = "x", color = xaxis.color, pos=xaxis.axis+vector(0, fudge, 0),box = False)
ylabel = label(text = "y", color = yaxis.color, pos=yaxis.axis+vector(0, fudge, 0),box = False)
zlabel = label(text = "-z", color = zaxis.color, pos=zaxis.axis+vector(0, fudge, 0),box = False)
# To make axes visible or invisible
axes = [xaxis, negXaxis, yaxis, negYaxis, zaxis, negZaxis, xlabel, ylabel, zlabel]
return
makeAxes(1)
g = shapes.gear(n = 20)
gear1 = extrusion (path = [vector(0, 0, 0), vector(0, 0, 0.1)], shape=g, opacity = 0.4)
# gear1.axis = vector(0, 0, 0)
debugArrow=arrow(length=6,shaftwidth=.1,color=color.white,axis=vector(0,0,0))
gearAxisArrow=arrow(shaftwidth=.1, color=color.red)
inputYawAngleYaxis = 0 # int(input("Enter an angle: "))
while True:
for cir in np.arange(0, 2*np.pi, 0.01):
rate(10)
# sleep(1)
pitch=0
# k = vector(cos(yaw)*cos(pitch), sin(pitch),sin(yaw)*cos(pitch)) ''' with pitch input '''
k = vector(cos(cir), 0 ,sin(cir)) # ''' without pitch input '''
y=vector(0,0,0)
s=cross(k,y)
v=cross(s,k)
rad = radians(45)
# gear1.axis = vector(1.23, -1.77418, 0) #vector(cos(inputYawAngleYaxis * pi/180), sin(pitch),sin(inputYawAngleYaxis* pi/180)*cos(pitch))
# gear1.pos = vector(-2.94957, 0, 2.70185)
# Gear Pos0: <0.707107, 0, 0.707107> Gear Axis0: <2.15647, 0.101243, -0.00237659>
gear1.pos = vector(0.707107, 0, 0.707107)
# gear1.pos = debugArrow.axis #frontArrow.axis # k # vector(0.707107, 0, 0.707107)
gear1.rotate(angle = -0.1, axis = vector(0, 0, 1), origin = vector(0, 0, 1 ))
# gear1.axis = vector(cos(radians(-45)), 0, sin(radians(-45)))
''' DebugArrow represents the position of the gear's center '''
debugArrow.axis = vector(cos(rad), 0, sin(rad))
''' Arrow inside the gear to track rotational axis of gear - This is to debug the yaw issue facing with gear object'''
gearAxisArrow.pos = gear1.pos
gearAxisArrow.axis = gear1.axis # vector(cos(radians(-45)), 0, sin(radians(-45))) # gear1.axis
gearAxisArrow.length = gear1.length/2
## Debugg
# print("Front Arrow Axis: ", frontArrow.axis, " K vec: ", k, " Ball pos: ", ball.pos )
print("Gear Pos0: ", gear1.pos, " Gear Axis0: ", gear1.axis, "gearAxisArrow: ", gearAxisArrow.pos, "gearAxisArrow: ", gearAxisArrow.axis)
'
I don't understand "I want the gear to remain rotating about Z axis but I would like to yaw the gear around Y-axis". If by "yaw" you mean that the axis of the gear should rotate about the y axis (while the gear itself rotates about that rotating axis), then obviously the axis of the gear can't remain in the direction of the z axis. Instead, the axis of the gear has to rotate. If it's of any help, here is the relevant page of the documentation:
https://www.glowscript.org/docs/VPythonDocs/rotation.html

Facebook DETR resnet 50 in HuggingFace Hub

Trying the pretrained Faceboook DETR model for object detection using the HuggingFace implementation.
The sample code listed below from https://huggingface.co/facebook/detr-resnet-50 is straightforward.
from transformers import DetrFeatureExtractor, DetrForObjectDetection
from PIL import Image
import requests
import numpy as np
url = 'http://images.cocodataset.org/val2017/000000039769.jpg'
image = Image.open(requests.get(url, stream=True).raw)
feature_extractor = DetrFeatureExtractor.from_pretrained('facebook/detr-resnet-50')
model = DetrForObjectDetection.from_pretrained('facebook/detr-resnet-50')
inputs = feature_extractor(images=image, return_tensors="pt")
outputs = model(**inputs)
# model predicts bounding boxes and corresponding COCO classes
logits = outputs.logits
bboxes = outputs.pred_boxes
I can use
threshod = 0.7
labels =['background', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
'train', 'truck', 'boat', 'traffic light', 'fire hydrant',
'street sign', 'stop sign', 'parking meter', 'bench', 'bird',
'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra',
'giraffe', 'hat', 'backpack', 'umbrella', 'shoe', 'eye glasses',
'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
'sports ball', 'kite', 'baseball bat', 'baseball glove',
'skateboard', 'surfboard', 'tennis racket', 'bottle', 'plate',
'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana',
'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog',
'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',
'mirror', 'dining table', 'window', 'desk', 'toilet', 'door', 'tv',
'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave',
'oven', 'toaster', 'sink', 'refrigerator', 'blender', 'book',
'clock', 'vase', 'scissors', 'teddy bear', 'hair drier',
'toothbrush']
np_softmax = (logits.softmax(-1)[0, :, :-1]).detach().numpy()
classes = []
probability = []
idx = []
for i, j in enumerate(np_softmax):
if np.max(j) > threshold:
classes.append(labels[np.argmax(j)])
probability.append(np.max(j))
idx.append(i)
to retrieve the detected classes. But I did not fully understand the coordinates in the bboxes.
This is a torch tensor with 100 bounded boxes coordinates of 4 dimensions. With idx I can get the index of the classes so I can get their corresponding boxes. Seems the coordinates are normalized because they are all between 0 and 1. I have a difficulty to remap the coordinates into pixels so I can draw the bounded boxes on the original images. Could not find documentation on this, any suggestions? Thanks
Okay, figured it out, the four coordinates are the normalized (X center, Y center, Width, Height)
if you want to draw a rectangle for each bbox you can use this code:
plt.figure(figsize=(16,10))
plt.imshow(pil_img)
ax = plt.gca()
(xmin, ymin, xmax, ymax) = bbox
ax.add_patch(plt.Rectangle(
(xmin, ymin),
xmax - xmin,
ymax - ymin,
fill = False,
color = c,
linewidth = 3
))

FuncAnimation not iterable

I'd like to create 2 animations and save them to one file, but get the error:
TypeError: 'FuncAnimation' object is not iterable
Separately each animation runs fine.
Here's a minimal-ish example that demonstrates the problem. The cosmetic stuff like ax.text and ax.axhline may help show what I'm trying to do, but is not essential to the problem. I'm running the code in a Jupyter notebook.
Thanks for any help.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
xdata = np.array([0.2, 0.4, 0.6, 0.8])
ydata = np.array([0, 0, 0, 0])
fig = plt.figure(figsize=(8,1.25))
ax = fig.add_subplot(111)
ax.set_xlim(0, 1)
ax.set_ylim(-0.5, 0.5)
ax.barh(0, 1, align='center', height=0.7, color='.95', ec='None', zorder=-20)
ax.axhline(0, 0, 1, color='0.25', linewidth=.5)
ax.text(0, -0.45, "0", verticalalignment = "center", horizontalalignment="center", fontsize=10)
ax.text(1, -0.45, "1", verticalalignment = "center", horizontalalignment="center", fontsize=10)
ax.text(-0.01, 0, "0", verticalalignment = "center", horizontalalignment="center", fontsize=10)
ax.text(0.75, -0.45, "3/4", verticalalignment = "center", horizontalalignment="center", fontsize=10)
ax.axvline(0.75, 0.15, 0.85, color='.5', linestyle='dotted', linewidth=0.75)
line, = ax.plot(xdata, ydata, 'ro', markersize=7)
def init0(): # initialization function for first animation
line.set_data(xdata, ydata)
return line,
def init1(): # second animation
ax.set_xlim(0.5, 1)
ax.text(0.5, -0.45, "1/2", verticalalignment = "center", horizontalalignment="center", fontsize=10)
line.set_data(xdata, ydata)
return line,
def animate(i): # update function
ax.figure.canvas.draw()
return line,
# call animators
anim0 = animation.FuncAnimation(fig, animate, init_func=init0, frames=150, interval=20, blit=True)
anim1 = animation.FuncAnimation(fig, animate, init_func=init1, frames=150, interval=20, blit=True)
fig.set_size_inches(16, 2.5, True) # improve resolution in animation
plt.axis('off')
anim0.save('anims.mp4', fps=30, extra_args=['-vcodec', 'libx264'], extra_anim=anim1)
plt.show()

Move SKSpriteNode until touches ended

I created this game in Spite Kit in Swift. I create a ship that I can determine its location be touching above or underneath the location of the ship. The ship will move towards the Y axis where I placed my finger. However at this point the ship will only move by a specific amount, in this case 30 or -30. How can I rewrite this code so the ship will keep on moving until my release of my finger?
Thanks!
func addShip() {
// Initializing spaceship node
ship = SKSpriteNode(imageNamed: "spaceship")
ship.setScale(0.45)
ship.zRotation = CGFloat(-M_PI/2)
// Adding SpriteKit physics body for collision detection
ship.physicsBody = SKPhysicsBody(rectangleOfSize: ship.size)
ship.physicsBody?.categoryBitMask = UInt32(shipCategory)
ship.physicsBody?.affectedByGravity = false
ship.physicsBody?.dynamic = true
ship.physicsBody?.contactTestBitMask = UInt32(obstacleCategory)
//NEWLY ADDED
ship.physicsBody?.contactTestBitMask = coinCategory
ship.physicsBody?.collisionBitMask = 0
ship.name = "ship"
ship.position = CGPointMake(120, 160)
self.addChild(ship)
actionMoveUp = SKAction.moveByX(0, y: 30, duration: 0.2)
actionMoveDown = SKAction.moveByX(0, y: -30, duration: 0.2)
}
i don't like to use SKActions for these types of things because they're really meant for one off simple animations.. However, it may be appropriate depending your game's requirements..
if you insist on using SKActions then instead of doing moveBy, why don't you just use moveTo utilizing touch location? The only thing you'd have to do is come up with a ratio based on the distance your sprite needs to travel so that your animation duration is correct. example:
let curPoint = self.sprite.position
let destinationPoint = touch.position
let diffPoint = CGPoint(
x: curPoint.x - destinationPoint.x,
y: curPoint.y - destinationPoint.y
)
let distance = sqrt(pow(diffPoint.x, 2) + pow(diffPoint.y, 2))
let durationRatio = distance / CGFloat(600)
let moveAction = SKAction.moveTo(point, duration: NSTimeInterval(durationRatio))
self.sprite.runAction(moveAction, withKey: "move")
then when you want to cancel the movement. in touchesEnded you do
self.sprite.removeActionForKey("move")
using physics velocity
let curPoint = CGPoint(x: 10, y: 10)
let destinationPoint = CGPoint(x: 100, y: 100)
let diffPoint = CGPoint(
x: curPoint.x - destinationPoint.x,
y: curPoint.y - destinationPoint.y
)
let distance = sqrt(pow(diffPoint.x, 2) + pow(diffPoint.y, 2))
let normalizedVector = CGPoint(
x: diffPoint.x / distance,
y: diffPoint.y / distance
)
let speed = CGFloat(100)
let velocity = CGVector(
dx: normalizedVector.x * speed,
dy: normalizedVector.y * speed
)
self.sprite.physicsBody!.velocity = velocity
in touchesEnded you do
self.sprite.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)

Kivy - [Critical] Warning too much iteration, when drawing Ellipse

I have been struggling recently creating a filled Circle in Kivy that stays a circle when the window is re-sized to a different width or height. I looked at the question here:
Centering an object in Kivy
But when I implement my Circle like so:
<BigCircle>
width: min(self.size)
height: min(self.size)
pos_hint: {'center_x': .5, 'center_y': .5}
canvas:
Color:
rgb: 1, 1, 0
Ellipse:
size: self.size
pos: self.pos
<MainScreen>:
FloatLayout
size: root.size
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
size: self.size
BigCircle:
id: big_cir
class MainScreen(Screen):
pass
class MyApp(App):
def build(self):
sm = ScreenManager(transition=NoTransition())
sm.add_widget(MainScreen(name="Main"))
return sm
I get the error:
[Critical][Clock ]Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute
I am doing nothing with the Clock, but I am using a ScreenManager. Currently, MainScreen is the only screen. If I change the height/width to not include the min() then it works, but that is necessary to keep the Circle circular. Otherwise it becomes elongated when re-sized and looks bad.
The problem is you have an infinite loop due to BigCircle width and height being adjusted based on its size (width, height). Try changing your BigCircle to:
<BigCircle>
canvas:
Color:
rgb: 1, 1, 0
Ellipse:
size: min(self.size), min(self.size)
pos: root.center_x - min(self.size)/2, root.center_y - min(self.size)/2

Resources