is there any possibility to move the cursor in Python with % starting from a certain coordinate like (1,1)?
I am using pyautogui atm to automate and I thought it would be quite convenient if this is independent from the monitor size making it universal.
Thanks for your help in advance!
It's possible indirectly. As detailed at the top of the Mouse Control Functions page of the documentation, you can get the screen size using the size() function (which returns a tuple of (X, Y)). You can then do the math to figure out how many screen pixels equal the percentage you're looking for, then call moveTo() to go there.
# script to move mouse 50% to the right and down
import pyautogui as pag
percentage = 0.5
cur_X, cur_Y = pag.position() # current X and Y coordinates
size_X, size_Y = pag.size() # screen size
goto_X = (size_X - cur_X) * percentage + cur_X # current location plus half
goto_Y = (size_Y - cur_Y) * percentage + cur_Y # the distance to the edge
pag.moveTo(goto_X, goto_Y, 1) # move to new position, taking 1 second
I am commanding a robot from a base station with radio. Base station takes location/orientation information from an overhead camera using the AR tag on the robot (with openCV). Moreover, base calculates the path robot should take to reach the target from location information (A* with each grid being 30 by 30 pixels in camera). My robot can only turn left/right (on its central point) and go forward/backward. Robot includes an Arduino Uno with two Lego NXT motors.
I use the following code to get robot to point at right direction. However, when the robot gets close to the angle that it is supposed to travel to, instead of stopping an going forward it tries to fix its orientation infinitely.
def correctOrientation(self, rx: int, ry: int):
#returns direction robot needs to point.
direction = self.getDirection((self.sx, self.sy), (rx, ry))
#method to stop robot.
self.comms.stop()
anglediff = (self.angle - direction + 180 + 360) % 360 - 180
while not (abs(anglediff) < 15):
#Decides which way to turn.
if self.isTurnLeft(self.angle, direction):
self.comms.turnLeft()
else:
self.comms.turnRight()
#Put sleeps because there is a delay in camera feed. Allows it to get the location right
time.sleep(0.3)
self.comms.stop()
#Updates position
self.getPos()
time.sleep(1)
#Calculates orientation of robot and updates it
self.angle = self.calcOrientation()
anglediff = (self.angle - direction + 180 + 360) % 360 - 180
print(anglediff)
time.sleep(1)
My helper function that are used. I calculate orientation of robot by using two points known on the robot and drawing a line in between those two point. Hence, line becomes parallel with th orientation.
def isTurnLeft(self, angle, touchAngle):
diff = touchAngle - angle
if diff < 0:
diff += 360
if diff < 180:
return False
else:
return True
def calcOrientation(self) -> float:
return self.getDirection(self.marker[0], self.marker[3])
def getDirection(self, source: Tuple[int], target: Tuple[int]) -> float :
return (math.degrees(math.atan2(target[1] - source[1], target[0] - source[0]))+360)%360
I can't figure out if my code is problematic in logic. If so what can I do about it? If code is fine and the problem is the delay/setup of the system, what are the other ways I can control the robot?
Thank you for the help.
Solved the problem by changing the image library for AR tag recognition. We were using 2 tags for one robot. It is significantly slower and fail prone to detect two tags. Updated it to only have one tag. Moreover, switched from angle based calculations to vector based which is way simpler to understand.
I'm new to ROS, and I have a mission to develop an algorithm that allows
the robot to move forward as long as he doesn't have an obstacle in front of
him, but it kept getting stuck in obstacles that I've put in front of him in the gazebo simulation.
When I checked it in depth, I figured that it seems that my robot scans to the sides instead of in front. And when I checked the specs for the scanner laser
it said that the angles of the scan should be maximum between -90 degrees to 90 degrees and preferably much less than that. So it seems that I can't complete my mission due to "hardware" problems but it seems strange to me.
Can anyone please help?
Here is my code:
#!/usr/bin/python
#
# stopper.py
#
# Created on:
# Author:
#
import rospy
import math
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
class Stopper(object):
def __init__(self, forward_speed):
self.forward_speed = forward_speed
self.min_scan_angle = -10/180*math.pi
self.max_scan_angle = 10 / 180 * math.pi
self.min_dist_from_obstacle = 0.5
self.keep_moving = True
self.command_pub = rospy.Publisher("/cmd_vel_mux/input/teleop", Twist, queue_size=10)
self.laser_subscriber = rospy.Subscriber("scan",LaserScan, self.scan_callback, queue_size=1)
def start_moving(self):
rate = rospy.Rate(10)
rospy.loginfo("Starting to move")
while not rospy.is_shutdown() and self.keep_moving:
self.move_forward()
rate.sleep()
def move_forward(self):
move_msg = Twist()
move_msg.linear.x = self.forward_speed
self.command_pub.publish(move_msg)
def scan_callback(self, scan_msg):
for dist in scan_msg.ranges:
if dist < self.min_dist_from_obstacle:
self.keep_moving = False
break
You should be able to select the angles you are interested in yourself. The -90 and +90 degrees are just the endpoints the laser scanner measures. So you get a dataset with a lot of distances in different angles. To detect obstacles in front of the robot you need to select a (or multiple) measurements in the middle of the dataset (my knowledge is rusty, I assume the ranges are sorted from -90° to 90° so 0° is in the middle of the array). So you may don't want to loop through all distances in msg.ranges but just a subset.
I found this tutorial that shows how to read out the data and access to the value from different angles.
Environment:
Python: 3.6.6
pyglet version: 1.3.2
Code base:
abstract_model.py
import pyglet
def get_texture_group(file, order_group_index):
texture = pyglet.image.load(file).texture
order_group = pyglet.graphics.OrderedGroup(order_group_index)
return pyglet.graphics.TextureGroup(texture, order_group)
class AbstractModel(object):
def _create_as_vertex(self):
v_x = self.cell_data.get("x") * 32
v_y = self.cell_data.get("y") * -1 * 32
texture_group = self.map_type_iamge.get(self.cell_data.get("t"))
x_offset = self.x_offset * self.scale
x, y, z = v_x + x_offset, v_y, self.z
x_ = (texture_group.texture.width * self.scale + x_offset + v_x)
y_ = (texture_group.texture.height * self.scale + v_y)
tex_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1))
self.vertices = self.batch.add(
4, pyglet.gl.GL_QUADS,
texture_group,
('v3f', (x, y, z,
x_, y, z,
x_, y_, z,
x, y_, z)),
tex_coords)
def _animate(self, dt):
# lets assume that I have list of pyglet.graphics.TextureGroup
# and they should somehow be drawn one after other
print("I need change image. dt=", dt, self)
pyglet.clock.schedule_once(self._animate, 1)
ground3d.py
import os
import pyglet
import settings
from models import abstract_model
GROUND_DIR = os.path.join(settings.STATIC_DIR, "ground")
order_group_index = 0
map_type_iamge = {
1: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "w1.png"), order_group_index),
2: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "t1.png"), order_group_index),
1001: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "t1_direction.png"), order_group_index),
}
class Ground3D(abstract_model.AbstractModel):
def __init__(self, cell_data, batch):
self.batch = batch
self.cell_data = cell_data
self.map_type_iamge = map_type_iamge
self.scale = 1
self.x_offset = 0
self.z = 0
self.entity = None
self._create_as_vertex()
pyglet.clock.schedule_once(self._animate, 1)
Explanation:
I have models(just flat rect for an example) which should be placed on 3 dimensions. And these models should be animated, like picture_1, after second picture_2, ... etc.
As I understood from my previous question using pyglet.sprite.Sprite() in 3D batch is not a good idea.
Question:
How I can change pictures(using TextureGroup or any other approaches) on self.vertices?
Or which arroach/classes I use use to implement it. I can't find any examples for such (as for my simple vision) usual case as animation for some flat models in 3 dimensions.
There are many example about rotating/moving/resizing of vertices, but how to build a correct question(is animation aspect) for getting answer in google - I don't know.
PS: If you, reader, have any usefull links on this subject(for pyglet or just for OpenGL) I would be very appreciated you share this link(s) in comment.
Texture coordinates.
You should have a single texture atlas for all frames of all different things that are animated ever.
Preferably, everything should have same animation speed and same amount of frames all the time.
Let's say there's two sprites that have 2 frames for entire animation, and they are stored in 64x64 texture atlas. (EDIT: sorry for ambiguity, 64x64 PIXELS, just because it could imply that we have 64x64 tile atlas, same everywhere else where I mention this)
Now, you need to have a global timer with global value which indicates current animation frame, not game frame. It should be independent of framerate.
Said value should be updated every once in a while at your desired speed like this:
current_frame = (current_frame + 1) % animation_length
Since we have 2 frames in this example, it will turn out like this:
# init
animation_length = 2
current_frame = 0
# updates:
current_frame = (0 + 1) % 2 # 1 % 2 -> 1
current_frame = (1 + 1) % 2 # 2 % 2 -> 0
...
Now, you need to update UV's of all your sprites only when the frame changes.
UV's start from left right and go from 0 to 1 (as far as I remember, for the sake of this example, they do, shhh).
Since we have 2 frames each, we can calculate "tiles" in the UV coordinates like this:
tile_width = 1.0 / frames # 2 frames each, width will be 0.5
tile_height = 1.0 / sprites # 2 sprites each, height will be 0.5 too, perfect
Now, on first frame, you generate your UV's like normal, you just take vertical ID or something, and use tile_height * sprite_id to get current V coordinate, and your U is calculated like tile_width * current_frame.
This assumes that you already have sprite batching so what you do is go over every sprite on update, and basically just recalculate new UV's with new frame, meaning all sprites change their frame to the next one, yay!
If you want to have systems that are independent of eachother, say, very slow animations for some, and faster for others, you'll need different sprite batches or proper calculation on from where to where you need to update UV's in vertex buffer array. Everything else is exactly the same, except now current_frame won't be global but rather contained, preferebly in some list or separate object that manages timers for animations.
You don't need to change anything in your shaders, they just need right UV's for the frames and you're set.
By the way, this is very basic, you could apply some logic yourself so you could instead have 16x16 grid of 32x32 pixels in your texture, each line of sprites having 4 different animations, these could be either sprite's states (attack, run, etc), but how you do it is entirely on you, most importantly, get it to work. Goodluck.
But if you do it the way I said, then state will be another integer, and UV for state, assuming all states have exactly the same width, it would be like this:
state_width = 1 / states
tile_width = 1 / (states * frames_per_state)
U = state_width * current_state + tile_width * current_frame
Now, one issue arises, player could start his animation at the last attack frame.
It's normal, entities with actions should all have individual timers, what I described above, is for tons of sprites that are just background, like grass. Now when you divided it up, you could have a proper way to reset current frame to 0 when new state is assigned.
If your entities are objects, you could write proper methods that recalculate UV's every time you rebuild the sprite batch using those sprites, and then timers itselves could be contained in objects.
We need to draw something? Check animation state, has it changed, no? Send UV's that were calculated before, otherwise, wait a bit, we need to recalculate, only then add those to VBO, and well, render your thing, in the end, it will appear as if you have animations, even though really, it's just a simple, but great UV manipulation.
Goodluck.
I'm trying to clone the Tetris game and already have PyGame pick a random shape and display it. I drew an array-backed grid and 'told' PyGame to draw colored squares in certain cells in order to get the cells.
def iShape():
grid [0][5] = 3
grid [0][6] = 3
grid [0][7] = 3
grid [0][8] = 3
pygame.init()
this tells the system on which cell of the grid it will draw the square in order to get the shape.
def draw():
allShapes = ['''all Shapes that I defined''']
pick = random.choice (allShapes)
... #otherstuff
if pick == iShape:
if grid[row][column] == 3:
color = orange
#draw the squares
I have been trying to think of how I could let the shapes fall slowly so the player can move/rotate them before they hit the ground but none of my ideas work out. Does anyone have a suggestion?
try to create a def called clock or tick(anything) and have that control the drop speed. or you could youse the in built python timer by doin inport mathand there is a command to have times so you could have then drop a pice of the grid every second or something like that sry about the brightness
I've found a Tetris clone called Tetromino online. I can't quite say it will work as it probably uses a different code style, but you could get an idea from it. Its at the link https://inventwithpython.com/pygame/chapter7.html