ropy/rp_lib.py

1405 lines
65 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import bge # Blender Game Engine (UPBGE)
import bpy # Blender
import aud # Sounds
import threading # Multithreading
import trace
import sys
import time
import math
import mathutils
import random
import serial # Liaison série (jumeau numérique)
from serial.tools.list_ports import comports # Détection du port automatique
import rp_map1 as rp_map # Map definition
###############################################################################
# rp_lib.py
# @title: Bibliothèque du Rover Ropy (rp_*)
# @project: Ropy (Blender-EduTech)
# @lang: fr
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2020-2024 Philippe Roy
# @license: GNU GPL
#
# Bibliothèque des actions du robot
#
# Ropy est destiné à la découverte de la programmation procédurale et du language Python.
# A travers plusieurs challenges, donc de manière graduée, les élèves vont apprendre à manipuler les structures algorithmiques de base et à les coder en Python.
###############################################################################
scene = bge.logic.getCurrentScene()
debug = scene.objects['Terrain']['debug']
# Sounds
audiodev = aud.Device()
snd_click = aud.Sound('asset/sounds/rp_click.ogg')
# Threads
threads_cmd=[]
threads_gostore=[]
debug_thread = scene.objects['Terrain']['debug_thread']
# Jumeau numérique
twins_serial = None
# UPBGE constants
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED
ACTIVATE = bge.logic.KX_INPUT_ACTIVE
# JUST_DEACTIVATED = bge.logic.KX_SENSOR_JUST_DEACTIVATED
###############################################################################
# Méthode kill pour les tâches (threads)
###############################################################################
class thread_with_trace(threading.Thread):
def __init__(self, *args, **keywords):
threading.Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self.__run_backup = self.run
self.run = self.__run
threading.Thread.start(self)
def __run(self):
sys.settrace(self.globaltrace)
self.__run_backup()
self.run = self.__run_backup
def globaltrace(self, frame, event, arg):
if event == 'call':
return self.localtrace
else:
return None
def localtrace(self, frame, event, arg):
if self.killed:
if event == 'line':
raise SystemExit()
return self.localtrace
def kill(self):
self.killed = True
###############################################################################
# Start et stop des tâches (threads)
###############################################################################
def thread_start(threads, type_txt, fct):
threads.append(thread_with_trace(target = fct))
threads[len(threads)-1].start()
if (debug_thread):
print ("Thread",type_txt, "#", len(threads)-1, "open.")
def thread_stop(threads, type_txt):
i=0
zombie_flag=False
for t in threads:
if not t.is_alive():
if (debug_thread):
print ("Thread",type_txt, "#",i,"closed.")
else:
if (debug_thread):
print ("Thread",type_txt, "#",i,"still open ...")
t.kill()
t.join()
if not t.is_alive():
if (debug_thread):
print ("Thread",type_txt, "#",i,"killed.")
else:
if (debug_thread):
print ("Thread",type_txt, "#",i,"zombie...")
zombie_flag=True
i +=1
if zombie_flag==False:
if (debug_thread):
print ("All threads",type_txt, "are closed.")
scene.objects['Terrain']['thread_cmd']=False
return True
else:
if (debug_thread):
print ("There are zombies threads",type_txt, ".")
return False
def thread_cmd_start(fct):
thread_start(threads_cmd, "commands", fct)
def thread_cmd_stop():
thread_stop(threads_cmd, "commands")
def thread_gostore_start(fct):
thread_start(threads_gostore, "go store", fct)
def thread_gostore_stop():
thread_stop(threads_gostore, "go store")
def rp_end():
# Jumeau numérique
if scene.objects['Commands']['twins']:
serial_msg = "FI\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
rp_jumeau_close()
# Thread
if (debug_thread):
print ("Thread commands is arrived.")
time.sleep(0.125)
scene.objects['Terrain']['thread_cmd']=False
time.sleep(0.125)
def rp_fin():
rp_end()
def rp_quit():
rp_end()
###############################################################################
# Sounds
###############################################################################
# FIXME : Sound crash in Windows (very strange : blender, UPBGE, python ?), no music for Bill
def sound_play (sound):
if scene.objects['Commands']['sound'] and sys.platform!="win32":
audiodev.play(sound)
###############################################################################
# Rover fonctions élève
###############################################################################
##
# Avancer le rover
# - twins (True|False) : envoi un ordre au jumeau réel
##
def rp_avancer (twins=True):
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
# Contrôle colision
x0 = obj.worldPosition.x
y0 = obj.worldPosition.y
z0 = obj.worldPosition.z
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
x1 = x0
y1 = y0-1
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
x1 = x0
y1 = y0+1
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
x1 = x0+1
y1 = y0
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
x1 = x0-1
y1 = y0
if [x1,y1] in scene.objects['Terrain']['map_tile_montain']:
print ("Crash dans la montagne !")
rover_colision_montain (False)
obj['stop'] = True
if [x1,y1] in scene.objects['Terrain']['map_tile_station']:
print ("Crash dans la station !")
rover_colision_station (False)
obj['stop'] = True
if x1 < scene.objects['Terrain']['size'][0] or x1 > scene.objects['Terrain']['size'][2] or y1 < scene.objects['Terrain']['size'][1] or y1 > scene.objects['Terrain']['size'][3] :
print ("Sortie de carte !")
obj['stop'] = True
if obj['stop']:
return False
# Points, console et jumeau numérique
if debug:
print ("rp_avancer()")
scene.objects['Points']['step'] +=1
if scene.objects['Commands']['twins'] and twins:
serial_msg = "AV\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Animation rapide
if scene.objects['Commands']['speed'] >= 10 and scene.objects['Points']['step']> 2: # A tendance à planter sur les premiers mouvements en rapide + balisage
rp_tempo (0.1)
x0 = obj.worldPosition.x
y0 = obj.worldPosition.y
z0 = obj.worldPosition.z
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.worldPosition=[x0, y0-1, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.worldPosition=[x0, y0+1, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.worldPosition=[x0+1, y0, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.worldPosition=[x0-1, y0, z0]
rp_tempo (0.1)
# FIXME : Animation sacadée
# step =1/100
# print (obj.worldOrientation.to_euler().z)
# x0 = obj.worldPosition.x
# y0 = obj.worldPosition.y
# z0 = obj.worldPosition.z
# for i in range (100) :
# if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
# obj.worldPosition=[x0, y0-step*i, z0]
# if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
# obj.worldPosition=[x0, y0+step*i, z0]
# if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
# obj.worldPosition=[x0+step*i, y0, z0]
# if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
# obj.worldPosition=[x0-step*i, y0, z0]
# rp_tempo (0.1*step)
# Animation
if scene.objects['Commands']['speed'] < 10 or scene.objects['Points']['step']<=2:
start = 1
end = 100
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-Avancer-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# obj.worldPosition=[x0, y0-step*i, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-Avancer-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# obj.worldPosition=[x0, y0+step*i, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-Avancer-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# obj.worldPosition=[x0+step*i, y0, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-Avancer-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# obj.worldPosition=[x0-step*i, y0, z0]
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# Forçage du redraw
while scene.objects['Rv-Wheel-right-front'].isPlayingAction():
rp_sleep(0.1)
# rp_tempo (0.1)
# # pass
# # scene.objects['Camera'].applyMovement((0, 0, 0), True)
# scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# Contrôle objectif
if rp_map.objectif_control(x1,y1):
rover_goal ()
return True
##
# Reculer le rover
# - twins (True|False) : envoi un ordre au jumeau réel
##
def rp_reculer (twins=True):
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
# Contrôle colision
x0 = obj.worldPosition.x
y0 = obj.worldPosition.y
z0 = obj.worldPosition.z
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
x1 = x0
y1 = y0+1
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
x1 = x0
y1 = y0-1
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
x1 = x0-1
y1 = y0
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
x1 = x0+1
y1 = y0
if [x1,y1] in scene.objects['Terrain']['map_tile_montain']:
print ("Crash dans la montagne !")
rover_colision_montain (True)
obj['stop'] = True
if [x1,y1] in scene.objects['Terrain']['map_tile_station']:
print ("Crash dans la station !")
rover_colision_station (True) # FIXME à faire en recul
obj['stop'] = True
if x1 < scene.objects['Terrain']['size'][0] or x1 > scene.objects['Terrain']['size'][2] or y1 < scene.objects['Terrain']['size'][1] or y1 > scene.objects['Terrain']['size'][3] :
print ("Sortie de carte !") # FIXME à faire en recul
obj['stop'] = True
if obj['stop']:
return False
# Points, console et jumeau numérique
if debug:
print ("rp_reculer()")
scene.objects['Points']['step'] +=1
if scene.objects['Commands']['twins'] and twins:
serial_msg = "RE\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Animation rapide
if scene.objects['Commands']['speed'] >= 10 and scene.objects['Points']['step']> 2: # A tendance à planter sur les premiers mouvements en rapide + balisage
rp_tempo (0.1)
x0 = obj.worldPosition.x
y0 = obj.worldPosition.y
z0 = obj.worldPosition.z
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.worldPosition=[x0, y0+1, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.worldPosition=[x0, y0-1, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.worldPosition=[x0-1, y0, z0]
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.worldPosition=[x0+1, y0, z0]
rp_tempo (0.1)
# Animation
if scene.objects['Commands']['speed'] < 10:
start = 1
end = 100
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-Avancer-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-Avancer-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-Avancer-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-Avancer-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Wheel-right-front'].isPlayingAction(): # Forçage du redraw
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# Contrôle objectif
if rp_map.objectif_control(x1,y1):
rover_goal ()
return True
##
# Tourner à gauche
# - twins (True|False) : envoi un ordre au jumeau réel
##
def rp_gauche (twins=True):
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
# Points, console et jumeau numérique
if debug:
print ("rp_gauche()")
scene.objects['Points']['step'] +=1
step=math.pi/2 # Pas angulaire
if scene.objects['Commands']['twins'] and twins:
serial_msg = "GA\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Animation rapide
if scene.objects['Commands']['speed'] >= 10:
rp_tempo (0.1)
obj.applyRotation((0, 0, step), True)
rp_tempo (0.1)
return True
# Animation
start = 1
end = 100
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
obj.playAction('Rover-Gauche', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Wheel-right-front'].isPlayingAction(): # Forçage du redraw
# scene.objects['Camera'].applyMovement((0, 0, 0), True)
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
return True
##
# Tourner à droite
# - twins (True|False) : envoi un ordre au jumeau réel
##
def rp_droite (twins=True):
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
# Points, console et jumeau numérique
if debug:
print ("rp_droite()")
scene.objects['Points']['step'] +=1
step=math.pi/2 # Pas angulaire
if scene.objects['Commands']['twins'] and twins:
serial_msg = "DR\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Rapide
if scene.objects['Commands']['speed'] >= 10:
rp_tempo (0.1)
obj.applyRotation((0, 0, -step), True)
rp_tempo (0.1)
return True
# Animation
start = 1
end = 100
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
obj.playAction('Rover-Droite', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Wheel-right-front'].isPlayingAction(): # Forçage du redraw
# scene.objects['Camera'].applyMovement((0, 0, 0), True)
pass
# rp_sleep(0.1)
# scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
return True
##
# Marquer
# - twins (True|False) : envoi un ordre au jumeau réel
##
def rp_marquer (twins=True):
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
x = obj.worldPosition.x
y = obj.worldPosition.y
z = obj.worldPosition.z
# Vérification de l'absence de balise sur la tuile
if [x,y] in scene.objects['Terrain']['map_tile_beacon'] :
print ("Case déjà marquée !")
return False
# Points, console et jumeau numérique
if debug:
print ("rp_marquer() -> balise #"+ str(len(scene.objects['Terrain']['map_tile_beacon'])))
if scene.objects['Commands']['twins'] and twins:
serial_msg = "MA\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Posage
rp_tempo (0.1)
if scene.objects['Points']['upgrade_beacon']:
beacon_max= 200
else:
beacon_max= 20
for i in range (beacon_max):
beacon = scene.objects["Beacon-"+str(i)]
if beacon['activated']==False:
beacon.worldPosition=[x,y,0.2]
beacon['activated']=True
beacon.setVisible(True, True)
if scene.objects['About']['quality'] < 2: # Qualité de rendu : faible -> sans la sphère
beacon.children[1].setVisible(False, True)
scene.objects['Terrain']['map_tile_beacon'].append([x,y])
break
if i ==beacon_max-1 :
print ("Plus de balise disponible !")
rp_tempo (0.1)
return True
##
# Détecter
##
def rp_detect ():
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return True
# Points et console
if debug:
print ("rp_detect")
# Détection
x0 = obj.worldPosition.x
y0 = obj.worldPosition.y
z0 = obj.worldPosition.z
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
x1 = x0
y1 = y0-1
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
x1 = x0
y1 = y0+1
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
x1 = x0+1
y1 = y0
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
x1 = x0-1
y1 = y0
if [x1,y1] in scene.objects['Terrain']['map_tile_montain']:
if debug:
print ("Présence de montage devant !")
if scene.objects['Points']['mission']==3: # Contrôle objectif mission 3
rover_goal ()
return True
if [x1,y1] in scene.objects['Terrain']['map_tile_station']:
if debug:
print ("Présence de la station devant !")
if scene.objects['Points']['mission']==3: # Contrôle objectif mission 3
rover_goal ()
return True
if [x1,y1] in scene.objects['Terrain']['map_tile_station']:
if debug:
print ("Sortie de carte devant !")
if scene.objects['Points']['mission']==3: # Contrôle objectif mission 3
rover_goal ()
return True
return False
##
# Prendre
##
def rp_prendre ():
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
# Points et console
if debug:
print ("rp_prendre")
# FIXME
##
# Radar
##
def rp_radar ():
obj=scene.objects['Rover']
# Pas de mouvement si colision ou objectif
if obj['stop']:
return False
# Points et console
if debug:
print ("rp_radar")
# FIXME
###############################################################################
# Rover fonctions avancées (upgrade) élève
###############################################################################
##
# Peindre : station, rover, balise
##
# Couleurs par défaut
color_yellow = (1, 0.503, 0.018, 1)
color_black = (0.019794, 0.032076, 0.037408, 1)
color_white = (0.799, 0.799, 0.799, 1)
color_windows_red = (0.617, 0.037, 0.019, 1)
color_light_red = (1, 0.003, 0.012, 1) # Balise
color_stone = (0.191, 0.227, 0.246, 1)
color_wooddark = (0.153, 0.117, 0.107, 1)
color_metal = (0.401, 0.478, 0.518, 1)
# Objets 3D par groupe
paint_part ={}
all_group_part = ("Rover 1", "Rover 2", "Rover 3", "Station 1", "Station 2", "Station 3", "Station 4", "Station cube 1", "Station cube 2", "Stone", "Metal", "Black", "Red windows")
paint_part.update({"Stone" : [['Rv-Wheel-left-front', 'Rv-Wheel-right-front','Rv-Wheel-left-mid', 'Rv-Wheel-right-mid', 'Rv-Wheel-left-rear', 'Rv-Wheel-right-rear'],color_stone]}) # Stone
paint_part.update({"Metal" : [['Rv-Power source', 'Rv-Mast-arm', 'Rv-Antenna-1', 'St-Sheath', 'Rv-Arm-Segment-1', 'Rv-Arm-Segment-2'],color_metal]}) # Metal
paint_part.update({"Black" : [['St-Block1-foot1','St-Block1-foot2','St-Block1-foot3', 'St-Door-2', 'St-Stair-2','St-Cable1','St-Cable2'],color_black]}) # Black
paint_part.update({"Red windows" : [['St-Block1-window','St-Block2-window'],color_windows_red]}) # Red windows
# Rover
rover_partlist =['Rover (Rv-Body-1)', 'Rv-Body-2', 'Rv-Body-3', 'Rv-Body-4', 'Rv-Body-5', 'Rv-Body-6', 'Rv-Body-7',
'Rv-Mast', 'Rv-Mast-2', 'Rv-Mast-3', 'Rv-Mast-4', 'Rv-Mast-cap', 'Rv-Mast-arm','Rv-Antenna-1','Rv-Antenna-2','Rv-Antenna-3',
'Rv-Arm-Head', 'Rv-Arm-Segment-1', 'Rv-Arm-Segment-2',
'Rv-Power source', 'Rv-Power source-2', 'Rv-Power source-3', 'Rv-Power source-4', 'Rv-Power source-5',
'Rv-Wheel-left-front', 'Rv-Wheel-right-front','Rv-Wheel-left-mid', 'Rv-Wheel-right-mid', 'Rv-Wheel-left-rear', 'Rv-Wheel-right-rear']
paint_part.update({"Rover 1" : [['Rv-Body-2', 'Rv-Body-7', 'Rv-Power source-2', 'Rv-Power source-5', 'Rv-Mast-3', 'Rv-Mast-4', 'Rv-Mast-cap', 'Rv-Antenna-2'],color_yellow]}) # Jaune
paint_part.update({"Rover 2" : [['Rover', 'Rv-Body-6', 'Rv-Mast', 'Rv-Antenna-3', 'Rv-Arm-Head'],color_white]}) # Blanc
paint_part.update({"Rover 3" : [['Rv-Body-3', 'Rv-Body-4', 'Rv-Power source-3', 'Rv-Power source-4','Rv-Mast-2'],color_wooddark]}) # WoodDark
# Station
station_partlist =['St-Block1', 'St-Block2', 'St-Block3',
'St-Block1-side1', 'St-Block1-side2', 'St-Block1-roof', 'St-Block1-foot1', 'St-Block1-foot2','St-Block1-foot3',
'St-Door', 'St-Door-2', 'St-Block1-window', 'St-Stair', 'St-Stair-2', 'St-Stair-3','St-Block1-panel-support',
'St-Block2-side', 'St-Block2-window', 'St-Block2-roof',
'St-Block3-side', 'St-Block3-greenhouse', 'St-Block3-greenhouse-base', 'St-Tunnel', 'St-Tube', 'St-Cable1', 'St-Cable2', 'St-Sheath']
paint_part.update({"Station 1" : [[ 'St-Door','St-Block1-side1','St-Block2-side','St-Block2-roof'],color_yellow]}) # Jaune
paint_part.update({"Station 2" : [[ 'St-Block1','St-Block2','St-Block3','St-Block3-side2','St-Tunnel','St-Tube'],color_white]}) # Blanc
paint_part.update({"Station 3" : [[ 'St-Block1-roof', 'St-Block1-side2', 'St-Block3-side1'],color_stone]}) # Stone
paint_part.update({"Station 4" : [[ 'St-Stair'],color_metal]}) # Metal
paint_part.update({"Station cube 1" : [[ 'St-Cube1-hole','St-Cube2-hole','St-Cube3-hole', 'St-Cube4-hole'],color_yellow]}) # Jaune
paint_part.update({"Station cube 2" : [[ 'St-Cubes','St-Cube2','St-Cube3', 'St-Cube4'],color_white]}) # Blanc
# Balise : Objet lors de l'initialisation
# beacon_partlist =['Beacon_antenne', 'Beacon_sphere']
# paint_part.update({"Balise" : [['Beacon_antenne', 'Beacon_sphere'],color_light_red]}) # Rouge
# Mise en couleur
def rp_couleur (group_part, new_color):
if scene.objects['Points']['upgrade_paint']:
if debug:
print ("Nouvelle couleur :", str(new_color),"->", group_part)
if "Balise" not in group_part :
for i in range (len(paint_part[group_part][0])):
scene.objects[paint_part[group_part][0][i]].color = new_color
else:
if group_part=="Balises":
for i in range (200):
beacon = scene.objects["Beacon-"+str(i)]
beacon.children[0].color = new_color
beacon.children[1].color = new_color
elif "Balise " in group_part :
beacon = scene.objects[group_part.replace("Balise ", "Beacon-")]
beacon.children[0].color = new_color
beacon.children[1].color = new_color
def rp_couleur_detail (part, new_color):
if scene.objects['Points']['upgrade_paint']:
if debug:
print ("Nouvelle couleur :", str(new_color),"->", part)
scene.objects[part].color = new_color
# Initialisation de la couleur
def rp_couleur_init (group_part=None):
if group_part is not None:
if scene.objects['Points']['upgrade_paint']:
if debug:
print ("Réinitialisation couleur ->", group_part)
for i in range (len(paint_part[group_part][0])):
scene.objects[paint_part[group_part][0][i]].color = paint_part[group_part][1]
return (paint_part[group_part][1])
else:
for i in range (len(all_group_part)):
for j in range (len(paint_part[all_group_part[i]][0])):
scene.objects[paint_part[all_group_part[i]][0][j]].color = paint_part[all_group_part[i]][1]
for i in range (200):
beacon = scene.objects["Beacon-"+str(i)]
beacon.children[0].color = color_light_red
beacon.children[1].color = color_light_red
# Affichage de la liste des composants 3D
def rp_couleur_listedetail (element, new_color):
if scene.objects['Points']['upgrade_paint']:
if element=="Rover":
print ("Mise en couleur : composants 3D du Rover :", rover_partlist)
if element=="Station":
print ("Mise en couleur : composants 3D de la Station :", station_partlist)
if element=="Balise":
print ("Mise en couleur : composants 3D des balises : Beacon-0.children[0|1] à Beacon-200.children[0|1].")
##
# Changer la vitesse
##
def rp_vitesse (new_speed):
if scene.objects['Points']['upgrade_speed']:
if new_speed is not None:
if debug:
print ("Nouvelle vitesse :", new_speed)
scene.objects['Text_speed']['Text']=str(new_speed)
scene.objects['Commands']['speed']=new_speed
return scene.objects['Commands']['speed']
##
# Connaitre le nombre de balise posées
##
def rp_balise ():
if scene.objects['Points']['upgrade_beacon']:
for i in range (200):
if scene.objects["Beacon-"+str(i)]['activated']==False:
break
if debug:
print ("Nombre de balises posées :", i)
return i
##
# Connaitre la charge de la batterie
##
def rp_batterie ():
if scene.objects['Points']['upgrade_battery']:
if debug:
print ("Charge de la batterie :", scene.objects['Points']['battery'])
return scene.objects['Points']['battery']
###############################################################################
# Rover fonctions de script
###############################################################################
##
# Retourne la visibilité de la grille
##
def rp_grid ():
if debug:
print ("Visibilité de la grille :", scene.objects['Grid-u'].visible)
return scene.objects['Grid-u'].visible
##
# Affiche/cache l'objectif et retour la visibilité
##
def rp_set_grid (visibility=False):
# Affiche la grille
if visibility and scene.objects['Grid-u'].visible == False:
scene.objects['Grid-u']['timer'] = 0
bpy.data.materials["Grid"].node_tree.nodes["Shader de mélange"].inputs[0].default_value = 0
bpy.data.materials["Grid-Yellow"].node_tree.nodes["Shader de mélange"].inputs[0].default_value = 0
bpy.data.materials["Grid-Green"].node_tree.nodes["Shader de mélange"].inputs[0].default_value = 0
bpy.data.materials["Grid-Holo"].node_tree.nodes["Émission"].inputs[1].default_value = 0
bpy.data.materials["Grid-Holo-Yellow"].node_tree.nodes["Émission.003"].inputs[1].default_value = 0
bpy.data.materials["Grid-Holo-Green"].node_tree.nodes["Émission"].inputs[1].default_value = 0
scene.objects['Grid-u'].setVisible(True,True)
scene.objects['Grid-v'].setVisible(True,True)
rp_map.aim_show()
scene.objects['Grid-u']['anim'] = True
# Cache la grille
if visibility==False and scene.objects['Grid-u'].visible:
scene.objects['Grid-u'].setVisible(False,True)
scene.objects['Grid-v'].setVisible(False,True)
rp_map.aim_hide()
##
# Retourne le numéro de la mission en cours
##
def rp_level ():
return scene.objects['Points']['mission']
##
# Sélectionner la mission
# FIXME : plantage
##
def rp_set_level (mission):
if mission != scene.objects['Points']['mission']:
scene.objects['Points']['mission'] = mission
scene.objects['Points-Map-text']['Text']="Mission "+str(scene.objects['Points']['mission'])
# scene.objects['Terrain']['thread_cmd']=False
rp_map.map_reset()
rp_map.task()
if scene.objects['Grid-u'].visible:
rp_map.aim_show()
scene.objects['Points']['mission_init'] = scene.objects['Points']['mission']
##
# Retourne la liste des upgrades actifs
##
def rp_upgrade ():
upgrade_card=("battery", "beacon", "paint", "speed")
upgrades_selected=[]
for i in range(len(upgrade_card)):
if scene.objects['Points']["upgrade_"+upgrade_card[i]]:
upgrades_selected.append(upgrade_card[i])
return upgrades_selected
##
# Sélectionner une amélioration
##
def rp_set_upgrade (upgrade, activation=True):
upgrade_card=("battery", "beacon", "paint", "speed")
for i in range(len(upgrade_card)):
if upgrade == upgrade_card[i]:
scene.objects['Points']["upgrade_"+upgrade_card[i]]=activation
break
###############################################################################
# Colision
###############################################################################
##
# Montagne
##
def rover_colision_montain (back):
obj=scene.objects['Rover']
# Jumeau numérique
if scene.objects['Commands']['twins']:
serial_msg = "CO\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Animation
start = 1
end = 120
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*2
if back==False: # Crash en avant
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-Crash-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-Crash-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-Crash-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-Crash-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
else: # Crash en arrière
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-Crash-Back-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-Crash-Back-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-Crash-Back-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-Crash-Back-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# Forçage du redraw
while scene.objects['Rv-Wheel-right-front'].isPlayingAction():
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
return True
##
# Station
##
def rover_colision_station (back):
obj=scene.objects['Rover']
# Jumeau numérique
if scene.objects['Commands']['twins']:
serial_msg = "CO\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Animation
start = 1
end = 120
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*2
if back==False: # Crash en avant
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-CrashStation-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-CrashStation-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-CrashStation-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-CrashStation-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
else:
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-CrashStation-Back-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-CrashStation-Back-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-CrashStation-Back-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-CrashStation-Back-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
# Forçage du redraw
while scene.objects['Rv-Wheel-right-front'].isPlayingAction():
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
return True
###############################################################################
# Goal
###############################################################################
##
# Fin de mission
##
def rover_goal ():
obj=scene.objects['Rover']
if debug:
print ("Goal !!")
obj['stop'] = True
# Jumeau numérique
if scene.objects['Commands']['twins']:
serial_msg = "OB\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Animation
start = 1
end = 160
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*4
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
rp_gauche()
rp_gauche()
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
rp_droite()
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
rp_gauche()
speed = scene.objects['Commands']['speed']
scene.objects['Rover'].playAction('Rover-Aim1', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Mast'].playAction('Mast-Aim1', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Mast-cap'].playAction('Mast-cap-Aim1', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Wheel-right-front'].isPlayingAction(): # Forçage du redraw
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# Revenir à une position propre
x0 = obj.worldPosition.x
y0 = obj.worldPosition.y
obj.worldPosition.x = round(x0)
obj.worldPosition.y = round(y0)
# Level
if scene.objects['Points']['mission']==scene.objects['Points']['level']:
scene.objects['Points']['level']+=1
scene.objects['Points']['level_new_flag']=True
##
# Forage
##
def rover_drill (x,y):
obj=scene.objects['Rover']
if debug:
print ("Goal : ", [x,y])
# Animation
if scene.objects['Commands']['speed'] < 10:
# Recul d'une 1/2 case
start = 1
end = 50
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-Avancer-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-Avancer-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-Avancer-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-Avancer-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Reculer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Wheel-right-front'].isPlayingAction(): # Forçage du redraw
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# Forage
start = 1
end = 300
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
scene.objects['Rv-Arm-Joint-1'].playAction('Arm-Joint-1-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Segment-1'].playAction('Arm-Segment-1-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Segment-2'].playAction('Arm-Segment-2-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Joint-2'].playAction('Arm-Joint-2-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Head'].playAction('Arm-Head-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Arm-Joint-1'].isPlayingAction(): # Forçage du redraw
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# Jumeau numérique
if scene.objects['Commands']['twins']:
serial_msg = "FO\n"
twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit )
# Tuile
for i in range (10):
if scene.objects['Drill_tile-'+str(i)].visible==False:
scene.objects['Drill_tile-'+str(i)].worldPosition.x = x
scene.objects['Drill_tile-'+str(i)].worldPosition.y = y
scene.objects['Drill_tile-'+str(i)].setVisible(True,True)
rp_tempo (0.1)
break
for obj_i in scene.objects:
if "tile_dirtHigh" in obj_i.name:
if round(obj_i.worldPosition.x) == x and round(obj_i.worldPosition.y) == y :
obj_i.setVisible(False, True)
rp_tempo (0.1)
if scene.objects['Commands']['speed'] < 10:
# Fin de forage
start = 300
end = 600
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
scene.objects['Rv-Arm-Joint-1'].playAction('Arm-Joint-1-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Segment-1'].playAction('Arm-Segment-1-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Segment-2'].playAction('Arm-Segment-2-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Joint-2'].playAction('Arm-Joint-2-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Arm-Head'].playAction('Arm-Head-Drill', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Arm-Joint-1'].isPlayingAction(): # Forçage du redraw
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# Avance d'une 1/2 case
start = 1
end = 50
layer = 0
priority = 1
blendin = 1.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = scene.objects['Commands']['speed']*8
if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud
obj.playAction('Rover-Avancer-Y-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord
obj.playAction('Rover-Avancer-Y+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est
obj.playAction('Rover-Avancer-X+', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest
obj.playAction('Rover-Avancer-X-', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-right-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-front'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-mid'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
scene.objects['Rv-Wheel-left-rear'].playAction('Wheel-Avancer', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
while scene.objects['Rv-Wheel-right-front'].isPlayingAction(): # Forçage du redraw
scene.objects['Sun'].applyMovement((0, 0, 0), True)
rp_tempo (0.1)
# # Tuile
# for i in range (10):
# if scene.objects['Drill_tile-'+str(i)].visible==False:
# scene.objects['Drill_tile-'+str(i)].worldPosition.x = x
# scene.objects['Drill_tile-'+str(i)].worldPosition.y = y
# scene.objects['Drill_tile-'+str(i)].setVisible(True,True)
# break
# for obj_i in scene.objects:
# if "tile_dirtHigh" in obj_i.name:
# if round(obj_i.worldPosition.x) == x and round(obj_i.worldPosition.y) == y :
# obj_i.setVisible(False, True)
###############################################################################
# Temporisation
###############################################################################
# Temporisation basée sur l'horloge de l'OS
def rp_sleep (duration):
time.sleep(duration)
# Temporisation basée par l'horloge de UPBGE
def rp_tempo (duration):
scene.objects['Commands']['time']=0
while scene.objects['Commands']['time']<duration*(1/scene.objects['Commands']['speed']):
# print (scene.objects['Commands']['time']
time.sleep(0.001)
###############################################################################
# Jumeau numérique
###############################################################################
##
# Activation de la communication avec la carte de communication (Arduino, Micro:bit)
# Vitesse : 115200 -> 7 fps, 38400 -> 6 fps, 9600 -> 2 fps
##
def rp_jumeau(port="auto", speed=115200):
global twins_serial
scene.objects['Points-Twins'].setVisible(True,True)
scene.objects['Points-Twins-text'].setVisible(True,False)
# Recherche automatique du port
if port=="auto" or port=="microbit" or port=="uno" or port=="mega":
[device,board] =serial_autoget_port(port)
else:
device = port
board=""
# Mise en place de la communication
twins_serial = serial_getSerialOrNone(device,speed)
if twins_serial is not None:
# twins_serial.set_buffer_size(rx_size = 12800, tx_size = 12800)
scene.objects['Commands']['twins'] = True
scene.objects['Commands']['twins_close'] = False
scene.objects['Commands']['twins_port'] = device
scene.objects['Commands']['twins_speed'] = speed
scene.objects['Commands']['twins_readline'] = ""
if board =="":
scene.objects['Points-Twins-text']['Text'] = "Connection ouverte :\n"+device+" - "+str(speed)+" baud."
else:
scene.objects['Points-Twins-text']['Text'] = "Connection ouverte :\n"+board+"\n"+device+" - "+str(speed)+" baud."
rp_tempo (0.1)
print (twins_serial)
else:
scene.objects['Commands']['twins'] = False
scene.objects['Points-Twins-text']['Text'] = "Port "+device+" pas prêt."
##
# Recherche automatique du port
##
def serial_autoget_port(port):
# USB Vendor ID, USB Product ID
board={'microbit' :[3368, 516],
'uno' :[9025, 67],
'mega' :[9025, 66]}
if port=="auto" or port=="microbit":
for com in comports():
if com.vid == board["microbit"][0] and com.pid == board["microbit"][1]:
return [com.device,"Micro:bit"]
if port=="auto" or port=="uno":
for com in comports():
if com.vid == board["uno"][0] and com.pid == board["uno"][1]:
return [com.device,"Arduino Uno"]
if port=="auto" or port=="mega":
for com in comports():
if com.vid == board["mega"][0] and com.pid == board["mega"][1]:
return [com.device,"Arduino Mega"]
return None
##
# Affiche la liste des ports (communication série)
##
def rp_serie_ports():
for com in comports():
print ("Name : "+str(com.name)+"\n"
+" Device : "+str(com.device)+"\n"
+" Hardware ID : "+str(com.hwid)+"\n"
+" USB Vendor ID : "+str(com.vid)+"\n"
+" USB Product ID : "+str(com.pid)+"\n"
+" USB device location : "+str(com.location)+"\n"
+" USB manufacturer : "+str(com.manufacturer)+"\n"
+" USB product : "+str(com.product)+"\n"
+" Interface-specific : "+str(com.interface))
##
# Création de l'objet serial (communication série)
##
def serial_getSerialOrNone(port,speed):
try:
# return serial.Serial(port,speed, bytesize=100)
return serial.Serial(port,speed)
except:
return None
##
# Fermeture de la communication série
##
def rp_jumeau_close():
global twins_serial
twins_serial.close() # Fermer proprement le port série
scene.objects['Commands']['twins'] = False
scene.objects['Points-Twins-text']['Text'] = "Connection fermée."
# Configuration de la vitesse et des temps
# FIXME : Bug dans le transfert des données
def rp_jumeau_config(speed, temps_avancer, temps_tourner):
global twins_serial
if scene.objects['Commands']['twins']:
serial_msg1 = "CF\n"
twins_serial.write(serial_msg1.encode())
rp_tempo (1)
serial_msg2 = str(speed)+"\n"
twins_serial.write(serial_msg2.encode())
rp_tempo (1)
serial_msg3 = str(temps_avancer)+"\n"
twins_serial.write(serial_msg3.encode())
rp_tempo (1)
serial_msg4 = str(temps_tourner)+"\n"
twins_serial.write(serial_msg4.encode())
rp_tempo (1)
serial_msg5 = "FC\n"
twins_serial.write(serial_msg5.encode())
##
# Envoi d'un message vers la communication série
##
def rp_serie_msg(text):
global twins_serial
text2= text+"\n"
scene.objects['Points-Twins-text']['Text'] = "Communication ...\nEnvoi message : "+text
twins_serial.write(text2.encode())
##
# Mise en écoute de jumeau numérique (figeage de la scène)
##
def twins_listen(cont):
global twins_serial
if scene.objects['Commands']['twins']:
if scene.objects['Commands']['twins_readline'] != "":
scene.objects['Points-Twins-text']['Text'] = "Écoute de la connection\nfigeage de la scène...\nMessage reçu : "+scene.objects['Commands']['twins_readline']
else:
scene.objects['Points-Twins-text']['Text'] = "Écoute de la connection\nfigeage de la scène..."
if cont.sensors['Property'].positive:
if scene.objects['Commands']['twins_listen'] :
serial_msg = twins_serial.readline()
if serial_msg is not None:
scene.objects['Commands']['twins_readline'] = str(serial_msg)
# scene.objects['Points-Twins-text']['Text'] = "Message reçu : "+str(serial_msg)
scene.objects['Commands']['twins_listen'] = False
##
# Réception d'un message de la communication série
##
def rp_serie_rcpt():
# scene.objects['Points-Twins-text']['Text'] = "Écoute de la \nconnection\n figeage de \n la scène"
scene.objects['Commands']['twins_readline'] = ""
scene.objects['Commands']['twins_listen'] = True
while scene.objects['Commands']['twins_readline'] == "":
if scene.objects['Commands']['twins_readline'] != "":
break
# scene.objects['Points-Twins-text']['Text'] = "Connection\nouverte :\n"+scene.objects['Commands']['twins_port']+"\n"+str(scene.objects['Commands']['twins_speed'])+" baud"
return scene.objects['Commands']['twins_readline']
###############################################################################
# Fonction bas niveau
###############################################################################
##
# Atteindre une orientation
##
def applyRotationTo(obj, rx=None, ry=None, rz=None, Local=True):
rres=0.001 # resolution rotation
# x
if rx is not None:
while (abs(rx-obj.worldOrientation.to_euler().x) > rres) :
if obj.worldOrientation.to_euler().x-rx > rres:
obj.applyRotation((-rres, 0, 0), Local)
if rx-obj.worldOrientation.to_euler().x > rres:
obj.applyRotation((rres, 0, 0), Local)
# print ("delta x ",rx-obj.worldOrientation.to_euler().x)
# y
if ry is not None:
while (abs(ry-obj.worldOrientation.to_euler().y) > rres) :
if obj.worldOrientation.to_euler().y-ry > rres:
obj.applyRotation((0, -rres, 0), Local)
if ry-obj.worldOrientation.to_euler().y > rres:
obj.applyRotation((0, rres, 0), Local)
# print ("delta y ",ry-obj.worldOrientation.to_euler().y)
# z
if rz is not None:
while (abs(rz-obj.worldOrientation.to_euler().z) > rres) :
if obj.worldOrientation.to_euler().z-rz > rres:
obj.applyRotation((0, 0, -rres), Local)
if rz-obj.worldOrientation.to_euler().z > rres:
obj.applyRotation((0, 0, rres), Local)
# print ("delta z ",rz-obj.worldOrientation.to_euler().z)