Доработан плагин экспорта SDF для FreeCAD
1
Init.py
|
@ -1 +0,0 @@
|
||||||
#I made this?
|
|
41
InitGui.py
|
@ -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())
|
|
33
README.md
|
@ -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`).
|
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
|
@ -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 FreeCAD
|
||||||
import ARTools
|
import Tools
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
from pivy import coin
|
from pivy import coin
|
||||||
|
@ -7,11 +20,11 @@ if FreeCAD.GuiUp:
|
||||||
import Part
|
import Part
|
||||||
import os
|
import os
|
||||||
|
|
||||||
__title__ = "ARFrames"
|
__title__ = 'Frames'
|
||||||
__author__ = "Mathias Hauan Arbo"
|
__author__ = 'brothermechanic'
|
||||||
__workbenchname__ = "ARBench"
|
__workbenchname__ = 'Frames'
|
||||||
__version__ = "0.1"
|
__version__ = '0.1'
|
||||||
__url__ = "https://github.com/mahaarbo/ARBench"
|
__url__ = ["https://robossembler.org"]
|
||||||
__doc__ = """"""
|
__doc__ = """"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +57,7 @@ class Frame(object):
|
||||||
def getDict(self):
|
def getDict(self):
|
||||||
d = {}
|
d = {}
|
||||||
d["label"] = str(self.obj.Label)
|
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)
|
d.update(self.additional_data)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -95,7 +108,7 @@ class FeatureFrame(PartFrame):
|
||||||
|
|
||||||
def getDict(self):
|
def getDict(self):
|
||||||
d = PartFrame.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["shapetype"] = str(self.obj.ShapeType)
|
||||||
d["positioning"] = str(self.obj.Positioning)
|
d["positioning"] = str(self.obj.Positioning)
|
||||||
return d
|
return d
|
||||||
|
@ -126,7 +139,7 @@ class ViewProviderFrame(object):
|
||||||
# and Toggle_DH_Frames by galou_breizh on the forums
|
# and Toggle_DH_Frames by galou_breizh on the forums
|
||||||
self.vframe = coin.SoType.fromName("SoShapeScale").createInstance()
|
self.vframe = coin.SoType.fromName("SoShapeScale").createInstance()
|
||||||
self.vframe.setPart("shape", coin.SoType.fromName("SoAxisCrossKit").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)
|
ax = self.vframe.getPart("shape", 0)
|
||||||
cone = ax.getPart("xHead.shape", 0)
|
cone = ax.getPart("xHead.shape", 0)
|
||||||
cone.bottomRadius.setValue(vobj.HeadSize)
|
cone.bottomRadius.setValue(vobj.HeadSize)
|
||||||
|
@ -245,9 +258,9 @@ def makeFrame(placement=FreeCAD.Placement()):
|
||||||
def makePartFrame(part):
|
def makePartFrame(part):
|
||||||
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "PartFrame")
|
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "PartFrame")
|
||||||
PartFrame(obj, part)
|
PartFrame(obj, part)
|
||||||
if int(FreeCAD.Version()[1]) > 16:
|
#if int(FreeCAD.Version()[1]) > 16:
|
||||||
geo_feature_group = part.getParentGeoFeatureGroup()
|
# geo_feature_group = part.getParentGeoFeatureGroup()
|
||||||
geo_feature_group.addObject(obj)
|
# geo_feature_group.addObject(obj)
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
ViewProviderPartFrame(obj.ViewObject)
|
ViewProviderPartFrame(obj.ViewObject)
|
||||||
return obj
|
return obj
|
||||||
|
@ -258,13 +271,18 @@ def makeFeatureFrame(part, featurepl):
|
||||||
"FeatureFrame")
|
"FeatureFrame")
|
||||||
FeatureFrame(obj, part, featurepl)
|
FeatureFrame(obj, part, featurepl)
|
||||||
# If we're >0.16, add the feature frame to the assembly
|
# If we're >0.16, add the feature frame to the assembly
|
||||||
if int(FreeCAD.Version()[1]) > 16:
|
#if int(FreeCAD.Version()[1]) > 16:
|
||||||
geo_feature_group = part.getParentGeoFeatureGroup()
|
# geo_feature_group = part.getParentGeoFeatureGroup()
|
||||||
geo_feature_group.addObject(obj)
|
# geo_feature_group.addObject(obj)
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
ViewProviderFeatureFrame(obj.ViewObject)
|
ViewProviderFeatureFrame(obj.ViewObject)
|
||||||
return obj
|
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():
|
def makeAllPartFrames():
|
||||||
dc = FreeCAD.activeDocument()
|
dc = FreeCAD.activeDocument()
|
||||||
|
@ -286,22 +304,28 @@ uidir = os.path.join(FreeCAD.getUserAppDataDir(),
|
||||||
"Mod", __workbenchname__, "UI")
|
"Mod", __workbenchname__, "UI")
|
||||||
icondir = os.path.join(uidir, "icons")
|
icondir = os.path.join(uidir, "icons")
|
||||||
|
|
||||||
ARTools.spawnClassCommand("FrameCommand",
|
Tools.spawnClassCommand("FrameCommand",
|
||||||
makeFrame,
|
makeFrame,
|
||||||
{"Pixmap": str(os.path.join(icondir, "frame.svg")),
|
{"Pixmap": str(os.path.join(icondir, "frame.svg")),
|
||||||
"MenuText": "Make a free frame",
|
"MenuText": "Make a free frame",
|
||||||
"ToolTip": "Make a freestanding reference 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,
|
makeAllPartFrames,
|
||||||
{"Pixmap": str(os.path.join(icondir, "allpartframes.svg")),
|
{"Pixmap": str(os.path.join(icondir, "allpartframes.svg")),
|
||||||
"MenuText": "All part frames",
|
"MenuText": "All parts frames",
|
||||||
"ToolTip": "Make all part frames."})
|
"ToolTip": "Make all parts frames."})
|
||||||
ARTools.spawnClassCommand("FeatureFrameCommand",
|
Tools.spawnClassCommand("FeatureFrameCommand",
|
||||||
spawnFeatureFrameCreator,
|
spawnFeatureFrameCreator,
|
||||||
{"Pixmap": str(os.path.join(icondir, "featureframecreator.svg")),
|
{"Pixmap": str(os.path.join(icondir, "featureframecreator.svg")),
|
||||||
"MenuText": "Feature frame creator",
|
"MenuText": "frame on selected primitive",
|
||||||
"ToolTip": "Create a feature frame on selected primitive."})
|
"ToolTip": "Create a frame on selected primitive."})
|
||||||
|
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
|
@ -327,7 +351,7 @@ class FeatureFramePanel:
|
||||||
self.reject()
|
self.reject()
|
||||||
|
|
||||||
# Choices related to selection
|
# Choices related to selection
|
||||||
so_desc = ARTools.describeSubObject(selected.SubObjects[0])
|
so_desc = Tools.describeSubObject(selected.SubObjects[0])
|
||||||
self.so_desc = so_desc
|
self.so_desc = so_desc
|
||||||
shape_choices = {
|
shape_choices = {
|
||||||
"Vertex": [],
|
"Vertex": [],
|
||||||
|
@ -428,7 +452,7 @@ class BaseFeaturePanel(object):
|
||||||
self.fframe = makeFeatureFrame(self.selected.Object, self.local_ffpl)
|
self.fframe = makeFeatureFrame(self.selected.Object, self.local_ffpl)
|
||||||
self.fframe.PrimitiveType = self.so_desc[0]
|
self.fframe.PrimitiveType = self.so_desc[0]
|
||||||
self.fframe.ShapeType = self.so_desc[1]
|
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.selected.SubObjects[0])
|
||||||
self.fframe.Proxy.additional_data.update(ad)
|
self.fframe.Proxy.additional_data.update(ad)
|
||||||
|
|
|
@ -65,7 +65,7 @@ def insert():
|
||||||
|
|
||||||
def controlled_insert(code):
|
def controlled_insert(code):
|
||||||
a = FreeCAD.ActiveDocument.Objects
|
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
|
b = FreeCAD.ActiveDocument.Objects
|
||||||
return list(set(b) - set(a))[0]
|
return list(set(b) - set(a))[0]
|
||||||
|
|
2
cg/freecad/Frames/Init.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""FreeCAD init script"""
|
70
cg/freecad/Frames/InitGui.py
Normal 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())
|
34
cg/freecad/Frames/README.md
Normal 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`).
|
||||||
|
|
|
@ -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 FreeCAD
|
||||||
import Part
|
import Part
|
||||||
import json # For exporting part infos
|
import json # For exporting part infos
|
||||||
|
@ -7,12 +20,12 @@ import GraspPose
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
from PySide import QtGui
|
from PySide import QtGui
|
||||||
|
import time
|
||||||
__title__ = "ARTools"
|
__title__ = 'Tools'
|
||||||
__author__ = "Mathias Hauan Arbo"
|
__author__ = 'brothermechanic'
|
||||||
__workbenchname__ = "ARBench"
|
__workbenchname__ = 'Frames'
|
||||||
__version__ = "0.1"
|
__version__ = '0.1'
|
||||||
__url__ = "https://github.com/mahaarbo/ARBench"
|
__url__ = ["https://robossembler.org"]
|
||||||
__doc__ = """
|
__doc__ = """
|
||||||
Useful tools for the Annotations for Robotics workbench."""
|
Useful tools for the Annotations for Robotics workbench."""
|
||||||
|
|
||||||
|
@ -161,8 +174,8 @@ def spawnClassCommand(classname, function, resources):
|
||||||
|
|
||||||
def getLocalPartProps(obj):
|
def getLocalPartProps(obj):
|
||||||
old_placement = obj.Placement
|
old_placement = obj.Placement
|
||||||
obj.Placement = FreeCAD.Placement()
|
# obj.Placement = FreeCAD.Placement()
|
||||||
# Part properties
|
""" Part properties """
|
||||||
partprops = {
|
partprops = {
|
||||||
"label": obj.Label,
|
"label": obj.Label,
|
||||||
"placement": placement2pose(old_placement),
|
"placement": placement2pose(old_placement),
|
||||||
|
@ -171,7 +184,7 @@ def getLocalPartProps(obj):
|
||||||
# "centerofmass": vector2list(obj.Shape.CenterOfMass),
|
# "centerofmass": vector2list(obj.Shape.CenterOfMass),
|
||||||
# "principalproperties": principalProperties2dict(obj.Shape.PrincipalProperties)
|
# "principalproperties": principalProperties2dict(obj.Shape.PrincipalProperties)
|
||||||
}
|
}
|
||||||
obj.Placement = old_placement
|
# obj.Placement = old_placement
|
||||||
return partprops
|
return partprops
|
||||||
|
|
||||||
# Longest match for mesh name
|
# Longest match for mesh name
|
||||||
|
@ -243,9 +256,9 @@ def exportGazeboModels():
|
||||||
parts[obj.PartToHandle.Label].update({"graspposes" : graspposes})
|
parts[obj.PartToHandle.Label].update({"graspposes" : graspposes})
|
||||||
|
|
||||||
# Add part placement position on Plane surface
|
# Add part placement position on Plane surface
|
||||||
import ARFrames
|
import Frames
|
||||||
if hasattr(obj, 'Proxy') and "ShapeType" in obj.PropertiesList:
|
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) } })
|
parts[obj.Part.Label].update({ "placements": { obj.Label: placement2pose(obj.Placement) } })
|
||||||
|
|
||||||
# Create SDF package from Parts or other packages
|
# 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:
|
with open(os.path.join(model_dir, 'model.config'), 'w') as config_file:
|
||||||
config_file.write(GazeboExport.config(name,
|
config_file.write(GazeboExport.config(name,
|
||||||
'model.sdf', 'Author', 'Email', 'Comment', 'Version'))
|
'model.sdf', 'Author', 'Email', 'Comment', 'Version'))
|
||||||
|
'''
|
||||||
with open(os.path.join(model_dir, 'frames.json'), 'w') as frames_file:
|
with open(os.path.join(model_dir, 'frames.json'), 'w') as frames_file:
|
||||||
json.dump({"label": name,
|
json.dump({"label": name,
|
||||||
"placement": placement2pose(parts[name]["obj"].Placement),
|
"placement": placement2pose(parts[name]["obj"].Placement),
|
||||||
|
@ -268,11 +281,15 @@ def exportGazeboModels():
|
||||||
{ "graspposes" : parts[name]["graspposes"]
|
{ "graspposes" : parts[name]["graspposes"]
|
||||||
, "placements" : parts[name]["placements"]}},
|
, "placements" : parts[name]["placements"]}},
|
||||||
frames_file, indent=1, separators=(',', ': '))
|
frames_file, indent=1, separators=(',', ': '))
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Export assets for parts
|
# Export assets for parts
|
||||||
for obj in selected_objects:
|
for obj in selected_objects:
|
||||||
create_package(obj.Label, [obj], export_dir)
|
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
|
# Export asset for subassembly
|
||||||
# subasm_name = "_".join(list(map(lambda x: x.Label[:8], selected_objects)))
|
# 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
|
For more information on principal properties, see TopoShape in OCCT
|
||||||
documentation.
|
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)
|
partprops = getLocalPartProps(obj)
|
||||||
with open(ofile, "w", encoding="utf8") as propfile:
|
with open(ofile, "w", encoding="utf8") as propfile:
|
||||||
json.dump(partprops, propfile, indent=1, separators=(',', ': '))
|
json.dump(partprops, propfile, indent=1, separators=(',', ': '))
|
||||||
return True
|
return ofile
|
||||||
|
|
||||||
|
|
||||||
def appendPartInfo(obj, ofile):
|
def appendPartInfo(obj, ofile):
|
||||||
|
@ -323,18 +334,12 @@ def appendPartInfo(obj, ofile):
|
||||||
def exportFeatureFrames(obj, ofile):
|
def exportFeatureFrames(obj, ofile):
|
||||||
"""Exports feature frames attached to a part."""
|
"""Exports feature frames attached to a part."""
|
||||||
# Get the feature frames
|
# Get the feature frames
|
||||||
import ARFrames
|
import Frames
|
||||||
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
|
||||||
ff_list = filter(ff_check, obj.InList)
|
ff_list = filter(ff_check, obj.InList)
|
||||||
ff_named = { ff.Label: ff.Proxy.getDict() for ff in ff_list }
|
ff_named = { ff.Label: ff.Proxy.getDict() for ff in ff_list }
|
||||||
feature_dict = { "features": ff_named }
|
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:
|
with open(ofile, "w", encoding="utf8") as propfile:
|
||||||
json.dump(feature_dict, propfile, indent=1, separators=(',', ': '))
|
json.dump(feature_dict, propfile, indent=1, separators=(',', ': '))
|
||||||
return True
|
return True
|
||||||
|
@ -344,12 +349,13 @@ def appendFeatureFrames(obj, ofile):
|
||||||
"""Rewrites/appends featureframes attached to a part to an existing json
|
"""Rewrites/appends featureframes attached to a part to an existing json
|
||||||
file."""
|
file."""
|
||||||
# Get the feature frames
|
# Get the feature frames
|
||||||
import ARFrames
|
import Frames
|
||||||
with open(ofile, "r", encoding="utf8") as propfile:
|
with open(ofile, "r", encoding="utf8") as propfile:
|
||||||
partprops = json.load(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_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 }
|
feature_dict = { "features": ff_named }
|
||||||
if "features" not in partprops.keys():
|
if "features" not in partprops.keys():
|
||||||
partprops.update(feature_dict)
|
partprops.update(feature_dict)
|
||||||
|
@ -413,7 +419,7 @@ def exportPartInfoDialogue():
|
||||||
def exportFeatureFramesDialogue():
|
def exportFeatureFramesDialogue():
|
||||||
"""Spawns a dialogue window for a part's feature frames to be exported."""
|
"""Spawns a dialogue window for a part's feature frames to be exported."""
|
||||||
# Select only true parts
|
# Select only true parts
|
||||||
import ARFrames
|
import Frames
|
||||||
s = FreeCADGui.Selection.getSelection()
|
s = FreeCADGui.Selection.getSelection()
|
||||||
FreeCADGui.Selection.clearSelection()
|
FreeCADGui.Selection.clearSelection()
|
||||||
if len(s) == 0:
|
if len(s) == 0:
|
||||||
|
@ -421,7 +427,7 @@ def exportFeatureFramesDialogue():
|
||||||
return False
|
return False
|
||||||
unique_selected = []
|
unique_selected = []
|
||||||
for item in s:
|
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
|
# Ensuring that we are parts
|
||||||
unique_selected.append(item)
|
unique_selected.append(item)
|
||||||
FreeCADGui.Selection.addSelection(item)
|
FreeCADGui.Selection.addSelection(item)
|
||||||
|
@ -461,7 +467,7 @@ def exportFeatureFramesDialogue():
|
||||||
|
|
||||||
def exportPartInfoAndFeaturesDialogue():
|
def exportPartInfoAndFeaturesDialogue():
|
||||||
"""Spawns a dialogue window for exporting both."""
|
"""Spawns a dialogue window for exporting both."""
|
||||||
import ARFrames
|
import Frames
|
||||||
s = FreeCADGui.Selection.getSelection()
|
s = FreeCADGui.Selection.getSelection()
|
||||||
FreeCADGui.Selection.clearSelection()
|
FreeCADGui.Selection.clearSelection()
|
||||||
if len(s) == 0:
|
if len(s) == 0:
|
||||||
|
@ -486,6 +492,14 @@ def exportPartInfoAndFeaturesDialogue():
|
||||||
if ofile == "":
|
if ofile == "":
|
||||||
# User cancelled
|
# User cancelled
|
||||||
return False
|
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):
|
if os.path.exists(ofile):
|
||||||
msgbox = QtGui.QMessageBox()
|
msgbox = QtGui.QMessageBox()
|
||||||
msgbox.setText("File already exists. We can overwrite the file, or add the information/rewrite only relevant sections.")
|
msgbox.setText("File already exists. We can overwrite the file, or add the information/rewrite only relevant sections.")
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
130
example.json
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|