Python matplotlib animate arc - python-2.7

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])".

Related

how to make the relationship between velocity and time be linear by ROS-python

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.

the result of density contour plot with histogram2d and matplotlib

i am trying to plot a 2D contour density map using histogram2d, i2d turned the histogram output into contour plot and plotted my data with contourf but i didn't appreciated the result, since it gives me a map with a huge rectangle in the middle.
here's the code i'm usingenter image description here
db = 1
lon_bins = np.linspace(min(lons)-db, max(lons)+db, (max(lons)-min(lons))*100)
lat_bins = np.linspace(min(lats)-db, max(lats)+db, (max(lats)-min(lats))*100)
h, xedges, yedges = (np.histogram2d(lats, lons,[lat_bins, lon_bins])
yi, xi = m(*np.meshgrid(lon_bins, lat_bins))
g = np.zeros(xi.shape)
g[:-1,:-1] = h
g[-1] = g[0] # copy the top row to the bottom
g[:,-1] = g[:,0] # copy the left column to the right
print g.shape,yi.shape,xi.shape
cs = m.contourf(yi, xi, g, cmap='Dark2')
cbar = plt.colorbar(cs, orientation='horizontal')
cbar.set_label('la densite des impacts foudre',size=18)
plt.gcf().set_size_inches(15,15)
plt.show()
And here's the result i got
so my request is how to have a nicer plotting, i don't want to have that rectangle in the middle ,i want my result being more smoothed...any ideas ?
I found the answer of my request,so in order to get rid of that rectangle i added this to my code :
g[g==0.0] = np.nan
which means, the bins that have density equal to 0 wouldn't appear on the plot and it's working fine.

Equal width plot sizes in pyplot, while keeping aspect ratio equal

I want to have two plots be the same width, however the resulting code shrinks the imshow plot.
xx = np.linspace(0.0,255.5,512)
yy = np.linspace(0.0,255.5,512)
Func = np.random.rand(len(xx),len(yy))
f, axarr = plt.subplots(2,1)
f.tight_layout()
im = axarr[0].imshow(Func, cmap = 'jet', interpolation = 'lanczos',origin = 'lower')
pos = axarr[0].get_position()
colorbarpos = [pos.x0+1.05*pos.width,pos.y0,0.02,pos.height]
cbar_ax = f.add_axes(colorbarpos)
cbar = f.colorbar(im,cax=cbar_ax)
axarr[1].plot(xx,Func[:,255],yy,Func[255,:])
plt.show()
plt.close('all')
EDIT: I would also like to keep imshow's plot from looking stretched (essentially, I need the width and length stretched appropriately so the aspect ratio's are still equal).
Some options:
A. `aspect="auto"
Use `aspect="auto" on the imshow plot
plt.imshow(..., aspect="auto")
B. adjust the figure margings
Adjust the figure margings or the figure size, such that the lower axes will have the same size as the imshow plot, e.g.
plt.subplots_adjust(left=0.35, right=0.65)
C. using a divider
You can use make_axes_locatable functionality from mpl_toolkits.axes_grid1 to divide the image axes to make space for the other axes.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
xx = np.linspace(0.0,255.5,512)
yy = np.linspace(0.0,255.5,512)
Func = np.random.rand(len(xx),len(yy))
fig, ax = plt.subplots(figsize=(4,5))
im = ax.imshow(Func, cmap = 'jet', interpolation = 'lanczos',origin = 'lower')
divider = make_axes_locatable(ax)
ax2 = divider.append_axes("bottom", size=0.8, pad=0.3)
cax = divider.append_axes("right", size=0.08, pad=0.1)
ax2.plot(xx,Func[:,255],yy,Func[255,:])
cbar = fig.colorbar(im,cax=cax)
plt.show()

How to create a grid on tkinter in python?

