Headless FreeCAD/pl

Wprowadzenie

Program FreeCAD można uruchomić bez jego interfejsu graficznego użytkownika (GUI), w trybie powszechnie określanym jako 'headless'. To daje dostęp do różnych efektywnych metod tworzenia skryptów, automatyzacji i osadzania jego możliwości w innych aplikacjach. Ta strona opisuje różne sposoby uruchamiania programu FreeCAD w trybie 'headless'.

Poprzez konsolę Pythona we FreeCAD

To interaktywny tryb, w którym FreeCAD uruchamiany jest bezpośrednio w konsoli Pythona. Ta konsola jest w pełni funkcjonalnym środowiskiem Pythona ze wszystkimi modułami Pythona programu FreeCAD, takimi jak Part, BIM oraz Draft, dostępnymi przez ich publiczne API. Moduł rdzenia FreeCAD jest wbudowany, więc nie trzeba go jawnie importować korzystając z sesji konsoli. Inne moduły można importować w czasie sesji (np. import Part) zgodnie z potrzebami.

Ten tryb można uruchomić z linii poleceń używając FreeCAD -c lub FreeCADCmd. Zapewnia to taką samą funkcjonalność jak konsola Pythona dostępna w pełnej aplikacji FreeCAD.

Najlepiej używać tej opcji do szybkiego testowania kodu Pythona, który korzysta dostępu do API programu FreeCAD lub do debugowania niewielkich skryptów, które można łatwo wkleić w konsolę.

Poprzez skrypt Pythona

W tym trybie, FreeCAD jest używany jako standardowa biblioteka Pythona. Pozwala to na importowanie jego pełnego API Pythona do dowolnego zewnętrznego skryptu Pythona lub aplikacji, traktując go jako natywny moduł.

Aby to uruchomić, interpreter Pythona musi mieć możliwość zlokalizowania pliku biblioteki FreeCAD o nazwie FreeCAD.so na Linux i macOS lub FreeCAD.pyd na innych platformach. Dokonuje się tego poprzez dodanie jego ścieżki do ścieżek wyszukiwania Pythona na samym początku skryptu. Po ustawieniu ścieżki, reszta skryptu może korzystać z dostępu do FreeCAD API jak do dowolnego innego modułu Pythona.

Poniżej znajduje się prosty przykład, który tworzy kostkę i podaje jej objętość oraz pole powierzchni:

# Set the path to your FreeCAD installation
# Example for Linux:
# FREECADPATH = '/usr/lib/freecad/lib'
# Example for macOS:
# FREECADPATH = '/Applications/FreeCAD.app/Contents/Resources/lib'
# Example for Windows:
FREECADPATH = 'C:\\Program Files\\FreeCAD\\bin'
import sys
sys.path.append(FREECADPATH)

# The rest of the script can now import and use the FreeCAD API
import FreeCAD
import Part

# Create a simple geometric shape
my_box = Part.makeBox(10, 20, 30)

# Access its properties
print(f"The volume of the box is: {my_box.Volume}")
print(f"The area of the box is: {my_box.Area}")

Aby uruchomić przykładowy skrypt, zapisz kod w pliku (np. run_box.py) i wykonaj go w terminalu systemowym za pomocą interpretera języka Python:

$ python run_box.py
The volume of the box is: 6000.0
The area of the box is: 2200.0

Jest to bardzo efektywne narzędzie, które odblokowuje pełne możliwości programu FreeCAD w zakresie automatyzacji i integracji. Przykładowo, można by napisać skrypt, który korzysta z API zarówno FreeCAD, jak i Blendera do automatycznego importu obiektów z pliku .FCStd bezpośrednio do sceny Blendera.

Zauważ, że ten tryb jest przeznaczony do użycia FreeCAD API bez GUI. Podczas gdy niektóre moduły zorientowane na GUI mogą zostać zaimportowane, użycie API, które korzysta z bezpośredniego dostępu lub manipuluje komponentami GUI jest bardzo ograniczone i generalnie niewspierane w kontekście trybu 'headless'.

Dodatkowe uwagi dotyczące modułów środowisk pracy w trybie bez GUI

W przypadku korzystania z FreeCAD jako biblioteki języka Python w kontekście bez GUI (na przykład za pośrednictwem standardowego interpretera języka Python lub FreeCADCmd), nie wszystkie moduły środowisk roboczych są automatycznie dostępne, nawet jeśli moduły podstawowe FreeCAD można pomyślnie zaimportować.

W szczególności moduły znajdujące się w katalogu Mod/ (takie jak Projekt Części lub podmoduły modułu Część) mogą nie być wykrywane przez Python, chyba że ich ścieżki zostaną wyraźnie dodane do sys.path. Może to prowadzić do sytuacji, w których obiekty dokumentu są ładowane jako typy generyczne (na przykład GeoFeature) zamiast ich typów konkretnych (na przykład PartDesign::Body), lub w których import modułów związanych ze środowiskiem pracy kończy się niepowodzeniem.

Aby zapewnić pełną funkcjonalność, konieczne może być ręczne rozszerzenie ścieżki wyszukiwania języka Python o katalog FreeCAD Mod/ oraz, w niektórych przypadkach, o określone podkatalogi:

import sys

# Example paths (adjust to your installation)
sys.path.append("/usr/lib/freecad/Mod")
sys.path.append("/usr/lib/freecad/Mod/Part")

# Workbench modules can now be imported
import PartDesign
from BOPTools import BOPFeatures

Dokładne ścieżki zależą od platformy i sposobu instalacji.

Ta ręczna konfiguracja gwarantuje, że moduły środowiska pracy można zaimportować, obiekty dokumentów są odtwarzane z zachowaniem właściwych typów, a dodatkowe narzędzia języka Python dołączone do środowisk pracy stają się dostępne.

Należy pamiętać, że środowisko graficzne FreeCAD wykonuje tę inicjalizację automatycznie. Jednak w przypadku korzystania z programu w trybie bez GUI użytkownik musi wykonać ten krok samodzielnie.

Zobacz stronę Osadzanie programu FreeCAD.

Poprzez skrypt w powłoce

Możesz również uruchomić FreeCAD w trybie 'headless' z poziomu skryptu w shellu, wywołując FreeCAD -c lub FreeCADCmd a następnie podając wymagane argumenty.

Pełna lista dostępnych argumentów linii poleceń może zostać wyświetlona przy pomocy flagi --help. Oto przykład informacji uzyskanych na wyjściu dla FreeCAD 1.0.2:

Command-line arguments for FreeCAD 1.0.2 (Click to expand)
$ FreeCAD -c --help
FreeCAD

For a detailed description see https://wiki.freecad.org/Start_up_and_Configuration

Usage: FreeCAD [options] File1 File2 ...

Allowed options:

Generic options:
  -v [ --version ]          Prints version string
  --verbose                 Prints verbose version string
  -h [ --help ]             Prints help message
  -c [ --console ]          Starts in console mode
  --response-file arg       Can be specified with '@name', too
  --dump-config             Dumps configuration
  --get-config arg          Prints the value of the requested configuration key
  --set-config arg          Sets the value of a configuration key
  --keep-deprecated-paths   If set then config files are kept on the old 
                            location

Configuration:
  -l [ --write-log ]        Writes FreeCAD.log to the user directory.
  --log-file arg            Unlike --write-log this allows logging to an 
                            arbitrary file
  -u [ --user-cfg ] arg     User config file to load/save user settings
  -s [ --system-cfg ] arg   System config file to load/save system settings
  -t [ --run-test ] arg     Run a given test case (use 0 (zero) to run all 
                            tests). If no argument is provided then return list
                            of all available tests.
  -r [ --run-open ] arg     Run a given test case (use 0 (zero) to run all 
                            tests). If no argument is provided then return list
                            of all available tests.  Keeps UI open after 
                            test(s) complete.
  -M [ --module-path ] arg  Additional module paths
  -E [ --macro-path ] arg   Additional macro paths
  -P [ --python-path ] arg  Additional python paths
  --disable-addon arg       Disable a given addon.
  --single-instance         Allow to run a single instance of the application
  --safe-mode               Force enable safe mode
  --pass arg                Ignores the following arguments and pass them 
                            through to be used by a script

Ta metoda jest idealna do skryptów dokonujących automatyzacji i ciągłej integracji (CI). Częste przypadki jej użycia obejmują uruchamianie całego zestawu testów z poleceniem FreeCADCmd -t 0 lub uruchamianie testów dla wybranego środowiska, jak np. FreeCADCmd -t TestArch (wszystkie testy dla środowiska BIM) lub FreeCADCmd -t TestArch.TestWall (tylko testy ścian środowiska BIM).

Uruchamianie kodu Pythona bezpośrednio

Pliki wykonywalne linii poleceń FreeCAD mogą również służyć jako wyspecjalizowane interpretery Pythona, pozwalając na bezpośrednie uruchamianie kodu Pythona. To zapewnia wygodną i efektywną alternatywę dla osadzania programu FreeCAD w obrębie zewnętrznego skryptu Pythona.

Uruchamianie wbudowanego skryptu

Możesz przekazać ciąg kodu Pythona bezpośrednio jako pojedynczy argument. Jest to przydatne do bardzo krótkich poleceń o jednym celu. Zauważ, że argument linii poleceń nie może być ścieżką do istniejącego pliku żeby to działało.

$ FreeCADCmd "import Part; print(Part.makeBox(10,5,15).Volume)"
$ FreeCAD -c "import Part; my_box = Part.makeBox(10,5,15)"

Uruchamianie pliku skryptu

Bardziej efektywną metodą jest użycie programu FreeCAD do bezpośredniego uruchomienia pliku skryptu Pythona. Jest to zalecane podejście dla każdego nietrywialnego zadania w trybie headless.

$ FreeCADCmd /path/to/my_script.py

Gdy skrypt jest uruchamiany w ten sposób, środowisko FreeCAD jest już skonfigurowane. Kluczową zaletą jest to, że skrypt nie potrzebuje szablonowego kodu sys.path.append(). Moduły FreeCAD są natychmiast dostępne do importu.

