I'm trying to make a game in python 3.5 using the canvas. I have a list of the coordinates of the triangle in a list. I'm using a class to make an object which is suppose to be the player. When I tried to implement a movement system I thought of using a list so that I can quickly change the coordinates using a for loop, however when I run the code and press the button it gives me this:
"TypeError: list indices must be integers or slices, not float"
Here's the code (sorry if it's primitive, it's my first time using both canvas and class and I typed this up in three hours)
import sys
from tkinter import*
w = 600
h = 400
gui = Tk()
gui.geometry('1000x650')
canvas = Canvas(gui,width=w,height=h,bg='black')
canvas.place(relx=0.5,rely=0.35,anchor=CENTER)
class player():
def __init__(self,x,y,a):
self.x1 = x
self.y1 = y
self.x2 = x-a/2
self.y2 = y+a
self.x3 = x+a/2
self.y3 = y+a
self.coords = [self.x1,self.y1,self.x2,self.y2,self.x3,self.y3]
def display(self):
canvas.create_polygon(self.x1,self.y1,self.x2,self.y2,self.x3,self.y3,outline='white')
def move(self,pos):
if pos == True:
thrust = 5
else:
thrust = -5
while thrust > 0.1:
for i in self.coords:
self.coords[i]=self.coords[i]+thrust
thrust-=1
up_arrow = Button(gui,text='^',command=lambda:p1.move(True))
up_arrow.place(relx=0.5,rely=0.7,anchor=CENTER)
p1 = player(w/2,h/2,50)
p1.display()
for i in self.coords:
this is going to set i to each item in self.coords in turn, not the indices of the items.
That means that when you wrote self.coords[i]=self.coords[i]+thrust was likely not what you wanted. (Since i is not an index, but an item in self.coords)
You will have to use the range() function to give i the value you want.
for i in range(len(self.coords)):
self.coords[i]=self.coords[i]+thrust
You might think that this would work
for i in self.coords:
i = i + thrust
but it does not work because i is the value at that position in self.coords. It is not a reference to it. Changing it will not change self.coords. It is temporary.
Related
IHello everyone I need help to understand how to access to each single object in list, if you have time...
I have a list 'objects' made by getting the user selection, I loop it to randomise position but even if seems that I properly select all the single objects, the random value is applied like they are just 1 object, everything moves together ...I'd like to random the single obj separately.
Thanks in advance
F
for j in objects:
mc.select(j)
print(j)
for i in j:
x = random.uniform(-1,15)
y = random.uniform(0, 12)
z = random.uniform(-5, 15)
mc.move(x, y, z)
Not sure what you need the second loop for, but it seems to work fine. I simplified it a little bit like this:
import random
import maya.cmds as cmds
objects = cmds.ls(sl=True)
for j in objects:
x = random.uniform(-1,15)
y = random.uniform(0, 12)
z = random.uniform(-5, 15)
cmds.move(x, y, z, j)
I created code which making turtlebot 2 following me depend on detecting my face and chose a value of velocity 0.2 m/s.
my issue is the movement of the robot when disappearing my face suddenly which making turtlebot stops suddenly, I need to make decreasing its velocity gradually like this figure enter link description here
my experience not good in ROS'time
I need it starting the count the seconds from zero every it lost my face.
my issue in my code, Once run the code, the time increase continuously whether it is lost my face or not.in this line
v = self.twist.linear.x = (-0.07 * t + 0.2)
my full code:
#!/usr/bin/env python
import rospy
from sensor_msgs.msg import Image
from geometry_msgs.msg import Twist
import cv2, cv_bridge
face_cascade = cv2.CascadeClassifier('/home/redhwan/1/run-webcam/Face-Detect-Demo-by-Ali-master/haarcascade_frontalface_default.xml' )
class Face_detection:
def __init__(self):
self.bridge = cv_bridge.CvBridge()
self.starting_time = rospy.get_rostime().to_sec()
self.save_time = True
self.image_sub = rospy.Subscriber('/usb_cam/image_raw',Image, self.image_callback)
self.cmd_vel_pub = rospy.Publisher('/cmd_vel_mux/input/teleop',Twist, queue_size=1)
self.twist = Twist()
def image_callback(self, msg):
image = self.bridge.imgmsg_to_cv2(msg,desired_encoding='bgr8')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale( gray,scaleFactor=1.1,minNeighbors=5,minSize=(30, 30),flags=cv2.cv2.CASCADE_SCALE_IMAGE)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
self.twist.linear.x = 0.2
self.cmd_vel_pub.publish(self.twist)
cv2.imshow('face ', image)
cv2.waitKey(3)
if(type(faces) == tuple):
if(self.save_time == False):
# self.save_time = False #Condition only the first time
self.starting_time = rospy.get_rostime().to_sec() #save the current time
now = rospy.get_rostime().to_sec()
# self.save_time == False
t = (now - self.starting_time)
print ('t',t)
if t <2.9:
v = self.twist.linear.x = (-0.07 * t + 0.2)
print v
self.cmd_vel_pub.publish(self.twist)
if t >= 2.9:
v = self.twist.linear.x = 0
print v
self.cmd_vel_pub.publish(self.twist)
rospy.init_node('face_detection')
follower = Face_detection()
rospy.spin()
please help me
Thank in advance
If all you need to do it make the movements of turtlebot smoother. You might find that the velocity smoother package will fulfill your needs.
You can install it by running:
sudo apt install ros-kinetic-yocs-velocity-smoother
The node takes raw velocity input and filters it based on acceleration parameters. So you can remap your cmd_velocity_mux output to raw_cmd_vel and remap the smoothed output smooth_cmd_vel to the input going to the turlebot.
Between mutliple .backward() passes I'd like to set the gradients to zero. Right now I have to do this for every component seperately (here these are x and t), is there a way to do this "globally" for all affected variables? (I imagine something like z.set_all_gradients_to_zero().)
I know there is optimizer.zero_grad() if you use an optimizer, but is there also a direct way without using an optimizer?
import torch
x = torch.randn(3, requires_grad = True)
t = torch.randn(3, requires_grad = True)
y = x + t
z = y + y.flip(0)
z.backward(torch.tensor([1., 0., 0.]), retain_graph = True)
print(x.grad)
print(t.grad)
x.grad.data.zero_() # both gradients need to be set to zero
t.grad.data.zero_()
z.backward(torch.tensor([0., 1., 0.]), retain_graph = True)
print(x.grad)
print(t.grad)
You can also use nn.Module.zero_grad(). In fact, optim.zero_grad() just calls nn.Module.zero_grad() on all parameters which were passed to it.
There is no reasonable way to do it globally. You can collect your variables in a list
grad_vars = [x, t]
for var in grad_vars:
var.grad = None
or create some hacky function based on vars(). Perhaps it's also possible to inspect the computation graph and zero the gradient of all leaf nodes, but I am not familiar with the graph API. Long story short, you're expected to use the object-oriented interface of torch.nn instead of manually creating tensor variables.
I have a large graph that I'm drawing that is taking a long time to
process.
Is it possible to return a status, current_node, or percentage of the current status of the drawing?
I'm not looking to incrementally draw the network as all I'm doing it is saving it to a high dpi image.
Here's an example of the code I'm using:
path = nx.shortest_path(G, source=u'1234', target=u'98765')
path_edges = zip(path, path[1:])
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G,pos,nodelist=path,node_color='r')
nx.draw_networkx_edges(G,pos,edgelist=path_edges,edge_color='r',width=10)
plt.axis('equal')
plt.savefig('prototype_map.png', dpi=1000)
plt.show()
I believe the only way to do it is to accommodate the source code of draw function to print something saying 10%, 20% complete.... But when I checked the source code of draw_networkx_nodes & draw_networkx, I realized that it is not a straight forward task as the draw function stores the positions (nodes and edges) in a numpy array, send it to the ax.scatter function of matplotlib (sourcecode) which is a bit hard to manipulate without messing something up. The only thing I can think of is to change:
xy = numpy.asarray([pos[v] for v in nodelist]) # In draw_networkx_nodes function
To
xy = []
count = 0
for v in nodelist:
xy.append(pos[v])
count +=1
if (count == len(nodelist)):
print '50% of nodes completed'
print '100% of nodes completed'
xy = numpy.asarray(xy)
Similarly when draw_network_edges is called, to indicate progress in edges drawing. I am not sure how far from truth this will be because I do not know how much time is spent in the ax.scatter function. I also, looked in the source code of the scatter function but I could not pin point a loop or something to print an indication that some progress has been done.
Some layout functions accept pos argument to conduct incremental work. We can use this fact to split the computation into chunks and draw a progress bar using tqdm
def plot_graph(g, iterations=50, pos=None, k_numerator=None, figsize=(10, 10)):
if k_numerator is None:
k = None
else:
k = k_numerator / np.sqrt(g.number_of_nodes())
with tqdm(total=iterations) as pbar:
step = 5
iterations_done = 0
while iterations_done < iterations:
pos = nx.layout.fruchterman_reingold_layout(
g, iterations=step, pos=pos, k=k
)
iterations_done += step
pbar.update(step)
fig = plt.figure(figsize=figsize, dpi=120)
nx.draw_networkx(
g,
pos,
)
return fig, pos
I am trying to animate arcs and circles. The circles are moving every frame. While the arcs are changing radius, position and disappearing as functions of the positions of the circles.
I am trying to animate these arcs , but they are not changing.
Below is the code sample:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import patches
import numpy as np
particle_one = np.zeros((10,2)) #10 times steps and x,y positions
particle_two = np.zeros((10,2)) #10 times steps and x,y positions
#the two particles are moving away from each other in the x direction
for i in range(0,10):
particle_one[i,0] = i
particle_two[i,0] = 2-i
particle_one[i,1] = 2
particle_two[i,1] = -2
particle_One_Radius = 1
particle_Two_Radius = 1.5
arc_Center = np.zeros((10,2))
for i in range(0,10):
arc_Center[i,0] = (particle_one[i,0] + particle_two[i,0])/2
#the arc should disappear for frame 5
arc_Center[5,0] = 0
arc_Center[5,1] = 0
fig = plt.figure()
plt.axis([-20,20, -5,5]) #axis that I like
ax = plt.gca()
circle_One = plt.Circle([particle_one[0,0],particle_one[0,1]],particle_One_Radius)
circle_Two = plt.Circle([particle_two[0,0],particle_two[0,1]],particle_Two_Radius)
circles = []
circles.append(circle_One)
circles.append(circle_Two)
arcs = []
#defines the arc
arc_one = patches.Arc([arc_Center[0,0],arc_Center[0,1]],5,3,angle =0 ,theta1 = 0,theta2= 270)
arcs.append(arc_one)
def init():
ax.add_patch(circles[0])
ax.add_patch(circles[1])
ax.add_patch(arcs[0])
return ax
#draw every frame by frame
def animate(m):
circles[0].center=((particle_one[m,0],particle_one[m,1]))
circles[1].center=((particle_two[m,0],particle_two[m,1]))
#the arcs does not change
arcs[0] =patches.Arc([arc_Center[m,0],arc_Center[m,1]],5+m,3+m,angle =0 ,theta1 = 0,theta2= 270)
return ax
#animation function that draws 10 frames
anim = animation.FuncAnimation(fig,animate , init_func= init , frames = 10 , interval = 20)
plt.show()
The circles animate correctly , but the arc does not change shape or location
Your problem is that instead of modifying your Arc patch as you do the circles, you create a new one at each step, but do not add it to the axes after it's created.
I've checked briefly, but I don't know how to modify the properties of an Arc instance, although I'm sure it's possible.
In the mean time, I've modified your function to remove the previous Arc from the patches list, create a new arc, and add it back to the Axes
#draw every frame by frame
def animate(m):
circles[0].center=((particle_one[m,0],particle_one[m,1]))
circles[1].center=((particle_two[m,0],particle_two[m,1]))
ax.patches.remove(arcs[0])
arcs[0] = patches.Arc([arc_Center[m,0],arc_Center[m,1]],5+m,3+m,angle =0 ,theta1 = 0,theta2= 270)
ax.add_patch(arcs[0])
print "step %d: arc = %s" % (m, arcs[0])
return circles,arcs
I have also ran into the problem of my arc not moving. Trying to remove the arc as Diziet suggested generated the
error: "x not in list".
However, what seems to work is to do both the instantiation of the arc and adding it to the axis within the animate function, but without the call to remove it - essentially, Diziet's solution minus the line "ax.patches.remove(arcs[0])".