I managed to create a function that with a given radius, starting point and a number of points. It will create a big circle and withing this circle it will create 4 small circles.
I want to add a grid on the background that will show the Y and X axis in TKinter every 100 pixels apart starting from the top left. The coordinate origin should be the top left corner.
For example if the screen is 300x300 then the window will have 3 lines (at 100, 200 and 300) on his X axis going from left to right and top up to bottom.
A grid as a coordinate system.
Example of how I create a normal line. I use a line class which contains 2 points start point and end point:
rootWindow = Tkinter.Tk()
rootFrame = Tkinter.Frame(rootWindow, width=1000, height=800, bg="white")
rootFrame.pack()
canvas = Tkinter.Canvas(rootFrame, width=1000, height=800, bg="white")
canvas.pack()
def draw_line(l):
"Draw a line with its two end points"
draw_point(l.p1)
draw_point(l.p2)
# now draw the line segment
x1 = l.p1.x
y1 = l.p1.y
x2 = l.p2.x
y2 = l.p2.y
id = canvas.create_line(x1, y1, x2, y2, width=2, fill="blue")
return id
This will create a grid on the canvas for you
import tkinter as tk
def create_grid(event=None):
w = c.winfo_width() # Get current width of canvas
h = c.winfo_height() # Get current height of canvas
c.delete('grid_line') # Will only remove the grid_line
# Creates all vertical lines at intevals of 100
for i in range(0, w, 100):
c.create_line([(i, 0), (i, h)], tag='grid_line')
# Creates all horizontal lines at intevals of 100
for i in range(0, h, 100):
c.create_line([(0, i), (w, i)], tag='grid_line')
root = tk.Tk()
c = tk.Canvas(root, height=1000, width=1000, bg='white')
c.pack(fill=tk.BOTH, expand=True)
c.bind('<Configure>', create_grid)
root.mainloop()

Colouring the surface of a sphere with a set of scalar values in matplotlib

I am rather new to matplotlib (and this is also my first question here). I'm trying to represent the scalp surface potential as recorded by an EEG. So far I have a two-dimensional figure of a sphere projection, which I generated using contourf, and pretty much boils down to an ordinary heat map.
Is there any way this can be done on half a sphere?, i.e. generating a 3D sphere with surface colours given by a list of values? Something like this, http://embal.gforge.inria.fr/img/inverse.jpg, but I have more than enough with just half a sphere.
I have seen a few related questions (for example, Matplotlib 3d colour plot - is it possible?), but they either don't really address my question or remain unanswered to date.
I have also spent the morning looking through countless examples. In most of what I've found, the colour at one particular point of a surface is indicative of its Z value, but I don't want that... I want to draw the surface, then specify the colours with the data I have.
You can use plot_trisurf and assign a custom field to the underlying ScalarMappable through set_array method.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
(n, m) = (250, 250)
# Meshing a unit sphere according to n, m
theta = np.linspace(0, 2 * np.pi, num=n, endpoint=False)
phi = np.linspace(np.pi * (-0.5 + 1./(m+1)), np.pi*0.5, num=m, endpoint=False)
theta, phi = np.meshgrid(theta, phi)
theta, phi = theta.ravel(), phi.ravel()
theta = np.append(theta, [0.]) # Adding the north pole...
phi = np.append(phi, [np.pi*0.5])
mesh_x, mesh_y = ((np.pi*0.5 - phi)*np.cos(theta), (np.pi*0.5 - phi)*np.sin(theta))
triangles = mtri.Triangulation(mesh_x, mesh_y).triangles
x, y, z = np.cos(phi)*np.cos(theta), np.cos(phi)*np.sin(theta), np.sin(phi)
# Defining a custom color scalar field
vals = np.sin(6*phi) * np.sin(3*theta)
colors = np.mean(vals[triangles], axis=1)
# Plotting
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
cmap = plt.get_cmap('Blues')
triang = mtri.Triangulation(x, y, triangles)
collec = ax.plot_trisurf(triang, z, cmap=cmap, shade=False, linewidth=0.)
collec.set_array(colors)
collec.autoscale()
plt.show()