Доработан плагин экспорта SDF для FreeCAD

This commit is contained in:
brothermechanic 2023-02-21 10:13:11 +00:00 committed by Igor Brylyov
parent 95437a4527
commit 0c433c10d5
43 changed files with 202 additions and 13630 deletions

1839
B.brep

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
#I made this?

View file

@ -1,41 +0,0 @@
class ARBench(Workbench):
MenuText = "ARBench"
ToolTip = "Annotation for Robotics workbench"
Icon = """"""
def __init__(self):
import os
self.Icon = os.path.join(FreeCAD.getUserAppDataDir(), "Mod",
"ARBench", "UI", "icons", "frame.svg")
def Initialize(self):
"""This function is executed when FreeCAD starts"""
import ARFrames
self.framecommands = ["FrameCommand",
"AllPartFramesCommand",
"FeatureFrameCommand"]
self.toolcommands = ["ExportPartInfoAndFeaturesDialogueCommand",
"ExportGazeboModels",
"InsertGraspPose"]
self.appendToolbar("AR Frames", self.framecommands)
self.appendToolbar("AR Tools", self.toolcommands)
def Activated(self):
"""This function is executed when the workbench is activated."""
#
return
def Deactivated(self):
"""This function is executed when the workbench is deactivated."""
#
return
def ContextMenu(self, recipient):
"""This is execcuted whenever the user right-clicks on screen."""
pass
def GetClassName(self):
# This function is mandatory if this is a full python workbench
return "Gui::PythonWorkbench"
Gui.addWorkbench(ARBench())

4951
L.brep

File diff suppressed because it is too large Load diff

1225
P.brep

File diff suppressed because it is too large Load diff

4951
R.brep

File diff suppressed because it is too large Load diff

View file

