Catia V5 - python générateur de profil d'aile

Créer une courbe dans CATIA V5 à partir d’un fichier de coordonnées XY

Une question qui revient souvent

Une question qui revient souvent dans le monde des utilisateurs de profils d’aile (ou airfoils in English):

  • Concepteurs d’avions grandeur
  • aéromodélistes
  • concepteur d’éolienne
  • créateurs de planche de surf

Le début

Cela commence par le choix du profil. Quelques logiciels et sites internet comme AirfoilTools.com nous permettent de télécharger les coordonnées cartésiennes des points définissants l’extrados et l’intrados des profils.(naca4418-il) NACA 4418 - NACA 4418 airfoil - Catia generateur de profil python

En aérodynamique, un profil est défini comme suit:

  • L’origine du profil est donné comme étant le point de tangence entre le bord d’attaque du profil et une verticale.
  • La longueur du profil est normalisée sur une abscisse sans dimension (le profil s’étend donc de 0 à 1 du bord d’attaque vers le bord de fuite).
  • Les ordonnées sont données pour l’extrados puis pour l’intrados de façon proportionnelle à l’abscisse (également sans dimension dans la table)
  • Le profil est orienté selon la corde de profil (la distance la plus longue entre le bord d’attaque et le bord de fuite) qui devient donc l’axe des abscisses

Cela donne un fichier structuré de la façon suivante:

Les coordonnées XY des deux courbes sont données l’une après l’autre en partant du bord de fuite pour décrire l’Extrados jusqu’au bord d’attaque puis l’Intrados vers le bord de fuite.

NACA 4418
1.0000     0.0019  Point final du Bord de fuite de l’EXTRADOS 
0.9500     0.0189  |
0.9000     0.0346  |
…                  |
…                  | (Abscisses décroissantes)
0.0250     0.0500  |  
0.0125     0.0376  |
0.0000     0.0000  Point origine du profil (Bord d’attaque)
0.0125     -0.0211 |
0.0250     -0.0299 |
…                  |
…                  |
0.7000     -0.0245 |
0.8000     -0.0167 | (Abscisses croissantes)
0.9000     -0.0093 |
0.9500     -0.0055 |
1.0000     -0.0019 Point final du Bord de fuite de l’INTRADOS

C’est le format proposé par défaut sur Airfoil tools (Lednicer format)

 

Important:

Vos fichiers de points doivent absolument avoir cette structure (format Selig qui est différent de Lednicer) pour que le programme puisse fonctionner, vous pouvez ajouter des lignes de commentaire en en-tête mais veillez à ce que la dernière ligne soit bien les dernières coordonnées du profil (pas de retour chariot après la dernière ligne).

Naca 4418 Selig format - catia génération de profil

Pas si facile

Catia comme ses concurrents n’offre pas nativement de fonction permettant de créer une courbe à partir d’un fichier de coordonnées nodales… Dommage, il faut donc passer par une macro pour faire cela.

Comment s’y prendre:

  • Soit réaliser un CatScript ou une VBScript
  • Soit comme ici mixer un peu de Python et de VBScript

Dans cette excellente et très instructive présentation de son logiciel  Decade  , Thomas Paviot  nous explique comment l’utilisation de la passerelle win32com nous permet d’atteindre CatiaV5 depuis l’extérieur (ici Python) et de le piloter à l’aide d’instructions du type CatVba.

L’utilisation dans le détail:

Python doit être installé sur votre machine Windows ainsi que win32com.
Rien de plus facile mais il faut installer d’abord Python (choisir votre version 2.x ou 3.x) puis installer la version de win32com correspondant en second lieu).

Vous devez avoir créé un répertoire de travail dans lequel doit être déposé les programmes Python que vous pouvez télécharger en bas de page.
Sous ce répertoire doit se trouver le répertoire dans lequel vous déposerez vos fichiers texte définissant vos profils (ici NACA dans lequel on trouve Naca4418.txt récupéré sur Airfoiltools).

Catia doit être lancé (il n’y a pas de Catpart à charger en prérequis)

Lançons ensuite le programme principal 01_Createur_profil.py (Vous trouverez un lien en bas de page pour récupérer les programmes python).

