reachy_ritable / scripts /generation_mouvement.py
ArthurPch
commentaires generation mouvement
48472f0
Raw
History Blame Contribute Delete
4.83 kB
import json
import math
#Identifie l'émotion grace à une combinaison de muscles faciaux
def trouver_emotion(donnees):
if donnees.get("mouth_smile", 0) > 0.15:
return "Joie"
elif (donnees.get("brow_outer_up", 0) > 0.08 and
donnees.get("eye_wide", 0) > 0.08 and
donnees.get("mouth_open", 0) > 0.08):
return "Surprise"
elif (donnees.get("brow_outer_up", 0) > 0.05 and
donnees.get("eye_wide", 0) > 0.05 and
donnees.get("mouth_open", 0) > 0.05):
return "Peur"
elif donnees.get("brow_inner_up", 0) > 0.15:
return "Tristesse"
elif (donnees.get("brow_furrow", 0) > 0.15 and
donnees.get("mouth_press", 0) > 0.1):
return "Colere"
return "Neutre"
# Génère les trajectoires des antennes du robot pour exprimer une émotion.
def calculer_cibles_antennes(emotion, temps_ecoule):
if emotion == "Joie":
bouge = math.radians(30 * math.sin(2 * math.pi * 0.5 * temps_ecoule))
return 0.0, bouge, 0.0, bouge
elif emotion == "Colere":
tremble = math.radians(6 * math.sin(2 * math.pi * 8 * temps_ecoule))
return math.radians(20), math.radians(-70) + tremble, math.radians(20), math.radians(70) - tremble
elif emotion == "Peur":
tremble = math.radians(6 * math.sin(2 * math.pi * 10 * temps_ecoule))
return 0.0, math.radians(-160) + tremble, 0.0, math.radians(160) - tremble
elif emotion == "Surprise":
x = math.radians(15 * math.sin(2 * math.pi * 3 * temps_ecoule))
y = math.radians(10 * math.cos(2 * math.pi * 3 * temps_ecoule))
return 0.0, x + y, 0.0, -(x - y)
elif emotion == "Tristesse":
ratio = min(temps_ecoule / 2.0, 1.0)
return 0.0, math.radians(-160 * ratio), 0.0, math.radians(160 * ratio)
return 0.0, 0.0, 0.0, 0.0
# Fonction de danse d'attente
def calculer_danse_antennes(temps_ecoule):
vague_x = math.radians(45 * math.sin(2 * math.pi * 2.5 * temps_ecoule))
vague_y = math.radians(45 * math.cos(2 * math.pi * 2.5 * temps_ecoule))
return vague_x, vague_y, vague_y, vague_x
def adoucir_mouvement(position_actuelle, position_cible, vitesse):
return position_actuelle + vitesse * (position_cible - position_actuelle)
# Converti un JSON de signaux en JSON de mouvements.
def generer_mouvement(input_json, output_json):
with open(input_json, 'r', encoding='utf-8') as f:
donnees_video = json.load(f)["face_data"]
frames_robot = []
emotion_validee = "Neutre"
emotion_en_cours = "Neutre"
confirmations = 0
chronometre_emotion = 0.0
if not donnees_video:
return
image_depart = donnees_video[0]
tete_p, tete_y, tete_r = image_depart.get("pitch", 0.0), image_depart.get("yaw", 0.0), image_depart.get("roll", 0.0)
ant_g_p, ant_g_r = 0.0, 0.0
ant_d_p, ant_d_r = 0.0, 0.0
for frame in donnees_video:
if not frame["face_detected"]:
continue
temps_actuel = frame["timestamp"]
emotion_detectee = trouver_emotion(frame)
if emotion_detectee == emotion_en_cours:
confirmations += 1
else:
emotion_en_cours = emotion_detectee
confirmations = 1
# Validation du changement d'état émotionnel
if confirmations >= 5 and emotion_en_cours != emotion_validee:
emotion_validee = emotion_en_cours
chronometre_emotion = temps_actuel
temps_animation = temps_actuel - chronometre_emotion
cible_tete_p, cible_tete_y, cible_tete_r = frame["pitch"], frame["yaw"], frame["roll"]
cible_ag_p, cible_ag_r, cible_ad_p, cible_ad_r = calculer_cibles_antennes(emotion_validee, temps_animation)
tete_p = adoucir_mouvement(tete_p, cible_tete_p, vitesse=0.6)
tete_y = adoucir_mouvement(tete_y, cible_tete_y, vitesse=0.6)
tete_r = adoucir_mouvement(tete_r, cible_tete_r, vitesse=0.6)
ant_g_p = adoucir_mouvement(ant_g_p, cible_ag_p, vitesse=0.5)
ant_g_r = adoucir_mouvement(ant_g_r, cible_ag_r, vitesse=0.5)
ant_d_p = adoucir_mouvement(ant_d_p, cible_ad_p, vitesse=0.5)
ant_d_r = adoucir_mouvement(ant_d_r, cible_ad_r, vitesse=0.5)
frames_robot.append({
"timestamp": temps_actuel,
"head": {"pitch": tete_p, "yaw": tete_y, "roll": tete_r},
"body_yaw": 0.0,
"antennas": {
"left": {"pitch": ant_g_p, "roll": ant_g_r},
"right": {"pitch": ant_d_p, "roll": ant_d_r}
}
})
with open(output_json, 'w', encoding='utf-8') as f:
json.dump({"mouvements": frames_robot}, f, indent=4)
if __name__ == "__main__":
generer_mouvement("../data/signaux_extraits.json", "../data/mouvement_reachy.json")