@ -21,36 +21,3 @@
- __Предикат стабильной осуществимости__. Верен для последовательности сборки, когда сборка на каждом из этапов приходит к стабильному состоянию.
- __Предикат степеней свободы__. Формируется на основе уже сгенерированных графов/графа сборки. В каких степенях свободы возможно перемещать деталь.
# Верстак ARBench
Разметка моделей деталей и сборок для роботизированного производства.
## Установка
Поддерживается версия FreeCAD>0.16. Скопируйте содержимое репозитория в директорию `.FreeCAD/Mod/`.
## Экспорт мета-данных дeталей (en)
1. Click a small feature e.g. a circle
2. Press the feature frame creator (cone with a magnifying glass on it icon)
3. Chose type of feature to create
4. Chose feature parameters if relevant and the offset of the frame from the feature.
5. Repeat 4 for each feature you want on each part
6. Click a part and press the export to json button (block->textfile icon)
7. Save json
8. Use the json with whatever you want. E.g. [`arbench_part_publisher`](https://github.com/mahaarbo/arbench_part_publisher)
## Генерация пакетов деталей для симулятора Gazebo
Для генерации SDF-пакета из документа FreeCAD выделите нужные детали и нажмите "Gazebo Export" в пользовательском интерфейсе верстака ARBench, после чего будет для каждого отдельного твёрдого тела (детали, `Solid`; `Compound` пока не поддерживаются) будет создана директория со следующей структурой
```
name_of_part
├── model.sdf
├── meshes
│ └── part.dae
└── model.config
```
По умолчанию эти пакеты будут размещены в директории с документом FreeCAD. Чтобы добавить их в Gazebo нужно копировать сгенерированные директории в папку моделей (обычно `~/.gazebo/models`).

View file

@ -1,401 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>323</width>
<height>325</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>316</width>
<height>325</height>
</size>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QLabel" name="TaskLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>71</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Task Label</string>
</property>
</widget>
<widget class="QPushButton" name="PushButton">
<property name="geometry">
<rect>
<x>150</x>
<y>290</y>
<width>161</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>Get from selection</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>100</x>
<y>20</y>
<width>211</width>
<height>27</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
<widget class="QLabel" name="HoleLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>31</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Hole</string>
</property>
</widget>
<widget class="QLabel" name="PegLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>130</y>
<width>31</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Peg</string>
</property>
</widget>
<widget class="QLabel" name="HolePartLabel">
<property name="geometry">
<rect>
<x>50</x>
<y>70</y>
<width>41</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Part:</string>
</property>
</widget>
<widget class="QLabel" name="HoleFaceLabel">
<property name="geometry">
<rect>
<x>50</x>
<y>90</y>
<width>41</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Face:</string>
</property>
</widget>
<widget class="QLabel" name="PegPartLabel">
<property name="geometry">
<rect>
<x>50</x>
<y>150</y>
<width>41</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Part:</string>
</property>
</widget>
<widget class="QLabel" name="PegFaceLabel">
<property name="geometry">
<rect>
<x>50</x>
<y>170</y>
<width>41</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Face:</string>
</property>
</widget>
<widget class="QLabel" name="HolePartField">
<property name="geometry">
<rect>
<x>100</x>
<y>70</y>
<width>231</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>PartLabel</string>
</property>
</widget>
<widget class="QLabel" name="HoleFaceIDField">
<property name="geometry">
<rect>
<x>100</x>
<y>90</y>
<width>231</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>FaceID</string>
</property>
</widget>
<widget class="QLabel" name="PegFaceIDField">
<property name="geometry">
<rect>
<x>100</x>
<y>170</y>
<width>231</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>FaceID</string>
</property>
</widget>
<widget class="QLabel" name="PegPartField">
<property name="geometry">
<rect>
<x>100</x>
<y>150</y>
<width>231</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>PartLabel</string>
</property>
</widget>
<widget class="QLabel" name="HoleFeatureSummary">
<property name="geometry">
<rect>
<x>100</x>
<y>110</y>
<width>231</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Feature Description</string>
</property>
</widget>
<widget class="QLabel" name="HoleFeatureLabel">
<property name="geometry">
<rect>
<x>30</x>
<y>110</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Feature:</string>
</property>
</widget>
<widget class="QLabel" name="PegFeatureSummary">
<property name="geometry">
<rect>
<x>100</x>
<y>190</y>
<width>231</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Feature Description</string>
</property>
</widget>
<widget class="QLabel" name="PegFeatureLabel">
<property name="geometry">
<rect>
<x>30</x>
<y>190</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Feature:</string>
</property>
</widget>
<widget class="QLabel" name="YLabel">
<property name="geometry">
<rect>
<x>80</x>
<y>250</y>
<width>16</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>y</string>
</property>
<property name="buddy">
<cstring>YBox</cstring>
</property>
</widget>
<widget class="QLabel" name="XLabel">
<property name="geometry">
<rect>
<x>80</x>
<y>230</y>
<width>16</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>x</string>
</property>
<property name="buddy">
<cstring>XBox</cstring>
</property>
</widget>
<widget class="QLabel" name="ZLabel">
<property name="geometry">
<rect>
<x>80</x>
<y>270</y>
<width>16</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>z</string>
</property>
<property name="buddy">
<cstring>ZBox</cstring>
</property>
</widget>
<widget class="QDoubleSpinBox" name="YBox">
<property name="geometry">
<rect>
<x>100</x>
<y>250</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="toolTip">
<string>offset in part frame z direction</string>
</property>
<property name="suffix">
<string/>
</property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
<widget class="QDoubleSpinBox" name="XBox">
<property name="geometry">
<rect>
<x>100</x>
<y>230</y>
<width>61</width>
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>Offset in part frame x direction</string>
</property>
<property name="suffix">
<string/>
</property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
<widget class="QDoubleSpinBox" name="ZBox">
<property name="geometry">
<rect>
<x>100</x>
<y>270</y>
<width>61</width>
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>offset in part frame z direction</string>
</property>
<property name="suffix">
<string/>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
<widget class="QLabel" name="AssemblyAxisLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>210</y>
<width>121</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Assembly Axis</string>
</property>
</widget>
<widget class="QPushButton" name="AnimateButton">
<property name="geometry">
<rect>
<x>10</x>
<y>290</y>
<width>131</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>Animate</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -1,5 +1,18 @@
# -*- coding: utf-8 -*-
# Copyright 2023 by brothermechanic. All Rights Reserved.
# Based on ARBench by github/mahaarbo
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import FreeCAD
import ARTools
import Tools
if FreeCAD.GuiUp:
import FreeCADGui
from pivy import coin
@ -7,11 +20,11 @@ if FreeCAD.GuiUp:
import Part
import os
__title__ = "ARFrames"
__author__ = "Mathias Hauan Arbo"
__workbenchname__ = "ARBench"
__version__ = "0.1"
__url__ = "https://github.com/mahaarbo/ARBench"
__title__ = 'Frames'
__author__ = 'brothermechanic'
__workbenchname__ = 'Frames'
__version__ = '0.1'
__url__ = ["https://robossembler.org"]
__doc__ = """"""
@ -44,7 +57,7 @@ class Frame(object):
def getDict(self):
d = {}
d["label"] = str(self.obj.Label)
d["placement"] = ARTools.placement2axisvec(self.obj.Placement)
d["placement"] = Tools.placement2axisvec(self.obj.Placement)
d.update(self.additional_data)
return d
@ -95,7 +108,7 @@ class FeatureFrame(PartFrame):
def getDict(self):
d = PartFrame.getDict(self)
d["featureplacement"] = ARTools.placement2axisvec(self.obj.FeaturePlacement)
d["featureplacement"] = Tools.placement2axisvec(self.obj.FeaturePlacement)
d["shapetype"] = str(self.obj.ShapeType)
d["positioning"] = str(self.obj.Positioning)
return d
@ -126,7 +139,7 @@ class ViewProviderFrame(object):
# and Toggle_DH_Frames by galou_breizh on the forums
self.vframe = coin.SoType.fromName("SoShapeScale").createInstance()
self.vframe.setPart("shape", coin.SoType.fromName("SoAxisCrossKit").createInstance())
self.vframe.scaleFactor.setValue(0.1)
self.vframe.scaleFactor.setValue(0.2)
ax = self.vframe.getPart("shape", 0)
cone = ax.getPart("xHead.shape", 0)
cone.bottomRadius.setValue(vobj.HeadSize)
@ -245,9 +258,9 @@ def makeFrame(placement=FreeCAD.Placement()):
def makePartFrame(part):
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "PartFrame")
PartFrame(obj, part)
if int(FreeCAD.Version()[1]) > 16:
geo_feature_group = part.getParentGeoFeatureGroup()
geo_feature_group.addObject(obj)
#if int(FreeCAD.Version()[1]) > 16:
# geo_feature_group = part.getParentGeoFeatureGroup()
# geo_feature_group.addObject(obj)
if FreeCAD.GuiUp:
ViewProviderPartFrame(obj.ViewObject)
return obj
@ -258,13 +271,18 @@ def makeFeatureFrame(part, featurepl):
"FeatureFrame")
FeatureFrame(obj, part, featurepl)
# If we're >0.16, add the feature frame to the assembly
if int(FreeCAD.Version()[1]) > 16:
geo_feature_group = part.getParentGeoFeatureGroup()
geo_feature_group.addObject(obj)
#if int(FreeCAD.Version()[1]) > 16:
# geo_feature_group = part.getParentGeoFeatureGroup()
# geo_feature_group.addObject(obj)
if FreeCAD.GuiUp:
ViewProviderFeatureFrame(obj.ViewObject)
return obj
def makeSelectedPartFrames():
for part in FreeCADGui.Selection.getSelection():
if isinstance(part, Part.Feature):
pf = makePartFrame(part)
pf.Label = "Frame"+str(part.Label)
def makeAllPartFrames():
dc = FreeCAD.activeDocument()
@ -286,22 +304,28 @@ uidir = os.path.join(FreeCAD.getUserAppDataDir(),
"Mod", __workbenchname__, "UI")
icondir = os.path.join(uidir, "icons")
ARTools.spawnClassCommand("FrameCommand",
Tools.spawnClassCommand("FrameCommand",
makeFrame,
{"Pixmap": str(os.path.join(icondir, "frame.svg")),
"MenuText": "Make a free frame",
"ToolTip": "Make a freestanding reference frame."})
ARTools.spawnClassCommand("AllPartFramesCommand",
Tools.spawnClassCommand("SelectedPartFrameCommand",
makeSelectedPartFrames,
{"Pixmap": str(os.path.join(icondir, "partframe.svg")),
"MenuText": "selected parts frames",
"ToolTip": "Make selected parts frames."})
Tools.spawnClassCommand("AllPartFramesCommand",
makeAllPartFrames,
{"Pixmap": str(os.path.join(icondir, "allpartframes.svg")),
"MenuText": "All part frames",
"ToolTip": "Make all part frames."})
ARTools.spawnClassCommand("FeatureFrameCommand",
"MenuText": "All parts frames",
"ToolTip": "Make all parts frames."})
Tools.spawnClassCommand("FeatureFrameCommand",
spawnFeatureFrameCreator,
{"Pixmap": str(os.path.join(icondir, "featureframecreator.svg")),
"MenuText": "Feature frame creator",
"ToolTip": "Create a feature frame on selected primitive."})
"MenuText": "frame on selected primitive",
"ToolTip": "Create a frame on selected primitive."})
###################################################################
@ -327,7 +351,7 @@ class FeatureFramePanel:
self.reject()
# Choices related to selection
so_desc = ARTools.describeSubObject(selected.SubObjects[0])
so_desc = Tools.describeSubObject(selected.SubObjects[0])
self.so_desc = so_desc
shape_choices = {
"Vertex": [],
@ -428,7 +452,7 @@ class BaseFeaturePanel(object):
self.fframe = makeFeatureFrame(self.selected.Object, self.local_ffpl)
self.fframe.PrimitiveType = self.so_desc[0]
self.fframe.ShapeType = self.so_desc[1]
ad = ARTools.getPrimitiveInfo(self.so_desc[0],
ad = Tools.getPrimitiveInfo(self.so_desc[0],
self.selected.SubObjects[0])
self.fframe.Proxy.additional_data.update(ad)

View file

@ -65,7 +65,7 @@ def insert():
def controlled_insert(code):
a = FreeCAD.ActiveDocument.Objects
Part.insert(u"C:/Users/ibryl/AppData/Roaming/FreeCAD/Mod/ARBench/"+code+".brep",FreeCAD.ActiveDocument.Name)
Part.insert(u"~/.local/share/FreeCAD/Mod/Frames/"+code+".brep",FreeCAD.ActiveDocument.Name)
b = FreeCAD.ActiveDocument.Objects
return list(set(b) - set(a))[0]

View file

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
"""FreeCAD init script"""

View file

@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
# Copyright 2023 by brothermechanic. All Rights Reserved.
# Based on ARBench by github/mahaarbo
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
__title__='Frames Workbench'
__author__ = 'brothermechanic'
__copyright__ = 'Copyright (c) 2023 brothermechanic'
__license__ = 'GPL-2.1'
__version__ = "0.1"
__email__ = 'brothermechanic@gmail.com'
__url__ = ["https://robossembler.org"]
__status__ = 'development'
class Frames(Workbench):
MenuText = "Frames"
ToolTip = "Frames Workbench"
Icon = """"""
def __init__(self):
import os
self.Icon = os.path.join(FreeCAD.getUserAppDataDir(), "Mod",
__class__.__name__, "UI", "icons", "frame.svg")
def Initialize(self):
"""This function is executed when FreeCAD starts"""
import Frames
self.framecommands = [
"FrameCommand",
"SelectedPartFrameCommand",
"AllPartFramesCommand",
"FeatureFrameCommand"
]
self.toolcommands = [
"ExportPartInfoAndFeaturesDialogueCommand",
"ExportGazeboModels",
"InsertGraspPose"
]
self.appendToolbar(f"{__class__.__name__} Frames", self.framecommands)
self.appendToolbar(f"{__class__.__name__} Tools", self.toolcommands)
def Activated(self):
"""This function is executed when the workbench is activated."""
#
return
def Deactivated(self):
"""This function is executed when the workbench is deactivated."""
#
return
def ContextMenu(self, recipient):
"""This is execcuted whenever the user right-clicks on screen."""
pass
def GetClassName(self):
# This function is mandatory if this is a full python workbench
return "Gui::PythonWorkbench"
Gui.addWorkbench(Frames())

View file

@ -0,0 +1,34 @@
# Плагин для FreeCAD
# Верстак ARBench
Разметка моделей деталей и сборок для роботизированного производства.
## Установка
Поддерживается версия FreeCAD>0.16. Скопируйте содержимое репозитория в директорию `.FreeCAD/Mod/`.
## Экспорт мета-данных дeталей (en)
1. Click a small feature e.g. a circle
2. Press the feature frame creator (cone with a magnifying glass on it icon)
3. Chose type of feature to create
4. Chose feature parameters if relevant and the offset of the frame from the feature.
5. Repeat 4 for each feature you want on each part
6. Click a part and press the export to json button (block->textfile icon)
7. Save json
8. Use the json with whatever you want. E.g. [`arbench_part_publisher`](https://github.com/mahaarbo/arbench_part_publisher)
## Генерация пакетов деталей для симулятора Gazebo
Для генерации SDF-пакета из документа FreeCAD выделите нужные детали и нажмите "Gazebo Export" в пользовательском интерфейсе верстака ARBench, после чего будет для каждого отдельного твёрдого тела (детали, `Solid`; `Compound` пока не поддерживаются) будет создана директория со следующей структурой
```
name_of_part
├── model.sdf
├── meshes
│ └── part.dae
└── model.config
```
По умолчанию эти пакеты будут размещены в директории с документом FreeCAD. Чтобы добавить их в Gazebo нужно копировать сгенерированные директории в папку моделей (обычно `~/.gazebo/models`).

View file

@ -1,3 +1,16 @@
# -*- coding: utf-8 -*-
# Copyright 2023 by brothermechanic. All Rights Reserved.
# Based on ARBench by github/mahaarbo
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import FreeCAD
import Part
import json # For exporting part infos
@ -7,12 +20,12 @@ import GraspPose
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtGui
__title__ = "ARTools"
__author__ = "Mathias Hauan Arbo"
__workbenchname__ = "ARBench"
__version__ = "0.1"
__url__ = "https://github.com/mahaarbo/ARBench"
import time
__title__ = 'Tools'
__author__ = 'brothermechanic'
__workbenchname__ = 'Frames'
__version__ = '0.1'
__url__ = ["https://robossembler.org"]
__doc__ = """
Useful tools for the Annotations for Robotics workbench."""
@ -161,8 +174,8 @@ def spawnClassCommand(classname, function, resources):
def getLocalPartProps(obj):
old_placement = obj.Placement
obj.Placement = FreeCAD.Placement()
# Part properties
# obj.Placement = FreeCAD.Placement()
""" Part properties """
partprops = {
"label": obj.Label,
"placement": placement2pose(old_placement),
@ -171,7 +184,7 @@ def getLocalPartProps(obj):
# "centerofmass": vector2list(obj.Shape.CenterOfMass),
# "principalproperties": principalProperties2dict(obj.Shape.PrincipalProperties)
}
obj.Placement = old_placement
# obj.Placement = old_placement
return partprops
# Longest match for mesh name
@ -243,9 +256,9 @@ def exportGazeboModels():
parts[obj.PartToHandle.Label].update({"graspposes" : graspposes})
# Add part placement position on Plane surface
import ARFrames
import Frames
if hasattr(obj, 'Proxy') and "ShapeType" in obj.PropertiesList:
if isinstance(obj.Proxy, ARFrames.FeatureFrame) and obj.ShapeType == 'Face':
if isinstance(obj.Proxy, Frames.FeatureFrame) and obj.ShapeType == 'Face':
parts[obj.Part.Label].update({ "placements": { obj.Label: placement2pose(obj.Placement) } })
# Create SDF package from Parts or other packages
@ -260,7 +273,7 @@ def exportGazeboModels():
with open(os.path.join(model_dir, 'model.config'), 'w') as config_file:
config_file.write(GazeboExport.config(name,
'model.sdf', 'Author', 'Email', 'Comment', 'Version'))
'''
with open(os.path.join(model_dir, 'frames.json'), 'w') as frames_file:
json.dump({"label": name,
"placement": placement2pose(parts[name]["obj"].Placement),
@ -268,11 +281,15 @@ def exportGazeboModels():
{ "graspposes" : parts[name]["graspposes"]
, "placements" : parts[name]["placements"]}},
frames_file, indent=1, separators=(',', ': '))
'''
# Export assets for parts
for obj in selected_objects:
create_package(obj.Label, [obj], export_dir)
exportPartInfo(obj, os.path.join(export_dir, obj.Label, 'frames.json') )
appendFeatureFrames(obj, os.path.join(export_dir, obj.Label, 'frames.json'))
# Export asset for subassembly
# subasm_name = "_".join(list(map(lambda x: x.Label[:8], selected_objects)))
@ -290,17 +307,11 @@ def exportPartInfo(obj, ofile):
For more information on principal properties, see TopoShape in OCCT
documentation.
"""
# File path stuff
odir, of = os.path.split(ofile)
if not os.path.exists(odir):
os.makedirs(odir)
if not of.lower().endswith(".json"):
ofile = ofile + ".json"
partprops = getLocalPartProps(obj)
with open(ofile, "w", encoding="utf8") as propfile:
json.dump(partprops, propfile, indent=1, separators=(',', ': '))
return True
return ofile
def appendPartInfo(obj, ofile):
@ -323,18 +334,12 @@ def appendPartInfo(obj, ofile):
def exportFeatureFrames(obj, ofile):
"""Exports feature frames attached to a part."""
# Get the feature frames
import ARFrames
ff_check = lambda x: isinstance(x.Proxy, ARFrames.FeatureFrame) if hasattr(x, 'Proxy') else False
import Frames
ff_check = lambda x: isinstance(x.Proxy, Frames.FeatureFrame) if hasattr(x, 'Proxy') else False
ff_list = filter(ff_check, obj.InList)
ff_named = { ff.Label: ff.Proxy.getDict() for ff in ff_list }
feature_dict = { "features": ff_named }
# File stuff
odir, of = os.path.split(ofile)
if not os.path.exists(odir):
os.makedirs(odir)
if not of.lower().endswith(".json"):
ofile = ofile + ".json"
with open(ofile, "w", encoding="utf8") as propfile:
json.dump(feature_dict, propfile, indent=1, separators=(',', ': '))
return True
@ -344,12 +349,13 @@ def appendFeatureFrames(obj, ofile):
"""Rewrites/appends featureframes attached to a part to an existing json
file."""
# Get the feature frames
import ARFrames
import Frames
with open(ofile, "r", encoding="utf8") as propfile:
partprops = json.load(propfile)
ff_check = lambda x: isinstance(x.Proxy, ARFrames.FeatureFrame) if hasattr(x, 'Proxy') else False
ff_check = lambda x: isinstance(x.Proxy, Frames.FeatureFrame) if hasattr(x, 'Proxy') else False
# part's children list
ff_list = filter(ff_check, obj.InList)
ff_named = { ff.Label: {"label": ff.Label, "placement": placement2pose(ff.Placement)} for ff in ff_list }
ff_named = { ff.Label: {"label": ff.Label, "placement": placement2pose(ff.FeaturePlacement)} for ff in ff_list }
feature_dict = { "features": ff_named }
if "features" not in partprops.keys():
partprops.update(feature_dict)
@ -413,7 +419,7 @@ def exportPartInfoDialogue():
def exportFeatureFramesDialogue():
"""Spawns a dialogue window for a part's feature frames to be exported."""
# Select only true parts
import ARFrames
import Frames
s = FreeCADGui.Selection.getSelection()
FreeCADGui.Selection.clearSelection()
if len(s) == 0:
@ -421,7 +427,7 @@ def exportFeatureFramesDialogue():
return False
unique_selected = []
for item in s:
if item not in unique_selected and isinstance(item.Proxy, ARFrames.FeatureFrame):
if item not in unique_selected and isinstance(item.Proxy, Frames.FeatureFrame):
# Ensuring that we are parts
unique_selected.append(item)
FreeCADGui.Selection.addSelection(item)
@ -461,7 +467,7 @@ def exportFeatureFramesDialogue():
def exportPartInfoAndFeaturesDialogue():
"""Spawns a dialogue window for exporting both."""
import ARFrames
import Frames
s = FreeCADGui.Selection.getSelection()
FreeCADGui.Selection.clearSelection()
if len(s) == 0:
@ -486,6 +492,14 @@ def exportPartInfoAndFeaturesDialogue():
if ofile == "":
# User cancelled
return False
# File path stuff
odir, of = os.path.split(ofile)
if not os.path.exists(odir):
os.makedirs(odir)
if not of.lower().endswith(".json"):
ofile = ofile + ".json"
if os.path.exists(ofile):
msgbox = QtGui.QMessageBox()
msgbox.setText("File already exists. We can overwrite the file, or add the information/rewrite only relevant sections.")

View file

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before After
Before After

View file

@ -1,130 +0,0 @@
{
"Gripper_for_Box": {
"Part name": "Box",
"Part label": "\u041a\u0443\u0431",
"Part position XYZ": [
0.0,
0.0,
0.0
],
"Part rotation axis XYZ": [
0.0,
0.0,
1.0
],
"Part rotation angle": 0.0,
"Gripper position XYZ": [
0.0,
0.0,
0.0
],
"Gripper rotation axis XYZ": [
0.0,
0.0,
1.0
],
"Gripper rotation angle": 0.0,
"Grip size": 10.0,
"OperationType": 0,
"Operation Priority": 0,
"a.Operation Parameter 1": 0.0,
"a.Operation Parameter 2": 0.0,
"a.Operation Parameter 3": 0.0
},
"Gripper_for_Cylinder": {
"Part name": "Cylinder",
"Part label": "\u0426\u0438\u043b\u0438\u043d\u0434\u0440",
"Part position XYZ": [
0.0,
0.0,
0.0
],
"Part rotation axis XYZ": [
0.0,
0.0,
1.0
],
"Part rotation angle": 0.0,
"Gripper position XYZ": [
0.0,
0.0,
0.0
],
"Gripper rotation axis XYZ": [
1.0,
0.0,
0.0
],
"Gripper rotation angle": 4.1887902047863905,
"Grip size": 3.9708354963922163,
"OperationType": 0,
"Operation Priority": 0,
"a.Operation Parameter 1": 0.0,
"a.Operation Parameter 2": 0.0,
"a.Operation Parameter 3": 0.0
},
"Gripper_for_Box001": {
"Part name": "Box001",
"Part label": "\u041a\u0443\u0431001",
"Part position XYZ": [
0.0,
9.0,
0.0
],
"Part rotation axis XYZ": [
0.0,
0.0,
1.0
],
"Part rotation angle": 0.0,
"Gripper position XYZ": [
3.8035643556662895,
99.89718356183919,
-9.331967349091768
],
"Gripper rotation axis XYZ": [
-0.6901619708141958,
0.717463959241293,
0.09445592216305763
],
"Gripper rotation angle": 3.570126372396101,
"Grip size": 20.0,
"OperationType": 0,
"Operation Priority": 0,
"a.Operation Parameter 1": 0.0,
"a.Operation Parameter 2": 0.0,
"a.Operation Parameter 3": 0.0
},
"Gripper_for_Tube": {
"Part name": "Tube",
"Part label": "Tube",
"Part position XYZ": [
0.0,
370.0,
10.0
],
"Part rotation axis XYZ": [
1.0,
0.0,
0.0
],
"Part rotation angle": 1.5707963267948966,
"Gripper position XYZ": [
0.0,
345.0,
10.0
],
"Gripper rotation axis XYZ": [
1.0,
0.0,
0.0
],
"Gripper rotation angle": 1.5707963267948966,
"Grip size": 50.0,
"OperationType": 0,
"Operation Priority": 0,
"a.Operation Parameter 1": 0.0,
"a.Operation Parameter 2": 0.0,
"a.Operation Parameter 3": 0.0
}
}

Binary file not shown.