FreeCAD: animacja ruchu tłoka i korbowodu sterowana szkicem

Poniżej widoczna jest prosta, sterowana szkicem animacja tłoka i korbowodu. Nie używa ona w ogóle modułu złożeń. Pozycja tłoka oraz pozycja i kąt obrotu korbowodu bazują na pozycji punktów zawartych w pomocniczym szkicu.

Szybka demonstracja

Otwórz plik conrod-piston-anim.fcstd w FreeCAD-zie i wklej do konsoli Pythona następujący skrypt:

import FreeCAD as App, FreeCADGui as Gui, Part, time, sys, math, Draft
from PyQt4 import QtGui,QtCore

class Animation(object):
def __init__(self):
App.Console.PrintMessage('init')

App.ActiveDocument.recompute()

self.timer = QtCore.QTimer()
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.my_update)
self.timer.start(50)

self.an = 0.1

def my_update(self):
string = '{0}'.format(self.an)
self.an = self.an + 0.01 if self.an < (2 * math.pi) else 0.0

angle = math.degrees(self.an)
App.Console.PrintMessage(str(angle)+" ")
App.ActiveDocument.getObjectsByLabel("drivingskt")[0].setDatum(5,App.Units.Quantity(str(angle)+' deg'))
App.ActiveDocument.recompute()
p1 = App.ActiveDocument.getObjectsByLabel("drivingskt")[0].Shape.Vertexes[0].Point
p2 = App.ActiveDocument.getObjectsByLabel("drivingskt")[0].Shape.Vertexes[1].Point
p1t = p1 + App.Vector(0, 37, 0)
conrodangle = math.degrees(Draft.DraftVecUtils.angle(App.Vector(0, 1, 0),(p1-p2)))
App.ActiveDocument.getObjectsByLabel("Piston")[0].Placement = App.Placement(p1t,App.Rotation(App.Vector(0, 1, 0), 90))
App.ActiveDocument.getObjectsByLabel("Conrod")[0].Placement = App.Placement(p2,App.Rotation(App.Vector(0, 0, 1),conrodangle))

def stop(self):
self.timer.stop()


animation = Animation()

Powinieneś zobaczyć animację. Możesz ją zatrzymać wpisując:

animation.stop()

Jak to zostało zrobione?

Potrzebne są pliki z modelami korbowodu (conrod) i tłoka (piston):

Otwórz je w FreeCAD-zie i utwórz trzeci, pusty plik. Następnie skopiuj ostatnie cechy z drzew cech tłoka i korbowodu. Wklej je do nowo utworzonego pliku – nazwy cech to odpowiednio “Fusion” i “Pocket002”. Potwierdź skopiowanie plików zależnych.

