Need help for delete canvas shape depending of position (PYTHON) - python

I'm trying to make one function which do thing which depend of a variable tool.
If tool == 1 that create canva rectangle. I want if tool == 5, that delete block from mouse position, everything is working exept delete, I'm probably giving wrong argument but I don't know. Thanks
names = {}
i = 0
a = 40
def evn(e):
xx = c.canvasx(e.x)
yy = c.canvasy(e.y)
t = c.find_withtag('point')
xg = (e.x+GRID/2)//GRID
yg = (e.y+GRID/2)//GRID
test=(xg*GRID, yg*GRID)
if tool==1:
global i
global a
i += 1
names[i] = (xg*GRID, yg*GRID)
oc = get_oval_centre(c.bbox(t))
oc[0] += GRID
oc[1] += GRID
test = c.create_rectangle(-12, -12, 12, 12, fill='white', outline='white', tags=test)
set_oval_coords(test, (xg*GRID, yg*GRID))
elif tool==5:
xx = c.canvasx(e.x)
yy = c.canvasy(e.y)
t = c.find_withtag('point')
xg = (e.x+GRID/2)//GRID
yg = (e.y+GRID/2)//GRID
oc = get_oval_centre(c.bbox(t))
oc[0] += GRID
oc[1] += GRID
if (xg*GRID, yg*GRID) in names.values():
print('found')
c.delete(test)

Related

Webots error: don't change robot's value about getposition(), lidar, imusensor

My robot use supervisor mode
I want to change value after robot action because i studying DQN now.
My purpose valuse are Robot position value(global coordinate x, y value), lidar value(distance and angle to obstacle), Robot's yaw(using IMU sensors)
Robot get value like this code
how to get robot position
def car_position(self):
self.pos = robot_node.getPosition()
x = self.pos[0]
y = self.pos[1]
return x, y
#how to get lidar value
lidar_point = lidar.getPointCloud() is input
def point_cloud(self, point, num):
lidar_distance = []
lidar_angle = []
for i in range(num):
point_distance = math.sqrt(point[i].x**2 + point[i].y**2 + point[i].z**2)
point_angle = math.atan(point[i].y / point[i].x)
lidar_distance.append(point_distance)
lidar_angle.append(point_angle)
min_dis = min(lidar_distance)
min_pos = lidar_distance.index(min_dis)
angle = lidar_angle[min_pos]
return min_dis, angle
distance function (goal position is random value)
#gx, gy is goal position
def distance(self, cx, cy, gx, gy):
distance = math.sqrt((cx - gx) ** 2 + (cy - gy) ** 2)
goal_angle = math.atan2((gy-cy),(gx-cx))
return distance, goal_angle
how to get Yaw
_, _, yaw = imu.getRollPitchYaw()
Robot main function
for n_epi in range(itteration):
while robot.step(timestep) != -1 and step < 6000:
lidar_point = lidar.getPointCloud()
_, _, yaw = imu.getRollPitchYaw()
car_x, car_y = env.car_position()
distance, robot_angle = env.distance(car_x, car_y, goal_x, goal_y)
obstacle_distance, obstacle_angle = env.point_cloud(lidar_point, len(lidar_point))
dif_angle = abs(robot_angle - yaw)
state = (distance, dif_angle, obstacle_distance, obstacle_angle)
select_action = car.sample_action(torch.tensor(state).float(), epsilon)
state_prime, total_reward, done_num = car.action(select_action, goal_x, goal_y)
action function example
def action(self, num, goal_x, goal_y):
left1.setVelocity(5.0)
right1.setVelocity(5.0)
nxt_car_x, nxt_car_y = env.car_position()
print("nxt_car_x", nxt_car_x)
_, _, next_yaw = imu.getRollPitchYaw()
next_dis, next_robot_angle = env.distance(nxt_car_x, nxt_car_y, goal_x, goal_y)
next_obs, next_angle = env.point_cloud(lidar_point, len(lidar_point))
next_dif_angle = abs(next_robot_angle - next_yaw)
return (next_dis, next_dif_angle, next_obs, next_angle)
OUTPUT (PROBLEM)
state = (7.6161052136099485, 2.6032981992833335, 0.3431832774215816, -1.5699999999690681)
state_prime = (7.6161052136099485, 2.6032981992833335, 0.3431832774215816, -1.5699999999690681)
My robot do action well, go straight and turn right, left But why my robot don't change value???
I think The Robot value must different past_value after action
example
state = (0,0,0,0) ---> action ---> state_prime = (1,1,1,1)
i think my code procedure is value save at car_x, car_y ~~ ---> do action like right1.setVelocity(5.0) --> save value car_x at next_car_x ----> abs(car_x - next_car_x) != 0
But my code value is 0
How can i solve this situation?
i try webots documentaition and code but don't change
plz help me

