Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Window simulator #26

Open
wants to merge 48 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
b5aa85a
Add state, constants, options and main files.
RiscadoA Sep 28, 2022
1738b3e
Fix new lines at eof
RiscadoA Sep 28, 2022
188b73e
Add comments and polish
RiscadoA Sep 28, 2022
918237a
Add Robot class and socket communication
RiscadoA Sep 30, 2022
0471740
Able to rotate cube with keyboard input
rui-abrantes Oct 24, 2022
2ae7765
Added loading stl files and hard coded rotating that object
rui-abrantes Oct 25, 2022
82e560a
Can control now angle with keys
rui-abrantes Oct 26, 2022
38b4f6b
Has 2 eyes rotation with arrows, needs math to follow mouse now
rui-abrantes Oct 27, 2022
61ba9cd
Changed Window to 2D, 3D had a lot of problems
rui-abrantes Dec 28, 2022
bd658fe
Add state, constants, options and main files. (#6)
RiscadoA Oct 9, 2022
323a864
Add frame capture code and restructured socket logic (#8)
RiscadoA Dec 11, 2022
6b73b2c
Add behaviour and recognition structural code (#14)
RiscadoA Dec 28, 2022
10958db
Add state, constants, options and main files.
RiscadoA Sep 28, 2022
88c4d3d
Fix new lines at eof
RiscadoA Sep 28, 2022
22eb5ec
Add Robot class and socket communication
RiscadoA Sep 30, 2022
cc5b3c5
Added loading stl files and hard coded rotating that object
rui-abrantes Oct 25, 2022
8ba8e05
Has 2 eyes rotation with arrows, needs math to follow mouse now
rui-abrantes Oct 27, 2022
b57a3c1
Changed Window to 2D, 3D had a lot of problems
rui-abrantes Dec 28, 2022
d3c2053
Rebasing
rui-abrantes Dec 28, 2022
49c21e6
Add state, constants, options and main files.
RiscadoA Sep 28, 2022
b0c0bce
Fix new lines at eof
RiscadoA Sep 28, 2022
46475f6
Add comments and polish
RiscadoA Sep 28, 2022
a86585a
Add Robot class and socket communication
RiscadoA Sep 30, 2022
0d118d8
Able to rotate cube with keyboard input
rui-abrantes Oct 24, 2022
610d176
Added loading stl files and hard coded rotating that object
rui-abrantes Oct 25, 2022
d580fa0
Can control now angle with keys
rui-abrantes Oct 26, 2022
65c1f68
Has 2 eyes rotation with arrows, needs math to follow mouse now
rui-abrantes Oct 27, 2022
e3b8010
Changed Window to 2D, 3D had a lot of problems
rui-abrantes Dec 28, 2022
b53cace
Add state, constants, options and main files. (#6)
RiscadoA Oct 9, 2022
1cad194
Add state, constants, options and main files.
RiscadoA Sep 28, 2022
d9aa6a9
Fix new lines at eof
RiscadoA Sep 28, 2022
564aa4c
Add Robot class and socket communication
RiscadoA Sep 30, 2022
e62c83b
Added loading stl files and hard coded rotating that object
rui-abrantes Oct 25, 2022
1c70390
Has 2 eyes rotation with arrows, needs math to follow mouse now
rui-abrantes Oct 27, 2022
b0c2a8a
Changed Window to 2D, 3D had a lot of problems
rui-abrantes Dec 28, 2022
050faff
Final Rebasing
rui-abrantes Dec 28, 2022
e319786
Merging main
rui-abrantes Dec 28, 2022
30d4c3a
Implemented the window for the options
rui-abrantes Jan 15, 2023
1d19b7b
Updating
rui-abrantes Feb 8, 2023
972eece
Needs checking
rui-abrantes Feb 8, 2023
8214fe5
Implementing State on Window
rui-abrantes Apr 7, 2023
8dc6698
Fixed minor problem, needs checking with true state
rui-abrantes Apr 7, 2023
b645930
Start structuring debug + window
rui-abrantes Apr 27, 2023
d7a5e5e
Added labels to window, windows needs to be class
rui-abrantes May 17, 2023
5728ffc
Started using sliders, need logic for debug
rui-abrantes May 23, 2023
d70f804
Debugg + Window working, maybe style it a bit (?)
rui-abrantes May 30, 2023
bd05679
Changed debugging, but needs checking to see if visual keeps working
rui-abrantes Jun 5, 2023
3fab89e
Window + Debug working fine
rui-abrantes Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions scripts/constants.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# How many times the robot is updated per second.
UPDATE_RATE = 60

DIMENSION_X = 800 + 300

DIMENSION_Y = 800
2 changes: 2 additions & 0 deletions scripts/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
from .robot import Robot
from .protocol import Protocol
from .state import State
from .debug import Debug
from .window import Window
53 changes: 53 additions & 0 deletions scripts/core/debug.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from core import Robot, State

class Debug:
"""
This class is intended to use Window Class so that it
is possible to debug some variables (ex. State, Emotion, etc)
This class will also provide heads on debugging, so it is
not necessary to code everything from scratch every time it is
intented to debug
"""

labels = []
sliders = []
y_position = 120

def add_label(self, name:str, variable:float, display:bool):

for label in self.labels:
if label["name"] == name:
label["value"] = variable
return

Debug.y_position += 40
self.labels.append({'name':name,'value':variable,'display':display, 'position':Debug.y_position})
return

def list_labels(self):
for label in self.labels:
print(f'{label["name"]}: {label["value"]}')
return

def all_labels(self):
return self.labels

def add_slider(self, name:str, value:list, upperValue:float, downValue:float, step:float ):

for slide in self.sliders:
if slide["name"] == name:
slide["value"] = value
return

Debug.y_position += 60
self.sliders.append({'name':name,'value':value,
'upperValue':upperValue, 'downValue':downValue, 'step':step,'position':Debug.y_position})
return

def list_sliders(self):
for slider in self.sliders:
print(f'{slider["name"]}: {slider["value"]}')
return

def all_sliders(self):
return self.sliders
166 changes: 166 additions & 0 deletions scripts/core/window.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import pygame
import pygame_widgets
import math
#from state import Servo
from constants import *

from core import Robot, Debug

from pygame_widgets.slider import Slider
from pygame_widgets.textbox import TextBox

# TODO: turn this into a class, move things from main


LEFT_EYE_CENTER = (320,400)
RIGHT_EYE_CENTER = (480,400)

EYE_RADIUS = 50
PUPIL_RADIUS = 15

PUPIL_LIMIT = 30 # EYE_RADIUS - PUPIL_RADIUS - 5 Pixels, so the pupil is not in the limit of the eye

ANGLE_OF_STATE_UNIT = EYE_RADIUS / 180

Z_PLANE = 1000


class Window:


def __init__(self, x_dimension, y_dimension, _robot: Robot):
self.isRunning = True

self.robot= _robot
self.win = pygame.display.set_mode((x_dimension,y_dimension))
pygame.display.set_caption("INAR Simulator")

self.sliders = []

def draw_eye(self, eye_x, eye_y, robot, position):
new_x, new_y = pygame.mouse.get_pos() # Gets mouse position

#TODO: State needs to be initialized when the program runs,
# otherwhise it is not possible to run the scrip bellow


robot_state = robot.getActualState()
# Checks which eye it is, and updates the new position of the pupil
# This new position is based on the angle given to the servos of the
# robot
"""
if position == "left":
new_x = robot_state.getPosition(Servo.L_EYE_X) * ANGLE_OF_STATE_UNIT * DIMENSION_X
new_y = robot_state.getPosition(Servo.L_EYE_Y) * ANGLE_OF_STATE_UNIT * DIMENSION_Y
if position == "right":
new_x = robot_state.getPosition(Servo.R_EYE_X) * ANGLE_OF_STATE_UNIT * DIMENSION_X
new_y = robot_state.getPosition(Servo.R_EYE_Y) * ANGLE_OF_STATE_UNIT * DIMENSION_Y
else:
print("Error, that eye does not exist")
"""

distance_x = new_x - eye_x
distance_y = new_y - eye_y

""""
Angle between plane and line:

|u.n|
sin(tetha) = ------------
|u|.|n|

In our case n = (0,0,1) and u = (distance_x, distance_y, Z_PLANE)
so |u.n| = uz.nz = Z_PLANE
and
|u|.|n| = |u|

"""
#NOTE: It may seem that there is no plane on the mouse but that's
# because of the dimensions are small, so we cant add a great distance
# to the mouse.

norm_u = math.sqrt(distance_x**2 + distance_y**2 + Z_PLANE**2)
calc_aux = Z_PLANE/norm_u
theta = math.asin(calc_aux) # in radians
true_distance = norm_u * math.cos(theta)

distance = min(true_distance, PUPIL_LIMIT)

angle = math.atan2(distance_y, distance_x) # angle for rotation
pupil_x = eye_x + (math.cos(angle) * distance) # position of pupil of the eye in axis X
pupil_y = eye_y + (math.sin(angle) * distance) # position of pupil of the eye in axis Y

pygame.draw.circle(surface=self.win, center=(eye_x, eye_y), radius=EYE_RADIUS, color=(255, 255, 255)) # draw eye
pygame.draw.circle(surface=self.win, center=(pupil_x, pupil_y), radius=PUPIL_RADIUS, color=(0, 255, 255)) # draw pupil

def draw_face(self,robot):
pygame.draw.rect(surface=self.win, color=(255,229,204), rect= (190, 250, 300, 300) )
self.draw_eye(260, 400, robot, "left") # left eye
self.draw_eye(420, 400, robot, "right") # right eye

pygame.draw.line(self.win, (0,0,0), (680, 0), (680, 800))
#pygame.display.flip()

self.draw_text("Debug:", 32, 100)

def draw_text(self, text, fontsize, y_position):
# Initialize the font system and create the font and font renderer
pygame.font.init()
default_font = pygame.font.get_default_font()
font_renderer = pygame.font.Font(default_font, fontsize)
# To create a surface containing `Some Text`
label = font_renderer.render(
text, # The font to render
1, # With anti aliasing
(0,0,0)) # RGB Color

self.win.blit(label, (700,y_position))

def draw_slider(self,upperValue,downValue,step,y_position):
slider = Slider(self.win, 700, y_position, 150, 10, min=downValue, max=upperValue, step=step)

self.sliders.append(slider)

def draw_slider_title(self, name, y_position, index):
self.draw_text( name + ": " + str(self.sliders[index].getValue()), 14, y_position-20)

def run(self):
pygame.init()
pygame.time.delay(100)

# x_start, y_start, widht_dimension, radius_dimension,
#slider = Slider(self.win, 700, 200, 150, 10, min=0, max=5, step=1)

for slider in Debug().all_sliders():
self.draw_slider(slider["upperValue"],
slider["downValue"],
slider["step"],
slider["position"])

while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
print("Quitting... Sya :)")
self.isRunning = False

if not self.isRunning:
break

self.win.fill((255,255,255)) # Fills with the colors inside

self.draw_face(self.robot)


for label in Debug().all_labels():
self.draw_text(label["name"] + ": " + str(label["value"]) ,18, label["position"])

for idx,slider in enumerate(Debug().all_sliders()):
self.draw_slider_title(slider["name"], slider["position"], idx)




pygame_widgets.update(events)
pygame.display.update()

109 changes: 109 additions & 0 deletions scripts/eyes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Eyes Follow Mouse Cursor</title>

<style>
body {
background-color: yellow;
margin: 0;
padding: 0;
grid-template-columns: 1fr;
grid-template-rows: 100vh;
display: grid;
align-items: center;
justify-items: center;
}

.eyesContainer {
width: 200px;
height: 200px;
background-color: tomato;
display: grid;
align-items: center;
justify-items: center;
grid-template-columns: 1fr 1fr;
border-radius: 10px;
transform-style: preserve-3d;
box-shadow: 0 30px 70px #666;
will-change: transform;
transform: perspective(500px) rotateX(var(--yAngle, 0deg)) rotateY(var(--xAngle, 0deg));
}

.eye {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: white;
transform: translateZ(50px) rotate(var(--eyeAngle, 0deg));
}

.pupil {
position: relative;
width: 16px;
height: 16px;
background: #000;
border-radius: 50%;
top: calc(50% - 8px);
left: 5px;
}
</style>
</head>

<body>
<div class="eyesContainer">
<div class="eye">
<div class="pupil"></div>
</div>
<div class="eye">
<div class="pupil"></div>
</div>
</div>
<script>

let eyes = document.querySelectorAll(".eye");

let eyeRect = eyes[0].getBoundingClientRect();

let container = document.querySelector(".eyesContainer");
let containerRect = container.getBoundingClientRect();

window.addEventListener("resize", updatePosition, false);

function updatePosition(e) {
eyeRect = eyes[0].getBoundingClientRect();
containerRect = container.getBoundingClientRect();
}

document.body.addEventListener("mousemove", eyesFollow, false);

function eyesFollow(e) {
requestAnimationFrame(() => {
let xPos = e.pageX;
let yPos = e.pageY;

let xDiff = (eyeRect.x + eyeRect.width / 2) - xPos;
let yDiff = (eyeRect.y + eyeRect.height / 2) - yPos;

let angle = Math.atan2(yDiff, xDiff) * 180 / Math.PI;

container.style.setProperty("--eyeAngle", angle.toFixed(2) + "deg");

let mouseXRelativetoContainer = xPos - containerRect.x - containerRect.width / 2;
let mouseYRelativetoContainer = yPos - containerRect.y - containerRect.height / 2;

let containerXAngle = 60 * (mouseXRelativetoContainer / window.innerWidth);
let containerYAngle = -1 * 60 * (mouseYRelativetoContainer / window.innerHeight);

container.style.setProperty("--xAngle", containerXAngle.toFixed(2) + "deg");
container.style.setProperty("--yAngle", containerYAngle.toFixed(2) + "deg");
});
}
</script>
</body>

</html>
Loading