W nowym pliku powinieneś zobaczyć obie części (jak na poniższym zrzucie). Jest kilka drobnych problemów: nie znasz długości korbowodu, pozycji otworu na sworzeń w tłoku, w końcu sam tłok jest obrócony wokół pionowej osi o 90 stopni.
Spróbuj zmienić obrót tłoka regulując wartość “Placement” z karcie Data tab i obserwuj konsolę Pythona. Ustawiając oś obrotu na Y i obracając tłok i 90 stopni powinieneś zobaczyć coś podobnego do:
App.Placement((App.Vector(0, 1, 0),App.Rotation(App.Vector(0, 1, 0), 90))
Pierwszym argumentem jest pozycja tłoka (X, Y, Z), kolejny opisuje oś obrotu (0, 1, 0 to Y), trzecim argumentem jest kąt w stopniach.

Długość korbowodu może zostać zmierzona przy użyciu narzędzi pomiarowych Warsztatu Part. Wybierz dolną ścianę (na stopie) i tworzącą walca otworu na sworzeń.

Jak znaleźć pozycję otworu sworznia w tłoku? Wróć do oryginalnego pliku z tłokiem i poszukaj szkicu użytego do wycięcia otworu lub utworzenia gniazda sworznia.

Zanotuj pozycję szkicu (Sketch004).  Jest on przesunięty -37 mm w kierunku Y. Zauważ, w naszym skrypcie, następującą linię:
p1t = p1 + App.Vector(0, 37, 0)

No koniec, najważniejszy etap, czyli szkic sterujący.Utwórz szkic na płaszczyźnie XY. 

Naszkicuj polilinie jak na powyższym zrzucie (punkt 0, 0 jest środkiem wyimaginowanego wału korbowego, oś pionowa jest osią symetrii cylindra). Zmień więz kąta i obserwuj konsolę Pythona Powinieneś zobaczyć coś takiego:
App.ActiveDocument.Sketch.setDatum(5,App.Units.Quantity('60.000000 deg'))
Zapisz numer więzu (5). Został on użyty w skrypcie w linii:
App.ActiveDocument.getObjectsByLabel("drivingskt")[0].setDatum(5,App.Units.Quantity(str(angle)+' deg'))

Zmień nazwy korbowodu, tłoka i szkicu odpowiednio na Conrod, Piston i drivingskt. Użyjemy wygodnej metody getObjectsByLabel() Ważne: metoda zwraca listę (jeden lub kilka obiektów). Użyj [0] by wybrać pierwszy obiekt, w skrypcie wygląda to następująco:
App.ActiveDocument.getObjectsByLabel("drivingskt")[0].setDatum(5,App.Units.Quantity(str(angle)+' deg'))
App.ActiveDocument.getObjectsByLabel("Piston")[0].Placement = App.Placement(p1t,App.Rotation(App.Vector(0, 1, 0), 90))
App.ActiveDocument.getObjectsByLabel("Conrod")[0].Placement = App.Placement(p2,App.Rotation(App.Vector(0, 0, 1),conrodangle))

Musisz znać nazwy wierzchołków szkicu. Po prostu najedź kursorem na interesujący wierzchołek i obserwuj pasek stanu. Powinieneś zobaczyć jago nazwę i pozycję.

Pozycja tłoka bazuje na górnym wierzchołku (Vertex1 w moim przykładzie – Vertexes[0], bo lista liczona jest od zera):
        p1 = App.ActiveDocument.getObjectsByLabel("drivingskt")[0].Shape.Vertexes[0].Point
        p1t = p1 + App.Vector(0, 37, 0)

        App.ActiveDocument.getObjectsByLabel("Piston")[0].Placement = App.Placement(p1t,App.Rotation(App.Vector(0, 1, 0), 90))

Pozycja korbowodu bazuje na środkowym wierzchołku (Vertex2, Vertexes[1]):
        p2 = App.ActiveDocument.getObjectsByLabel("drivingskt")[0].Shape.Vertexes[1].Point
        App.ActiveDocument.getObjectsByLabel("Conrod")[0].Placement = App.Placement(p2,App.Rotation(App.Vector(0, 0, 1),conrodangle))

Kąt obrotu korbowodu jest obliczony z wykorzystaniem pozycji wierzchołków (Vertex1 i Vertex2) oraz wektora (0, 1, 0)  (kierunku Y):
        p1 = App.ActiveDocument.getObjectsByLabel("drivingskt")[0].Shape.Vertexes[0].Point
        p2 = App.ActiveDocument.
getObjectsByLabel("drivingskt")[0].Shape.Vertexes[1].Point
        conrodangle = math.degrees(Draft.DraftVecUtils.angle(App.Vector(0, 1, 0),(p1-p2)))
        App.ActiveDocument.getObjectsByLabel("Conrod")[0].Placement = App.Placement(p2,App.Rotation(App.Vector(0, 0, 1),conrodangle))

Jak jest zmieniany kąt w szkicu?
Użyłem regulatora czasowego (timera) z bibliotek Qt. Limit czasu został ustawiony na 50 ms:
self.timer.start(50)

Po 50 ms zostaje wywołane my_update:
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.my_update)

self.an i angle jest kątem obrotu wału odpowiednio w radianach (self.an wynosi 0,01 do 6,28 z krokiem 0,01) i stopniach:

        self.an = self.an + 0.01 if self.an < (2 * math.pi) else 0.0
        angle = math.degrees(self.an)

To wszystko. Baw się dobrze i zaglądaj na forum FreeCAD-a i społeczność Google+!

    Inspiracja
    FreeCAD Python API

    FreeCAD
    Version: 0.14.3653 (Git)

    Dodaj komentarz