Using a for loop to plot arrays from dictionaries

I have a dictionary with multiple key defined as (arbitrary inputs):
colors = {}
colors['red'] = {}
colors['blue'] = {}
colors['red'][clustname] = np.array([])
colors['blue'][clustname] = np.array([])
basically I want to plot a red v blue graph for each 'cluster'. I have 13 'clusters' in total with differing color values for each. The names in my code are different from the arbitrary ones above, but I figured it would be easier to understand with basic values then to look at the overall code:
colpath = '/home/jacob/PHOTOMETRY/RESTFRAME_COLOURS/' #This is the path to the restframe colors
goodcolindx = {}
colfiledat = {}
colors = {}
colors['UMINV'] = {}
colors['VMINJ'] = {}
colors['NUVMINV'] = {}
colors['id'] = {}
for iclust in range(len(clustname)):
colors['UMINV'][clustname[iclust]] = np.array([])
colors['VMINJ'][clustname[iclust]] = np.array([])
colors['id'][clustname[iclust]] = np.array([])
colors['NUVMINV'][clustname[iclust]] = np.array([])
filepath = catpath + clustname[iclust] + "_totalall_" + extname[iclust] + ".cat"
photdat[clustname[iclust]] = ascii.read(filepath)
filepath = zpath + "compilation_" + clustname[iclust] + ".dat"
zdat[clustname[iclust]] = ascii.read(filepath)
colfilepath = colpath + 'RESTFRAME_MASTER_' + clustname[iclust] + '_indivredshifts.cat'
colfiledat[clustname[iclust]] = ascii.read(colfilepath)
goodcolindx[clustname[iclust]] = np.where((colfiledat[clustname[iclust]]['REDSHIFTUSED'] > 0.9) & \
(colfiledat[clustname[iclust]]['REDSHIFTUSED'] < 1.5) & \
(photdat[clustname[iclust]]['totmask'] == 0) & \
(photdat[clustname[iclust]]['K_flag'] == 0) & \
((zdat[clustname[iclust]]['quality'] == 3) | (zdat[clustname[iclust]]['quality'] == 4)))
goodcolindx[clustname[iclust]] = goodcolindx[clustname[iclust]][0]
for igood in range(len(goodcolindx[clustname[iclust]])):
idstring = str(photdat[clustname[iclust]]['id'][goodcolindx[clustname[iclust]][igood]])
colors['NUVMINV'][clustname[iclust]] = np.append(colors['NUVMINV'][clustname[iclust]], -2.5 *
np.log10(colfiledat[clustname[iclust]]['NUV'][goodcolindx[clustname[iclust]][igood]]
/ colfiledat[clustname[iclust]]['V'][goodcolindx[clustname[iclust]][igood]]))'SpARCS-0035'
colors['UMINV'][clustname[iclust]] = np.append(colors['UMINV'][clustname[iclust]], colfiledat[clustname[iclust]]['UMINV'][goodcolindx[clustname[iclust]][igood]])
colors['id'][clustname[iclust]] = np.append(colors['id'][clustname[iclust]], photdat[clustname[iclust]]['id'][goodcolindx[clustname[iclust]][igood]])
colors['VMINJ'][clustname[iclust]] = np.append(colors['VMINJ'][clustname[iclust]], colfiledat[clustname[iclust]]['VMINJ'][goodcolindx[clustname[iclust]][igood]])
for iclustc in colors:
plt.plot(colors['VMINJ'][clustname[iclustc]], colors['UMINV'][clustname[iclustc]], 'ko')
plt.show()
So in this case, my 'red' is the VMINJ and my 'blue' is the UMINV. I am trying to use a for loop to cycle through all the cluster names that I have, but I keep getting the error back 'String indices must be integers'. I understand the basics of that, but don't know how to fix my code to make plots for each 'red' v 'blue' for each cluster. Any help would be awesome, let me know if you have questions
I figured it out. I changed the for loop to:
for iclust in range(len(clustname)):
plt.plot(colors['UMINV'][clustname[iclust]]....
and that worked

While loop incrementer not functioning properly

Right now, my code is correctly spitting out the first game (identified by start_id) in games. I am trying to increment in the bottom two lines, but the while loop doesn't seem to read the fact that I'm incrementing. So the input of this with start_id 800 and end_id 802 is just the information from 800, for some reason.
Am I using the incrementers correctly? Should I be initializing one of i or start_id elsewhere?
games = console(start_id, end_id)
final_output = []
while start_id < (end_id + 1):
single_game = []
i = 0
game_id = games[i][0]
time_entries = games[i][1][2][0]
play_entries = games[i][1][2][1]
score_entries = games[i][1][2][2]
team_entries = games[i][1][2][3]
bovada = games[i][1][0][0][0]
at_capacity = games[i][1][0][1]
idisagree_yetrespect_thatcall = games[i][1][0][2][0]
imsailingaway = games[i][1][1][0][0]
homeiswheretheheartis = games[i][1][1][1][0]
zipper = zip(time_entries, play_entries, score_entries, team_entries)
for play_by_play in zipper:
single_game.append(game_id)
single_game.append(play_by_play)
single_game.append(bovada)
single_game.append(at_capacity)
single_game.append(idisagree_yetrespect_thatcall)
single_game.append(imsailingaway)
single_game.append(homeiswheretheheartis)
start_id += 1
i += 1
final_output.append(single_game)
return final_output
Your problem is that you initialize the increment-er i inside the while loop so every time your loop iterates i is reset to zero.
Try changing it to:
i = 0
while start_id < (end_id + 1):
...

Select and zoom features of a layer using PyQgis

I want to select features and to zoom on them and do all these steps using PyQgis.
And I'm able to do both of them separatly but it doesn't seems to work when I try to mix the two of them.
Both of the codes I use for them are from the internet. Here's what I use to select features of a layer :
from qgis.core import *
import qgis.utils
lyrMap = QgsVectorLayer('C:/someplace', 'MapName', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(lyrMap)
expr = QgsExpression("'Attribute' IS NOT NULL")
it = lyrMap.getFeatures(QgsFeatureRequest(expr))
ids = [i.id() for i in it] #select only the features for which the expression is true
lyrMap.setSelectedFeatures(ids)
And it seems to do the trick as features appear selected on QGis.
In order to zoom the code is much more simple, it's just :
canvas = qgis.utils.iface.mapCanvas()
canvas.zoomToSelected(lyrMap)
But it seems that canvas doesn't consider that there's a selection on lyrMap and simply do nothing. I've tried to do the selection manually in QGis, and then zoom using zoomToSelected, and it worked.
But my objective is to do it without needing to do the selection manually...
Note : I don't think that's the issue, but the attribute I'm doing the selection on is from a join between lyrMap and another layer (I didn't put the code here because I don't think it's linked).
Thanks in advances for answers, clues or anything really :) !
This is working for my plugin. I am using python 2.7 and QGIS 1.8 and 2.0.1.You can use this code after including using vector file and adding it to the registry.
self.rubberBand = None
#create vertex marker for point..older versons..
self.vMarker = None
#add rubberbands
self.crossRb = QgsRubberBand(iface.mapCanvas(),QGis.Line)
self.crossRb.setColor(Qt.black)
def pan(self):
print "pan button clicked!"
x = self.dlg.ui.mTxtX.text()
y = self.dlg.ui.mTxtY.text()
if not x:
return
if not y:
return
print x + "," + y
canvas = self.canvas
currExt = canvas.extent()
canvasCenter = currExt.center()
dx = float(x) - canvasCenter.x()
dy = float(y) - canvasCenter.y()
xMin = currExt.xMinimum() + dx
xMax = currExt.xMaximum() + dx
yMin = currExt.yMinimum() + dy
yMax = currExt.yMaximum() + dy
newRect = QgsRectangle(xMin,yMin,xMax,yMax)
canvas.setExtent(newRect)
pt = QgsPoint(float(x),float(y))
self.zoom(pt)
canvas.refresh()
def zoom(self,point):
canvas = self.canvas
currExt = canvas.extent()
leftPt = QgsPoint(currExt.xMinimum(),point.y())
rightPt = QgsPoint(currExt.xMaximum(),point.y())
topPt = QgsPoint(point.x(),currExt.yMaximum())
bottomPt = QgsPoint(point.x(),currExt.yMinimum())
horizLine = QgsGeometry.fromPolyline( [ leftPt , rightPt ] )
vertLine = QgsGeometry.fromPolyline( [ topPt , bottomPt ] )
self.crossRb.reset(QGis.Line)
self.crossRb.addGeometry(horizLine,None)
self.crossRb.addGeometry(vertLine,None)
if QGis.QGIS_VERSION_INT >= 10900:
rb = self.rubberBand
rb.reset(QGis.Point)
rb.addPoint(point)
else:
self.vMarker = QgsVertexMarker(self.canvas)
self.vMarker.setIconSize(10)
self.vMarker.setCenter(point)
self.vMarker.show()
# wait .5 seconds to simulate a flashing effect
QTimer.singleShot(500,self.resetRubberbands)
def resetRubberbands(self):
print "resetting rubberbands.."
canvas = self.canvas
if QGis.QGIS_VERSION_INT >= 10900:
self.rubberBand.reset()
else:
self.vMarker.hide()
canvas.scene().removeItem(self.vMarker)
self.crossRb.reset()
print "completed resetting.."

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