Pages : 1
#1 Le 14/10/2007, à 18:55
- L. Grondin
animation moteur rotatif à quatre chambres
Bonjour,
j'ai réussi à écrire un truc pour modèliser géométriquement une quasiturbine
(http://quasiturbine.promci.qc.ca/).
Nécessite bc, plotutils, imagemagick et mplayer.
On peut changer les paramètres a et b dans le code
pour modifier la taille du rotor et l' "exentricité" du stator.
Ca m'a pris tout le WE, mais j'suis assez fier du résultat
#!/usr/bin/sh
export BC_LINE_LENGTH=1000
output="quasiturbine.avi"
bc -ql <<EOF |sh
pi=3.14159265359
a=0.3
b=0.4
c=4
define phi(arg) {
return pi/4*(1+a*c(2*arg))
}
define r(arg) {
return c(phi(arg))
}
reso=50
print "cat << FIN_STATOR > /tmp/stator\n"
print "1 0 ", r(0), " 0\n"
for(k=0;k<4*reso;k++) {
theta = pi/2*k/reso
r = r(theta)-b/2
dr = a*pi/2*s(2*theta)*s(phi(theta))
n = sqrt( r^2 + dr^2 )
print r*(1+b/2/n)*c(theta)+b/2*dr/n*s(theta), " "
print r*(1+b/2/n)*s(theta)-b/2*dr/n*c(theta), "\n"
}
print c(theta), " ", r*(1+b/2/n)*s(theta)-b/2*dr/n*c(theta), "\n"
while(k--) {
theta = pi/2*k/reso
print c(theta), " ", s(theta), "\n"
}
print "FIN_STATOR\n"
reso=100
for(k=0;k<reso;k++) {
print "cat << FIN_ROTOR > /tmp/rotor\n"
for(j=0;j<c;j++) {
theta = pi/4+pi/2*(j+k/reso)
cos = c(theta)
sin = s(theta)
x1 = (r(theta)-b/2)*cos
y1 = (r(theta)-b/2)*sin
x2 = -(r(theta+pi/2)-b/2)*sin
y2 = (r(theta+pi/2)-b/2)*cos
for(i=0;i<reso;i++) {
gamma = theta - phi(theta) - (pi - pi/6/2) + (2*pi - pi/6)*i/reso
print x1 + b/4*c(gamma), " ", y1 + b/4*s(gamma), "\n"
}
for(i=0;i<reso;i++) {
gamma = theta - phi(theta) - 3*pi/4 + pi*i/reso
print x2 + b/2*c(pi+gamma), " ", y2 + b/2*s(pi+gamma), "\n"
}
for(i=0;i<reso;i++) {
gamma = theta - phi(theta) - 3*pi/4 + pi - 3*pi/2*i/reso
print x2 + b/4*c(pi+gamma), " ", y2 + b/4*s(pi+gamma), "\n"
}
print x2 + b/2*c(pi+gamma), " ", y2 + b/2*s(pi+gamma), "\n"
print x1 + b/4*c(theta - phi(theta) - (pi - pi/6/2)), " ", y1 + b/4*s(theta - phi(theta) - (pi - pi/6/2)), "\n"
print "\n"
}
print "FIN_ROTOR\n"
print "graph -T png -g 0 -q .4 -x -1 1 -y -1 1 --blankout 0.0 /tmp/stator -C "
print "--reposition 0 0 1 -q .2 /tmp/rotor "
print "|convert - img-", reso+k, ".jpg"
print "\n"
}
quit
EOF
mencoder "mf://img-*.jpg" -mf fps=45:type=jpeg -ovc copy -oac copy -o $output
rm -f *.jpg /tmp/stator /tmp/rotor
mplayer $output -loop 0
#2 Le 20/10/2007, à 21:12
- olleg
Re : animation moteur rotatif à quatre chambres
C'est enorme ce que tu as fait. félicitation.
Bel exemple de code.
MSI S260, Pentium M740, 1,5Go de RAM, 60Go de DD. Ubuntu 9.04
Zotac geforce 9300-itx wifi + SG05 + Intel E8400 + 4Go de RAM. Ubuntu 9.04
Hors ligne
#3 Le 28/10/2007, à 13:08
- eric42
Re : animation moteur rotatif à quatre chambres
Bonjour,
J'ai du rater quelque chose mais je n'arrive pas à éxécuter ton script.
J'ai copier le code que j'ai collé dans un fichier texte que j'ai enfin rendu exécutable.
Rien ne se passe.
Merci d'avance.
Eric
#4 Le 29/10/2007, à 11:21
- jeremix
Re : animation moteur rotatif à quatre chambres
Salut, idem que eric42.
Un p'tit coup de pouce svp
ubuntucounter user 8236
Hors ligne
#5 Le 29/10/2007, à 11:28
- eric42
Re : animation moteur rotatif à quatre chambres
En collant le code directement dansun terminal voilà le résultat :
sh: graph: not found
convert: missing an image filename `img-100.jpg'.
sh: graph: not found
convert: missing an image filename `img-101.jpg'.
sh: graph: not found
sh: graph: not found
convert: missing an image filename `img-199.jpg'.
eric@eric-desktop:~$
eric@eric-desktop:~$ mencoder "mf://img-*.jpg" -mf fps=45:type=jpeg -ovc copy -oac copy -o $output
MEncoder 2:1.0~rc1-0ubuntu13 (C) 2000-2006 MPlayer Team
CPU: Intel(R) Pentium(R) 4 CPU 2.93GHz (Family: 15, Model: 4, Stepping: 1)
CPUflags: Type: 15 MMX: 1 MMX2: 1 3DNow: 0 3DNow2: 0 SSE: 1 SSE2: 1
Compiled with runtime CPU detection.
success: format: 16 data: 0x0 - 0x0
MF file format detected.
[mf] search expr: img-*.jpg
============ Sorry, this file format is not recognized/supported =============
=== If this file is an AVI, ASF or MPEG stream, please contact the author! ===
Cannot open demuxer.
Exiting...
eric@eric-desktop:~$ rm -f *.jpg /tmp/stator /tmp/rotor
eric@eric-desktop:~$ mplayer $output -loop 0
Je vais vérifier que les programmes nécessaires soient correctement installés et je vous tiens au courant.
Eric
#6 Le 04/11/2007, à 13:42
- L. Grondin
Re : animation moteur rotatif à quatre chambres
Bonjour,
ravi de voir que ce truc interesse du monde.
l'erreur "graph : not found" signifie que le package plotutils n'est pas installé.
sinon dans l'entête il vaut mieux mettre #!/usr/bin/bash plutôt que #!/usr/bin/sh.
Normalement il suffit de copier dans un fichier texte "qt.sh" et de taper
$ bash qt.sh
attention à ce que lors du copier/coller le navigateur n'ajoute pas des "> " à chaque début
de ligne..
le calcul et la création de l'anim prend environ 20 secondes.
Il y a quelques erreurs dans le code que j'ai envoyé :
tout n'est géométriquement pas tout à fait exact.
Enfin j'ai persévéré, j'ai corrigé quelques erreurs dans le code
et surtout j'ai écrit la même chose en mieux et avec python pour
faire un modèle 3D :
http://picasaweb.google.fr/grondilu/quasiturbine
je vais essayer d'animer la version 3D maintenant...
#7 Le 04/11/2007, à 14:26
- eric42
Re : animation moteur rotatif à quatre chambres
Bonjour,
C'est vrai qu'avec les bonnes dépendances celà fonctionne.
Très intéressant ton travail, je me pose quelques questions les forces ne vont elles pas s'annuler ?
L'axe principal permettant de transmettre le mouvement rotatif est composé des quatre axes des bielles ?
Les lobbys ont complètement ruiné la créativité" et l'invitivité ...
Merci de ton complément d'informations.
Eric
#8 Le 04/11/2007, à 19:55
- L. Grondin
Re : animation moteur rotatif à quatre chambres
Salut,
en parlant de forces qui s'annulent,
je suppose que tu te demandes si la force crée lors de la détente peut
l'emporter sur celle nécessaire à la compression. Bah à priori oui puisque
la détente est en fait une explosion où l'énergie chimique du combustible
entre en jeu... Sans parler du fait que le système peut fonctionner à l'air comprimé,
auquel cas il n'y a pas de phase de compression.
Mais bon la page de wikipedia décrit tout ça très bien :
http://fr.wikipedia.org/wiki/Quasiturbine
Les liens qui s'y trouvent dirigent aussi vers des vidéos où on voit des prototypes fonctionner
à l'air comprimé (d'après wikipedia à ce jour aucun prototype n'a jamais
été montré en fonctionnant comme un moteur à explosion)
Concernant la transmission du mouvement,
c'est une vrai question qui m'a donné du fil à retordre pour faire un modèle 3D.
Les concepteurs initiaux préconisent l'usage de deux manivelles reliées
aux centres des faces du losange. Ne sachant pas ce qu'est exactement
une "manivelle", j'ai préféré ôpter pour un arbre relié aux sommets par des pivots
glissants.
Voici mon code python pour mon modèle 3D sous Blender
(un peu long certes, il doit y avoir moyen de faire plus court...) :
import Blender
from Blender import Scene, Mathutils
from Blender.Mathutils import *
from math import *
scn=Scene.getCurrent()
for ob in scn.objects:
if ob.type == 'Mesh':
scn.unlink(ob)
Blender.Redraw()
# PARAMETRES
a=.3 # "exentricit\'e" du stator
b=.2 # rayon des cylindres de contact
N=200 # r\'esolution angulaire
global_angle=0 # dephasage du moteur
# FONCTIONS
def phi(arg): # angle au sommet du losange
return pi/4*(1+a*cos(2*arg))
def phip(arg): # deriv\'ee premi\`ere de phi
return -a*pi/2*sin(2*arg)
def r(arg): # \'equation polaire des centres des cylindres
return (1-b)*cos(phi(arg))
def rp(arg): # deriv\'ee premi\`ere de r
return -(1-b)*phip(arg)*sin(phi(arg))
# STATOR
angles=[k*2*pi/N for k in range(N)]
statorInterieur2D=[]
statorExterieur2D=[]
for theta in angles:
n=sqrt(r(theta)**2+rp(theta)**2)
statorInterieur2D+=[[cos(theta)*r(theta)*(1+b/n)+b*rp(theta)/n*sin(theta), \
sin(theta)*r(theta)*(1+b/n)-b*rp(theta)/n*cos(theta)]]
statorExterieur2D+=[[cos(theta), sin(theta)]]
verts=[]
for k in range(N):
verts+=[ statorInterieur2D[k]+[0],\
statorInterieur2D[k]+[1],\
statorExterieur2D[k]+[1],\
statorExterieur2D[k]+[0]]
faces=[]
for k in range(0,4*N,4):
faces+=[ [k, (k-4)%(4*N), (k-3)%(4*N), k+1], \
[k, (k-4)%(4*N), (k-1)%(4*N), k+3], \
[k+3, (k-1)%(4*N), (k-2)%(4*N), k+2], \
[k+1, k+2, (k-2)%(4*N), (k-3)%(4*N)] ]
me=Blender.Mesh.New('stator')
me.verts.extend(verts)
me.faces.extend(faces)
stator=Blender.Scene.GetCurrent().objects.new(me, 'stator')
# ROTOR
rotor=[]
alpha=pi/3
for n in range(4):
repere=[]
verts=[]
faces=[]
i=0
za, zb = .025 + n*.25, .225 + n*.25
theta=-pi+alpha/2
for z in 0, 1, za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
theta=-pi+alpha/2
while(theta<pi+alpha/2):
if theta<=pi-alpha/2:
for z in 0, 1, za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
faces.append([i-8,i-6,i-2,i-4])
faces.append([i-5,i-1,i-3,i-7])
faces.append([3,i-1,i-5])
faces.append([2,i-2,i-6])
faces.append([1,i-3,i-7])
faces.append([0,i-4,i-8])
elif theta<pi:
if len(repere)==0:
repere.append(i-4)
theta_backup=theta-2*pi/N
for z in za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
faces.append([3,i-1,i-3])
faces.append([2,i-2,i-4])
faces.append([i-1,i-2,i-4,i-3])
else:
if len(repere)==1:
theta=pi
repere.append(i)
for z in za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
faces.append([3,i-1,i-3])
faces.append([2,i-2,i-4])
theta+=2*pi/N
theta=theta_backup
for z in 0, 1:
verts.append([b*cos(theta),b*sin(theta),z])
i+=1
faces.append([repere[0],repere[0]+1,i-1,i-2])
# repère 2
repere.append(i-2)
for z in 0, 1:
verts.append([b*cos(theta)-b*(1-sin(theta))*sin(theta)/cos(theta),b,z])
i+=1
faces.append([i-1,i-2,i-4,i-3])
for z in 0, 1:
verts.append([b-1,b,z])
i+=1
faces.append([i-1,i-2,i-4,i-3])
theta=pi/2
while theta < 2*pi-alpha/2-pi/2*(1+a):
for z in 0,1:
verts.append([b-1+b*cos(theta),b*sin(theta),z])
i+=1
faces.append([i-1,i-2,i-4,i-3])
theta+=2*pi/N
# repère 3
repere.append(i-2)
theta-=2*pi/N
for z in 0, 1:
verts.append([b-1+b/2*cos(theta),b/2*sin(theta),z])
i+=1
faces.append([i-1,i-2,i-4,i-3])
while theta > 0:
for z in 0, 1:
verts.append([b-1+b/2*cos(theta), b/2*sin(theta),z])
i+=1
faces.append([i-1,i-2,i-4,i-3])
theta-=2*pi/N
za, zb = .025 + (n+1)%4*.25, .225 + (n+1)%4*.25
theta=0
for z in 0, 1, za, zb:
verts.append([b-1+b/2*cos(theta), b/2*sin(theta),z])
i+=1
theta-=2*pi/N
faces.append([i-4,i-3,i-5,i-6])
# repère 4
repere.append(i-4)
thetamax = max(alpha/2-pi/2*(1-a),-pi*a)
while theta > thetamax:
for z in 0, 1, za, zb:
verts.append([b-1+b/2*cos(theta), b/2*sin(theta),z])
i+=1
theta-=2*pi/N
faces.append([i-4,i-2,i-6,i-8])
faces.append([i-1,i-3,i-7,i-5])
theta+=2*pi/N
for z in 0, 1, za, zb:
verts.append([b-1+b*cos(theta), b*sin(theta),z])
i+=1
faces.append([i-4,i-2,i-6,i-8])
faces.append([i-1,i-3,i-7,i-5])
# repère 5
repere.append(i-4)
for z in 0,1,za, zb:
verts.append([3*b/2-1+b/2*sin(alpha/2)/tan(pi/4*(1-a)),-b/2*sin(alpha/2),z])
i+=1
for j in range(4):
faces.append([i-8+j,i-12+j,i-4+j])
k=i-12+j
while k>repere[4]+j:
faces.append([k,k-4,i-4+j])
k-=4
faces.append([i-4,i-2,i-6,i-8])
faces.append([i-1,i-3,i-7,i-5])
faces.append([repere[4]+2,repere[4]+3,i-1,i-2])
za, zb = .025 + n*.25, .225 + n*.25
for z in za, zb:
verts.append([-b/2*(1+sin(alpha/2)/tan(pi/4*(1-a))),-b/2*sin(alpha/2),z])
i+=1
faces.append([i-1,i-2,repere[1],repere[1]+1])
j=repere[1]+2
while (verts[j][1]<verts[j-2][1]):
faces.append([j,j-2,i-2])
faces.append([j+1,j-1,i-1])
j+=2
faces.append([j-2,2,i-2])
faces.append([j-1,3,i-1])
if n<3:
faces.append([i-2,2,0,i-6])
faces.append([i-6,i-4,i-1,i-2])
faces.append([i-4,i-3,3,i-1])
faces.append([3,i-3,i-5,1])
else:
faces.append([i-1,3,1,i-5])
faces.append([i-3,i-2,i-1,i-5])
faces.append([i-3,i-4,2,i-2])
faces.append([i-4,i-6,0,2])
for k in 0, 1:
faces.append([k,repere[0]+k,repere[2]+k, repere[-1]+4+k])
faces.append([repere[4]+k,repere[2]+2+k,repere[2]+k, repere[-1]+4+k])
k=0
while repere[3]-k>=repere[2]+6:
faces.append([repere[3]-k+1,repere[3]-k-1,repere[3]+k+7,repere[3]+k+5])
faces.append([repere[3]-k,repere[3]-k-2,repere[3]+k+6,repere[3]+k+4])
k+=2
k1=repere[3]+k
k2=repere[4]
while k1+4<k2-2:
faces.append([k1+4, k1+2, repere[2]+6])
faces.append([k1+5, k1+3, repere[2]+7])
k1+=2
faces.append([k2, k2-2, repere[2]+2])
faces.append([k2+1, k2-1, repere[2]+3])
k2-=2
for k in 0, 1:
if k1+4<>k2-2:
faces.append([k1+4+k,k2-2+k,repere[2]+6+k,repere[2]+2+k])
else:
faces.append([k1+4+k,k1+2+k,repere[2]+6+k,repere[2]+2+k])
faces.append([k2+k,k2-2+k,repere[2]+6+k,repere[2]+2+k])
theta=n*pi/2+global_angle
R = RotationMatrix(-360*(theta-phi(theta))/(2*pi),4,'z')
T = TranslationMatrix(Vector([r(theta)*cos(theta), r(theta)*sin(theta), 0]))
Verts=[]
for v in verts:
Verts.append(Vector(R*Vector(v)*T))
me=Blender.Mesh.New('rotor_' +str(n))
me.verts.extend(Verts)
me.faces.extend(faces)
rotor.append(Blender.Scene.GetCurrent().objects.new(me, 'rotor_'+ str(n)))
za, zb = .025 + n*.25, .225 + n*.25
i=0
verts=[]
faces=[]
theta=-pi+pi/4*(1-a)
for z in za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
theta=-pi+pi/4*(1-a)
while(theta<pi-pi/4*(1-a)):
for z in za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
faces.append([i-3,i-1,i-2,i-4])
faces.append([1,i-1,i-3])
faces.append([0,i-2,i-4])
theta+=2*pi/N
theta=pi-pi/4*(1-a)
for z in za, zb:
verts.append([b/2*cos(theta), b/2*sin(theta),z])
i+=1
faces.append([i-3,i-1,i-2,i-4])
faces.append([1,i-1,i-3])
faces.append([0,i-2,i-4])
for z in za, zb:
verts.append([b-2*(1-b)*cos(pi/4*(1+a)),b/2*sin(theta),z])
verts.append([b-2*(1-b)*cos(pi/4*(1+a)),-b/2*sin(theta),z])
i+=2
faces.append([i-1,i-2,i-4,i-3])
faces.append([i-1,i-3,0,1])
faces.append([i-1,i-2,i-5,1])
faces.append([i-5,i-6,i-4,i-2])
faces.append([i-4,i-3,0,i-6])
theta=n*pi/2+global_angle
R = RotationMatrix(-360*theta/(2*pi),4,'z')
T = TranslationMatrix(Vector([r(theta)*cos(theta), r(theta)*sin(theta), 0]))
Verts=[]
for v in verts:
Verts.append(Vector(R*Vector(v)*T))
me=Blender.Mesh.New('axe_' +str(n))
me.verts.extend(Verts)
me.faces.extend(faces)
rotor.append(Blender.Scene.GetCurrent().objects.new(me, 'axe_'+ str(n)))
i=0
verts=[]
faces=[]
L=((1-b)*cos(pi/4*(1+a))-b)
l=b/2*sin(pi/4*(1-a))
for x in -L, L:
for y in -b/2, -l, l, b/2:
for z in za-.0125, za, zb, zb +.0125:
verts.append([x,y,z])
i+=1
faces.append([0,16,19,3])
faces.append([3,19,31,15])
faces.append([0,12,28,16])
faces.append([12,28,31,15])
faces.append([5,21,22,6])
faces.append([9,25,26,10])
faces.append([5,9,25,21])
faces.append([22,26,10,6])
for k in 0, 16:
faces.append([0+k,3+k,6+k,5+k])
faces.append([0+k,12+k,9+k,5+k])
faces.append([12+k,15+k,10+k,9+k])
faces.append([15+k,3+k,6+k,10+k])
Verts=[]
for v in verts:
Verts.append(Vector(R*Vector(v)))
me=Blender.Mesh.New('centre_' +str(n))
me.verts.extend(Verts)
me.faces.extend(faces)
rotor.append(Blender.Scene.GetCurrent().objects.new(me, 'centre_'+ str(n)))
Blender.Redraw()
#9 Le 04/11/2007, à 20:45
- eric42
Re : animation moteur rotatif à quatre chambres
Bonjour,
Merci de ces informations complémentaires.
Je reste vraiment pensif sur le moyen de transmettre le mouvement rotatif à un arbre externe.
C'est super ce concept.
Eric
Dernière modification par eric42 (Le 04/11/2007, à 20:46)
#10 Le 08/11/2007, à 07:17
- Brunod
Re : animation moteur rotatif à quatre chambres
Salut, Je pense qu'une "manivelle" est un autre terme pour désigner un villebrequin mais qui peut-être n'aurait qu'un seul pallier.
Brunod
Windows est un système d'exploitation de l'homme par l'ordinateur. Linux, c'est le contraire...
39 pc linux convertis
Hors ligne