Catia V5 - python générateur de profil d'aile code

Ce programme appelle les sous-programmes permettant de :

  • Lire le fichier texte du profil et créer les listes de coordonnées XY que le fichier en contient soit extrados et intrados ( _Recup_profil.py et _lect_profil.py )
  • Créer une Catpart avec les set géométriques nécessaires ( _NewPart_profil.py  )
  • Créer les courbes de Bézier passant par les points de définition de chaque courbe ( _Courbe_TxtCv5.py )

A la fin du traitement, on obtient une Catpart présentant:

  • un profil de 100 mm constitué de 2 courbes de Bézier désignée Spline_Extrados et Spline_Intrados.
  • Les points sont dans des sets géométriques que l’on peut cacher.
  • La Catpart est nommée Profil_[Nom du profil.txt] et est sauvegardée dans le répertoire de travail
  • Les deux courbes sont publiées pour une utilisation future.
Catia V5 - python générateur de profil d'aile Extrados et intrados splines

A partir de cette base, on peut simplement dupliquer les courbes et les placer plus loin comme ici avec une opération scale et tirer deux peaux entres les courbes d’extrados et d’intrados. Il est tout aussi facile de rajouter une rotation du profil externe pour vriller l’aile (ou la pale).

Catia V5 - python générateur de profil d'aile création de la peau de l'aile

Bref, le plus dur est fait, à vous de jouer pour le reste avec amusement et créativité.

Avant de finir, je vous conseille de créer votre aile, pale d’hélice, safran, etc… dans une autre catpart en lien avec la/les “part profil” comme cela si vous voulez changer un ou plusieurs profils cela se fera simplement en re-pointant vers une autre part profil et la magie s’opèrera facilement le temps d’un Update).

En images animées cela donne ceci:

Les programmes Python

Le programme principal à la loupe:

Je n’ai pas voulu surcharger le programme Python avec une IHM ou une quelconque interactivité.
Vous pouvez bien sûr l’améliorer si bon vous semble.
Ici pour vos besoins du jour, il faudra juste éditer ce programme avec votre éditeur Python préféré (IDLE par exemple) et modifier deux variables:

  • La variable Chemin_txt_profil = « NACA » donne le nom du répertoire dans lequel se trouve les profils en fichier text. Si vous utilisez autrechose que du NACA, créez un autre répertoire et changez la valeur de la variable.
  • La variable  Nom_profil = « NACA4418 » donne le nom du fichier txt à utiliser dans le répertoire de profils ici une classique NACA4418.

et ensuite F5 pour lancer l’exécution… Enjoy !

# -*- coding: ISO-8859-1 -*-

####################################################################
#                                                                  #
#   Programme permettant de tracer un profil d'aile dans Catia V5  #
#   à partir d'un fichier texte de coordonnées XY donné            #
#                                                                  #
#                                               PSX59              #
#                               Apprendre-la-CAO.com               #
####################################################################

import sys, os
from _NewPart_profil import Cree_NewPart_profil
from _Recup_profil import Recup_profil



# Recupère le répertoire de travail 

try:
 dir_path = os.path.dirname(os.path.abspath(__file__))
except NameError: # We are the main py2exe script, not a module
 import sys
 dir_path = os.path.dirname(os.path.abspath(sys.argv[0]))

print 'repertoire de travail: \n',dir_path

# Définition du répertoire de stockage des profils
Chemin_txt_profil = "NACA"

# Définition du nom du profil à tracer dans CV5
Nom_profil = "NACA4418"

#######################
# Programme principal #
#######################

#Cree une nouvelle part avec les sets geom prédéfinis
Cree_NewPart_profil(dir_path,"Profil_"+Nom_profil,"Profil_"+Nom_profil)
print ("Part creee")

#Recupération du profil  et creation dans catia
Recup_profil(Nom_profil,"Profil_"+Nom_profil,"Profil_"+Nom_profil,dir_path+"//"+Chemin_txt_profil)

print ("Profil "+Nom_profil+" cree et Catpart sauvegardee dans le repertoire de travail")

_NewPart_profil.py à la loupe:

# -*- coding: ISO-8859-1 -*-


def Cree_NewPart_profil(Chemin,Nom_part,Nom_set):

    

    import win32com.client

    CATIA=win32com.client.Dispatch('catia.application') #->la communication est établie

    PartDoc = CATIA.Documents.Add("Part")

    partDocument1 = CATIA.ActiveDocument

    #recup nom de la part

    Nom_ProvisoirComplet_CATPart = partDocument1.Name

    Coupure_Nom_provisoir_CATPart = Nom_ProvisoirComplet_CATPart.split(".")

    Nom_prov_CatPart = Coupure_Nom_provisoir_CATPart[0]

    #change le nom de la part

    part1 = partDocument1.Part

    parameters1 = part1.Parameters

    Nom_parametre = str(Nom_prov_CatPart) + "\Référence"



    strParam1 = parameters1.Item(Nom_parametre)

    strParam1.Value = Nom_part

    #creation du set geom pour le profil

    hybridBodies1 = PartDoc.Part.HybridBodies
    Set_Import = hybridBodies1.Add()
    print Nom_set
    Set_Import.Name = Nom_set

    part1.Update()



    # Sauvegarde de la part
    #print Chemin + "\\" + Nom_part + ".CATPart"
    partDocument1.SaveAs(Chemin + "\\" + Nom_part + ".CATPart")
    

_Recup_profil.py à la loupe:

# -*- coding: cp1252 -*-

from _lect_profil import lect_profil
from _Courbe_TxtCv5 import Courbe_CV5

def Recup_profil(Nom_profil,Set_geom, Nom_part, Rep):
    Chemin_Fich = Rep + "\\" + Nom_profil + ".txt"
    print Chemin_Fich
    Coord_Nds_Txt = lect_profil(Chemin_Fich) #On lit le fichier texte
    print len(Coord_Nds_Txt)
    Nom_courbes = ['Extrados','Intrados']
    a = 0
    for Liste in Coord_Nds_Txt: #pour chacune des deux courbes...
        if Liste==[]:
            pass
        else:
            Courbe_CV5(Nom_courbes[a] , Liste,   Set_geom, Nom_part) #On crée les courbes dans Catia
            a = a + 1
    return 'profil ',Nom_profil,' charge'

_lect_profil.py à la loupe:

# -*- coding: ISO-8859-1 -*-


def lect_profil(Chemin_Fich):

    #lect_profil("G:/Etudes_avions/Sites_web/Apprendre_la_CAO/Sujets/Profil_aile/NACA/NACA4418_airfoiltools.txt")
    Fichier_profil = open(Chemin_Fich, 'r')
    Liste_ligne = Fichier_profil.readlines()

    Nb_lignes = len (Liste_ligne)

    print ("nombre de lignes dans le fichier : " + str(Nb_lignes))

    Liste1 = [] #extrados
    Liste2 = [] #intrados

    
    Liste_coord = [Liste1, Liste2]

    X = 1
    
    a = 0 #Numéro de ligne
        

    while a <  Nb_lignes:
        print 'ligne N°',a
        Elem_ligne = Liste_ligne[a].split()
        print '--->', Elem_ligne
        try:
            premier_elem = round(float(Elem_ligne[0]),6)
            second_elem = round(float(Elem_ligne[1]),6)
        except:
            print 'ligne inutile'
            print 'ligne decoupée',Elem_ligne
            a = a + 1


        else:
            deltaX = X - premier_elem #X est l'ancienne valeur d'abscisse et premier_elem est l'abscisse actuelle
            X = premier_elem
            Y = second_elem

            if deltaX >= 0: #Abscisses décroissantes ?
                Liste1.append([X,Y])
                print 'Liste1 -->',[X,Y]
                a=a+1

            if X == 0.000: #lorsque l'on tombe sur le point origine on le duplique en l'ajoutant à la liste2
                Liste2.append([0.00,0.00])
                
            if deltaX < 0: #Abscisses croissantes ?
                Liste2.append([X,Y])
                print 'Liste2 -->',[X,Y]
                a=a+1
                
                
    return Liste_coord