Przykładowo, plik nazwany create_box.py mógłby zawierać:

import Part
# The FreeCAD module is already available, but it can be imported explicitly
import FreeCAD

# Create a new document and add a box to it
doc = FreeCAD.newDocument()
box_obj = doc.addObject("Part::Box", "MyBox")
doc.recompute()

# Export the part to a STEP file
Part.export([box_obj], "my_box_model.step")

print("Box created and exported successfully to my_box_model.step")

Uruchomienie tego skryptu z terminala jest tak proste jak:

$ FreeCADCmd create_box.py
Box created and exported successfully to my_box_model.step

Za pośrednictwem pełnej aplikacji z interfejsem graficznym uruchomionej w wirtualnym środowisku wyświetlania

Powyższe metody (FreeCADCmd, FreeCAD -c oraz użycie FreeCAD jako osadzonej biblioteki Pythona) nie umożliwiają tworzenia dostawców widoku. Jeśli skrypt wymaga dostępu do ViewObject (na przykład do właściwości takich jak styl tekstu lub rozmiar czcionki), żadna z powyższych metod nie będzie działać.

Aby uzyskać w pełni zainicjalizowaną sesję GUI (w tym działających dostawców widoku) bez fizycznego monitora, w systemie Linux można uruchomić właściwy plik wykonywalny interfejsu graficznego FreeCAD na wirtualnym serwerze X, takim jak Xvfb. W przeciwieństwie do trybów konsolowych, plik wykonywalny interfejsu graficznego wykonuje standardową procedurę uruchamiania (tworząc MainWindow i rzeczywistych dostawców widoku).

W systemie Linux można to osiągnąć za pomocą xvfb-run, który automatycznie zajmuje się przydzieleniem wirtualnego ekranu i jego zwolnieniem po zakończeniu działania:

$ xvfb-run -a FreeCAD my_script.py

Podobnie jak w przypadku uruchamiania pliku skryptu opisanego w Uruchamianie i konfiguracja, plik przekazany w wierszu poleceń może mieć rozszerzenie .py lub .FCMacro; oba są uruchamiane w ten sam sposób.

Aplikacja nie zamyka się automatycznie po zakończeniu działania skryptu. W przeciwieństwie do FreeCADCmd, plik wykonywalny GUI zawsze uruchamia standardową pętlę zdarzeń Qt i pozostaje otwarty, niezależnie od tego, czy ekran jest widoczny dla użytkownika. Skrypt musi sam zażądać zakończenia działania aplikacji.

Samo wywołanie FreeCADGui.getMainWindow().close() nie jest w tym przypadku niezawodne: przechodzi ono przez standardową sekwencję zamykania interaktywnego, która obejmuje monit FreeCAD "zapisać zmiany?" dla każdego dokumentu z niezapisanymi modyfikacjami. W środowisku z wirtualnym ekranem spowoduje to zawieszenie procesu w nieskończoność, ponieważ do zamknięcia monitu wymagana jest interakcja użytkownika. Najpierw wyczyść flagę modyfikacji każdego dokumentu, aby nie było o co pytać:

import FreeCAD as App
import FreeCADGui as Gui

# ... script code ...

for doc in App.listDocuments().values():
    Gui.getDocument(doc.Name).Modified = False
Gui.getMainWindow().close()

Jeśli mimo to coś nadal będzie utrzymywać proces przy życiu (na przykład inne modalne okno dialogowe niezwiązane z niezapisanymi zmianami), skrypt może w ostateczności użyć wymuszonego zakończenia, które całkowicie omija pętlę zdarzeń Qt:

import os
# ... script code ...
os._exit(0)

Używaj tego tylko w ostateczności: pomija ono standardowe zamykanie i czyszczenie wykonywane przez Qt i FreeCAD, dlatego wszystko, co zostałoby usunięte podczas zamykania (na przykład pliki blokad), pozostaje. W miarę możliwości preferuj wyczyszczenie flagi modyfikacji i normalne zamknięcie aplikacji.

Przykłady

Przeszukiwanie modułów FreeCAD

  1. Otwórz terminal i wpisz:
    $ /path/to/FreeCAD -c
    lub
    $ /ścieżka/do/FreeCADCmd
  2. Powłoka Python uruchomi się z promptem. Wpisz help().
  3. Zostanie wyświetlony tekst pomocy.
  4. Wpisz modules freecad.

Reprezentacja scenografii

Ponieważ nie jest możliwe utworzenie lub dostęp do dostawcy widoku w trybie bez użycia GUI. Co jest możliwe, to załadowanie FreeCADGui w trybie bez GUI, ale nie ma możliwości dostępu do dokumentu GUI, ponieważ nie zostanie on utworzony i w konsekwencji nie będzie istniał żaden dostawca widoku.

Możliwe jest jednak stworzenie Scenogramu reprezentacji obiektu:

import FreeCADGui as Gui
from pivy import coin

Gui.setupWithoutGUI()
doc = App.newDocument()
obj = doc.addObject("Part::Box","Box")
doc.recompute()
view = Gui.subgraphFromObject(obj)

Zobacz: wątek na forum.

Powiązane