_Courbe_TxtCv5.py à la loupe:

# -*- coding: ISO-8859-1 -*-


import win32com.client


def Courbe_CV5(a , Liste, Set_geom, Nom_part):
        CATIA=win32com.client.Dispatch('catia.application') #->la communication est établie

        PartDoc = CATIA.ActiveDocument
        part1 = PartDoc.Part

        sel = PartDoc.Selection
        sel.Clear()
        #ouvre le SET geom du profil
        hybridBodies1 = PartDoc.Part.HybridBodies
        hybridBody_import = hybridBodies1.Item(Set_geom)
        hybridBodies2 = hybridBody_import.HybridBodies
        #cree un set pour la courbe
        hybridBody_Courbe = hybridBodies2.Add()
        hybridBody_Courbe.Name = "Courbe_" + a

        if Liste==[]:
            pass
        else:
            hybridShapes1 = hybridBody_Courbe.HybridShapes
            b = 1
            for Coord in Liste:
                X = Coord[0]*100 # modifiez ici si vous voulez modifier l'échelle du profil (ici 100 fois plus grand soit 100mm de long) Rappel: le profil à une longueur de 1 (sans unité). Si le fcteur vaut 1 alors cela fera 1mm dans catia
                Y = Coord[1]*100 # idem
                Point1 = part1.HybridShapeFactory.AddNewPointCoord(X, Y, 0) #cree le point de ccord XY
                hybridBody_Courbe.AppendHybridShape(Point1)
                sel.Add(Point1)
                Point1.Name = "Point_" + str(b) # renomme le point
                part1.UpdateObject(Point1)
                b = b + 1
        
        Nb_pt_dans_set = hybridShapes1.Count #compte les points
        print 'Nb points = ',Nb_pt_dans_set 

        hybridShapeSpline1 = part1.HybridShapeFactory.AddNewSpline() #cree une spline vide
        hybridShapeSpline1.SetSplineType(0)
        hybridShapeSpline1.SetClosing(0)
        hybridShapeSpline1.Name = "Spline_" + str(a) # Nomme la spline
        # Je n'ai pas ajouté de tangence verticale au point d'origine (normale au plan XY), il y aura donc une vraie arête au bord d'attaque à imposer manuellement dans catia sur chaque spline ou ajouter une contrainte dans ce script

        nb = 1
        while nb < Nb_pt_dans_set +1 :
                hybridShapePointOnPlane1 = hybridShapes1.Item("Point_" + str(nb)) # appel le point par son nom
                reference1 = part1.CreateReferenceFromObject(hybridShapePointOnPlane1)
                hybridShapeSpline1.AddPoint(reference1) #ajoute le point à la spline
                nb = nb + 1
                
        hybridBody_import.AppendHybridShape(hybridShapeSpline1) #ajoute la spline au set geom
        part1.UpdateObject(hybridShapeSpline1)

        #Publication des courbes

        PartDoc = CATIA.ActiveDocument

        product1 = PartDoc.GetItem(Nom_part)
        publications1 = product1.Publications

        Nom_publication = Nom_part+"_Courbe_" + a
        publication1 = publications1.Add(Nom_publication)

        Nom_courbe = Nom_publication+"/!Spline_" + a

        reference1 = product1.CreateReferenceFromName(Nom_courbe)
        
        publications1.SetDirect (Nom_publication, reference1)

        product1.update()    

        #Sauvegarde du profil

        PartDoc.Save()

C’est fini : )

Vous pouvez facilement et gratuitement recopier les programmes Python ci-dessus. Vous pouvez également les arranger à votre goût et vous en inspirer.

J’espère que cet article vous a aidé à concevoir et vous a fait gagner du temps.
Si vous l’avez aimé, n’hésitez pas à partager sur les réseaux sociaux et me laisser un commentaire en bas de page.

12 Responses

  1. Merci pour le sujet c’est très instructif sur tout pour la programmation VBSCRIPT et PYTHON.
    J’utilise une autre approche
    1- conception sur Alias studio Tools
    2-translation sur UGS NX
    3- conception des nervures d’ailes par intersection Plans/Surfaces d’ailes
    4- traitement des nervures en Pars
    5- Translation sur INVENTOR HSM
    6- Création des programmes de FAO par assemblage et nesting des nervures
    7- Fabrication des nervures sur CN
    J’ai réalisé la structure d’un PULSARE ainsi que la conception et la fabrication d’un CANOE CANADIEN le « CARIBOU »
    le lien youtube
    https://www.youtube.com/watch?v=B4kLbwuUPLc&feature=youtu.be

    • Bonjour Abdelhamid,
      Merci pour ce commentaire et bravo pour vos réalisations.
      Je vois que nous partageons les mêmes passions.
      Bravo pour vos réalisations, j’ai brièvement regardé vos vidéos sur Youtube.
      Votre démarche de conception est intéressante. Elle met en œuvre beaucoup de logiciels et de passerelles mais le résultat est là, c’est bien le principal.
      Cela montre également qu’il existe maintenant de nombreuses solutions CAO et CFAO.
      Je suis en train de mettre à disposition des articles concernant la CFAO sur Catia V5.

  2. Bonjour,
    Lorsque je lance le programme, il me met une syntaxError « Missing Parentheses in call to ‘print’ et je ne comprend pas pourquoi!

    • Bonjour Philippe,
      Merci pour votre retour.
      Je pense qu’il s’agit simplement d’un problème de version de Python. En effet, j’ai peut être oublié de le préciser mais le programme est écrit en Python 2.7 et la fonction « print » ne demande pas de parenthèses alors qu’en Python 3.4 il en faut. Vérifiez dans votre message d’erreur, mais cela doit être le cas.
      Il y a quelques différences entre la version 2.x et la version 3.x au niveau de la syntaxe. Le plus simple serait peut être que vous installiez Python 2.7 à coté de la 3.4.
      Il faut cependant faire attention au fait que votre PC lance bien la 2.7 (voir dans system/path) lorsque vous exécutez le *.py . Ou alors vous désinstallez la 3.x pour laisser seule la 2.7.

  3. Bonjour,

    Je voudrais faire une aile d’avion mais ce que vous expliquez en macro est incompréhensible.
    Comment pourrez faire une aile sur catia svp?

    • Bonjour Badara,
      Oui, en effet cet article montre comment obtenir un profil d’aile à partir d’un fichier de coordonnées à l’aide d’une macro.
      Vous n’avez pas forcément besoin d’utiliser une macro pour dessiner les profils de l’aile.
      Il suffit de tracer dans une esquisse tous les points du profil de votre choix puis de relier les points avec une courbe (spline) pour tracer l’extrados et l’intrados.
      C’est un peu long mais faisable.
      Une fois que vous avez les profils aux bons endroits, vous pouvez tendre une peau entre ces profils; cela vous donnera votre aile.

      • Bonjour PSX59 (je vais t’appeler Chef vu que tu t’y connais mieux que moi),

        Merci pour ta réaction si rapide.
        Y aurait-il pas une vidéo qui illustre ça sur catia, parce que j’ai vu et lue le lien mais ça ne m’aide vraiment pas.

        • En fait, je n’ai rien dans l’immédiat pour illustrer cela mais je pourrai faire un article là dessus si ce n’est pas trop pressant.
          J’ai compris que votre objectif est de faire la surface d’une aile à partir de profils. C’est bien cela ?

          • Bonjour Chef,
            Vous avez très bien compris, mon objectif est de pouvoir faire la surface d’aile, le fuselage d’un avion à partir de profil..

  4. Bonsoir,
    Merci pour ce tuto tres interessant.
    Helas, j’utilise CATIA V5.12 et lorsque j’execute le programme 01_Createur_profil, j’obtiens seulement Part1.
    Il me semble que cela bloque sur Hybridbodies, qui n’existe pas dans CATIA V5.12.
    Est-il possible d’utiliser directement Courbe ?

    • Bonjour,
      Merci pour ce retour.
      En R12, je pense les « sets géométriques » (=HybridBodies) existaient déjà.
      Il faut savoir où cela bloque précisément (quel sous programme et quelle ligne).
      Pourriez vous m’envoyer le message d’erreur de Python ?

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.