From 9f31e27b84ff61430d1538c91a67cb5f8f00704c Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Tue, 9 Jan 2024 17:56:11 +0300 Subject: [PATCH 1/9] first steps towards model imports --- .gitignore | 4 +- InitGui.py | 4 +- .../{RD_parser => RD_utils}/RD_parse_sdf.py | 2 +- .../initialize_element_tree.py | 4 +- robot_descriptor/RD_utils/parse_asm4_model.py | 51 +++++ .../{RD_parser => RD_utils}/readme.md | 0 robot_descriptor/{RD_globals.py => common.py} | 15 +- robot_descriptor/forms/model_editor.ui | 57 ++++++ robot_descriptor/initialize.py | 2 +- robot_descriptor/model_editor.py | 58 ++++++ robot_descriptor/sdf_elements/atmosphere.py | 22 +-- robot_descriptor/sdf_elements/light.py | 76 ++++---- robot_descriptor/sdf_elements/physics.py | 176 +++++++++--------- robot_descriptor/sdf_elements/road.py | 72 +++---- robot_descriptor/sdf_elements/scene.py | 98 +++++----- .../sdf_elements/spherical_coordinates.py | 40 ++-- robot_descriptor/sdf_elements/world.py | 46 ++--- 17 files changed, 439 insertions(+), 288 deletions(-) rename robot_descriptor/{RD_parser => RD_utils}/RD_parse_sdf.py (99%) rename robot_descriptor/{RD_parser => RD_utils}/initialize_element_tree.py (96%) create mode 100644 robot_descriptor/RD_utils/parse_asm4_model.py rename robot_descriptor/{RD_parser => RD_utils}/readme.md (100%) rename robot_descriptor/{RD_globals.py => common.py} (95%) create mode 100644 robot_descriptor/forms/model_editor.ui create mode 100644 robot_descriptor/model_editor.py diff --git a/.gitignore b/.gitignore index bad6d9c..66e077c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ __pycache__ notes.txt .vscode test.py -out.xml \ No newline at end of file +out.xml +fnrpl.sh +TODO.txt \ No newline at end of file diff --git a/InitGui.py b/InitGui.py index b582a5a..09f55a0 100644 --- a/InitGui.py +++ b/InitGui.py @@ -22,9 +22,9 @@ def Initialize(self): __dirname__ = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", "RobotDescriptor") #print("got dir:" + __dirname__); - from robot_descriptor import initialize + from robot_descriptor import initialize ,model_editor from robot_descriptor.sdf_elements import world - self.list = ['RD_initialize','world_properties'] + self.list = ['RD_initialize','world_properties','Model_Editor'] self.appendToolbar("RobotDescription",self.list) # creates a new toolbar with your commands self.appendMenu("Robot Description",self.list) # creates a new menu #self.appendMenu(["Robot Description","Tools"],self.list) # appends a submenu to an existing menu diff --git a/robot_descriptor/RD_parser/RD_parse_sdf.py b/robot_descriptor/RD_utils/RD_parse_sdf.py similarity index 99% rename from robot_descriptor/RD_parser/RD_parse_sdf.py rename to robot_descriptor/RD_utils/RD_parse_sdf.py index 414fc9f..1ccf3a7 100644 --- a/robot_descriptor/RD_parser/RD_parse_sdf.py +++ b/robot_descriptor/RD_utils/RD_parse_sdf.py @@ -1,6 +1,6 @@ import xml.etree.ElementTree as ET import os -from .. import RD_globals +from .. import common diff --git a/robot_descriptor/RD_parser/initialize_element_tree.py b/robot_descriptor/RD_utils/initialize_element_tree.py similarity index 96% rename from robot_descriptor/RD_parser/initialize_element_tree.py rename to robot_descriptor/RD_utils/initialize_element_tree.py index c16b4ed..60c8c05 100644 --- a/robot_descriptor/RD_parser/initialize_element_tree.py +++ b/robot_descriptor/RD_utils/initialize_element_tree.py @@ -1,5 +1,5 @@ -from .. import RD_globals +from .. import common from . import RD_parse_sdf @@ -63,7 +63,7 @@ def get_element(self)->ET.Element: t=convdict_2_tree("world.sdf") tree=t.get_tree elm=t.get_elements - e_elem=RD_globals.set_xml_data('linear_velocity',elm,False,[12,9,8]) + e_elem=common.set_xml_data('linear_velocity',elm,False,[12,9,8]) e_elem_t=ET.ElementTree(e_elem) tree.write("out.xml",encoding='utf8',xml_declaration=True) e_elem_t.write("out.xml",encoding='utf8',xml_declaration=True) \ No newline at end of file diff --git a/robot_descriptor/RD_utils/parse_asm4_model.py b/robot_descriptor/RD_utils/parse_asm4_model.py new file mode 100644 index 0000000..799c869 --- /dev/null +++ b/robot_descriptor/RD_utils/parse_asm4_model.py @@ -0,0 +1,51 @@ +import FreeCAD +import FreeCADGui +import robot_descriptor.common as common +import os + +''' +assembly4 Technical manual +https://github.com/Zolko-123/FreeCAD_Assembly4/blob/master/TECHMANUAL.md + +''' + +def read_assembly(): + links=FreeCAD.ActiveDocument.findObjects("App::Link") + #links in Assembly4 are of type "App::Link" + #this is a list + #this will store a list of dictionaries + def create_structure(data,dest): + #check the parent objects + children=[child for child in data if child["parent"]==dest["name"]] + if len (children)==0: + return + for ch in children: + dest["children"].append(ch) + create_structure(data,ch) + + + link_data=[] + #create the root parent + structured_data={} + for child in links: + name=child.Label + #attachedTo returns a string of the format 'Parent Assembly#LCS_Origin' hence + #hence separating by the the '#' and taking the first element will be the parent + #the 2nd the coordinate system its attached to + parent,attachement=child.AttachedTo.split('#') + #Attachmensts are usually made with reference to coordiante systems of type "PartDesign::CoordinateSystem" find them in all links + # and remove lcs with label 'LCS_Origin' in case it exists in model + coordinate_systems=[ lcs for lcs in child.Document.findObjects("PartDesign::CoordinateSystem") if lcs.Label !='LCS_Origin' ] + link_data.append({"link":child,"name":name,"parent":parent,"attachment":attachement,"coordinate_systems":coordinate_systems,'children':[]}) + # + #create a hierarchial data + + root_lcs=FreeCAD.ActiveDocument.findObjects("PartDesign::CoordinateSystem") + structured_data={"link":None,'name':"Parent Assembly","attachment":None,"coordinate_systems":root_lcs,"children":[]} + + #this will just create a hierarchial data representation + create_structure(link_data,structured_data) + del link_data + return structured_data + + diff --git a/robot_descriptor/RD_parser/readme.md b/robot_descriptor/RD_utils/readme.md similarity index 100% rename from robot_descriptor/RD_parser/readme.md rename to robot_descriptor/RD_utils/readme.md diff --git a/robot_descriptor/RD_globals.py b/robot_descriptor/common.py similarity index 95% rename from robot_descriptor/RD_globals.py rename to robot_descriptor/common.py index 161d898..3c166db 100644 --- a/robot_descriptor/RD_globals.py +++ b/robot_descriptor/common.py @@ -245,14 +245,19 @@ def merge_elements(destination_el:ET.Element,source_el:ET.Element,recursive:bool #implemtatation for all other elements #the ones that are not recursive and not physics else: + # Update attributes of destination_el with source_el destination_el.attrib.update(source_el.attrib) + if source_el.text: + destination_el.text = source_el.text + # Merge child elements recursively for child in source_el: - existing_el=destination_el.find(child.tag) + existing_el = destination_el.find(child.tag) if existing_el is not None: - destination_el.remove(existing_el) - destination_el.append(child) + merge_elements(existing_el, child) # Recursively merge the existing element with the new one else: - destination_el.append(child) + # If the element doesn't exist in destination, simply append it + # destination_el.append(child) + pass import math @@ -260,6 +265,8 @@ def merge_elements(destination_el:ET.Element,source_el:ET.Element,recursive:bool class color_pickr: + '''class that implements color picker methods + ''' def __init__(self) -> None: pass #color picker diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui new file mode 100644 index 0000000..1756fe9 --- /dev/null +++ b/robot_descriptor/forms/model_editor.ui @@ -0,0 +1,57 @@ + + + model_editor + + + + 0 + 0 + 909 + 557 + + + + Dialog + + + + + + + 220 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 2 + 4 + 213 + 527 + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + diff --git a/robot_descriptor/initialize.py b/robot_descriptor/initialize.py index d7400fe..8001fe5 100644 --- a/robot_descriptor/initialize.py +++ b/robot_descriptor/initialize.py @@ -6,7 +6,7 @@ #import Spreadsheet import xml.etree.ElementTree as ET -from .RD_parser import initialize_element_tree +from .RD_utils import initialize_element_tree #directory to initilize icon __dirname__ = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", "RobotDescriptor")+"/robot_descriptor/icons/initialize.svg" #class to store the selected properties diff --git a/robot_descriptor/model_editor.py b/robot_descriptor/model_editor.py new file mode 100644 index 0000000..e3a34c3 --- /dev/null +++ b/robot_descriptor/model_editor.py @@ -0,0 +1,58 @@ +import FreeCAD +import FreeCADGui +import robot_descriptor.common as common +import os + +from .RD_utils import parse_asm4_model +from PySide.QtGui import QStandardItemModel,QStandardItem + + +class standard_item(QStandardItem): + def __init__(self,text): + super().__init__() + self.model_elem=None + self.setText(text) + +class ModelEditor: + def __init__(self): + # find all objects of type 'App::Link' + #doc=FreeCAD.ActiveDocument + self.links_hierarchy=parse_asm4_model.read_assembly() + self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) + self.link_model=QStandardItemModel() + self.root_node=self.link_model.invisibleRootItem() + self.tree_setup(self.links_hierarchy["children"],self.root_node) + #hide header + self.ModelEditorUi.link_tree.setHeaderHidden(True) + self.ModelEditorUi.link_tree.setModel(self.link_model) + self.ModelEditorUi.exec() + + def tree_setup(self,link_hierarchy,item): + for child in link_hierarchy: + row=standard_item(child["name"]) + item.appendRow(row) + self.tree_setup(child["children"],row) + return + + + +class Model_properties(): + """My new command""" + + def GetResources(self): + return {"Pixmap" : os.path.join(common.ICON_PATH,"edit.svg"),# the name of a svg file available in the resources + "Accel" : "Shift+E", # a default shortcut (optional) + "MenuText": "Model Edits", + "ToolTip" : "Edit link and joint properties"} + + def Activated(self): + self.edits=ModelEditor() + return + + def IsActive(self): + if hasattr(FreeCAD.ActiveDocument, "Robot_Description"): + return True + else: + return False + +FreeCADGui.addCommand("Model_Editor", Model_properties()) diff --git a/robot_descriptor/sdf_elements/atmosphere.py b/robot_descriptor/sdf_elements/atmosphere.py index a18af29..87ad8bf 100644 --- a/robot_descriptor/sdf_elements/atmosphere.py +++ b/robot_descriptor/sdf_elements/atmosphere.py @@ -1,6 +1,6 @@ -from .. import RD_globals +from .. import common #reponsible for creating an element tree using xml.etree -from ..RD_parser import initialize_element_tree +from ..RD_utils import initialize_element_tree import xml.etree.ElementTree as ET import FreeCAD @@ -87,23 +87,23 @@ def configUI(self): self.ui.atm_temp_grad.valueChanged.connect(self.on_temp_gradient) #callbacks def on_atm_temp(self): - RD_globals.set_xml_data(self._atm_elem,"temperature",False,self.properties.temperature) + common.set_xml_data(self._atm_elem,"temperature",False,self.properties.temperature) def on_type_change(self): - RD_globals.set_xml_data(self._atm_elem,"atmosphere",True,{"type":self.properties.type}) + common.set_xml_data(self._atm_elem,"atmosphere",True,{"type":self.properties.type}) def on_atm_pressure(self): - RD_globals.set_xml_data(self._atm_elem,"pressure",False,self.properties.pressure) + common.set_xml_data(self._atm_elem,"pressure",False,self.properties.pressure) def on_temp_gradient(self): - RD_globals.set_xml_data(self._atm_elem,"temperature_gradient",False,self.properties.temp_gradient) + common.set_xml_data(self._atm_elem,"temperature_gradient",False,self.properties.temp_gradient) #end callbacks def update_ui(self): - self.properties.temperature=float(RD_globals.get_xml_data(self._atm_elem,"temperature",False)) - self.properties.pressure=float(RD_globals.get_xml_data(self._atm_elem,"pressure",False)) - self.properties.temp_gradient=float(RD_globals.get_xml_data(self._atm_elem,"temperature_gradient",False)) + self.properties.temperature=float(common.get_xml_data(self._atm_elem,"temperature",False)) + self.properties.pressure=float(common.get_xml_data(self._atm_elem,"pressure",False)) + self.properties.temp_gradient=float(common.get_xml_data(self._atm_elem,"temperature_gradient",False)) #the reset method should also be used for extracting previously configured values @@ -117,7 +117,7 @@ def reset(self,default:bool=True): #use RD_globals parse dict to get the element doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: el_str=el_dict['elem_str'] self.merge(el_str) @@ -128,7 +128,7 @@ def reset(self,default:bool=True): self.update_ui() def merge(self, el_str): - RD_globals.merge_elements(self._atm_elem,ET.fromstring(el_str)) + common.merge_elements(self._atm_elem,ET.fromstring(el_str)) def is_checked(self): status=self.ui.atmosphere_group.isChecked() diff --git a/robot_descriptor/sdf_elements/light.py b/robot_descriptor/sdf_elements/light.py index 44d34ba..420a1ac 100644 --- a/robot_descriptor/sdf_elements/light.py +++ b/robot_descriptor/sdf_elements/light.py @@ -2,8 +2,8 @@ from PySide import QtCore from PySide.QtGui import QMessageBox import FreeCAD -from ..RD_parser import initialize_element_tree -from .. import RD_globals +from ..RD_utils import initialize_element_tree +from .. import common import copy import re from PySide.QtGui import QColorDialog @@ -194,7 +194,7 @@ def pose(self,vals:list): #light #================================================================= -class light(RD_globals.color_pickr): +class light(common.color_pickr): def __init__(self,ui) -> None: self.ui=ui self.file_name='light.sdf' @@ -247,7 +247,7 @@ def add_sun(self): 'quadratic':0.001} for key in sun_properties.keys(): - RD_globals.set_xml_data(sun,key,False,sun_properties[key]) + common.set_xml_data(sun,key,False,sun_properties[key]) #append to sun self.lights['sun']=copy.deepcopy(sun) @@ -377,7 +377,7 @@ def on_name(self): #update the current name self.current_light=name #update the values in the ui - self.properties.name=RD_globals.get_xml_data(self._current_light_element,[self.tag,'name'],True) + self.properties.name=common.get_xml_data(self._current_light_element,[self.tag,'name'],True) #update type name in the list widget #get current iten current_item=self.ui.light_listWidget.currentRow() @@ -403,51 +403,51 @@ def on_type(self): self.ui.direction_groupbox.setEnabled(False) def on_intensity(self): - RD_globals.set_xml_data(self._current_light_element,"intensity",False,self.properties.intensity) + common.set_xml_data(self._current_light_element,"intensity",False,self.properties.intensity) def on_cast_shadows(self): - RD_globals.set_xml_data(self._current_light_element,"cast_shadows",False,self.properties.cast_shadows) + common.set_xml_data(self._current_light_element,"cast_shadows",False,self.properties.cast_shadows) def on_visualize(self): - RD_globals.set_xml_data(self._current_light_element,"visualize",False,self.properties.visualize) + common.set_xml_data(self._current_light_element,"visualize",False,self.properties.visualize) def on_light(self): - RD_globals.set_xml_data(self._current_light_element,"light_on",False,self.properties.light_on) + common.set_xml_data(self._current_light_element,"light_on",False,self.properties.light_on) def on_diffuse(self): - RD_globals.set_xml_data(self._current_light_element,"diffuse",False,self.properties.diffuse) + common.set_xml_data(self._current_light_element,"diffuse",False,self.properties.diffuse) self.set_widget_color('diffuse',self.ui.light_diffuse_color_pkr) def on_specular(self): - RD_globals.set_xml_data(self._current_light_element,"specular",False,self.properties.specular) + common.set_xml_data(self._current_light_element,"specular",False,self.properties.specular) self.set_widget_color('specular',self.ui.light_specular_color_pkr) def on_range(self): - RD_globals.set_xml_data(self._current_light_element,"range",False,self.properties.range) + common.set_xml_data(self._current_light_element,"range",False,self.properties.range) def on_constant(self): - RD_globals.set_xml_data(self._current_light_element,"constant",False,self.properties.constant) + common.set_xml_data(self._current_light_element,"constant",False,self.properties.constant) def on_linear(self): - RD_globals.set_xml_data(self._current_light_element,"linear",False,self.properties.linear) + common.set_xml_data(self._current_light_element,"linear",False,self.properties.linear) def on_quadratic(self): - RD_globals.set_xml_data(self._current_light_element,"quadratic",False,self.properties.quadratic) + common.set_xml_data(self._current_light_element,"quadratic",False,self.properties.quadratic) def on_pose(self): - RD_globals.set_xml_data(self._current_light_element,"pose",False,self.properties.pose) + common.set_xml_data(self._current_light_element,"pose",False,self.properties.pose) def on_direction(self): - RD_globals.set_xml_data(self._current_light_element,"direction",False,self.properties.direction) + common.set_xml_data(self._current_light_element,"direction",False,self.properties.direction) def on_inner_angle(self): - RD_globals.set_xml_data(self._current_light_element,"inner_angle",False,self.properties.inner_angle) + common.set_xml_data(self._current_light_element,"inner_angle",False,self.properties.inner_angle) def on_outer_angle(self): - RD_globals.set_xml_data(self._current_light_element,"outer_angle",False,self.properties.outer_angle) + common.set_xml_data(self._current_light_element,"outer_angle",False,self.properties.outer_angle) def on_falloff(self): - RD_globals.set_xml_data(self._current_light_element,"falloff",False,self.properties.falloff) + common.set_xml_data(self._current_light_element,"falloff",False,self.properties.falloff) def on_add(self): @@ -512,25 +512,25 @@ def on_remove(self): #update ui def update_ui(self): - self.properties.name=RD_globals.get_xml_data(self._current_light_element,[self.tag,'name'],True) - self.properties.type=RD_globals.get_xml_data(self._current_light_element,['light','type'],True) - self.properties.intensity=float(RD_globals.get_xml_data(self._current_light_element,"intensity",False)) - self.properties.cast_shadows=RD_globals.get_xml_data(self._current_light_element,"cast_shadows",False) - self.properties.visualize=RD_globals.get_xml_data(self._current_light_element,"visualize",False) - self.properties.light_on=RD_globals.get_xml_data(self._current_light_element,"light_on",False) - self.properties.diffuse=RD_globals.get_xml_data(self._current_light_element,"diffuse",False) + self.properties.name=common.get_xml_data(self._current_light_element,[self.tag,'name'],True) + self.properties.type=common.get_xml_data(self._current_light_element,['light','type'],True) + self.properties.intensity=float(common.get_xml_data(self._current_light_element,"intensity",False)) + self.properties.cast_shadows=common.get_xml_data(self._current_light_element,"cast_shadows",False) + self.properties.visualize=common.get_xml_data(self._current_light_element,"visualize",False) + self.properties.light_on=common.get_xml_data(self._current_light_element,"light_on",False) + self.properties.diffuse=common.get_xml_data(self._current_light_element,"diffuse",False) - self.properties.specular=RD_globals.get_xml_data(self._current_light_element,"specular",False) - self.properties.range=float(RD_globals.get_xml_data(self._current_light_element,"range",False)) - self.properties.constant=float(RD_globals.get_xml_data(self._current_light_element,"constant",False)) - self.properties.linear=float(RD_globals.get_xml_data(self._current_light_element,"linear",False)) - self.properties.quadratic=float(RD_globals.get_xml_data(self._current_light_element,"quadratic",False)) + self.properties.specular=common.get_xml_data(self._current_light_element,"specular",False) + self.properties.range=float(common.get_xml_data(self._current_light_element,"range",False)) + self.properties.constant=float(common.get_xml_data(self._current_light_element,"constant",False)) + self.properties.linear=float(common.get_xml_data(self._current_light_element,"linear",False)) + self.properties.quadratic=float(common.get_xml_data(self._current_light_element,"quadratic",False)) - self.properties.pose=RD_globals.get_xml_data(self._current_light_element,"pose",False) - self.properties.direction=RD_globals.get_xml_data(self._current_light_element,"direction",False) - self.properties.inner_angle=float(RD_globals.get_xml_data(self._current_light_element,"inner_angle",False)) - self.properties.outer_angle=float(RD_globals.get_xml_data(self._current_light_element,"outer_angle",False)) - self.properties.falloff=float(RD_globals.get_xml_data(self._current_light_element,"falloff",False)) + self.properties.pose=common.get_xml_data(self._current_light_element,"pose",False) + self.properties.direction=common.get_xml_data(self._current_light_element,"direction",False) + self.properties.inner_angle=float(common.get_xml_data(self._current_light_element,"inner_angle",False)) + self.properties.outer_angle=float(common.get_xml_data(self._current_light_element,"outer_angle",False)) + self.properties.falloff=float(common.get_xml_data(self._current_light_element,"falloff",False)) #set color picker button colors self.set_widget_color('diffuse',self.ui.light_diffuse_color_pkr) @@ -549,7 +549,7 @@ def reset(self,default:bool=True): direction=self._light_element.find('direction') doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: #clear list widget an light self.ui.light_listWidget.clear() diff --git a/robot_descriptor/sdf_elements/physics.py b/robot_descriptor/sdf_elements/physics.py index 9f91fd8..ebf620e 100644 --- a/robot_descriptor/sdf_elements/physics.py +++ b/robot_descriptor/sdf_elements/physics.py @@ -1,7 +1,7 @@ import xml.etree.ElementTree as ET -from ..RD_parser import initialize_element_tree -from .. import RD_globals +from ..RD_utils import initialize_element_tree +from .. import common import copy from PySide import QtCore @@ -394,67 +394,67 @@ def configUI(self): #callbacks def on_type(self): - RD_globals.set_xml_data(self._ode_elem,"type",False,self.solver.type) + common.set_xml_data(self._ode_elem,"type",False,self.solver.type) def on_min_step_size(self): - RD_globals.set_xml_data(self._ode_elem,"min_step_size",False,self.solver.min_step_size) + common.set_xml_data(self._ode_elem,"min_step_size",False,self.solver.min_step_size) def on_island_threads(self): - RD_globals.set_xml_data(self._ode_elem,"island_threads",False,self.solver.island_threads) + common.set_xml_data(self._ode_elem,"island_threads",False,self.solver.island_threads) def on_friction_model(self): - RD_globals.set_xml_data(self._ode_elem,"friction_model",False,self.solver.friction_model) + common.set_xml_data(self._ode_elem,"friction_model",False,self.solver.friction_model) def on_iters(self): - RD_globals.set_xml_data(self._ode_elem,"iters",False,self.solver.iters) + common.set_xml_data(self._ode_elem,"iters",False,self.solver.iters) def on_precon_iters(self): - RD_globals.set_xml_data(self._ode_elem,"precon_iters",False,self.solver.precon_iters) + common.set_xml_data(self._ode_elem,"precon_iters",False,self.solver.precon_iters) def on_sor(self): - RD_globals.set_xml_data(self._ode_elem,"sor",False,self.solver.sor) + common.set_xml_data(self._ode_elem,"sor",False,self.solver.sor) def on_dynamic_moi_rescaling(self): - RD_globals.set_xml_data(self._ode_elem,"use_dynamic_moi_rescaling",False,self.solver.use_dynamic_moi_rescaling) + common.set_xml_data(self._ode_elem,"use_dynamic_moi_rescaling",False,self.solver.use_dynamic_moi_rescaling) def on_thread_position_correction(self): - RD_globals.set_xml_data(self._ode_elem,"thread_position_correction",False,self.solver.thread_position_correction) + common.set_xml_data(self._ode_elem,"thread_position_correction",False,self.solver.thread_position_correction) def on_cfm(self): - RD_globals.set_xml_data(self._ode_elem,"cfm",False,self.constraints.cfm) + common.set_xml_data(self._ode_elem,"cfm",False,self.constraints.cfm) def on_erp(self): - RD_globals.set_xml_data(self._ode_elem,"erp",False,self.constraints.erp) + common.set_xml_data(self._ode_elem,"erp",False,self.constraints.erp) def on_contact_max_correction_vel(self): - RD_globals.set_xml_data(self._ode_elem,"contact_max_correcting_vel",False,self.constraints.contact_max_correcting_vel) + common.set_xml_data(self._ode_elem,"contact_max_correcting_vel",False,self.constraints.contact_max_correcting_vel) def on_contact_surface_layer(self): - RD_globals.set_xml_data(self._ode_elem,"contact_surface_layer",False,self.constraints.contact_surface_layer) + common.set_xml_data(self._ode_elem,"contact_surface_layer",False,self.constraints.contact_surface_layer) #end callbacks def update_ui(self): #solver - self.solver.type=RD_globals.get_xml_data(self._ode_elem,"type",False) - self.solver.min_step_size=float(RD_globals.get_xml_data(self._ode_elem,"min_step_size",False)) - self.solver.island_threads=int(RD_globals.get_xml_data(self._ode_elem,"island_threads",False)) - self.solver.iters=float(RD_globals.get_xml_data(self._ode_elem,"iters",False)) - self.solver.precon_iters=int(RD_globals.get_xml_data(self._ode_elem,"precon_iters",False)) - self.solver.sor=float(RD_globals.get_xml_data(self._ode_elem,"sor",False)) - self.solver.friction_model=RD_globals.get_xml_data(self._ode_elem,"friction_model",False) - - if RD_globals.get_xml_data(self._ode_elem,"use_dynamic_moi_rescaling",False)=='true': + self.solver.type=common.get_xml_data(self._ode_elem,"type",False) + self.solver.min_step_size=float(common.get_xml_data(self._ode_elem,"min_step_size",False)) + self.solver.island_threads=int(common.get_xml_data(self._ode_elem,"island_threads",False)) + self.solver.iters=float(common.get_xml_data(self._ode_elem,"iters",False)) + self.solver.precon_iters=int(common.get_xml_data(self._ode_elem,"precon_iters",False)) + self.solver.sor=float(common.get_xml_data(self._ode_elem,"sor",False)) + self.solver.friction_model=common.get_xml_data(self._ode_elem,"friction_model",False) + + if common.get_xml_data(self._ode_elem,"use_dynamic_moi_rescaling",False)=='true': self.solver.use_dynamic_moi_rescaling=True else: self.solver.use_dynamic_moi_rescaling=False - if RD_globals.get_xml_data(self._ode_elem,"thread_position_correction",False)=='true': + if common.get_xml_data(self._ode_elem,"thread_position_correction",False)=='true': self.solver.thread_position_correction=True else: self.solver.thread_position_correction=False #constraints - self.constraints.cfm=float(RD_globals.get_xml_data(self._ode_elem,"cfm",False)) - self.constraints.erp=float(RD_globals.get_xml_data(self._ode_elem,"erp")) - self.constraints.contact_max_correcting_vel=float(RD_globals.get_xml_data(self._ode_elem,"contact_max_correcting_vel")) - self.constraints.contact_surface_layer=float(RD_globals.get_xml_data(self._ode_elem,"contact_surface_layer")) + self.constraints.cfm=float(common.get_xml_data(self._ode_elem,"cfm",False)) + self.constraints.erp=float(common.get_xml_data(self._ode_elem,"erp")) + self.constraints.contact_max_correcting_vel=float(common.get_xml_data(self._ode_elem,"contact_max_correcting_vel")) + self.constraints.contact_surface_layer=float(common.get_xml_data(self._ode_elem,"contact_surface_layer")) #this takes an element and updates the internal ones def reset(self,new_elem:ET.Element): self._get_ode_elem(new_elem) @@ -495,45 +495,45 @@ def configUI(self): self.ui.bullet_split_impulse_penetration_threshold.valueChanged.connect(self.on_splt_impl_pen_tr) #solver def on_type(self): - RD_globals.set_xml_data(self._bullet_element,"solver",False,self.solver.type) + common.set_xml_data(self._bullet_element,"solver",False,self.solver.type) def on_min_step_size(self): - RD_globals.set_xml_data(self._bullet_element,"min_step_size",False,self.solver.min_step_size) + common.set_xml_data(self._bullet_element,"min_step_size",False,self.solver.min_step_size) def on_iters(self): - RD_globals.set_xml_data(self._bullet_element,"iters",False,self.solver.iters) + common.set_xml_data(self._bullet_element,"iters",False,self.solver.iters) def on_sor(self): - RD_globals.set_xml_data(self._bullet_element,"sor",False,self.solver.sor) + common.set_xml_data(self._bullet_element,"sor",False,self.solver.sor) #constraints def on_cfm(self): - RD_globals.set_xml_data(self._bullet_element,"cfm",False,self.constraints.cfm) + common.set_xml_data(self._bullet_element,"cfm",False,self.constraints.cfm) def on_erp(self): - RD_globals.set_xml_data(self._bullet_element,"erp",False,self.constraints.erp) + common.set_xml_data(self._bullet_element,"erp",False,self.constraints.erp) def on_cont_surf_layer(self): - RD_globals.set_xml_data(self._bullet_element,"contact_surface_layer",False,self.constraints.contact_surface_layer) + common.set_xml_data(self._bullet_element,"contact_surface_layer",False,self.constraints.contact_surface_layer) def on_split_impulse(self): - RD_globals.set_xml_data(self._bullet_element,"split_impulse",False,self.constraints.split_impulse) + common.set_xml_data(self._bullet_element,"split_impulse",False,self.constraints.split_impulse) def on_splt_impl_pen_tr(self): - RD_globals.set_xml_data(self._bullet_element,"split_impulse_penetration_threshold",False,self.constraints.split_impulse_penetration_threshold) + common.set_xml_data(self._bullet_element,"split_impulse_penetration_threshold",False,self.constraints.split_impulse_penetration_threshold) def update_ui(self): #solver ui - self.solver.type=RD_globals.get_xml_data(self._bullet_element,"type",False) - self.solver.min_step_size=float(RD_globals.get_xml_data(self._bullet_element,"min_step_size",False)) - self.solver.iters=int(RD_globals.get_xml_data(self._bullet_element,"iters",False)) - self.solver.sor=float(RD_globals.get_xml_data(self._bullet_element,"sor",False)) + self.solver.type=common.get_xml_data(self._bullet_element,"type",False) + self.solver.min_step_size=float(common.get_xml_data(self._bullet_element,"min_step_size",False)) + self.solver.iters=int(common.get_xml_data(self._bullet_element,"iters",False)) + self.solver.sor=float(common.get_xml_data(self._bullet_element,"sor",False)) #constrains ui - self.constraints.cfm=float(RD_globals.get_xml_data(self._bullet_element,"cfm",False)) - self.constraints.erp=float(RD_globals.get_xml_data(self._bullet_element,"erp",False)) - self.constraints.contact_surface_layer=float(RD_globals.get_xml_data(self._bullet_element,"contact_surface_layer")) - self.constraints.split_impulse_penetration_threshold=float(RD_globals.get_xml_data(self._bullet_element, + self.constraints.cfm=float(common.get_xml_data(self._bullet_element,"cfm",False)) + self.constraints.erp=float(common.get_xml_data(self._bullet_element,"erp",False)) + self.constraints.contact_surface_layer=float(common.get_xml_data(self._bullet_element,"contact_surface_layer")) + self.constraints.split_impulse_penetration_threshold=float(common.get_xml_data(self._bullet_element, "split_impulse_penetration_threshold")) - if RD_globals.get_xml_data(self._bullet_element,"split_impulse")=='true': + if common.get_xml_data(self._bullet_element,"split_impulse")=='true': self.constraints.split_impulse=True else: self.constraints.split_impulse=False @@ -579,58 +579,58 @@ def configUI(self): #callbacks #properties def on_min_step_size(self): - RD_globals.set_xml_data(self._simbody_element,"min_step_size",False,self.properties.min_step_size) + common.set_xml_data(self._simbody_element,"min_step_size",False,self.properties.min_step_size) def on_accuracy(self): - RD_globals.set_xml_data(self._simbody_element,"accuracy",False,self.properties.accuracy) + common.set_xml_data(self._simbody_element,"accuracy",False,self.properties.accuracy) def on_max_trans_vel(self): - RD_globals.set_xml_data(self._simbody_element,"max_transient_velocity",False,self.properties.maximum_transient_velocity) + common.set_xml_data(self._simbody_element,"max_transient_velocity",False,self.properties.maximum_transient_velocity) #contact def on_stiffness(self): - RD_globals.set_xml_data(self._simbody_element,"stiffness",False,self.contact.stiffness) + common.set_xml_data(self._simbody_element,"stiffness",False,self.contact.stiffness) def on_plst_coef_rest(self): - RD_globals.set_xml_data(self._simbody_element,"plastic_coef_restitution",False,self.contact.plastic_coef_restitution) + common.set_xml_data(self._simbody_element,"plastic_coef_restitution",False,self.contact.plastic_coef_restitution) def on_plst_imp_vel(self): - RD_globals.set_xml_data(self._simbody_element,"plastic_impact_velocity",False,self.contact.plastic_impact_velocity) + common.set_xml_data(self._simbody_element,"plastic_impact_velocity",False,self.contact.plastic_impact_velocity) def on_ovr_imp_cpt_vel(self): - RD_globals.set_xml_data(self._simbody_element,"override_impact_capture_velocity",False,self.contact.override_impact_capture_velocity) + common.set_xml_data(self._simbody_element,"override_impact_capture_velocity",False,self.contact.override_impact_capture_velocity) def on_dissipation(self): - RD_globals.set_xml_data(self._simbody_element,"dissipation",False,self.contact.dissipation) + common.set_xml_data(self._simbody_element,"dissipation",False,self.contact.dissipation) def on_static_fric(self): - RD_globals.set_xml_data(self._simbody_element,"static_friction",False,self.contact.static_friction) + common.set_xml_data(self._simbody_element,"static_friction",False,self.contact.static_friction) def on_dyn_fric(self): - RD_globals.set_xml_data(self._simbody_element,"dynamic_friction",False,self.contact.dynamic_friction) + common.set_xml_data(self._simbody_element,"dynamic_friction",False,self.contact.dynamic_friction) def on_vsc_fric(self): - RD_globals.set_xml_data(self._simbody_element,"viscous_friction",False,self.contact.viscous_friction) + common.set_xml_data(self._simbody_element,"viscous_friction",False,self.contact.viscous_friction) def on_ovr_st_tr_vel(self): - RD_globals.set_xml_data(self._simbody_element,"override_stiction_transition_velocity",False,self.contact.override_stiction_transition_velocity) + common.set_xml_data(self._simbody_element,"override_stiction_transition_velocity",False,self.contact.override_stiction_transition_velocity) #update ui def update_ui(self): #properties - self.properties.min_step_size=float(RD_globals.get_xml_data(self._simbody_element,"min_step_size",False)) - self.properties.accuracy=float(RD_globals.get_xml_data(self._simbody_element,"accuracy",False)) - self.properties.maximum_transient_velocity=float(RD_globals.get_xml_data(self._simbody_element,"max_transient_velocity",False)) + self.properties.min_step_size=float(common.get_xml_data(self._simbody_element,"min_step_size",False)) + self.properties.accuracy=float(common.get_xml_data(self._simbody_element,"accuracy",False)) + self.properties.maximum_transient_velocity=float(common.get_xml_data(self._simbody_element,"max_transient_velocity",False)) #contact - self.contact.stiffness=float(RD_globals.get_xml_data(self._simbody_element,"stiffness",False)) - self.contact.plastic_coef_restitution=float(RD_globals.get_xml_data(self._simbody_element,"plastic_coef_restitution",False)) - self.contact.plastic_impact_velocity=float(RD_globals.get_xml_data(self._simbody_element,"plastic_impact_velocity",False)) - self.contact.override_impact_capture_velocity=float(RD_globals.get_xml_data(self._simbody_element,"override_impact_capture_velocity",False)) - self.contact.dissipation=float(RD_globals.get_xml_data(self._simbody_element,"dissipation",False)) - self.contact.static_friction=float(RD_globals.get_xml_data(self._simbody_element,"static_friction",False)) - self.contact.dynamic_friction=float(RD_globals.get_xml_data(self._simbody_element,"dynamic_friction",False)) - self.contact.viscous_friction=float(RD_globals.get_xml_data(self._simbody_element,"viscous_friction",False)) - self.contact.override_stiction_transition_velocity=float(RD_globals.get_xml_data(self._simbody_element,"override_stiction_transition_velocity",False)) + self.contact.stiffness=float(common.get_xml_data(self._simbody_element,"stiffness",False)) + self.contact.plastic_coef_restitution=float(common.get_xml_data(self._simbody_element,"plastic_coef_restitution",False)) + self.contact.plastic_impact_velocity=float(common.get_xml_data(self._simbody_element,"plastic_impact_velocity",False)) + self.contact.override_impact_capture_velocity=float(common.get_xml_data(self._simbody_element,"override_impact_capture_velocity",False)) + self.contact.dissipation=float(common.get_xml_data(self._simbody_element,"dissipation",False)) + self.contact.static_friction=float(common.get_xml_data(self._simbody_element,"static_friction",False)) + self.contact.dynamic_friction=float(common.get_xml_data(self._simbody_element,"dynamic_friction",False)) + self.contact.viscous_friction=float(common.get_xml_data(self._simbody_element,"viscous_friction",False)) + self.contact.override_stiction_transition_velocity=float(common.get_xml_data(self._simbody_element,"override_stiction_transition_velocity",False)) @property def element(self): @@ -657,14 +657,14 @@ def configUI(self): self.ui.dart_collison_detector.currentTextChanged.connect(self.on_collision) #callbacks def on_type(self): - RD_globals.set_xml_data(self._dart_element,"solver_type",False,self.properties.solver_type) + common.set_xml_data(self._dart_element,"solver_type",False,self.properties.solver_type) def on_collision(self): - RD_globals.set_xml_data(self._dart_element,"collision_detector",False,self.properties.collision_detector) + common.set_xml_data(self._dart_element,"collision_detector",False,self.properties.collision_detector) def update_ui(self): - self.properties.solver_type=RD_globals.get_xml_data(self._dart_element,"solver_type",False) - self.properties.collision_detector=RD_globals.get_xml_data(self._dart_element,"collision_detector",False) + self.properties.solver_type=common.get_xml_data(self._dart_element,"solver_type",False) + self.properties.collision_detector=common.get_xml_data(self._dart_element,"collision_detector",False) @property def element(self): return self._dart_element @@ -781,22 +781,22 @@ def on_reset(self): print("physics resets applied \n") def on_step_sz(self): - RD_globals.set_xml_data(self._physics_elem,"max_step_size",False,self.properties.max_step_size) + common.set_xml_data(self._physics_elem,"max_step_size",False,self.properties.max_step_size) def on_real_time_fct(self): - RD_globals.set_xml_data(self._physics_elem,"real_time_factor",False,self.properties.real_time_factor) + common.set_xml_data(self._physics_elem,"real_time_factor",False,self.properties.real_time_factor) def on_update_rt(self): - RD_globals.set_xml_data(self._physics_elem,"real_time_update_rate",False,self.properties.real_time_update_rate) + common.set_xml_data(self._physics_elem,"real_time_update_rate",False,self.properties.real_time_update_rate) def on_max_cnt(self): - RD_globals.set_xml_data(self._physics_elem,"max_contacts",False,self.properties.max_contacts) + common.set_xml_data(self._physics_elem,"max_contacts",False,self.properties.max_contacts) #ode radio button def on_ode_radio_button(self): self._physics_elem.remove(self._physics_elem.iter(self.current_type_tag).__next__()) self.current_type_tag="ode" - RD_globals.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) + common.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) self._physics_elem.append(self._ode.element) #ode is at index 0 self.ui.physics_type_stack.setCurrentIndex(0) @@ -805,7 +805,7 @@ def on_ode_radio_button(self): def on_bullet_radio_button(self): self._physics_elem.remove(self._physics_elem.iter(self.current_type_tag).__next__()) self.current_type_tag="bullet" - RD_globals.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) + common.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) self._physics_elem.append(self._bullet.element) #bullet is at index 1 self.ui.physics_type_stack.setCurrentIndex(1) @@ -815,7 +815,7 @@ def on_simbody_radio_button(self): #remove current element self._physics_elem.remove(self._physics_elem.iter(self.current_type_tag).__next__()) self.current_type_tag="simbody" - RD_globals.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) + common.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) self._physics_elem.append(self._simbody.element) #simbody is at index 2 self.ui.physics_type_stack.setCurrentIndex(2) @@ -825,17 +825,17 @@ def on_dart_radio_button(self): #remove current element self._physics_elem.remove(self._physics_elem.iter(self.current_type_tag).__next__()) self.current_type_tag="dart" - RD_globals.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) + common.set_xml_data(self._physics_elem,self.tag,True,{"type":self.current_type_tag}) self._physics_elem.append(self._dart.element) #dart is at index 3 self.ui.physics_type_stack.setCurrentIndex(3) def update_ui(self): - self.properties.max_contacts=int(RD_globals.get_xml_data(self._physics_elem,"max_contacts",False)) - self.properties.real_time_update_rate=float(RD_globals.get_xml_data(self._physics_elem,"real_time_update_rate",False)) - self.properties.real_time_factor=float(RD_globals.get_xml_data(self._physics_elem,"real_time_factor",False)) - self.properties.max_step_size=float(RD_globals.get_xml_data(self._physics_elem,"max_step_size")) + self.properties.max_contacts=int(common.get_xml_data(self._physics_elem,"max_contacts",False)) + self.properties.real_time_update_rate=float(common.get_xml_data(self._physics_elem,"real_time_update_rate",False)) + self.properties.real_time_factor=float(common.get_xml_data(self._physics_elem,"real_time_factor",False)) + self.properties.max_step_size=float(common.get_xml_data(self._physics_elem,"max_step_size")) def reset(self,default:bool=True): @@ -853,7 +853,7 @@ def reset(self,default:bool=True): else: doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: el_str=el_dict['elem_str'] diff --git a/robot_descriptor/sdf_elements/road.py b/robot_descriptor/sdf_elements/road.py index 26055e8..5a8b41e 100644 --- a/robot_descriptor/sdf_elements/road.py +++ b/robot_descriptor/sdf_elements/road.py @@ -1,5 +1,5 @@ -from ..import RD_globals -from ..RD_parser import initialize_element_tree +from .. import common +from ..RD_utils import initialize_element_tree import copy from PySide import QtGui,QtCore import re @@ -164,7 +164,7 @@ def emissive(self,vals): #material element #============================================ #============================================ -class material(RD_globals.color_pickr): +class material(common.color_pickr): def __init__(self,ui) -> None: super().__init__() self.ui=ui @@ -219,13 +219,13 @@ def configUI(self): def on_uri(self): - RD_globals.set_xml_data(self._material_element,'uri',False,self.properties.script_uri) + common.set_xml_data(self._material_element,'uri',False,self.properties.script_uri) def on_uri_name(self): - RD_globals.set_xml_data(self._material_element,'name',False,self.properties.script_name) + common.set_xml_data(self._material_element,'name',False,self.properties.script_name) def on_shader_type(self): - RD_globals.set_xml_data(self._material_element,'shader',True,{'type':self.properties.shader_type}) + common.set_xml_data(self._material_element,'shader',True,{'type':self.properties.shader_type}) #enable and disable normal map def on_normal_map_state(self): @@ -236,29 +236,29 @@ def on_normal_map_state(self): #normal map def on_normal_map(self): - RD_globals.set_xml_data(self._material_element,'normal_map',False,self.properties.normal_map) + common.set_xml_data(self._material_element,'normal_map',False,self.properties.normal_map) #material render order def on_material_render_ord(self): - RD_globals.set_xml_data(self._material_element,'render_order',False,self.properties.render_order) + common.set_xml_data(self._material_element,'render_order',False,self.properties.render_order) def on_shininess(self): - RD_globals.set_xml_data(self._material_element,'shininess',False,self.properties.shininess) + common.set_xml_data(self._material_element,'shininess',False,self.properties.shininess) def on_ambient(self): - RD_globals.set_xml_data(self._material_element,'ambient',False,self.properties.ambient) + common.set_xml_data(self._material_element,'ambient',False,self.properties.ambient) self.set_widget_color('ambient',self.ui.material_ambient_color_pkr) def on_diffuse(self): - RD_globals.set_xml_data(self._material_element,'diffuse',False,self.properties.diffuse) + common.set_xml_data(self._material_element,'diffuse',False,self.properties.diffuse) self.set_widget_color('diffuse',self.ui.material_diffuse_color_pkr) def on_specular(self): - RD_globals.set_xml_data(self._material_element,'specular',False,self.properties.specular) + common.set_xml_data(self._material_element,'specular',False,self.properties.specular) self.set_widget_color('specular',self.ui.material_specular_color_pkr) def on_emissive(self): - RD_globals.set_xml_data(self._material_element,'emissive',False,self.properties.emissive) + common.set_xml_data(self._material_element,'emissive',False,self.properties.emissive) self.set_widget_color('emissive',self.ui.material_emissive_color_pkr) def on_ambient_color_pkr(self): @@ -274,16 +274,16 @@ def on_emissive_color_pkr(self): self.color_picker('emissive',self.ui.material_emissive_color_pkr) def updateUi(self): - self.properties.script_uri=RD_globals.get_xml_data(self._material_element,'uri',False) - self.properties.script_name=RD_globals.get_xml_data(self._material_element,'name',False) - self.properties.shader_type=RD_globals.get_xml_data(self._material_element,'type') - self.properties.normal_map=RD_globals.get_xml_data(self._material_element,'normal_map',False) - self.properties.render_order=RD_globals.get_xml_data(self._material_element,'render_order',False) - self.properties.shininess=RD_globals.get_xml_data(self._material_element,'shininess',False) - self.properties.ambient=RD_globals.get_xml_data(self._material_element,'ambient',False) - self.properties.diffuse=RD_globals.get_xml_data(self._material_element,'diffuse',False) - self.properties.specular=RD_globals.get_xml_data(self._material_element,'specular',False) - self.properties.emissive=RD_globals.get_xml_data(self._material_element,'emissive',False) + self.properties.script_uri=common.get_xml_data(self._material_element,'uri',False) + self.properties.script_name=common.get_xml_data(self._material_element,'name',False) + self.properties.shader_type=common.get_xml_data(self._material_element,'type') + self.properties.normal_map=common.get_xml_data(self._material_element,'normal_map',False) + self.properties.render_order=common.get_xml_data(self._material_element,'render_order',False) + self.properties.shininess=common.get_xml_data(self._material_element,'shininess',False) + self.properties.ambient=common.get_xml_data(self._material_element,'ambient',False) + self.properties.diffuse=common.get_xml_data(self._material_element,'diffuse',False) + self.properties.specular=common.get_xml_data(self._material_element,'specular',False) + self.properties.emissive=common.get_xml_data(self._material_element,'emissive',False) #style sheets self.set_widget_color('ambient',self.ui.material_ambient_color_pkr) self.set_widget_color('diffuse',self.ui.material_diffuse_color_pkr) @@ -299,7 +299,7 @@ def reset(self,default=True): else: doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: #find the material element from road elem=ET.fromstring(el_dict['elem_str']).find('.//material') @@ -313,19 +313,7 @@ def reset(self,default=True): #merger #this merge method repeats alot def merge_elements(self,destination_el, source_el): - # Update attributes of destination_el with source_el - destination_el.attrib.update(source_el.attrib) - if source_el.text: - destination_el.text = source_el.text - # Merge child elements recursively - for child in source_el: - existing_el = destination_el.find(child.tag) - if existing_el is not None: - self.merge_elements(existing_el, child) # Recursively merge the existing element with the new one - else: - # If the element doesn't exist in destination, simply append it - # destination_el.append(child) - pass + common.merge_elements(destination_el,source_el) @property def element(self): @@ -411,10 +399,10 @@ def on_road_reset(self): print('road resets applied\n') def on_road_name(self): - RD_globals.set_xml_data(self._road_element,'road',True,{'name':self._road_properties.name}) + common.set_xml_data(self._road_element,'road',True,{'name':self._road_properties.name}) def on_road_width(self): - RD_globals.set_xml_data(self._road_element,'width',False,self._road_properties.width) + common.set_xml_data(self._road_element,'width',False,self._road_properties.width) def get_sheet_data(self): #get spread sheet with points data @@ -439,8 +427,8 @@ def get_sheet_data(self): def updateUI(self): - self._road_properties.name=RD_globals.get_xml_data(self._road_element,['road','name'],True) - self._road_properties.width=RD_globals.get_xml_data(self._road_element,'width',False) + self._road_properties.name=common.get_xml_data(self._road_element,['road','name'],True) + self._road_properties.width=common.get_xml_data(self._road_element,'width',False) def reset(self,default=True): @@ -451,7 +439,7 @@ def reset(self,default=True): else: doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: elem=ET.fromstring(el_dict['elem_str']) self._road_element=elem diff --git a/robot_descriptor/sdf_elements/scene.py b/robot_descriptor/sdf_elements/scene.py index 3a99c0f..9908030 100644 --- a/robot_descriptor/sdf_elements/scene.py +++ b/robot_descriptor/sdf_elements/scene.py @@ -1,8 +1,8 @@ -from .. import RD_globals +from .. import common import copy import xml.etree.ElementTree as ET import FreeCAD -from ..RD_parser import initialize_element_tree +from ..RD_utils import initialize_element_tree from PySide import QtCore from PySide.QtGui import QColorDialog import math @@ -217,7 +217,7 @@ def fog_density(self,value): #============================================== #=============================================== -class scene(RD_globals.color_pickr): +class scene(common.color_pickr): def __init__(self,ui): self.ui=ui self.parent_path=['sdf','world'] @@ -329,91 +329,91 @@ def on_scene_ambient(self): self.set_widget_color('scene_ambient',self.ui.scene_ambient_color_pkr) def on_background(self): - RD_globals.set_xml_data(self._scene_element,"background",False,self.properties.background) + common.set_xml_data(self._scene_element,"background",False,self.properties.background) self.set_widget_color('background',self.ui.scene_background_color_pkr) def on_time(self): - RD_globals.set_xml_data(self._scene_element,"time",False,self.properties.time) + common.set_xml_data(self._scene_element,"time",False,self.properties.time) def on_sunrise(self): - RD_globals.set_xml_data(self._scene_element,"sunrise",False,self.properties.sunrise) + common.set_xml_data(self._scene_element,"sunrise",False,self.properties.sunrise) def on_sunset(self): - RD_globals.set_xml_data(self._scene_element,"sunset",False,self.properties.sunset) + common.set_xml_data(self._scene_element,"sunset",False,self.properties.sunset) def on_speed(self): - RD_globals.set_xml_data(self._scene_element,"speed",False,self.properties.speed) + common.set_xml_data(self._scene_element,"speed",False,self.properties.speed) def on_direction(self): - RD_globals.set_xml_data(self._scene_element,"direction",False,self.properties.direction) + common.set_xml_data(self._scene_element,"direction",False,self.properties.direction) def on_humidity(self): - RD_globals.set_xml_data(self._scene_element,"humidity",False,self.properties.humidity) + common.set_xml_data(self._scene_element,"humidity",False,self.properties.humidity) def on_cloud_ambient(self): #write to the ambient in clouds element - RD_globals.set_xml_data(self._scene_element.find("sky"),"ambient",False,self.properties.clouds_ambient) + common.set_xml_data(self._scene_element.find("sky"),"ambient",False,self.properties.clouds_ambient) self.set_widget_color('clouds_ambient',self.ui.cloud_ambient_color_pkr) def on_mean_size(self): - RD_globals.set_xml_data(self._scene_element,"mean_size",False,self.properties.mean_size) + common.set_xml_data(self._scene_element,"mean_size",False,self.properties.mean_size) def on_cube_map(self): - RD_globals.set_xml_data(self._scene_element,"cubemap_uri",False,self.properties.cubemap_uri) + common.set_xml_data(self._scene_element,"cubemap_uri",False,self.properties.cubemap_uri) def on_shadow(self): - RD_globals.set_xml_data(self._scene_element,"shadows",False,self.properties.shadows) + common.set_xml_data(self._scene_element,"shadows",False,self.properties.shadows) def on_grid(self): - RD_globals.set_xml_data(self._scene_element,"grid",False,self.properties.grid) + common.set_xml_data(self._scene_element,"grid",False,self.properties.grid) def on_origin_visual(self): - RD_globals.set_xml_data(self._scene_element,"origin_visual",False,self.properties.origin_visual) + common.set_xml_data(self._scene_element,"origin_visual",False,self.properties.origin_visual) def on_fog_color(self): - RD_globals.set_xml_data(self._scene_element,"color",False,self.properties.fog_color) + common.set_xml_data(self._scene_element,"color",False,self.properties.fog_color) self.set_widget_color('fog_color',self.ui.fog_color_picker_btn) def on_fog_type(self): - RD_globals.set_xml_data(self._scene_element,"type",False,self.properties.fog_type) + common.set_xml_data(self._scene_element,"type",False,self.properties.fog_type) def on_fog_start(self): - RD_globals.set_xml_data(self._scene_element,"start",False,self.properties.fog_start) + common.set_xml_data(self._scene_element,"start",False,self.properties.fog_start) def on_fog_end(self): - RD_globals.set_xml_data(self._scene_element,"end",False,self.properties.fog_end) + common.set_xml_data(self._scene_element,"end",False,self.properties.fog_end) def on_fog_density(self): - RD_globals.set_xml_data(self._scene_element,"density",False,self.properties.fog_density) + common.set_xml_data(self._scene_element,"density",False,self.properties.fog_density) #callbacks #end def update_ui(self): - self.properties.scene_ambient=RD_globals.extract_vector_n(self._scene_element.find("ambient").text) + self.properties.scene_ambient=common.extract_vector_n(self._scene_element.find("ambient").text) - self.properties.background=RD_globals.get_xml_data(self._scene_element,"background",False) + self.properties.background=common.get_xml_data(self._scene_element,"background",False) - self.properties.time=float(RD_globals.get_xml_data(self._scene_element,"time",False)) - self.properties.sunrise=float(RD_globals.get_xml_data(self._scene_element,"sunrise",False)) - self.properties.sunset=float(RD_globals.get_xml_data(self._scene_element,"sunset",False)) - self.properties.speed=float(RD_globals.get_xml_data(self._scene_element,"speed",False)) - self.properties.direction=float(RD_globals.get_xml_data(self._scene_element,"direction",False)) - self.properties.humidity=float(RD_globals.get_xml_data(self._scene_element,"humidity",False)) - - self.properties.clouds_ambient=RD_globals.get_xml_data(self._scene_element.find("sky"),"ambient",False) - self.properties.mean_size=RD_globals.get_xml_data(self._scene_element,"mean_size",False) + self.properties.time=float(common.get_xml_data(self._scene_element,"time",False)) + self.properties.sunrise=float(common.get_xml_data(self._scene_element,"sunrise",False)) + self.properties.sunset=float(common.get_xml_data(self._scene_element,"sunset",False)) + self.properties.speed=float(common.get_xml_data(self._scene_element,"speed",False)) + self.properties.direction=float(common.get_xml_data(self._scene_element,"direction",False)) + self.properties.humidity=float(common.get_xml_data(self._scene_element,"humidity",False)) + + self.properties.clouds_ambient=common.get_xml_data(self._scene_element.find("sky"),"ambient",False) + self.properties.mean_size=common.get_xml_data(self._scene_element,"mean_size",False) - self.properties.cubemap_uri=RD_globals.get_xml_data(self._scene_element,"cubemap_uri",False) - self.properties.shadows=RD_globals.get_xml_data(self._scene_element,"shadows",False) - self.properties.grid=RD_globals.get_xml_data(self._scene_element,"grid",False) - self.properties.origin_visual=RD_globals.get_xml_data(self._scene_element,"origin_visual",False) - self.properties.fog_color=RD_globals.get_xml_data(self._scene_element,"color",False) - self.properties.fog_type=RD_globals.get_xml_data(self._scene_element,"type",False) - self.properties.fog_start=RD_globals.get_xml_data(self._scene_element,"start",False) - self.properties.fog_end=RD_globals.get_xml_data(self._scene_element,"end",False) - self.properties.fog_density=RD_globals.get_xml_data(self._scene_element,"density",False) + self.properties.cubemap_uri=common.get_xml_data(self._scene_element,"cubemap_uri",False) + self.properties.shadows=common.get_xml_data(self._scene_element,"shadows",False) + self.properties.grid=common.get_xml_data(self._scene_element,"grid",False) + self.properties.origin_visual=common.get_xml_data(self._scene_element,"origin_visual",False) + self.properties.fog_color=common.get_xml_data(self._scene_element,"color",False) + self.properties.fog_type=common.get_xml_data(self._scene_element,"type",False) + self.properties.fog_start=common.get_xml_data(self._scene_element,"start",False) + self.properties.fog_end=common.get_xml_data(self._scene_element,"end",False) + self.properties.fog_density=common.get_xml_data(self._scene_element,"density",False) #update color of the color picker buttons color_list=[['fog_color',self.ui.fog_color_picker_btn],['clouds_ambient',self.ui.cloud_ambient_color_pkr], @@ -432,26 +432,14 @@ def reset(self,default:bool=True): doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: el_str=el_dict["elem_str"] self.merge_elements(self._scene_element,ET.fromstring(el_str)) self.update_ui() def merge_elements(self,destination_el, source_el): - # Update attributes of destination_el with source_el - destination_el.attrib.update(source_el.attrib) - if source_el.text: - destination_el.text = source_el.text - # Merge child elements recursively - for child in source_el: - existing_el = destination_el.find(child.tag) - if existing_el is not None: - self.merge_elements(existing_el, child) # Recursively merge the existing element with the new one - else: - # If the element doesn't exist in destination, simply append it - # destination_el.append(child) - pass + common.merge_elements(destination_el,source_el) @property def element(self): diff --git a/robot_descriptor/sdf_elements/spherical_coordinates.py b/robot_descriptor/sdf_elements/spherical_coordinates.py index ae3bec4..d93f166 100644 --- a/robot_descriptor/sdf_elements/spherical_coordinates.py +++ b/robot_descriptor/sdf_elements/spherical_coordinates.py @@ -1,6 +1,6 @@ -from .. import RD_globals +from .. import common import xml.etree.ElementTree as ET -from ..RD_parser import initialize_element_tree +from ..RD_utils import initialize_element_tree import copy import FreeCAD @@ -134,40 +134,40 @@ def on_reset(self): print("spherical resets applied \n") def on_surface_model(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"surface_model",False,self.properties.surface_model) + common.set_xml_data(self._spherical_coord_elem,"surface_model",False,self.properties.surface_model) def on_world_frame(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"world_frame_orientation",False,self.properties.world_frame_orientation) + common.set_xml_data(self._spherical_coord_elem,"world_frame_orientation",False,self.properties.world_frame_orientation) def on_latitude_deg(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"latitude_deg",False,self.properties.latitude_deg) + common.set_xml_data(self._spherical_coord_elem,"latitude_deg",False,self.properties.latitude_deg) def on_longitude(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"longitude_deg",False,self.properties.longitude_deg) + common.set_xml_data(self._spherical_coord_elem,"longitude_deg",False,self.properties.longitude_deg) def on_elevation(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"elevation",False,self.properties.elevation) + common.set_xml_data(self._spherical_coord_elem,"elevation",False,self.properties.elevation) def on_s_a_eq(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"surface_axis_equatorial",False,self.properties.surface_axis_equatorial) + common.set_xml_data(self._spherical_coord_elem,"surface_axis_equatorial",False,self.properties.surface_axis_equatorial) def on_s_a_p(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"surface_axis_polar",False,self.properties.surface_axis_polar) + common.set_xml_data(self._spherical_coord_elem,"surface_axis_polar",False,self.properties.surface_axis_polar) def on_heading(self): - RD_globals.set_xml_data(self._spherical_coord_elem,"heading_deg",False,self.properties.heading_deg) + common.set_xml_data(self._spherical_coord_elem,"heading_deg",False,self.properties.heading_deg) #end callbacks def update_ui(self): - self.properties.surface_model=RD_globals.get_xml_data(self._spherical_coord_elem,"surface_model",False) - self.properties.world_frame_orientation=RD_globals.get_xml_data(self._spherical_coord_elem,"world_frame_orientation",False) - self.properties.latitude_deg=float(RD_globals.get_xml_data(self._spherical_coord_elem,"latitude_deg",False)) - self.properties.longitude_deg=float(RD_globals.get_xml_data(self._spherical_coord_elem,"longitude_deg",False)) - self.properties.elevation=float(RD_globals.get_xml_data(self._spherical_coord_elem,"elevation",False)) - self.properties.surface_axis_equatorial=float(RD_globals.get_xml_data(self._spherical_coord_elem,"surface_axis_equatorial",False)) - self.properties.surface_axis_polar=float(RD_globals.get_xml_data(self._spherical_coord_elem,"surface_axis_polar",False)) - self.properties.heading_deg=float(RD_globals.get_xml_data(self._spherical_coord_elem,"heading_deg",False)) + self.properties.surface_model=common.get_xml_data(self._spherical_coord_elem,"surface_model",False) + self.properties.world_frame_orientation=common.get_xml_data(self._spherical_coord_elem,"world_frame_orientation",False) + self.properties.latitude_deg=float(common.get_xml_data(self._spherical_coord_elem,"latitude_deg",False)) + self.properties.longitude_deg=float(common.get_xml_data(self._spherical_coord_elem,"longitude_deg",False)) + self.properties.elevation=float(common.get_xml_data(self._spherical_coord_elem,"elevation",False)) + self.properties.surface_axis_equatorial=float(common.get_xml_data(self._spherical_coord_elem,"surface_axis_equatorial",False)) + self.properties.surface_axis_polar=float(common.get_xml_data(self._spherical_coord_elem,"surface_axis_polar",False)) + self.properties.heading_deg=float(common.get_xml_data(self._spherical_coord_elem,"heading_deg",False)) def reset(self,default:bool=True): @@ -176,7 +176,7 @@ def reset(self,default:bool=True): else: doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag_name]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag_name]) if el_dict is not None: el_str=el_dict['elem_str'] self.merge(el_str) @@ -186,7 +186,7 @@ def reset(self,default:bool=True): self.update_ui() def merge(self, el_str): - RD_globals.merge_elements(self._spherical_coord_elem,ET.fromstring(el_str)) + common.merge_elements(self._spherical_coord_elem,ET.fromstring(el_str)) @property diff --git a/robot_descriptor/sdf_elements/world.py b/robot_descriptor/sdf_elements/world.py index 2cfa462..4460652 100644 --- a/robot_descriptor/sdf_elements/world.py +++ b/robot_descriptor/sdf_elements/world.py @@ -5,11 +5,11 @@ import copy import xml.etree.ElementTree as ET -from .. import RD_globals +from .. import common #reponsible for creating an element tree using xml.etree -from ..RD_parser import initialize_element_tree +from ..RD_utils import initialize_element_tree -_icon_dir__=os.path.join(RD_globals.ICON_PATH,"world_properties.svg") +_icon_dir__=os.path.join(common.ICON_PATH,"world_properties.svg") '''setters will do nothing for optional part ''' @@ -109,7 +109,7 @@ def __init__(self): self.tag='world' self.file_name="world.sdf" - self.ui_path=os.path.join(RD_globals.UI_PATH,"world.ui") + self.ui_path=os.path.join(common.UI_PATH,"world.ui") self.world_form=FreeCADGui.PySideUic.loadUi(self.ui_path) mw=FreeCADGui.getMainWindow() #centre dialog to main window @@ -150,11 +150,11 @@ def closeEvent(self, event): event.accept() def update_ui(self): - self.properties.name=RD_globals.get_xml_data(self.world_elem,["world","name"],True) - self.properties.gravity=RD_globals.get_xml_data(self.world_elem,"gravity",False) - self.properties.wind=RD_globals.get_xml_data(self.world_elem,"linear_velocity",False) - self.properties.audio=RD_globals.get_xml_data(self.world_elem,"device",False) - self.properties.magnetic_field=RD_globals.get_xml_data(self.world_elem,"magnetic_field",False) + self.properties.name=common.get_xml_data(self.world_elem,["world","name"],True) + self.properties.gravity=common.get_xml_data(self.world_elem,"gravity",False) + self.properties.wind=common.get_xml_data(self.world_elem,"linear_velocity",False) + self.properties.audio=common.get_xml_data(self.world_elem,"device",False) + self.properties.magnetic_field=common.get_xml_data(self.world_elem,"magnetic_field",False) #this will be called by the reset callback def reset(self,default:bool=True): @@ -166,7 +166,7 @@ def reset(self,default:bool=True): else: doc=FreeCAD.ActiveDocument _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=RD_globals.parse_dict(_root_dict,self.parent_path+[self.tag]) + el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) if el_dict is not None: el_str=el_dict['elem_str'] self.merge(el_str) @@ -177,7 +177,7 @@ def reset(self,default:bool=True): self.update_ui() def merge(self, el_str): - RD_globals.merge_elements(self.world_elem,ET.fromstring(el_str)) + common.merge_elements(self.world_elem,ET.fromstring(el_str)) def configUI(self): self.world_form.world_name_input.textEdited.connect(self.on_world_name) @@ -230,15 +230,15 @@ def on_reset(self): def on_world_name(self): name=self.properties.name - RD_globals.set_xml_data(self.world_elem,"world",True,{"name":name}) + common.set_xml_data(self.world_elem,"world",True,{"name":name}) def on_gravity(self): - RD_globals.set_xml_data(self.world_elem,"gravity",False,self.properties.gravity) + common.set_xml_data(self.world_elem,"gravity",False,self.properties.gravity) def on_magn(self): - RD_globals.set_xml_data(self.world_elem,"magnetic_field",False,self.properties.magnetic_field) + common.set_xml_data(self.world_elem,"magnetic_field",False,self.properties.magnetic_field) def on_wind(self): - RD_globals.set_xml_data(self.world_elem,"linear_velocity",False,self.properties.wind) + common.set_xml_data(self.world_elem,"linear_velocity",False,self.properties.wind) def on_audio(self): - RD_globals.set_xml_data(self.world_elem,"device",False,self.properties.audio) + common.set_xml_data(self.world_elem,"device",False,self.properties.audio) #ok push button pressed callback def on_ok(self): @@ -248,33 +248,33 @@ def on_ok(self): def on_apply_pb(self): #read string element data from RD_description proxy updated_elem=self.update_element() - RD_globals.update_dictionary(self.parent_path,self.tag,updated_elem) + common.update_dictionary(self.parent_path,self.tag,updated_elem) #append elements in hierachy as they are supposed to appear in the tree e.g world is appended #before atmosphere since its atmospheres parent, this helpsFreeCADGui.PySideUic.loadUi(self.ui_path,self) reduce the complexity #of having to implement a way of ensuring parents are available # dont add atmosphere element if the group box is not checked if self.atmosphere.is_checked(): - RD_globals.update_dictionary(self.atmosphere.parent_path,self.atmosphere.tag,self.atmosphere.atmosphere_element) + common.update_dictionary(self.atmosphere.parent_path,self.atmosphere.tag,self.atmosphere.atmosphere_element) #add physics properties - RD_globals.update_dictionary(self._physics.parent_path,self._physics.tag,self._physics.element) + common.update_dictionary(self._physics.parent_path,self._physics.tag,self._physics.element) #add spherical coordiates if self.world_form.spherical_coordinates_groupbox.isChecked(): - RD_globals.update_dictionary( + common.update_dictionary( self._spherical_coordinates.parent_path, self._spherical_coordinates.tag_name, self._spherical_coordinates.spherical_cood_elem) #dont attempt to add a lights if there are no light sources if len(self._lights.lights) >0: - RD_globals.update_dictionary(self._lights.parent_path,self._lights.tag,self._lights.element) + common.update_dictionary(self._lights.parent_path,self._lights.tag,self._lights.element) #add scene based on state of a checkbox if self.world_form.enable_scene_checkBox.isChecked(): - RD_globals.update_dictionary(self._scene.parent_path,self._scene.tag,self._scene.element) + common.update_dictionary(self._scene.parent_path,self._scene.tag,self._scene.element) #append the road element if self.world_form.enable_road_checkbox.isChecked(): - RD_globals.update_dictionary(self._road.parent_path,self._road.tag,self._road.element) + common.update_dictionary(self._road.parent_path,self._road.tag,self._road.element) print("updated\n") From c803ecd7fedee5e5a264349f29d50f93d702ae45 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Wed, 10 Jan 2024 09:31:56 +0300 Subject: [PATCH 2/9] model TreeView --- robot_descriptor/RD_utils/parse_asm4_model.py | 24 +++++++++++++++---- robot_descriptor/model_editor.py | 17 ++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/robot_descriptor/RD_utils/parse_asm4_model.py b/robot_descriptor/RD_utils/parse_asm4_model.py index 799c869..c62c101 100644 --- a/robot_descriptor/RD_utils/parse_asm4_model.py +++ b/robot_descriptor/RD_utils/parse_asm4_model.py @@ -11,6 +11,18 @@ def read_assembly(): links=FreeCAD.ActiveDocument.findObjects("App::Link") + + #get all objects of type part feature + objs=FreeCAD.ActiveDocument.findObjects("Part::Feature") + #get objects in the parts group + parts=FreeCAD.ActiveDocument.Parts.Group + #get fasteners since fasteners might not be accesed through links + #remove objects in parts , coordinate systems + #coordinate systems are removed by checking the MapMode attribute + #hopefully this is will get only fasteners + fasteners=[fast for fast in objs if fast not in parts and not hasattr(fast,'MapMode')] + links= links+fasteners + #links in Assembly4 are of type "App::Link" #this is a list #this will store a list of dictionaries @@ -33,13 +45,15 @@ def create_structure(data,dest): #hence separating by the the '#' and taking the first element will be the parent #the 2nd the coordinate system its attached to parent,attachement=child.AttachedTo.split('#') - #Attachmensts are usually made with reference to coordiante systems of type "PartDesign::CoordinateSystem" find them in all links - # and remove lcs with label 'LCS_Origin' in case it exists in model - coordinate_systems=[ lcs for lcs in child.Document.findObjects("PartDesign::CoordinateSystem") if lcs.Label !='LCS_Origin' ] - link_data.append({"link":child,"name":name,"parent":parent,"attachment":attachement,"coordinate_systems":coordinate_systems,'children':[]}) + #returned type has '#' preceeding the coordinate remove it + attached_by=child.AttachedBy.replace('#','') + link_data.append({"link":child,"name":name,"parent":parent,"attached_to":attachement,"attached_by":attached_by,'children':[]}) # #create a hierarchial data - + if hasattr(child,"LinkedObject"): + if hasattr(child.LinkedObject.Document,"Assembly"): + FreeCAD.Console.PrintError("Sub assemblies not supported yet \n") + return None root_lcs=FreeCAD.ActiveDocument.findObjects("PartDesign::CoordinateSystem") structured_data={"link":None,'name':"Parent Assembly","attachment":None,"coordinate_systems":root_lcs,"children":[]} diff --git a/robot_descriptor/model_editor.py b/robot_descriptor/model_editor.py index e3a34c3..4bed886 100644 --- a/robot_descriptor/model_editor.py +++ b/robot_descriptor/model_editor.py @@ -6,18 +6,24 @@ from .RD_utils import parse_asm4_model from PySide.QtGui import QStandardItemModel,QStandardItem - +#start standard item class standard_item(QStandardItem): def __init__(self,text): super().__init__() self.model_elem=None self.setText(text) - + self.setEditable(False) +#end standard Item +#============================================== +#model editor class ModelEditor: def __init__(self): # find all objects of type 'App::Link' #doc=FreeCAD.ActiveDocument + self.links_hierarchy=parse_asm4_model.read_assembly() + if self.links_hierarchy is None: + return self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) self.link_model=QStandardItemModel() self.root_node=self.link_model.invisibleRootItem() @@ -28,8 +34,10 @@ def __init__(self): self.ModelEditorUi.exec() def tree_setup(self,link_hierarchy,item): + #iterate throuhg all children create items and the to tree for child in link_hierarchy: row=standard_item(child["name"]) + item.appendRow(row) self.tree_setup(child["children"],row) return @@ -46,7 +54,10 @@ def GetResources(self): "ToolTip" : "Edit link and joint properties"} def Activated(self): - self.edits=ModelEditor() + if hasattr(FreeCAD.ActiveDocument,"Assembly"): + self.edits=ModelEditor() + else: + FreeCAD.Console.PrintMessage("document does not contain an assembly\n") return def IsActive(self): From 2c37fb64efb165477fe6b983acee9dd790294325 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Fri, 12 Jan 2024 20:01:39 +0300 Subject: [PATCH 3/9] model_editor ui --- robot_descriptor/RD_utils/parse_asm4_model.py | 9 +- robot_descriptor/common.py | 14 +- robot_descriptor/forms/material.ui | 2397 ++++++---- robot_descriptor/forms/model_editor.ui | 1865 +++++++- robot_descriptor/forms/surface.ui | 1363 ++++++ robot_descriptor/forms/world.ui | 3960 +++++++---------- robot_descriptor/model_editor.py | 44 +- robot_descriptor/sdf_elements/collision.py | 0 robot_descriptor/sdf_elements/light.py | 2 + robot_descriptor/sdf_elements/link.py | 134 + robot_descriptor/sdf_elements/material.py | 746 ++++ robot_descriptor/sdf_elements/model.py | 9 + robot_descriptor/sdf_elements/road.py | 349 +- robot_descriptor/sdf_elements/world.py | 11 +- 14 files changed, 7100 insertions(+), 3803 deletions(-) create mode 100644 robot_descriptor/forms/surface.ui create mode 100644 robot_descriptor/sdf_elements/collision.py create mode 100644 robot_descriptor/sdf_elements/link.py create mode 100644 robot_descriptor/sdf_elements/material.py create mode 100644 robot_descriptor/sdf_elements/model.py diff --git a/robot_descriptor/RD_utils/parse_asm4_model.py b/robot_descriptor/RD_utils/parse_asm4_model.py index c62c101..04699d6 100644 --- a/robot_descriptor/RD_utils/parse_asm4_model.py +++ b/robot_descriptor/RD_utils/parse_asm4_model.py @@ -21,7 +21,14 @@ def read_assembly(): #coordinate systems are removed by checking the MapMode attribute #hopefully this is will get only fasteners fasteners=[fast for fast in objs if fast not in parts and not hasattr(fast,'MapMode')] - links= links+fasteners + + #ensure that the link and the fastener are not the same object + #this might occur when the parts folder contains some parts that are used in the assembly + #get link documents + lnk_docs=[lnk.LinkedObject.Document for lnk in links] + for fastener in fasteners: + if fastener.Document not in lnk_docs: + links.append(fastener) #links in Assembly4 are of type "App::Link" #this is a list diff --git a/robot_descriptor/common.py b/robot_descriptor/common.py index 3c166db..4f94cca 100644 --- a/robot_descriptor/common.py +++ b/robot_descriptor/common.py @@ -114,9 +114,9 @@ def get_value(elem_data): try: try: return int(elem_data) - except: + except Exception: return float(elem_data) - except: + except Exception: return elem_data if Is_Attribute is not True: @@ -126,7 +126,7 @@ def get_value(elem_data): #only a single element exists no need to use a for loop try: elem=elem_iter.__next__() - except: + except Exception: return None if Is_Attribute is False: txt=elem.text @@ -138,9 +138,9 @@ def get_value(elem_data): try: try: return int(elem.attrib[tag[1]]) - except: + except Exception: return float(elem.attrib[tag[1]]) - except: + except Exception: return elem.attrib[tag[1]] #deleting attributes @@ -165,14 +165,17 @@ def parse_dict(root_dict:dict,path:list): # used to track the current index of the path list current_idx=0 + #if only one element is left return it if len(path)==1: if path[-1]=='sdf': return root_dict[path[-1]] + #check if the element exists elif path[-1] in list(root_dict.keys()): return root_dict[path[-1]] else: return None else: + #get the first item in the dictionary parent_key=path[current_idx] current_idx+=1 #child element tag @@ -202,6 +205,7 @@ def update_dictionary(path:list,child_tag:Union[str,None],elem:Union[list,ET.Ele parent_dict=parse_dict(elem_dict,path) if parent_dict is not None: + #this allows update of an element not its children basically None means not the children if child_tag is None: if isinstance(elem,list): parent_dict["elem_str"]=list(map(lambda e:ET.tostring(e,encoding="unicode"),elem)) diff --git a/robot_descriptor/forms/material.ui b/robot_descriptor/forms/material.ui index faf70fa..fbf8c92 100644 --- a/robot_descriptor/forms/material.ui +++ b/robot_descriptor/forms/material.ui @@ -1,530 +1,225 @@ - Form - + material + 0 0 - 573 - 690 + 548 + 1545 - Form + material - + - 8 - 82 - 259 - 89 + 0 + 14 + 538 + 1536 - - - 0 - 89 - - - - script - - - true - - - false - - - - - 18 - 28 - 16 - 15 - - - - uri - - - - - - 52 - 24 - 175 - 23 - - - - - - - 12 - 56 - 34 - 15 - - - - name - - - - - - 52 - 52 - 113 - 23 - - - - - - - - 280 - 84 - 259 - 89 - - - - - 0 - 89 - - - - shader - - - true - - - false - - - - - 12 - 32 - 57 - 15 - - - - TextLabel - - - - - - 80 - 28 - 79 - 23 - - - - - vertex - - - - - pixel - - - - - normal_map_object_space - - - - - normal_map_tangent_space - - - - - - - 8 - 60 - 100 - 21 - - - - normal_map - - - - - - 114 - 60 - 113 - 23 - - - - - - - - 10 - 184 - 78 - 24 - - - - - 0 - 24 - - - - render_order - - - - - - 94 - 180 - 83 - 24 - - - - - 0 - 24 - - - - Set render order for coplanar polygons. The higher value will be rendered on top of the other coplanar polygons - - - - - - 8 - 650 - 85 - 24 - - - - - 0 - 24 - - - - lighting - - - - - - 4 - 210 - 520 - 100 - - - - - 520 - 100 - - - 520 - 100 + 538 + 2000 - - background color - - - ambient - - - true - - - false - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - - + + + - 0 - 24 + 240 + 89 - 16777215 - 24 + 240 + 95 + + script + + + true + + + false + + + + + + uri + + + + + + + + 160 + 16777215 + + + + + + + + + 50 + 24 + + + + name + + + + + + + + 115 + 16777215 + + + + + - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter - - - - - + + - 0 - 24 + 240 + 95 - 16777215 - 24 + 240 + 95 + + shader + + + true + + + false + + + + + 12 + 30 + 57 + 16 + + + + type + + + + + + 82 + 26 + 100 + 21 + + + + + 100 + 16777215 + + + + + pixel + + + + + vertex + + + + + normal_map_object_space + + + + + normal_map_tangent_space + + + + + + + 12 + 57 + 100 + 20 + + + + normal_map + + + + + + 118 + 57 + 100 + 20 + + + + + 100 + 16777215 + + + - - - - - 45 - 16777215 - - - - - - - - - - - - - 6 - 322 - 520 - 100 - - - - - 520 - 100 - - - - - 520 - 100 - - - - background color - - - diffuse - - - true - - - false - - - + - 0 - 24 - - - - - 16777215 - 24 - - - - - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 16777215 + 85 24 - - A - - - Qt::AlignCenter - - - - - - 16777215 - 24 + 85 + 28 - R - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - + render_order - + 0 @@ -533,272 +228,826 @@ - 16777215 - 24 + 100 + 105 - - - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter + + Set render order for coplanar polygons. The higher value will be rendered on top of the other coplanar polygons - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - - + + - 45 + 56 16777215 - + shininess - - - - - - 6 - 434 - 520 - 100 - - - - - 520 - 100 - - - - - 520 - 100 - - - - background color - - - specular - - - true - - - false - - - - + + - 0 + 90 24 - 16777215 - 24 + 100 + 27 - - - + + + - 16777215 - 24 + 520 + 100 - - B - - - Qt::AlignCenter - - - - - - 16777215 - 24 + 520 + 100 - - A - - - Qt::AlignCenter - + + background color + + + ambient + + + true + + + false + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + B + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + A + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + G + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 45 + 16777215 + + + + + + + + - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - + + - 0 - 24 + 520 + 100 - 16777215 - 24 + 520 + 100 + + background color + + + diffuse + + + true + + + false + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + B + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + A + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + G + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 45 + 16777215 + + + + + + + + - - + + - 0 - 24 + 520 + 100 - 16777215 - 24 - - - - - - - - - 16777215 - 24 + 520 + 100 - - G - - - Qt::AlignCenter - + + background color + + + specular + + + true + + + false + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + B + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + A + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + G + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 45 + 16777215 + + + + + + + + - - + + - 0 - 24 - - - - - 16777215 - 24 + 520 + 100 - - - - - 45 - 16777215 + 520 + 100 - - - + + background color + + + emissive + + + true + + + false + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + B + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + A + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + G + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 45 + 16777215 + + + + + + + + - - - - - - 6 - 544 - 520 - 100 - - - - - 520 - 100 - - - - - 520 - 100 - - - - background color - - - emissive - - - true - - - false - - - - + + 0 @@ -807,78 +1056,17 @@ - 16777215 - 24 - - - - - - - - - 16777215 - 24 + 120 + 25 - B - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - + lighting - - + + 0 @@ -887,231 +1075,542 @@ - 16777215 - 24 - - - - - - - - - 16777215 - 24 + 120 + 25 - G - - - Qt::AlignCenter + double_sided - - + + - 0 - 24 + 470 + 933 - 16777215 - 24 + 520 + 1100 - - - - - - - 45 - 16777215 - - - - - + + pbr + + + true + + + false + + + + + + metal + + + false + + + false + + + + + + albedo_map + + + + + + + + + + roughness_map + + + + + + + + + + roughness + + + + + + + + + + metalness_map + + + + + + + + + + metalness + + + + + + + + 250 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + environment_map + + + + + + + + + + ambient_occlusion_map + + + + + + + + + + emissive_map + + + + + + + + + + + 100 + 140 + + + + + 210 + 140 + + + + normal_map + + + true + + + false + + + + + + + 0 + 24 + + + + + + + + + 50 + 24 + + + + + 75 + 26 + + + + type + + + + + + + + 105 + 24 + + + + + 110 + 27 + + + + + tangent + + + + + object + + + + + + + + + + + + 220 + 75 + + + + + 250 + 140 + + + + light_map + + + true + + + false + + + + + + + 135 + 24 + + + + + 175 + 27 + + + + + + + + + 0 + 24 + + + + uv_set + + + + + + + + 90 + 24 + + + + + 120 + 27 + + + + + + + + + + + + + + + 400 + 370 + + + + + 450 + 370 + + + + specular + + + true + + + false + + + + + + albedo_map + + + + + + + specular_map + + + + + + + glossiness + + + + + + + + 250 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + environment_map + + + + + + + ambient_occlusion_map + + + + + + + + + + emissive_map + + + + + + + glossiness_map + + + + + + + + 200 + 100 + + + + + 210 + 130 + + + + light_map + + + true + + + false + + + + + + + 100 + 24 + + + + + 170 + 30 + + + + + + + + + 50 + 24 + + + + + 95 + 30 + + + + uv_set + + + + + + + + 85 + 24 + + + + + + + + + + + + 200 + 94 + + + + + 300 + 130 + + + + normal_map + + + false + + + true + + + false + + + + + + + + + type + + + + + + + + tangent + + + + + object + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - 382 - 184 - 57 - 15 - - - - shininess - - - - - - 446 - 180 - 87 - 24 - - - - - 0 - 24 - - - - - - - 116 - 650 - 105 - 24 - - - - - 0 - 24 - - - - double_sided - - - - - - 60 - 52 - 62 - 24 - - - - - 0 - 24 - - - - - - - 446 - 20 - 80 - 24 - - - - - 0 - 24 - - - - browse - - - - - - 326 - 20 - 113 - 24 - - - - - 0 - 24 - - - - - - - 282 - 18 - 37 - 24 - - - - - 0 - 24 - - - - points - - - - - - 18 - 52 - 34 - 24 - - - - - 0 - 24 - - - - width - - - - - - 62 - 18 - 113 - 24 - - - - - 0 - 24 - - - - - - - 16 - 18 - 34 - 24 - - - - - 0 - 24 - - - - name - - diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui index 1756fe9..3eef09d 100644 --- a/robot_descriptor/forms/model_editor.ui +++ b/robot_descriptor/forms/model_editor.ui @@ -6,47 +6,1858 @@ 0 0 - 909 - 557 + 959 + 775 - Dialog + Model Editor - - - + + + + + + 216 + 716 + + - 220 - 16777215 + 250 + 800 + + + + + + + + + 685 + 530 - - QFrame::StyledPanel + + + 700 + 720 + - - QFrame::Raised + + 1 - - - - 2 - 4 - 213 - 527 - - + + + link + + + + + 6 + 2 + 107 + 25 + + + + __link_name__ + + + + + + 12 + 42 + 215 + 91 + + + + + 215 + 91 + + + + link states + + + true + + + false + + + + + + If true, the link is affected by gravity + + + gravity + + + + + + + If true, the link is affected by the wind + + + enable_wind + + + + + + + If true, the link is kinematic only + + + kinematic + + + + + + + If true, the link can collide with other links in the model. +Two links within a model will collide if link1.self_collide OR link2.self_collide. +Links connected by a joint will never collide + + + self_collide + + + + + + + + + 12 + 140 + 217 + 98 + + + + + 217 + 98 + + + + Exponential damping of the link's velocity. + + + velocity_decay + + + true + + + false + + + + + + + 35 + 15 + + + + + 45 + 16 + + + + linear + + + + + + + 5 + + + 1000.000000000000000 + + + + + + + + 50 + 25 + + + + + 55 + 27 + + + + angular + + + + + + + 5 + + + 1000.000000000000000 + + + + + + + + + 14 + 244 + 213 + 63 + + + + + 213 + 63 + + + + inertial + + + true + + + false + + + + + + auto + + + + + + + + + 234 + 6 + 433 + 707 + + + + true + + + + + 0 + 0 + 417 + 918 + + + + + + + + 348 + 900 + + + + + 413 + 950 + + + + This link's fluid added mass matrix about the link's origin. + This matrix represents the inertia of the fluid that is dislocated when the + body moves. Added mass should be zero if the density of the surrounding + fluid is negligible with respect to the body's density. + The 6x6 matrix is symmetric, therefore only 21 unique elements can be set. + The elements of the matrix follow the [x, y, z, p, q, r] notation, where + [x, y, z] correspond to translation and [p, q, r] to rotation + + + fluid_added_mass + + + true + + + false + + + + + 12 + 30 + 370 + 190 + + + + + 370 + 190 + + + + + 372 + 190 + + + + x_axis + + + + + 18 + 28 + 344 + 66 + + + + + 340 + 66 + + + + + 344 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to linear acceleration in the X axis, in kg + + + kg + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to linear acceleration in the Y axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + Added mass in the X axis due to linear acceleration in the Z axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + 12 + 108 + 345 + 66 + + + + + 343 + 66 + + + + + 345 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the X axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m + + + kgm + + + 1000.000000000000000 + + + + + + + + + + 12 + 226 + 370 + 190 + + + + + 370 + 190 + + + + + 372 + 190 + + + + y_axis + + + + + 8 + 30 + 343 + 66 + + + + + 343 + 66 + + + + + 344 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to linear acceleration in the Y axis, in kg + + + kg + + + 1000.000000000000000 + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to linear acceleration in the Z axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + 12 + 108 + 345 + 66 + + + + + 343 + 66 + + + + + 345 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the X axis, and vice-versa, in kg * m + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + + + 12 + 422 + 370 + 190 + + + + + 370 + 190 + + + + + 372 + 190 + + + + z_axis + + + + + 8 + 30 + 343 + 66 + + + + + 343 + 66 + + + + + 344 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + 78 + 30 + 112 + 26 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to linear acceleration in the Z axis, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + + 12 + 108 + 345 + 66 + + + + + 343 + 66 + + + + + 345 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the X axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + + + 12 + 618 + 370 + 255 + + + + + 370 + 255 + + + + + 372 + 265 + + + + moment + + + + + 16 + 100 + 343 + 66 + + + + + 343 + 66 + + + + + 345 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_y + + + + + 12 + 30 + 120 + 26 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + 149 + 30 + 120 + 26 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + + + + + + + + 12 + 28 + 345 + 66 + + + + + 343 + 66 + + + + + 345 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_x + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the X axis, in kg * m^2. + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2. + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + 18 + 174 + 343 + 66 + + + + + 343 + 66 + + + + + 344 + 67 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_z + + + + + 79 + 30 + 118 + 26 + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 + + + kgm^2 + + + + + + + + + + + + + + + + collision + + + + + 16 + 76 + 629 + 603 + + + + true + + + + + 0 + 0 + 627 + 601 + + + + + + + + 16 + 6 + 455 + 26 + + + + + + + + 70 + 24 + + + + + 75 + 30 + + + + laser_retro + + + + + + + + + + max_contacts + + + + + + + + + + + + Material + + + + + 18 + 12 + 567 + 655 + + + + true + + + + + 0 + 0 + 565 + 653 + + + + - - - - QFrame::StyledPanel + + + + + 90 + 24 + + + + + 95 + 30 + + + + Reset + + + + + + + + 90 + 24 + + + + + 95 + 30 + + + + Apply + + + + + + + + 90 + 24 + + + + + 100 + 30 + - - QFrame::Raised + + Ok diff --git a/robot_descriptor/forms/surface.ui b/robot_descriptor/forms/surface.ui new file mode 100644 index 0000000..b2103d0 --- /dev/null +++ b/robot_descriptor/forms/surface.ui @@ -0,0 +1,1363 @@ + + + Form + + + + 0 + 0 + 600 + 816 + + + + + 600 + 0 + + + + + 653 + 16777215 + + + + Form + + + + + + + + + surface + + + + + + bounce + + + true + + + false + + + + + + + 90 + 24 + + + + + 110 + 27 + + + + Bounciness coefficient of restitution, from [0...1], where 0=no bounciness + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + threshold + + + + + + + + 90 + 24 + + + + + 110 + 27 + + + + Bounce capture velocity, below which effective coefficient of restitution is 0 + + + 10000.000000000000000 + + + 1.000000000000000 + + + + + + + restitution_coefficient + + + + + + + + + + + 0 + 630 + + + + 1 + + + + friction + + + + + 10 + 14 + 533 + 162 + + + + + 0 + 160 + + + + + 16777215 + 170 + + + + torsional + + + true + + + false + + + + + + + 0 + 24 + + + + + 70 + 16777215 + + + + coefficient + + + + + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Torsional friction coefficient, unitless maximum ratio of + tangential stress to normal stress. + + + + + + + + 180 + 120 + + + + + 210 + 16777215 + + + + Torsional friction parameters for ODE + + + ode + + + true + + + + + 16 + 30 + 57 + 15 + + + + slip + + + + + + 56 + 26 + 111 + 24 + + + + force dependent slip for torsional friction, + equivalent to inverse of viscous damping coefficient + with units of rad/s/(Nm). + A slip value of 0 is infinitely viscous + + + + + + + + + 0 + 24 + + + + + 130 + 16777215 + + + + If this flag is true, + torsional friction is calculated using the "patch_radius" parameter. + If this flag is set to false, + "surface_radius" (R) and contact depth (d) + are used to compute the patch radius as sqrt(R*d). + + + use_patch_radius + + + + + + + + 0 + 24 + + + + + 80 + 16777215 + + + + patch_radius + + + + + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Radius of contact patch surface + + + + + + + + 0 + 24 + + + + + 130 + 16777215 + + + + surface_radius + + + + + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Surface radius on the point of contact + + + + + + + + + 14 + 186 + 541 + 205 + + + + + 0 + 205 + + + + + 16777215 + 220 + + + + ODE + + + true + + + false + + + + + 100 + 34 + 62 + 24 + + + + Coefficient of friction in first friction pyramid direction, + the unitless maximum ratio of force in first friction pyramid + direction to normal force. + + + + + + 102 + 74 + 62 + 24 + + + + Coefficient of friction in second friction pyramid direction, + the unitless maximum ratio of force in second friction pyramid + direction to normal force. + + + + + + 18 + 104 + 493 + 66 + + + + + 500 + 465 + + + + unit vector specifying first friction pyramid direction in + collision-fixed reference frame. + If the friction pyramid model is in use, + and this value is set to a unit vector for one of the + colliding surfaces + + + fdir1 + + + true + + + + + + + 27 + 16777215 + + + + x + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 27 + 16777215 + + + + y + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 27 + 27 + + + + z + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + + 10 + 38 + 85 + 21 + + + + mu + + + + + + 10 + 74 + 85 + 21 + + + + mu2 + + + + + + 218 + 44 + 85 + 21 + + + + slip1 + + + + + + 214 + 84 + 85 + 21 + + + + slip2 + + + + + + 312 + 42 + 62 + 24 + + + + Force dependent slip in first friction pyramid direction, +equivalent to inverse of viscous damping coefficient + with units of m/s/N. + A slip value of 0 is infinitely viscous + + + + + + 314 + 82 + 62 + 24 + + + + Force dependent slip in second friction pyramid direction, + equivalent to inverse of viscous damping coefficient + with units of m/s/N. + A slip value of 0 is infinitely viscous. + + + + + + + 12 + 400 + 549 + 138 + + + + bullet + + + true + + + false + + + + + + friction + + + + + + + Coefficient of friction in first friction pyramid direction, + the unitless maximum ratio of force in first friction pyramid + direction to normal force + + + + + + + friction2 + + + + + + + Coefficient of friction in second friction pyramid direction, + the unitless maximum ratio of force in second friction pyramid + direction to normal force + + + + + + + rolling_friction + + + + + + + Coefficient of rolling friction + + + + + + + + 500 + 465 + + + + Unit vector specifying first friction pyramid direction in + collision-fixed reference frame + + + fdir1 + + + true + + + + + + + 27 + 16777215 + + + + x + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 27 + 16777215 + + + + y + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 27 + 27 + + + + z + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + contact + + + + + + + 220 + 16777215 + + + + Flag to disable contact force generation, while still allowing collision checks and contact visualization to occur + + + collide_without_contact + + + + + + + + 220 + 16777215 + + + + collide_without_contact_bitmask + + + + + + + + 50 + 24 + + + + + 120 + 16777215 + + + + Bitmask for collision filtering when collide_without_contact is on + + + + + + + + 120 + 16777215 + + + + collide_bitmask + + + + + + + + 50 + 24 + + + + + 120 + 16777215 + + + + Bitmask for collision filtering. This will override collide_without_contact. Parsed as 16-bit unsigned integer + + + 65535 + + + + + + + + 0 + 24 + + + + + 120 + 16777215 + + + + category_bitmask + + + + + + + + 50 + 24 + + + + + 120 + 16777215 + + + + Bitmask for category of collision filtering. +Collision happens if ((category1 & collision2) | (category2 & collision1)) is not zero. +If not specified, the category_bitmask should be interpreted as being the same as collide_bitmask. +Parsed as 16-bit unsigned integer + + + 65535 + + + + + + + + 120 + 16777215 + + + + poissons_ratio + + + + + + + + 50 + 24 + + + + + 120 + 16777215 + + + + Poisson's ratio is the unitless ratio between transverse and axial strain. + This value must lie between (-1, 0.5). Defaults to 0.3 for typical steel. + Note typical silicone elastomers have Poisson's ratio near 0.49 ~ 0.50 + + + + + + + + 120 + 16777215 + + + + elastic_modulus + + + + + + + + 50 + 24 + + + + + 120 + 16777215 + + + + Young's Modulus in SI derived unit Pascal. + Defaults to -1. If value is less or equal to zero, + contact using elastic modulus (with Poisson's Ratio) is disabled. + + + + + + + ode + + + true + + + false + + + + + + soft_cfm + + + + + + + Soft constraint force mixing + + + + + + + kd + + + + + + + dynamically "damping"-equivalent coefficient for contact joints + + + + + + + soft_erp + + + + + + + Soft error reduction parameter + + + + + + + max_vel + + + + + + + dynamically "damping"-equivalent coefficient for contact joints + + + + + + + kp + + + + + + + dynamically "stiffness"-equivalent coefficient for contact joints + + + 2000000000000.000000000000000 + + + + + + + min_depth + + + + + + + minimum allowable depth before contact correction impulse is applied + + + + + + + + + + + 551 + 155 + + + + bullet + + + true + + + false + + + + + 10 + 86 + 117 + 21 + + + + kp + + + + + + 133 + 25 + 146 + 24 + + + + Soft constraint force mixing + + + + + + 10 + 56 + 117 + 21 + + + + soft_erp + + + + + + 133 + 55 + 146 + 24 + + + + see ode + + + + + + 285 + 26 + 117 + 21 + + + + kd + + + + + + 408 + 25 + 117 + 24 + + + + see ode + + + + + + 133 + 85 + 146 + 24 + + + + see ode + + + 2000000000000.000000000000000 + + + + + + 10 + 26 + 117 + 21 + + + + soft_cfm + + + + + + 292 + 60 + 159 + 21 + + + + split_impulse + + + + + + 10 + 124 + 217 + 15 + + + + split_impulse_penetration_threshold + + + + + + 236 + 120 + 71 + 24 + + + + imilar to ODE's max_vel implementation + + + + + + + + + soft_contact + + + + + 12 + 14 + 359 + 156 + + + + soft_contact + + + true + + + + + + bone_attachment + + + + + + + This is variable k_v in the soft contacts paper. Its unit is N/m + + + N/m + + + + + + + stiffness + + + + + + + This is variable k_e in the soft contacts paper + + + N/m + + + + + + + damping + + + + + + + Viscous damping of point velocity in body frame + + + N/m/s + + + + + + + flesh_mass_fraction + + + + + + + Fraction of mass to be distributed among deformable nodes + + + + + + + + + + + + + + + + + + + diff --git a/robot_descriptor/forms/world.ui b/robot_descriptor/forms/world.ui index f81e4fe..466b3ee 100644 --- a/robot_descriptor/forms/world.ui +++ b/robot_descriptor/forms/world.ui @@ -65,8 +65,8 @@ 12 14 - 589 - 655 + 587 + 648 @@ -1575,8 +1575,8 @@ to zero if you want the min COR always to be used 10 10 - 541 - 333 + 543 + 421 @@ -1588,323 +1588,374 @@ to zero if you want the min COR always to be used false - - - - 170 - 30 - 119 - 23 - - - - name of planetary surface model, used to determine the surface altitude + + + + + + 95 + 24 + + + + + 100 + 24 + + + + surface_model + + + + + + + + 117 + 21 + + + + + 120 + 24 + + + + name of planetary surface model, used to determine the surface altitude at a given latitude and longitude. The default is an ellipsoid model of the earth based on the WGS-84 standard. It is used in Gazebo's GPS sensor implementation. - - - false - - - - EARTH_WGS84 - + + + false + + + + EARTH_WGS84 + + + - - - - - 20 - 40 - 88 - 15 - - - - surface_model - - - - - - 20 - 70 - 147 - 15 - - - - world_frame_orientation - - - - - - 170 - 60 - 153 - 23 - - - - This field identifies how Gazebo world frame is aligned in Geographical + + + + + 155 + 24 + + + + world_frame_orientation + + + + + + + + 151 + 21 + + + + + 155 + 24 + + + + This field identifies how Gazebo world frame is aligned in Geographical sense. The final Gazebo world frame orientation is obtained by rotating a frame aligned with following notation by the field heading_deg. Options are: - - - false - - - - ENU (East-North-Up) - + + + false + + + + ENU (East-North-Up) + + + - - - - - 20 - 100 - 75 - 15 - - - - latitude_deg - - - - - - 170 - 96 - 81 - 24 - - - - Geodetic latitude at origin of gazebo reference frame, specified + + + + + 85 + 24 + + + + latitude_deg + + + + + + + + 88 + 24 + + + + + 90 + 24 + + + + Geodetic latitude at origin of gazebo reference frame, specified in units of degrees. - - - - - - ° - - - 4 - - - -90.000000000000000 - - - 90.000000000000000 - - - - - - 20 - 130 - 86 - 15 - - - - longitude_deg - - - - - - 168 - 126 - 81 - 24 - - - - Longitude at origin of gazebo reference frame, specified in units + + + + + + ° + + + 4 + + + -90.000000000000000 + + + 90.000000000000000 + + + + + + + + 95 + 24 + + + + longitude_deg + + + + + + + + 0 + 24 + + + + + 100 + 24 + + + + Longitude at origin of gazebo reference frame, specified in units of degrees - - - ° - - - 4 - - - -180.000000000000000 - - - 180.000000000000000 - - - - - - 20 - 158 - 57 - 15 - - - - elevation - - - - - - 168 - 154 - 85 - 24 - - - - Elevation of origin of gazebo reference frame, specified in meters - - - m - - - 4 - - - 10000.000000000000000 - - - - - - 340 - 30 - 78 - 15 - - - - heading_deg - - - - - - 428 - 26 - 89 - 24 - - - - Heading offset of gazebo reference frame, measured as angle between + + + ° + + + 4 + + + -180.000000000000000 + + + 180.000000000000000 + + + + + + + + 65 + 24 + + + + elevation + + + + + + + + 112 + 24 + + + + + 120 + 24 + + + + Elevation of origin of gazebo reference frame, specified in meters + + + m + + + 4 + + + 10000.000000000000000 + + + + + + + + 85 + 24 + + + + heading_deg + + + + + + + + 80 + 24 + + + + + 85 + 24 + + + + Heading offset of gazebo reference frame, measured as angle between Gazebo world frame and the world_frame_orientation type. The direction of rotation follows the right-hand rule, so a positive angle indicates clockwise rotation (from east to north) when viewed from top-down. Note that this is not consistent with compass heading convention. The angle is specified in degrees. - - - ° - - - -360.000000000000000 - - - 360.000000000000000 - - - - - - 16 - 260 - 161 - 67 - - - - surface_axis_polar - - - true - - - false - - - - - 8 - 26 - 109 - 24 - - - - Polar axis of a custom surface type, specified in meters. - This is only required for custom surfaces - - - m - - - 4 - - - 10000.000000000000000 - - - - - - - 14 - 182 - 165 - 69 - - - - surface_axis_equatorial - - - true - - - false - - - - - 4 - 28 - 104 - 24 - - - - Equatorial axis of a custom surface type, specified in meters. + + + ° + + + -360.000000000000000 + + + 360.000000000000000 + + + + + + + + 175 + 65 + + + + + 180 + 70 + + + + surface_axis_equatorial + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + Equatorial axis of a custom surface type, specified in meters. This is only required for custom surfaces. - - - m - - - 4 - - - 1000.000000000000000 - - - - - + + + m + + + 4 + + + 1000.000000000000000 + + + + + + + + + + + 159 + 61 + + + + + 170 + 70 + + + + surface_axis_polar + + + true + + + false + + + + + + Polar axis of a custom surface type, specified in meters. + This is only required for custom surfaces + + + m + + + 4 + + + 10000.000000000000000 + + + + + + + + + 6 @@ -1923,13 +1974,10 @@ of degrees light - - - - - 16777215 - 100 - + + + + Reset @@ -1953,6 +2001,16 @@ of degrees + + + + + 16777215 + 100 + + + + @@ -1963,67 +2021,11 @@ of degrees 0 0 - 551 + 549 771 - - - - name - - - - - - - - 0 - 23 - - - - - - - - type - - - - - - - - 0 - 23 - - - - - point - - - - - spot - - - - - directional - - - - - - - - intensity - - - @@ -2040,219 +2042,205 @@ of degrees - - - - - 0 - 21 - - - - cast_shadows - - - - - - - - 0 - 21 - - - - visualize - - - true - - - - - - - - 0 - 21 - - + + - light_on - - - true + intensity - - + + - 489 - 98 - - - - - 533 - 16777215 + 505 + 145 - Diffuse + pose - - - - - - 0 - 25 - + + + + + x - - - 64 - 16777215 - + + Qt::AlignCenter - - 1.000000000000000 + + + + + + y - - 0.100000000000000 + + Qt::AlignCenter - - 1.000000000000000 + + + + + + z + + + Qt::AlignCenter - + 0 25 - - - 64 - 16777215 - - - - 1.000000000000000 + + 4 - - 0.100000000000000 + + -100.000000000000000 - - 1.000000000000000 + + 1000.000000000000000 - - + + 0 25 - - - 64 - 16777215 - - - - 1.000000000000000 + + 4 - - 0.100000000000000 + + -100.000000000000000 - - 1.000000000000000 + + 1000.000000000000000 - - - - A - - + + + + + 0 + 25 + + + + 4 + + + -100.000000000000000 + + + 1000.000000000000000 + + + + + + + roll + + Qt::AlignCenter - - + + - R + pitch Qt::AlignCenter - - + + + + yaw + + + Qt::AlignCenter + + + + + 0 25 - - - 64 - 16777215 - + + rad - - 1.000000000000000 + + 4 - - 0.100000000000000 + + -6.283200000000000 - - 1.000000000000000 + + 6.283200000000000 - - - - G + + + + + 0 + 25 + - - Qt::AlignCenter + + rad - - - - - - B + + 4 - - Qt::AlignCenter + + -6.283200000000000 + + + 6.283200000000000 - - - + + + - 45 - 16777215 + 0 + 25 - - + + rad + + + 4 + + + -6.283200000000000 + + + 6.283200000000000 @@ -2469,407 +2457,466 @@ of degrees - - + + 0 - 75 - - - - - 534 - 16777215 + 94 - attenuation + direction - - - + + + - constant + x + + + Qt::AlignCenter - - - - - 64 - 25 - - - - 0.100000000000000 + + + + y - - 1.000000000000000 + + Qt::AlignCenter - - - - Qt::Horizontal + + + + z + + + Qt::AlignCenter - - - quadratic - - - - - - 64 - 25 - - - - 0.100000000000000 - - - - - - linear + + + + + 0 + 25 + + + + -100.000000000000000 - - + + - 64 + 0 25 - - 0.100000000000000 - - - 1.000000000000000 + + -100.000000000000000 - - + + - 64 + 0 25 - - 100000.000000000000000 - - - 0.100000000000000 + + -100.000000000000000 - 10.000000000000000 - - - - - - - range + -1.000000000000000 - - + + - 505 - 145 + 0 + 21 - - pose + + cast_shadows - - - - - x - - - Qt::AlignCenter - - - - - - - y - - - Qt::AlignCenter - - - - - - - z - - - Qt::AlignCenter - - - - - + + + + + + + 489 + 98 + + + + + 533 + 16777215 + + + + Diffuse + + + + 0 25 - - 4 - - - -100.000000000000000 + + + 64 + 16777215 + - 1000.000000000000000 + 1.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 - - + + 0 25 - - 4 - - - -100.000000000000000 + + + 64 + 16777215 + - 1000.000000000000000 + 1.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 - - + + 0 25 - - 4 - - - -100.000000000000000 + + + 64 + 16777215 + - 1000.000000000000000 + 1.000000000000000 - - - - - - roll + + 0.100000000000000 - - Qt::AlignCenter + + 1.000000000000000 - - + + - pitch + A Qt::AlignCenter - - + + - yaw + R Qt::AlignCenter - - + + 0 25 - - rad + + + 64 + 16777215 + - - 4 + + 1.000000000000000 - - -6.283200000000000 + + 0.100000000000000 - - 6.283200000000000 + + 1.000000000000000 - - - - - 0 - 25 - - - - rad + + + + G - - 4 + + Qt::AlignCenter - - -6.283200000000000 + + + + + + B - - 6.283200000000000 + + Qt::AlignCenter - - - + + + - 0 - 25 + 45 + 16777215 - - rad - - - 4 - - - -6.283200000000000 - - - 6.283200000000000 + + - - + + 0 - 94 + 21 + + + + visualize + + + true + + + + + + + + 0 + 75 + + + + + 534 + 16777215 - direction + attenuation - - - + + + - x - - - Qt::AlignCenter + constant - - - - y + + + + + 64 + 25 + - - Qt::AlignCenter + + 0.100000000000000 + + + 1.000000000000000 - - - - z - - - Qt::AlignCenter + + + + Qt::Horizontal + + + + 65 + 24 + + + + quadratic + + + + + + 64 + 25 + + + + 0.100000000000000 + + - - - - - 0 - 25 - - - - -100.000000000000000 + + + + linear - - + + - 0 + 64 25 - - -100.000000000000000 + + 0.100000000000000 + + + 1.000000000000000 - - + + - 0 + 64 25 - - -100.000000000000000 + + 100000.000000000000000 + + + 0.100000000000000 - -1.000000000000000 + 10.000000000000000 + + + + + + + range + + + + name + + + + + + + + 0 + 23 + + + + + point + + + + + spot + + + + + directional + + + + + + + + + 0 + 21 + + + + light_on + + + true + + + @@ -2960,17 +3007,27 @@ of degrees + + + + + 0 + 23 + + + + + + + + type + + + - - - - Reset - - - @@ -3397,1535 +3454,52 @@ of degrees true - - - - - cubemap_uri - - - - - - - time - - - - - - - 24.000000000000000 - - - - - - - - 0 - 23 - - - - - - - - sunset - - - - - - - clouds - - - true - - - - - - mean_size - - - - - - - humidity - - - - - - - direction - - - - - - - Density of clouds - - - 4 - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 100 - - - - - - - ambient - - - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - - - - 45 - 16777215 - - - - - - - - - - - - - - Direction of the cloud movement - - - 4 - - - 3.145600000000000 - - - 0.100000000000000 - - - - - - - speed - - - - - - - - 70 - 16777215 - - - - Speed of the clouds - - - 4 - - - - - - - - 60 - 24 - - - - 4 - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - 80 - 16777215 - - - - 24.000000000000000 - - - - - - - sunrise - - - - - - - 24.000000000000000 - - - - - - - - - - - 0 - 24 - - - - - 150 - 16777215 - - - - shadows - - - - - - - - 0 - 24 - - - - - 150 - 16777215 - - - - grid - - - - - - - - 160 - 24 - - - - - 150 - 16777215 - - - - origin_visual - - - - - - - - 520 - 203 - - - - - 530 - 16777215 - - - - fog - - - true - - - - - - type - - - - - - - - 0 - 24 - - - - - 100 - 25 - - - - - none - - - - - constant - - - - - linear - - - - - quadratic - - - - - - - - - 450 - 100 - - - - - 16777215 - 100 - - - - fog color - - - color - - - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 46 - 16777215 - - - - - - - - - - - - - - density - - - - - - - Density of fog - - - - - - - end - - - - - - - Distance to end of fog - - - 1000.000000000000000 - - - - - - - Distance to start of fog - - - - - - - start - - - - - - - - - - - - - 8 - 586 - 80 - 23 - - - - Reset - - - - - - 456 - 586 - 110 - 21 - - - - enable_scene - - - - - - road - - - - - 432 - 592 - 105 - 21 - - - - - 105 - 0 - - - - Enable_road - - - - - - 10 - 596 - 80 - 23 - - - - Reset - - - - - - 10 - 12 - 569 - 571 - - - - true - - - - - 0 - 0 - 553 - 672 - - - - - - - Qt::Horizontal - - - - - 0 - 24 - - - - name - - - - - - 0 - 24 - - - - - - - - - - 500 - 624 - - - - - 570 - 630 - - - - material - - - true - - - false - - - - - - - 240 - 89 - - - - - 240 - 16777215 - - - - script - - - true - - - false - - - - - 18 - 28 - 16 - 15 - - - - uri - - - - - - 52 - 24 - 153 - 23 - - - - - 160 - 16777215 - - - - - - - 12 - 56 - 34 - 15 - - - - name - - - - - - 52 - 52 - 113 - 23 - - - - - 115 - 16777215 - - - - - - - - - - 240 - 95 - - - - - 240 - 16777215 - - - - shader - - - true - - - false - - - - - 12 - 30 - 57 - 16 - - - - type - - - - - - 82 - 26 - 100 - 21 - - - - - 100 - 16777215 - - - - - pixel - - - - - vertex - - - - - normal_map_object_space - - - - - normal_map_tangent_space - - - - - - - 12 - 57 - 100 - 20 - - - - normal_map - - - - - - 118 - 57 - 100 - 20 - - - - - 100 - 16777215 - - - - - - - - - Qt::Horizontal - - - - - 85 - 24 - - - - - 85 - 28 - - - - render_order - - - - - - 0 - 24 - - - - - 100 - 16777215 - - - - Set render order for coplanar polygons. The higher value will be rendered on top of the other coplanar polygons - - - - - - - - Qt::Horizontal - - - - - 56 - 16777215 - - - - shininess - - - - - - 0 - 24 - - - - - 100 - 27 - - - - - - - - - - 520 - 100 - - - - - 520 - 100 - - - - background color - - - ambient - - - true - - - false - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 45 - 16777215 - - - - - - - - - - - - - - - 520 - 100 - - - - - 520 - 100 - - - - background color - - - diffuse - - - true - - - false - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 45 - 16777215 - - - - - - - - + + false + + + + + + cubemap_uri + - - - - - 520 - 100 - + + + + time - + + + + + + 24.000000000000000 + + + + + + - 520 - 100 + 0 + 23 - - background color + + + + + + sunset + + + + - specular + clouds true @@ -4933,150 +3507,276 @@ of degrees false - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 + + + + + mean_size - - - - - 16777215 - 24 - - + + - B - - - Qt::AlignCenter + humidity - - - - 16777215 - 24 - - + - A + direction - - Qt::AlignCenter + + + + + + Density of clouds + + + 4 + + + 1.000000000000000 + + + 0.100000000000000 - - + + 16777215 - 24 + 100 - - R + + - - Qt::AlignCenter + + ambient + + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + B + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + G + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + A + + + Qt::AlignCenter + + + + + + + + 45 + 16777215 + + + + + + + + - - - - - 0 - 24 - + + + + Direction of the cloud movement - - - 16777215 - 24 - + + 4 - 1.000000000000000 + 3.145600000000000 0.100000000000000 - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 + + + + speed - + - 16777215 - 24 + 70 + 16777215 - - G + + Speed of the clouds - - Qt::AlignCenter + + 4 - - + + - 0 + 60 24 - - - 16777215 - 24 - + + 4 1.000000000000000 @@ -5086,73 +3786,202 @@ of degrees - - - - - 45 - 16777215 - - - - - - - - - + + + + + 80 + 16777215 + + + + 24.000000000000000 + + + + + + + sunrise + + + + + + + 24.000000000000000 + + + + + + + + + + + 0 + 24 + + + + + 150 + 16777215 + + + + shadows + + + + + + + + 0 + 24 + + + + + 150 + 16777215 + + + + grid + + + + + + + + 160 + 24 + + + + + 150 + 16777215 + + + + origin_visual + + + + + + + + 520 + 203 + + + + + 530 + 16777215 + + + + fog + + + true + + + false + + + + + + type + + + + + + + + 0 + 24 + + + + + 100 + 25 + + + + + none + + + + + constant + + + + + linear + + + + + quadratic + + + + + + - 520 + 450 100 - 520 + 16777215 100 - background color + fog color - emissive - - - true - - - false + color - - - - - - 0 - 24 - - + + + 16777215 24 - - 1.000000000000000 + + B - - 0.100000000000000 + + Qt::AlignCenter - - + + 16777215 @@ -5160,31 +3989,37 @@ of degrees - B + A Qt::AlignCenter - - + + + + + 0 + 24 + + 16777215 24 - - A + + 1.000000000000000 - - Qt::AlignCenter + + 0.100000000000000 - - + + 16777215 @@ -5192,7 +4027,7 @@ of degrees - R + G Qt::AlignCenter @@ -5200,7 +4035,7 @@ of degrees - + 0 @@ -5222,7 +4057,7 @@ of degrees - + 0 @@ -5243,24 +4078,8 @@ of degrees - - - - - 16777215 - 24 - - - - G - - - Qt::AlignCenter - - - - + 0 @@ -5281,11 +4100,33 @@ of degrees + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + - + + + + 0 + 0 + + - 45 + 46 16777215 @@ -5297,51 +4138,222 @@ of degrees - - - - - 0 - 24 - + + + + density + + + + + + + Density of fog + + + + + + + end + + + + + + + Distance to end of fog + + + 1000.000000000000000 + + + + + + + Distance to start of fog + + + + - lighting + start - - - - Qt::Horizontal - - - - - 0 - 24 - - - - width - - - - - - 0 - 24 - - - - - + + + + 8 + 586 + 80 + 23 + + + + Reset + + + + + + 456 + 586 + 110 + 21 + + + + enable_scene + + + + + + road + + + + + + Qt::Horizontal + + + + + 50 + 24 + + + + + 55 + 27 + + + + name + + + + + + 100 + 16777215 + + + + + + + + + Qt::Horizontal + + + + + 50 + 24 + + + + + 55 + 25 + + + + width + + + + + + 60 + 24 + + + + + 100 + 25 + + + + + + + + + + 565 + 540 + + + + true + + + + + 0 + 0 + 563 + 540 + + + + + + + + + + 100 + 16777215 + + + + Reset + + + + + + + + 105 + 0 + + + + + 100 + 16777215 + + + + Enable_road + + + + + + + include_material_info + + + + diff --git a/robot_descriptor/model_editor.py b/robot_descriptor/model_editor.py index 4bed886..486710d 100644 --- a/robot_descriptor/model_editor.py +++ b/robot_descriptor/model_editor.py @@ -4,35 +4,50 @@ import os from .RD_utils import parse_asm4_model -from PySide.QtGui import QStandardItemModel,QStandardItem +from PySide.QtGui import QStandardItemModel,QStandardItem,QHeaderView #start standard item class standard_item(QStandardItem): - def __init__(self,text): + def __init__(self,text,elements): super().__init__() - self.model_elem=None + # data to describe the model + self.link_elem=elements[0] + self.collision_elem=elements[1] + self.material_elem=elements[2] + #set the text to be displayed self.setText(text) self.setEditable(False) + #end standard Item #============================================== #model editor class ModelEditor: - def __init__(self): + def __init__(self,elem_struct): # find all objects of type 'App::Link' #doc=FreeCAD.ActiveDocument - + self._elem_struct=elem_struct self.links_hierarchy=parse_asm4_model.read_assembly() if self.links_hierarchy is None: return self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) self.link_model=QStandardItemModel() + self.link_model.setColumnCount(1) self.root_node=self.link_model.invisibleRootItem() self.tree_setup(self.links_hierarchy["children"],self.root_node) - #hide header - self.ModelEditorUi.link_tree.setHeaderHidden(True) + + # start header related + self.ModelEditorUi.link_tree.setHeaderHidden(False) + self.link_model.setHorizontalHeaderLabels(["Model Tree"]) + #set the tree to resize automatically based on the display requirements + header = self.ModelEditorUi.link_tree.header() + header.setSectionResizeMode(QHeaderView.ResizeToContents) + #end header related + self.ModelEditorUi.link_tree.setModel(self.link_model) + self.ModelEditorUi.exec() + #create the tree structure def tree_setup(self,link_hierarchy,item): #iterate throuhg all children create items and the to tree for child in link_hierarchy: @@ -41,9 +56,14 @@ def tree_setup(self,link_hierarchy,item): item.appendRow(row) self.tree_setup(child["children"],row) return - - - + + + + + +#+=============================== +#start command +#================================ class Model_properties(): """My new command""" @@ -55,7 +75,9 @@ def GetResources(self): def Activated(self): if hasattr(FreeCAD.ActiveDocument,"Assembly"): - self.edits=ModelEditor() + doc=FreeCAD.ActiveDocument + self._root_dict=doc.Robot_Description.Proxy.element_dict + self.edits=ModelEditor(self._root_dict) else: FreeCAD.Console.PrintMessage("document does not contain an assembly\n") return diff --git a/robot_descriptor/sdf_elements/collision.py b/robot_descriptor/sdf_elements/collision.py new file mode 100644 index 0000000..e69de29 diff --git a/robot_descriptor/sdf_elements/light.py b/robot_descriptor/sdf_elements/light.py index 420a1ac..eb0f3c1 100644 --- a/robot_descriptor/sdf_elements/light.py +++ b/robot_descriptor/sdf_elements/light.py @@ -221,6 +221,7 @@ def initialize(self): del self.pose.attrib["degrees"] # append pose to light self._light_element.append(self.pose) + #this variable will store all the lights added to th world self.lights={} #the lights dictionary format # @@ -583,6 +584,7 @@ def reset(self,default:bool=True): @property def element(self): + #get all the lights el_dict=copy.deepcopy(self.lights) el_list=[] #remove elements depending on type selection diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py new file mode 100644 index 0000000..86cbe00 --- /dev/null +++ b/robot_descriptor/sdf_elements/link.py @@ -0,0 +1,134 @@ +import FreeCAD +from .. import common +from ..RD_utils import initialize_element_tree + +from PySide import QtCore + +class link_properties: + def __init__(self,ui) -> None: + self.ui=ui + +#gravity + @property + def gravity(self): + + state= self.ui.link_gravity_checkbox.isChecked() + if state: + return str('true') + else: + return str('false') + + @gravity.setter + def gravity(self,state): + if state=='true': + self.ui.link_gravity_checkbox.setCheckState(QtCore.Qt.Ckecked) + else: + self.ui.link_gravity_checkbox.setCheckState(QtCore.Qt.Unchecked) + +#enable wind + @property + def enable_wind(self): + state=self.ui.link_enable_wind_checkbox.isChecked(QtCore.Qt.Checked) + if state: + return str('true') + else: + return str('false') + + @enable_wind.setter + def enable_wind(self,state): + if state=='true': + self.ui.link_enable_wind_checkbox.setCheckState(QtCore.Qt.Ckecked) + else: + self.ui.link_enable_wind_checkbox.setCheckState(QtCore.Qt.Unchecked) + +#self_collide + @property + def self_collide(self): + return str('true') if self.ui.link_self_collide_checkbox.isChecked() else str('false') + + @self_collide.setter + def self_collide(self,state): + self.ui.link_self_collide_checkbox.setCheckState(QtCore.Qt.Ckecked) if state=='true' else self.ui.link_self_collide_checkbox.setCheckState(QtCore.Qt.Unchecked) + +#kinematic + @property + def kinematic(self): + return str('true') if self.ui.link_kinematic_checkbox.isChecked() else str('false') + @kinematic.setter + def kinematic(self,state): + self.ui.link_kinematic_checkbox.setCheckState(QtCore.Qt.Ckecked) if state=='true' else self.ui.link_kinematic_checkbox.setCheckState(QtCore.Qt.Unchecked) + +#velocity decay + #linear + @property + def linear(self): + return self.ui.velocity_decay_linear_sp.value() + @linear.setter + def linear(self,value): + self.ui.velocity_decay_linear_sp.setValue(value) + + #angular + @property + def angular(self): + return self.ui.link_angular_vel_decay_sp.value() + @angular.setter + def angular(self,value): + self.ui.link_angular_vel_decay_sp.setValue(value) +#====================== +#link +#==================== +class link: + def __init__(self,ui,elem_struct): + self.ui=ui + self.file_name='link.sdf' + self.tag='link' + #models will be store as children of sdf + self.parent_path=['sdf','model'] + self.properties=link_properties(self.ui) + self.link_element=initialize_element_tree.convdict_2_tree(self.file_name) + self._root_dict=elem_struct + self.configUI() + + def configUI(self): + self.ui.link_gravity_checkbox.stateChanged.connect(self.onGravity) + self.ui.link_enable_wind_checkbox.stateCahanged.connect(self.onEnableWind) + self.ui.ink_self_collide_checkbox.stateChanged.connect(self.onSelfCollide) + self.ui.link_kinematic_checkbox.stateChanged.conned(self.onKinematic) + self.ui.velocity_decay_linear_sp.clicked.connect(self.onLinear) + self.ui.link_angular_vel_decay_sp.clicked.connect(self.onAngular) + + def onGravity(self): + common.set_xml_data(self.link_element,'gravity',False,self.properties.gravity) + + def onEnableWind(self): + common.set_xml_data(self.link_element,'enable_wind',False,self.properties.enable_wind) + + def onSelfCollide(self): + common.set_xml_data(self.link_element,'self_collide',False,self.properties.self_collide) + + def onKinematic(self): + common.set_xml_data(self.link_element,'kinematic',False,self.properties.kinematic) + + def onLinear(self): + common.set_xml_data(self.link_element,'linear',False,self.properties.linear) + + def onAgular(self): + common.set_xml_data(self.link_element,'angular',False,self.properties.angular) + + #element to be updaed sent to the list + def UpdateUi(self,element): + self.properties.gravity=common.get_xml_data(element,'gravity',False) + self.properties.enable_wind=common.get_xml_data(self.element,'enable_wind',False) + self.properties.self_collide=common.get_xml_data(element,'self_collide',False) + self.properties.kinematic= common.get_xml_data(element,'kinematic') + self.properties.linear=common.set_xml_data(element,'linear') + self.properties.angular=common.set_xml_data(element,'angular') + + #this needs to reset the data of all links in the model + #how will this information be extracted + def reset(self,default=True): + if default: + self.link_element=initialize_element_tree.convdict_2_tree(self.file_name) + else: + elem_dict=common.parse_dict(self._root_dict,self.parent_path+[self.tag]) + \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/material.py b/robot_descriptor/sdf_elements/material.py new file mode 100644 index 0000000..6719ed6 --- /dev/null +++ b/robot_descriptor/sdf_elements/material.py @@ -0,0 +1,746 @@ +from .. import common +from ..RD_utils import initialize_element_tree +import copy +from PySide import QtGui,QtCore +import re +import math +import csv +# import Spreadsheet +import os +import xml.etree.ElementTree as ET +import FreeCAD ,FreeCADGui + + +#matreial +class material_properties: + def __init__(self,ui) -> None: + self.ui=ui +#script uri + @property + def script_uri(self): + return self.ui.material_script_uri_input.text() + @script_uri.setter + def script_uri(self,text): + self.ui.material_script_uri_input.setText(text) + +#script name + @property + def script_name(self): + return self.ui.material_script_name.text() + @script_name.setter + def script_name(self,text): + self.ui.material_script_name.setText(text) + +#shader_type + @property + def shader_type(self): + return self.ui.shader_type.currentText() + @shader_type.setter + def shader_type(self,text): + self.ui.shader_type.setCurrentText(text) +#normal map + @property + def normal_map(self): + return self.ui.material_normal_map_input.text() + @normal_map.setter + def normal_map(self,text): + self.ui.material_normal_map_input.setText(text) + +#this checkebox is not part of the sdf data its just used to enable and disable the normal_map input +# so no need to convert bool to strinf + @property + def normal_map_checkbox(self): + return str('true') if self.ui.normal_map_checkBox.isChecked() else str('false') + + @normal_map_checkbox.setter + def normal_map_checkbox(self,state): + self.ui.normal_map_checkBox.setState(QtCore.Qt.Checked) if state else self.ui.normal_map_checkBox.setState(QtCore.Qt.Unchecked) + + + +#render order + @property + def render_order(self): + return self.ui.material_render_order_sp.value() + @render_order.setter + def render_order(self,value): + self.ui.material_render_order_sp.setValue(value) + +#shininess + @property + def shininess(self): + return self.ui.material_shininess_sp.value() + @shininess.setter + def shininess(self,value): + self.ui.material_shininess_sp.setValue(value) + +#lighting + @property + def lighting(self): + state= self.ui.material_lighting_checkbox.isChecked() + if state is True: + return str('true') + else: + return str('false') + @lighting.setter + def lighting(self,state): + if state is True: + self.ui.material_lighting_checkbox.setState(QtCore.Qt.Checked) + else: + self.ui.material_lighting_checkbox.setState(QtCore.Qt.Unchecked) + + +#ambient + @property + def ambient(self): + return [self.ui.material_ambient_R_sp.value(),self.ui.material_ambient_G_sp.value(), + self.ui.material_ambient_B_sp.value(),self.ui.material_ambient_A_sp.value()] + @ambient.setter + def ambient(self,vals): + self.ui.material_ambient_R_sp.setValue(vals[0]) + self.ui.material_ambient_G_sp.setValue(vals[1]) + self.ui.material_ambient_B_sp.setValue(vals[2]) + self.ui.material_ambient_A_sp.setValue(vals[3]) +#diffuse + @property + def diffuse(self): + return [self.ui.material_diffuse_R_sp.value(),self.ui.material_diffuse_G_sp.value(), + self.ui.material_diffuse_B_sp.value(),self.ui.material_diffuse_A_sp.value()] + @diffuse.setter + def diffuse(self,vals): + self.ui.material_diffuse_R_sp.setValue(vals[0]) + self.ui.material_diffuse_G_sp.setValue(vals[1]) + self.ui.material_diffuse_B_sp.setValue(vals[2]) + self.ui.material_diffuse_A_sp.setValue(vals[3]) +#specular + @property + def specular(self): + return [self.ui.material_specular_R_sp.value(),self.ui.material_specular_G_sp.value(), + self.ui.material_specular_B_sp.value(),self.ui.material_specular_A_sp.value()] + @specular.setter + def specular(self,vals): + self.ui.material_specular_R_sp.setValue(vals[0]) + self.ui.material_specular_G_sp.setValue(vals[1]) + self.ui.material_specular_B_sp.setValue(vals[2]) + self.ui.material_specular_A_sp.setValue(vals[3]) +#emissive + @property + def emissive(self): + return [self.ui.material_emissive_R_sp.value(),self.ui.material_emissive_G_sp.value(), + self.ui.material_emissive_B_sp.value(),self.ui.material_emissive_A_sp.value()] + @emissive.setter + def emissive(self,vals): + self.ui.material_emissive_R_sp.setValue(vals[0]) + self.ui.material_emissive_G_sp.setValue(vals[1]) + self.ui.material_emissive_B_sp.setValue(vals[2]) + self.ui.material_emissive_A_sp.setValue(vals[3]) + +#pbr +#================================================= + @property + def double_sided(self): + return str('true') if self.ui.material_double_sided_checkBox.isChecked() else str('false') + + @double_sided.setter + def double_sided(self,state): + self.ui.material_double_sided_checkBox.setCheckState(QtCore.Qt.Checked) if state else self.ui.material_double_sided_checkBox.setCheckState(QtCore.Qt.Unchecked) + +#metal_albedo_map + @property + def metal_albedo_map(self): + return self.ui.metal_albedo_map_lineEdit.text() + @metal_albedo_map.setter + def metal_albedo_map(self,text): + self.ui.metal_albedo_map_lineEdit.setText(text) + +#metal_roughness_map + @property + def metal_roughness_map(self): + return self.ui.metal_roughness_map_lineEdit.text() + @metal_roughness_map.setter + def metal_roughness_map(self,text): + self.ui.metal_roughness_map_lineEdit.setText(text) + +#metal_roughness + @property + def metal_roughness(self): + return self.ui.metal_roughness_lineEdit.text() + @metal_roughness.setter + def metal_roughness(self,text): + self.ui.metal_roughness_lineEdit.setText(text) + +#metalness_map + @property + def metalness_map(self): + return self.ui.metalness_map_lineEdit.text() + @metalness_map.setter + def metalness_map(self,text): + self.ui.metalness_map_lineEdit.setText(text) + +#metalness + @property + def metalness(self): + return self.ui.metalness_sp.value() + @metalness.setter + def metalness(self,val): + + self.ui.metalness_sp.setValue(val) + +#metal_environment_map + @property + def metal_environment_map(self): + return self.ui.metal_environment_map_lineEdit.text() + @metal_environment_map.setter + def metal_environment_map(self,text): + self.ui.metal_environment_map_lineEdit.setText(text) + +#metal_ambient_occlusion_map + @property + def metal_ambient_occlusion_map(self): + return self.ui.metal_ambient_occlusion_map_lineEdit.text() + @metal_ambient_occlusion_map.setter + def metal_ambient_occlusion_map(self,text): + self.ui.metal_ambient_occlusion_map_lineEdit.setText(text) + +#metal_emissive_map + @property + def metal_emissive_map(self): + return self.ui.metal_emissive_map_lineEdit.text() + @metal_emissive_map.setter + def metal_emissive_map(self,text): + self.ui.metal_emissive_map_lineEdit.setText(text) + +#metal_light_map + @property + def metal_light_map(self): + return self.ui.metal_light_map_lineEdit.text() + @metal_light_map.setter + def metal_light_map(self,text): + self.ui.metal_light_map_lineEdit.setText(text) + +#metal_uv_set + @property + def metal_uv_set(self): + def metal_uv_set(self): + return self.ui.metal_uv_set_sp.value() + @metal_uv_set.setter + def metal_uv_set(self,value): + self.ui.metal_uv_set_sp.setValue(value) + +#metal_normal_map + @property + def metal_normal_map(self): + return self.ui.metal_normal_map_lineEdit.text() + @metal_normal_map.setter + def metal_normal_map(self,text): + self.ui.metal_normal_map_lineEdit.setText(text) + +#metal_normal_map_type + @property + def metal_normal_map_type(self): + return self.ui.metal_normal_map_type_comboBox.currentText() + + @metal_normal_map_type.setter + def metal_normal_map_type(self,text): + self.ui.metal_normal_map_type_comboBox.setCurrentText(text) + +#========== +#specular + +#specular_albedo_map + @property + def specular_albedo_map(self): + return self.ui.specular_albedo_map_lineEdit.text() + @specular_albedo_map.setter + def specular_albedo_map(self,text): + self.ui.specular_albedo_map_lineEdit.setText(text) + +#specular_map + @property + def specular_map(self): + self.ui.specular_map_lineEdit.text() + @specular_map.setter + def specular_map(self,text): + self.ui.specular_map_lineEdit.setText(text) + +#specular_glossiness + @property + def specular_glossiness(self): + return self.ui.specular_glossiness_sp.value() + @specular_glossiness.setter + def specular_glossiness(self,val): + self.ui.specular_glossiness_sp.setValue(val) + +#specular_environment_map + @property + def specular_environment_map(self): + return self.ui.specular_environment_map_lineEdit.text() + @specular_environment_map.setter + def specular_environment_map(self,text): + self.ui.specular_environment_map_lineEdit.setText(text) + +#specular_ambient_occlusion_map + @property + def specular_ambient_occlusion_map(self): + return self.ui.specular_ambient_occlusion_map_lineEdit.text() + @specular_ambient_occlusion_map.setter + def specular_ambient_occlusion_map(self,text): + self.ui.specular_ambient_occlusion_map_lineEdit.setText(text) + +#specular_emissive_map + @property + def specular_emissive_map(self): + return self.ui.specular_emissive_map_lineEdit.text() + @specular_emissive_map.setter + def specular_emissive_map(self,text): + self.ui.specular_emissive_map_lineEdit.setText(text) + +#specular_glossiness_map + @property + def specular_glossiness_map(self): + return self.ui.specular_glossiness_map_lineEdit.text() + @specular_glossiness_map.setter + def specular_glossiness_map(self,text): + self.ui.specular_glossiness_map_lineEdit.setText(text) + +#specular_light_map + @property + def specular_light_map(self): + return self.ui.specular_light_map_lineEdit.text() + @specular_light_map.setter + def specular_light_map(self,text): + self.ui.specular_light_map_lineEdit.setText(text) + +#specular_uv_set + @property + def specular_uv_set(self): + return self.ui.specular_uv_set_sp.value() + @specular_uv_set.setter + def specular_uv_set(self,val): + self.ui.specular_uv_set_sp.setValue(val) + +#specular_normal_map + @property + def specular_normal_map(self): + return self.ui.specular_normal_map_lineEdit.text() + @specular_normal_map.setter + def specular_normal_map(self,text): + self.ui.specular_normal_map_lineEdit.setText(text) + +#specular_normal_map_type + @property + def specular_normal_map_type(self): + return self.ui.specular_normal_map_type_comboBox.currentText() + @specular_normal_map_type.setter + def specular_normal_map_type(self,text): + self.ui.specular_normal_map_type_comboBox.setCurrentText(text) + +#Read only attributes +#used for optional properties +#pbr + #metal + @property + def metal_albedo_map_cb(self): + return self.ui.metal_albedo_map_checkBox.isChecked() + + @property + def metal_roughness_map_cb(self): + return self.ui.metal_roughness_map_checkBox.isChecked() + + @property + def metal_roughness_cb(self): + return self.ui.metal_roughness_checkBox.isChecked() + @property + def metalness_map_cb(self): + return self.ui.metalness_map_checkBox.isChecked() + + @property + def metalness_cb(self): + return self.ui.metalness_checkBox.isChecked() + @property + def metal_environment_map_cb(self): + return self.ui.metal_environment_map_checkBox.isChecked() + @property + def metal_ambient_occlusion_map_cb(self): + return self.ui.metal_ambient_occlusion_map_checkBox.isChecked() + + @property + def metal_emissive_map_cb(self): + return self.ui.metal_emissive_map_checkBox.isChecked() + @property + def metal_normal_map_cb(self): + return self.ui.normal_map_groupBox.isChecked() + + @property + def metal_light_map_cb(self): + return self.ui.metal_light_map_groupBox.isChecked() + + #specular + @property + def specular_albedo_map_cb(self): + return self.ui.specular_albedo_map_checkBox.isChecked() + @property + def specular_map_cb(self): + return self.ui.specular_map_checkBox.isChecked() + @property + def specular_glossiness_cb(self): + return self.ui.specular_glossiness_checkBox.isChecked() + @property + def specular_environment_map_cb(self): + return self.ui.specular_environment_map_checkBox.isChecked() + @property + def specular_ambient_occlusion_map_cb(self): + return self.ui.specular_ambient_occlusion_map_checkBox.isChecked() + @property + def specular_emissive_map_cb(self): + return self.ui.specular_emissive_map_checkBox.isChecked() + @property + def specular_glossiness_map_cb(self): + return self.ui.specular_glossiness_map_checkBox.isChecked() + @property + def specular_light_map_cb(self): + return self.ui.specular_light_map_groupBox.isChecked() + @property + def specular_normal_map_cb(self): + return self.ui.specular_normal_map_groupBox.isChecked() + + #pbr cb + @property + def pbr_enabled(self): + return self.ui.material_pbr_groupbox.isChecked() + #metal cb + @property + def metal_enabled(self): + return self.ui.material_matal_groupbox.isChecked() + #speculat cb + @property + def specular_enabled(self): + return self.ui.pbr_specular_groupBox.isChecked() + + + +#=========================================== +#=========================================== +#material element +#============================================ +#============================================ +class material(common.color_pickr): + #since material has multiple parents let the parent class + # the parent and parent path data + def __init__(self,ui,ParentPath) -> None: + super().__init__() + self.ui=ui + #use the road tag since material will be implemented as part of the road element + self.tag='road' + self.parent_path=ParentPath + self.file_name='material.sdf' + + self._material_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element + self.properties=material_properties(self.ui) + self.configUI() + self.reset(default=False) + + def configUI(self): + self.ui.material_script_uri_input.textEdited.connect(self.on_uri) + self.ui.material_script_name.textEdited.connect(self.on_uri_name) + self.ui.shader_type.currentTextChanged.connect(self.on_shader_type) + self.ui.normal_map_checkBox.stateChanged.connect(self.on_normal_map_state) + self.ui.material_normal_map_input.textEdited.connect(self.on_normal_map) + self.ui.material_render_order_sp.valueChanged.connect(self.on_material_render_ord) + self.ui.material_shininess_sp.valueChanged.connect(self.on_shininess) + + #ambient + self.ui.material_ambient_R_sp.valueChanged.connect(self.on_ambient) + self.ui.material_ambient_G_sp.valueChanged.connect(self.on_ambient) + self.ui.material_ambient_B_sp.valueChanged.connect(self.on_ambient) + self.ui.material_ambient_A_sp.valueChanged.connect(self.on_ambient) + #diffuse + self.ui.material_diffuse_R_sp.valueChanged.connect(self.on_diffuse) + self.ui.material_diffuse_G_sp.valueChanged.connect(self.on_diffuse) + self.ui.material_diffuse_B_sp.valueChanged.connect(self.on_diffuse) + self.ui.material_diffuse_A_sp.valueChanged.connect(self.on_diffuse) + #specular + self.ui.material_specular_R_sp.valueChanged.connect(self.on_specular) + self.ui.material_specular_G_sp.valueChanged.connect(self.on_specular) + self.ui.material_specular_B_sp.valueChanged.connect(self.on_specular) + self.ui.material_specular_A_sp.valueChanged.connect(self.on_specular) + #emissive + self.ui.material_emissive_R_sp.valueChanged.connect(self.on_emissive) + self.ui.material_emissive_G_sp.valueChanged.connect(self.on_emissive) + self.ui.material_emissive_B_sp.valueChanged.connect(self.on_emissive) + self.ui.material_emissive_A_sp.valueChanged.connect(self.on_emissive) + + #color picker buttons + self.ui.material_ambient_color_pkr.clicked.connect(self.on_ambient_color_pkr) + self.ui.material_diffuse_color_pkr.clicked.connect(self.on_diffuse_color_pkr) + self.ui.material_specular_color_pkr.clicked.connect(self.on_specular_color_pkr) + self.ui.material_emissive_color_pkr.clicked.connect(self.on_emissive_color_pkr) + +#pbr + #metal + #properties under the metal element + metal=self._material_element.find('.//pbr/metal') + self.ui.metal_albedo_map_lineEdit.textEdited.connect( + lambda :common.set_xml_data(metal,'albedo_map',False,self.properties.metal_albedo_map)) + + self.ui.metal_roughness_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(metal,'roughness_map',False,self.properties.metal_roughness_map)) + self.ui.metal_roughness_lineEdit.textEdited.connect(lambda :common.set_xml_data(metal, + "roughness",False,self.properties.metal_roughness)) + + self.ui.metalness_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(metal,"metalness_map",False,self.properties.metalness_map)) + + self.ui.metalness_sp.valueChanged.connect(lambda : + common.set_xml_data(metal,"metalness",False,self.properties.metalness)) + + self.ui.metal_environment_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(metal,"environment_map",False,self.properties.metal_environment_map)) + + self.ui.metal_ambient_occlusion_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(metal,"ambient_occlusion_map",False,self.properties.metal_ambient_occlusion_map)) + + self.ui.metal_emissive_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(metal,"emissive_map",False,self.properties.metal_emissive_map)) + + self.ui.metal_light_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(metal,"light_map",False,self.properties.metal_light_map)) + + self.ui.metal_uv_set_sp.valueChanged.connect(lambda : + common.set_xml_data(metal,"light_map",True,{"uv_set":self.properties.metal_uv_set})) + + self.ui.metal_normal_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(metal,"normal_map",False,self.properties.metal_normal_map)) + self.ui.metal_normal_map_type_comboBox.currentTextChanged.connect(lambda : + common.set_xml_data(metal,"normal_map",True,{"type":self.properties.metal_normal_map_type})) + + #specular + #elements under the specular subelement + specular=self._material_element.find(".//pbr/specular") + self.ui.specular_albedo_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(specular,"albedo_map",False,self.properties.specular_albedo_map)) + + self.ui.specular_map_lineEdit.textEdited.connect(lambda : + common.set_xml_data(specular,"specular_map",False,self.properties.specular_map)) + + self.ui.specular_glossiness_sp.valueChanged.connect(lambda : + common.set_xml_data(specular,"glossiness",False,self.properties.specular_glossiness)) + + self.ui.specular_environment_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(specular,"environment_map",False,self.properties.specular_environment_map) + ) + self.ui.specular_ambient_occlusion_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(specular,"ambient_occlusion_map",False,self.properties.specular_ambient_occlusion_map) + ) + self.ui.specular_emissive_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(specular,"emissive_map",False,self.properties.specular_emissive_map) + ) + self.ui.specular_glossiness_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(specular,"glossiness_map",False,self.properties.specular_glossiness_map) + ) + self.ui.specular_light_map_lineEdit.textEdited.connect( + lambda :common.set_xml_data(specular,"light_map",False,self.properties.specular_light_map) + ) + self.ui.specular_uv_set_sp.valueChanged.connect( + lambda : common.set_xml_data(specular,"light_map",True,{"uv_set":self.properties.specular_uv_set}) + ) + self.ui.specular_normal_map_lineEdit.textEdited.connect( + lambda : common.set_xml_data(specular,"normal_map",False,self.properties.specular_normal_map) + ) + self.ui.specular_normal_map_type_comboBox.currentTextChanged.connect( + lambda : common.set_xml_data(specular,"normal_map",True,{"type":self.properties.specular_normal_map_type}) + ) + + + + def on_uri(self): + common.set_xml_data(self._material_element,'uri',False,self.properties.script_uri) + + def on_uri_name(self): + common.set_xml_data(self._material_element,'name',False,self.properties.script_name) + + def on_shader_type(self): + common.set_xml_data(self._material_element,'shader',True,{'type':self.properties.shader_type}) + +#enable and disable normal map + def on_normal_map_state(self): + if self.properties.normal_map_checkbox: + self.ui.material_normal_map_input.setEnabled(True) + else: + self.ui.material_normal_map_input.setEnabled(False) + +#normal map + def on_normal_map(self): + common.set_xml_data(self._material_element,'normal_map',False,self.properties.normal_map) + +#material render order + def on_material_render_ord(self): + common.set_xml_data(self._material_element,'render_order',False,self.properties.render_order) + + def on_shininess(self): + common.set_xml_data(self._material_element,'shininess',False,self.properties.shininess) + + def on_ambient(self): + common.set_xml_data(self._material_element,'ambient',False,self.properties.ambient) + self.set_widget_color('ambient',self.ui.material_ambient_color_pkr) + + def on_diffuse(self): + common.set_xml_data(self._material_element,'diffuse',False,self.properties.diffuse) + self.set_widget_color('diffuse',self.ui.material_diffuse_color_pkr) + + def on_specular(self): + common.set_xml_data(self._material_element,'specular',False,self.properties.specular) + self.set_widget_color('specular',self.ui.material_specular_color_pkr) + + def on_emissive(self): + common.set_xml_data(self._material_element,'emissive',False,self.properties.emissive) + self.set_widget_color('emissive',self.ui.material_emissive_color_pkr) + + def on_ambient_color_pkr(self): + self.color_picker('ambient',self.ui.material_ambient_color_pkr) + + def on_diffuse_color_pkr(self): + self.color_picker('diffuse',self.ui.material_diffuse_color_pkr) + + def on_specular_color_pkr(self): + self.color_picker('specular',self.ui.material_specular_color_pkr) + + def on_emissive_color_pkr(self): + self.color_picker('emissive',self.ui.material_emissive_color_pkr) + + def updateUi(self): + self.properties.script_uri=common.get_xml_data(self._material_element,'uri',False) + self.properties.script_name=common.get_xml_data(self._material_element,'name',False) + self.properties.shader_type=common.get_xml_data(self._material_element,'type') + self.properties.normal_map=common.get_xml_data(self._material_element,'normal_map',False) + self.properties.render_order=common.get_xml_data(self._material_element,'render_order',False) + self.properties.shininess=common.get_xml_data(self._material_element,'shininess',False) + self.properties.ambient=common.get_xml_data(self._material_element,'ambient',False) + self.properties.diffuse=common.get_xml_data(self._material_element,'diffuse',False) + self.properties.specular=common.get_xml_data(self._material_element,'specular',False) + self.properties.emissive=common.get_xml_data(self._material_element,'emissive',False) + #pbr + #metal + metal=self._material_element.find('.//pbr/metal') + # { tag : property } + #properties is the property name defined in the properties class + items={'albedo_map':"metal_albedo_map",'roughness_map':"metal_roughness_map","metalness_map":"metalness_map","metalness":"metalness", + "environment_map":"metal_environment_map","ambient_occlusion_map":"metal_ambient_occlusion_map","emissive_map":"metal_emissive_map", + "light_map":"metal_light_map","normal_map":"metal_normal_map"} + #set the data for all items + for tag in items.keys(): + setattr(self.properties,items[tag],common.get_xml_data(metal,tag,False)) + #set element attributes + self.properties.metal_uv_set=common.get_xml_data(metal,["light_map","uv_set"],True) + self.properties.metal_normal_map_type=common.get_xml_data(metal,["normal_map","type"],True) + #specular + specular=self._material_element.find(".//pbr/specular") + #{tag : attribute} + specular_items={"albedo_map":"specular_albedo_map","specular_map":"specular_map","glossiness":"specular_glossiness","environment_map":"specular_environment_map", + "ambient_occlusion_map": "specular_ambient_occlusion_map","emissive_map":"specular_emissive_map","glossiness_map":"specular_glossiness_map", + "light_map":"specular_light_map","normal_map":"specular_normal_map"} + for tag in specular_items: + setattr(self.properties,specular_items[tag],common.get_xml_data(specular,tag,False)) + + self.properties.specular_uv_set=common.get_xml_data(specular,["light_map","uv_set"],True) + self.properties.specular_normal_map_type=common.get_xml_data(specular,["normal_map","type"],True) + + #style sheets + self.set_widget_color('ambient',self.ui.material_ambient_color_pkr) + self.set_widget_color('diffuse',self.ui.material_diffuse_color_pkr) + self.set_widget_color('specular',self.ui.material_specular_color_pkr) + self.set_widget_color('emissive',self.ui.material_emissive_color_pkr) + + def reset(self,default=True): + if default: + self._material_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element + else: + doc=FreeCAD.ActiveDocument + _root_dict=doc.Robot_Description.Proxy.element_dict + #since material does not exist independently find the parent + el_dict=common.parse_dict(_root_dict,self.parent_path) + if el_dict is not None: + #find the material element in parent element + elem=ET.fromstring(el_dict['elem_str']).find('.//material') + #make check since material might not always be included in the final element tree + # since its optional + if elem is not None: + self.merge_elements(self._material_element,elem) + self.updateUi() + + +#merger +#this merge method repeats alot + def merge_elements(self,destination_el, source_el): + common.merge_elements(destination_el,source_el) + + @property + def element(self): + #make deep copy to avoid altering local element + temp_el=copy.deepcopy(self._material_element) + #script + if self.ui.material_script_groupBox.isChecked(): + #if script is checked remove al other color properties + tags=['shader','ambient','diffuse','specular','emissive','shininess','render_order' + ,'lighting'] + for elem_tag in tags: + temp_el.remove(temp_el.find('.//'+elem_tag)) + else: + temp_el.remove(temp_el.find('.//script')) + #shader + if self.ui.material_shader_groupBox.isChecked(): + #if shader is checked check if the normal map is checked and remve it if neccessary + if self.properties.normal_map_checkbox is False: + shader_el=temp_el.find('.//shader') + shader_el.remove(shader_el.find('.//normal_map')) + + else: + temp_el.remove(temp_el.find('.//shader')) + + #remove color related configs + if self.ui.material_ambient_groupbox.isChecked() is False: + temp_el.remove(temp_el.find('.//ambient')) + + if self.ui.material_diffuse_groupbox.isChecked() is False: + temp_el.remove(temp_el.find('.//diffuse')) + + if self.ui.material_specular_groupbox.isChecked() is False: + temp_el.remove(temp_el.find('.//specular')) + + if self.ui.material_emissive_groupbox.isChecked() is False: + temp_el.remove(temp_el.find('.//emissive')) + + #logic for materials related to pbr + if self.properties.pbr_enabled and temp_el.find('pbr') is not None: + metal=temp_el.find('.//pbr/metal') + if self.properties.metal_enabled and metal is not None: + #{tag : property} + #where propertty are the propertieswhose names end with with _cb + metal_opt_elems={'albedo_map':"metal_albedo_map_cb",'roughness_map':"metal_roughness_map_cb","metalness_map":"metalness_map_cb" + ,"metalness":"metalness_cb", + "environment_map":"metal_environment_map_cb","ambient_occlusion_map":"metal_ambient_occlusion_map_cb","emissive_map":"metal_emissive_map_cb", + "light_map":"metal_light_map_cb","normal_map":"metal_normal_map_cb"} + for tag in metal_opt_elems.keys(): + if getattr(self.properties,metal_opt_elems[tag]) is not True: + metal.remove(metal.find('.//'+tag)) + else: + if metal is not None: + temp_el.remove(metal) + #related to specular + specular=temp_el.find(".//pbr/specular") + if self.properties.specular_enabled and specular is not None: + #{tag : property} + #where propertty are the properties whose names end with with _cb + specular_opts={"albedo_map":"specular_albedo_map_cb","specular_map":"specular_map_cb","glossiness":"specular_glossiness_cb", + "environment_map":"specular_environment_map_cb", + "ambient_occlusion_map": "specular_ambient_occlusion_map_cb","emissive_map":"specular_emissive_map_cb", + "glossiness_map":"specular_glossiness_map_cb", + "light_map":"specular_light_map_cb","normal_map":"specular_normal_map_cb"} + for tag in specular_opts.keys(): + if getattr(self.properties,specular_opts[tag]) is not True: + specular.remove(specular.find('.//'+tag)) + else: + if specular is not None: + temp_el.remove(specular) + + return temp_el \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/model.py b/robot_descriptor/sdf_elements/model.py new file mode 100644 index 0000000..a75a114 --- /dev/null +++ b/robot_descriptor/sdf_elements/model.py @@ -0,0 +1,9 @@ +from ..RD_utils import initialize_element_tree + + +class model: + def __intit__(self,root_d): + self.file_name='model.sdf' + self.parent_path=['sdf'] + self._root_dict=root_d + self.model_element=initialize_element_tree.convdict_2_tree(self.file_name) \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/road.py b/robot_descriptor/sdf_elements/road.py index 5a8b41e..98ad00a 100644 --- a/robot_descriptor/sdf_elements/road.py +++ b/robot_descriptor/sdf_elements/road.py @@ -8,7 +8,7 @@ # import Spreadsheet import os import xml.etree.ElementTree as ET -import FreeCAD +import FreeCAD ,FreeCADGui #======================================== #road properties #======================================== @@ -31,330 +31,6 @@ def width(self): def width(self,value): self.ui.road_width_sp.setValue(value) - -#================================================== -# road material -#================================================== -class material_properties: - def __init__(self,ui) -> None: - self.ui=ui -#script uri - @property - def script_uri(self): - return self.ui.material_script_uri_input.text() - @script_uri.setter - def script_uri(self,text): - self.ui.material_script_uri_input.setText(text) - -#script name - @property - def script_name(self): - return self.ui.material_script_name.text() - @script_name.setter - def script_name(self,text): - self.ui.material_script_name.setText(text) - -#shader_type - @property - def shader_type(self): - return self.ui.shader_type.currentText() - @shader_type.setter - def shader_type(self,text): - self.ui.shader_type.setCurrentText(text) -#normal map - @property - def normal_map(self): - return self.ui.material_normal_map_input.text() - @normal_map.setter - def normal_map(self,text): - self.ui.material_normal_map_input.setText(text) - -#this checkebox is not part of the sdf data its just used to enable and disable the normal_map input -# so no need to convert bool to strinf - @property - def normal_map_checkbox(self): - return self.ui.normal_map_checkBox.isChecked() - - @normal_map_checkbox.setter - def normal_map_checkbox(self,state): - if state is True: - self.ui.normal_map_checkBox.setState(QtCore.Qt.Checked) - else: - self.ui.normal_map_checkBox.setState(QtCore.Qt.Unchecked) - -#render order - @property - def render_order(self): - return self.ui.material_render_order_sp.value() - @render_order.setter - def render_order(self,value): - self.ui.material_render_order_sp.setValue(value) - -#shininess - @property - def shininess(self): - return self.ui.materroad_pointsial_shininess_sp.value() - @shininess.setter - def shininess(self,value): - self.ui.material_shininess_sp.setValue(value) - -#lighting - @property - def lighting(self): - state= self.ui.material_lighting_checkbox.isChecked() - if state is True: - return str('true') - else: - return str('false') - @lighting.setter - def lighting(self,state): - if state is True: - self.ui.material_lighting_checkbox.setState(QtCore.Qt.Checked) - else: - self.ui.material_lighting_checkbox.setState(QtCore.Qt.Unchecked) - - -#ambient - @property - def ambient(self): - return [self.ui.material_ambient_R_sp.value(),self.ui.material_ambient_G_sp.value(), - self.ui.material_ambient_B_sp.value(),self.ui.material_ambient_A_sp.value()] - @ambient.setter - def ambient(self,vals): - self.ui.material_ambient_R_sp.setValue(vals[0]) - self.ui.material_ambient_G_sp.setValue(vals[1]) - self.ui.material_ambient_B_sp.setValue(vals[2]) - self.ui.material_ambient_A_sp.setValue(vals[3]) -#diffuse - @property - def diffuse(self): - return [self.ui.material_diffuse_R_sp.value(),self.ui.material_diffuse_G_sp.value(), - self.ui.material_diffuse_B_sp.value(),self.ui.material_diffuse_A_sp.value()] - @diffuse.setter - def diffuse(self,vals): - self.ui.material_diffuse_R_sp.setValue(vals[0]) - self.ui.material_diffuse_G_sp.setValue(vals[1]) - self.ui.material_diffuse_B_sp.setValue(vals[2]) - self.ui.material_diffuse_A_sp.setValue(vals[3]) -#specular - @property - def specular(self): - return [self.ui.material_specular_R_sp.value(),self.ui.material_specular_G_sp.value(), - self.ui.material_specular_B_sp.value(),self.ui.material_specular_A_sp.value()] - @specular.setter - def specular(self,vals): - self.ui.material_specular_R_sp.setValue(vals[0]) - self.ui.material_specular_G_sp.setValue(vals[1]) - self.ui.material_specular_B_sp.setValue(vals[2]) - self.ui.material_specular_A_sp.setValue(vals[3]) -#emissive - @property - def emissive(self): - return [self.ui.material_emissive_R_sp.value(),self.ui.material_emissive_G_sp.value(), - self.ui.material_emissive_B_sp.value(),self.ui.material_emissive_A_sp.value()] - @emissive.setter - def emissive(self,vals): - self.ui.material_emissive_R_sp.setValue(vals[0]) - self.ui.material_emissive_G_sp.setValue(vals[1]) - self.ui.material_emissive_B_sp.setValue(vals[2]) - self.ui.material_emissive_A_sp.setValue(vals[3]) - -#=========================================== -#=========================================== -#material element -#============================================ -#============================================ -class material(common.color_pickr): - def __init__(self,ui) -> None: - super().__init__() - self.ui=ui - #use the road tag since material will be implemented as part of the road element - self.tag='road' - self.parent_path=['sdf','world'] - self.file_name='material.sdf' - - self._material_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element - self.properties=material_properties(self.ui) - #remove unused material elements - self._material_element.remove(self._material_element.find('.//pbr')) - self._material_element.remove(self._material_element.find('.//double_sided')) - self.configUI() - self.reset(default=False) - - def configUI(self): - self.ui.material_script_uri_input.textEdited.connect(self.on_uri) - self.ui.material_script_name.textEdited.connect(self.on_uri_name) - self.ui.shader_type.currentTextChanged.connect(self.on_shader_type) - self.ui.normal_map_checkBox.stateChanged.connect(self.on_normal_map_state) - self.ui.material_normal_map_input.textEdited.connect(self.on_normal_map) - self.ui.material_render_order_sp.valueChanged.connect(self.on_material_render_ord) - self.ui.material_shininess_sp.valueChanged.connect(self.on_shininess) - - #ambient - self.ui.material_ambient_R_sp.valueChanged.connect(self.on_ambient) - self.ui.material_ambient_G_sp.valueChanged.connect(self.on_ambient) - self.ui.material_ambient_B_sp.valueChanged.connect(self.on_ambient) - self.ui.material_ambient_A_sp.valueChanged.connect(self.on_ambient) - #diffuse - self.ui.material_diffuse_R_sp.valueChanged.connect(self.on_diffuse) - self.ui.material_diffuse_G_sp.valueChanged.connect(self.on_diffuse) - self.ui.material_diffuse_B_sp.valueChanged.connect(self.on_diffuse) - self.ui.material_diffuse_A_sp.valueChanged.connect(self.on_diffuse) - #specular - self.ui.material_specular_R_sp.valueChanged.connect(self.on_specular) - self.ui.material_specular_G_sp.valueChanged.connect(self.on_specular) - self.ui.material_specular_B_sp.valueChanged.connect(self.on_specular) - self.ui.material_specular_A_sp.valueChanged.connect(self.on_specular) - #emissive - self.ui.material_emissive_R_sp.valueChanged.connect(self.on_emissive) - self.ui.material_emissive_G_sp.valueChanged.connect(self.on_emissive) - self.ui.material_emissive_B_sp.valueChanged.connect(self.on_emissive) - self.ui.material_emissive_A_sp.valueChanged.connect(self.on_emissive) - - #color picker buttons - self.ui.material_ambient_color_pkr.clicked.connect(self.on_ambient_color_pkr) - self.ui.material_diffuse_color_pkr.clicked.connect(self.on_diffuse_color_pkr) - self.ui.material_specular_color_pkr.clicked.connect(self.on_specular_color_pkr) - self.ui.material_emissive_color_pkr.clicked.connect(self.on_emissive_color_pkr) - - - def on_uri(self): - common.set_xml_data(self._material_element,'uri',False,self.properties.script_uri) - - def on_uri_name(self): - common.set_xml_data(self._material_element,'name',False,self.properties.script_name) - - def on_shader_type(self): - common.set_xml_data(self._material_element,'shader',True,{'type':self.properties.shader_type}) - -#enable and disable normal map - def on_normal_map_state(self): - if self.properties.normal_map_checkbox: - self.ui.material_normal_map_input.setEnabled(True) - else: - self.ui.material_normal_map_input.setEnabled(False) - -#normal map - def on_normal_map(self): - common.set_xml_data(self._material_element,'normal_map',False,self.properties.normal_map) - -#material render order - def on_material_render_ord(self): - common.set_xml_data(self._material_element,'render_order',False,self.properties.render_order) - - def on_shininess(self): - common.set_xml_data(self._material_element,'shininess',False,self.properties.shininess) - - def on_ambient(self): - common.set_xml_data(self._material_element,'ambient',False,self.properties.ambient) - self.set_widget_color('ambient',self.ui.material_ambient_color_pkr) - - def on_diffuse(self): - common.set_xml_data(self._material_element,'diffuse',False,self.properties.diffuse) - self.set_widget_color('diffuse',self.ui.material_diffuse_color_pkr) - - def on_specular(self): - common.set_xml_data(self._material_element,'specular',False,self.properties.specular) - self.set_widget_color('specular',self.ui.material_specular_color_pkr) - - def on_emissive(self): - common.set_xml_data(self._material_element,'emissive',False,self.properties.emissive) - self.set_widget_color('emissive',self.ui.material_emissive_color_pkr) - - def on_ambient_color_pkr(self): - self.color_picker('ambient',self.ui.material_ambient_color_pkr) - - def on_diffuse_color_pkr(self): - self.color_picker('diffuse',self.ui.material_diffuse_color_pkr) - - def on_specular_color_pkr(self): - self.color_picker('specular',self.ui.material_specular_color_pkr) - - def on_emissive_color_pkr(self): - self.color_picker('emissive',self.ui.material_emissive_color_pkr) - - def updateUi(self): - self.properties.script_uri=common.get_xml_data(self._material_element,'uri',False) - self.properties.script_name=common.get_xml_data(self._material_element,'name',False) - self.properties.shader_type=common.get_xml_data(self._material_element,'type') - self.properties.normal_map=common.get_xml_data(self._material_element,'normal_map',False) - self.properties.render_order=common.get_xml_data(self._material_element,'render_order',False) - self.properties.shininess=common.get_xml_data(self._material_element,'shininess',False) - self.properties.ambient=common.get_xml_data(self._material_element,'ambient',False) - self.properties.diffuse=common.get_xml_data(self._material_element,'diffuse',False) - self.properties.specular=common.get_xml_data(self._material_element,'specular',False) - self.properties.emissive=common.get_xml_data(self._material_element,'emissive',False) - #style sheets - self.set_widget_color('ambient',self.ui.material_ambient_color_pkr) - self.set_widget_color('diffuse',self.ui.material_diffuse_color_pkr) - self.set_widget_color('specular',self.ui.material_specular_color_pkr) - self.set_widget_color('emissive',self.ui.material_emissive_color_pkr) - - def reset(self,default=True): - if default: - self._material_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element - #remove unused elements - self._material_element.remove(self._material_element.find('.//pbr')) - self._material_element.remove(self._material_element.find('.//double_sided')) - else: - doc=FreeCAD.ActiveDocument - _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) - if el_dict is not None: - #find the material element from road - elem=ET.fromstring(el_dict['elem_str']).find('.//material') - #make check since material might not always be included in the final element tree - # since its optional - if elem is not None: - self.merge_elements(self._material_element,elem) - self.updateUi() - - -#merger -#this merge method repeats alot - def merge_elements(self,destination_el, source_el): - common.merge_elements(destination_el,source_el) - - @property - def element(self): - #make deep copy to avoid altering local element - temp_el=copy.deepcopy(self._material_element) - #script - if self.ui.material_script_groupBox.isChecked(): - #if script is checked remove al other color properties - tags=['shader','ambient','diffuse','specular','emissive','shininess','render_order' - ,'lighting'] - for elem_tag in tags: - temp_el.remove(temp_el.find('.//'+elem_tag)) - else: - temp_el.remove(temp_el.find('.//script')) - #shader - if self.ui.material_shader_groupBox.isChecked(): - #if shader is checked check if the normal map is checked and remve it if neccessary - if self.properties.normal_map_checkbox is False: - shader_el=temp_el.find('.//shader') - shader_el.remove(shader_el.find('.//normal_map')) - - else: - temp_el.remove(temp_el.find('.//shader')) - - #remove color related configs - if self.ui.material_ambient_groupbox.isChecked() is False: - temp_el.remove(temp_el.find('.//ambient')) - - if self.ui.material_diffuse_groupbox.isChecked() is False: - temp_el.remove(temp_el.find('.//diffuse')) - - if self.ui.material_specular_groupbox.isChecked() is False: - temp_el.remove(temp_el.find('.//specular')) - - if self.ui.material_emissive_groupbox.isChecked() is False: - temp_el.remove(temp_el.find('.//emissive')) - - return temp_el - - - #================================================= #================================================= #road @@ -369,13 +45,19 @@ def __init__(self,ui): self._road_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element self._road_properties=road_properties(self.ui) #material element - self._material=material(self.ui) + from . import material + self.material_widget=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"material.ui")) + self._material=material.material(self.material_widget,self.parent_path+[self.tag]) + + #disable unused material ui elements + self.material_widget.material_pbr_groupbox.setEnabled(False) + self.material_widget.material_double_sided_checkBox.setEnabled(False) self.point_element=copy.deepcopy(self._road_element.find('.//point')) #disable the scroll widget + + self.ui.road_scroll.setWidget(self.material_widget.widget) self.ui.road_scroll.setEnabled(False) - - #remove elements that will not be edited #configure the Ui and callbacks self.configUI() @@ -448,7 +130,13 @@ def reset(self,default=True): #material is an optional element hence might not be included if mat is not None: - self._road_element.remove(mat ) + self._road_element.remove(mat) + self._material.reset(default=False) + + #remove unused material elements + self._material._material_element.remove(self._material._material_element.find('.//pbr')) + self._material._material_element.remove(self._material._material_element.find('.//double_sided')) + self.updateUI() @property @@ -456,10 +144,9 @@ def element(self): #update data in sheet before export self.get_sheet_data() - _elem=copy.deepcopy(self._road_element) #check if materialis enabled - if self.ui.road_material_groupbox.isChecked(): + if self.ui.include_material_info.isChecked(): mat_el=self._material.element _elem.append(mat_el) return _elem diff --git a/robot_descriptor/sdf_elements/world.py b/robot_descriptor/sdf_elements/world.py index 4460652..dc5154b 100644 --- a/robot_descriptor/sdf_elements/world.py +++ b/robot_descriptor/sdf_elements/world.py @@ -108,9 +108,9 @@ def __init__(self): self.parent_path=["sdf"] self.tag='world' self.file_name="world.sdf" - self.ui_path=os.path.join(common.UI_PATH,"world.ui") self.world_form=FreeCADGui.PySideUic.loadUi(self.ui_path) + #get main window for use in aligning mw=FreeCADGui.getMainWindow() #centre dialog to main window self.world_form.move( @@ -142,8 +142,10 @@ def __init__(self): self.configUI() #update ui with previously configured values if available + self.reset(False) - + #display window + self.world_form.exec_() #window close event this is called when the (x) widget icon is pressed def closeEvent(self, event): print('closing widget\n') @@ -204,8 +206,7 @@ def configUI(self): # reset Pb self.world_form.world_reset_btn.clicked.connect(self.on_reset) - #display window - self.world_form.exec_() + def update_element(self): @@ -273,7 +274,7 @@ def on_apply_pb(self): if self.world_form.enable_scene_checkBox.isChecked(): common.update_dictionary(self._scene.parent_path,self._scene.tag,self._scene.element) #append the road element - if self.world_form.enable_road_checkbox.isChecked(): + if self.world_form.include_material_info.isChecked(): common.update_dictionary(self._road.parent_path,self._road.tag,self._road.element) print("updated\n") From 86416d4b6405a9ff25aefb22d9a25424040e1884 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Thu, 18 Jan 2024 11:26:38 +0300 Subject: [PATCH 4/9] completed model ui --- robot_descriptor/common.py | 8 +- robot_descriptor/forms/material.ui | 814 +++++--- robot_descriptor/forms/model_editor.ui | 710 ++++--- robot_descriptor/forms/surface.ui | 2104 ++++++++++---------- robot_descriptor/forms/world.ui | 20 +- robot_descriptor/model_editor.py | 2 - robot_descriptor/sdf_elements/collision.py | 92 + robot_descriptor/sdf_elements/light.py | 6 +- robot_descriptor/sdf_elements/link.py | 242 ++- robot_descriptor/sdf_elements/material.py | 223 ++- robot_descriptor/sdf_elements/surface.py | 795 ++++++++ robot_descriptor/sdf_elements/visual.py | 115 ++ 12 files changed, 3454 insertions(+), 1677 deletions(-) create mode 100644 robot_descriptor/sdf_elements/surface.py create mode 100644 robot_descriptor/sdf_elements/visual.py diff --git a/robot_descriptor/common.py b/robot_descriptor/common.py index 4f94cca..86ca60a 100644 --- a/robot_descriptor/common.py +++ b/robot_descriptor/common.py @@ -14,10 +14,10 @@ - +import os import FreeCAD -ICON_PATH=FreeCAD.getUserAppDataDir()+"Mod/RobotDescriptor/robot_descriptor/icons" -UI_PATH=FreeCAD.getUserAppDataDir()+"Mod/RobotDescriptor/robot_descriptor/forms" +ICON_PATH=os.path.join(FreeCAD.getUserAppDataDir()+"Mod","RobotDescriptor","robot_descriptor","icons") +UI_PATH=os.path.join(FreeCAD.getUserAppDataDir()+"Mod","RobotDescriptor","robot_descriptor","forms") DOCUMENT=FreeCAD.ActiveDocument import copy import xml.etree.ElementTree as ET @@ -90,7 +90,7 @@ def set_xml_data(element:ET.Element,tag:str,Is_Attribute:bool,value:Union[dict,f else: #add/edit attributes for key in value.keys(): - elem.set(key,value[key]) + elem.set(key,str(value[key])) return element diff --git a/robot_descriptor/forms/material.ui b/robot_descriptor/forms/material.ui index fbf8c92..e2ea512 100644 --- a/robot_descriptor/forms/material.ui +++ b/robot_descriptor/forms/material.ui @@ -182,6 +182,9 @@ + + false + 118 @@ -266,8 +269,8 @@ - - + + 520 @@ -284,7 +287,7 @@ background color - ambient + diffuse true @@ -292,9 +295,9 @@ false - - - + + + 0 @@ -315,24 +318,8 @@ - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - + 16777215 @@ -347,46 +334,8 @@ - - - - - 16777215 - 24 - - - - R - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - + 0 @@ -407,8 +356,8 @@ - - + + 16777215 @@ -416,37 +365,15 @@ - G + B Qt::AlignCenter - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - + 45 @@ -458,36 +385,6 @@ - - - - - - - - 520 - 100 - - - - - 520 - 100 - - - - background color - - - diffuse - - - true - - - false - - @@ -510,40 +407,8 @@ - - - - - 16777215 - 24 - - - - B - - - Qt::AlignCenter - - - - - - - - 16777215 - 24 - - - - A - - - Qt::AlignCenter - - - - - + + 16777215 @@ -551,7 +416,7 @@ - R + G Qt::AlignCenter @@ -580,30 +445,8 @@ - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - + + 16777215 @@ -611,48 +454,13 @@ - G + R Qt::AlignCenter - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 45 - 16777215 - - - - - - - @@ -1109,12 +917,12 @@ - + metal - false + true false @@ -1128,7 +936,11 @@ - + + + false + + @@ -1138,7 +950,11 @@ - + + + false + + @@ -1148,7 +964,11 @@ - + + + false + + @@ -1158,7 +978,11 @@ - + + + false + + @@ -1169,6 +993,9 @@ + + false + 250 @@ -1191,7 +1018,11 @@ - + + + false + + @@ -1201,7 +1032,11 @@ - + + + false + + @@ -1211,7 +1046,11 @@ - + + + false + + @@ -1350,6 +1189,9 @@ + + false + 90 @@ -1417,6 +1259,9 @@ + + false + 250 @@ -1446,7 +1291,11 @@ - + + + false + + @@ -1523,6 +1372,9 @@ + + false + 85 @@ -1589,19 +1441,39 @@ - + + + false + + - + + + false + + - + + + false + + - + + + false + + - + + + false + + @@ -1609,9 +1481,493 @@ + + + + + 520 + 100 + + + + + 520 + 100 + + + + background color + + + ambient + + + true + + + false + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + B + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + A + + + Qt::AlignCenter + + + + + + + + 16777215 + 24 + + + + R + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 16777215 + 24 + + + + G + + + Qt::AlignCenter + + + + + + + + 0 + 24 + + + + + 16777215 + 24 + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 45 + 16777215 + + + + + + + + + + - + + + metal_albedo_map_checkBox + toggled(bool) + metal_albedo_map_lineEdit + setEnabled(bool) + + + 140 + 689 + + + 356 + 689 + + + + + metal_roughness_map_checkBox + toggled(bool) + metal_roughness_map_lineEdit + setEnabled(bool) + + + 140 + 728 + + + 356 + 728 + + + + + metal_roughness_checkBox + toggled(bool) + metal_roughness_lineEdit + setEnabled(bool) + + + 140 + 767 + + + 356 + 767 + + + + + metalness_map_checkBox + toggled(bool) + metalness_map_lineEdit + setEnabled(bool) + + + 140 + 806 + + + 356 + 806 + + + + + metalness_checkBox + toggled(bool) + metalness_sp + setEnabled(bool) + + + 140 + 845 + + + 356 + 845 + + + + + metal_environment_map_checkBox + toggled(bool) + metal_environment_map_lineEdit + setEnabled(bool) + + + 140 + 885 + + + 356 + 885 + + + + + metal_ambient_occlusion_map_checkBox + toggled(bool) + metal_ambient_occlusion_map_lineEdit + setEnabled(bool) + + + 140 + 924 + + + 356 + 924 + + + + + metal_emissive_map_checkBox + toggled(bool) + metal_emissive_map_lineEdit + setEnabled(bool) + + + 140 + 963 + + + 356 + 963 + + + + + metal_uv_set_checkBox + toggled(bool) + metal_uv_set_sp + setEnabled(bool) + + + 321 + 1091 + + + 422 + 1091 + + + + + normal_map_checkBox + toggled(bool) + material_normal_map_input + setEnabled(bool) + + + 334 + 89 + + + 440 + 89 + + + + + specular_albedo_map_checkBox + toggled(bool) + specular_albedo_map_lineEdit + setEnabled(bool) + + + 122 + 1200 + + + 338 + 1200 + + + + + specular_map_checkBox + toggled(bool) + specular_map_lineEdit + setEnabled(bool) + + + 122 + 1229 + + + 338 + 1229 + + + + + specular_glossiness_map_checkBox + toggled(bool) + specular_glossiness_map_lineEdit + setEnabled(bool) + + + 122 + 1375 + + + 338 + 1375 + + + + + specular_glossiness_checkBox + toggled(bool) + specular_glossiness_sp + setEnabled(bool) + + + 122 + 1258 + + + 338 + 1258 + + + + + specular_environment_map_checkBox + toggled(bool) + specular_environment_map_lineEdit + setEnabled(bool) + + + 122 + 1288 + + + 338 + 1288 + + + + + specular_ambient_occlusion_map_checkBox + toggled(bool) + specular_ambient_occlusion_map_lineEdit + setEnabled(bool) + + + 155 + 1317 + + + 374 + 1317 + + + + + specular_emissive_map_checkBox + toggled(bool) + specular_emissive_map_lineEdit + setEnabled(bool) + + + 122 + 1346 + + + 338 + 1346 + + + + + specular_uv_set_checkBox + toggled(bool) + specular_uv_set_sp + setEnabled(bool) + + + 110 + 1484 + + + 201 + 1484 + + + + diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui index 3eef09d..70e5e77 100644 --- a/robot_descriptor/forms/model_editor.ui +++ b/robot_descriptor/forms/model_editor.ui @@ -14,6 +14,63 @@ Model Editor + + + + + 90 + 24 + + + + + 100 + 30 + + + + Ok + + + + + + + + 90 + 24 + + + + + 95 + 30 + + + + Apply + + + + + + + + 90 + 24 + + + + + 95 + 30 + + + + Reset + + + @@ -222,6 +279,9 @@ Links connected by a joint will never collide + + false + 14 @@ -279,6 +339,9 @@ Links connected by a joint will never collide + + false + 348 @@ -869,7 +932,7 @@ Links connected by a joint will never collide - + 90 @@ -1044,9 +1107,9 @@ Links connected by a joint will never collide - 78 - 30 - 112 + 81 + 32 + 139 26 @@ -1074,7 +1137,7 @@ Links connected by a joint will never collide - + 90 @@ -1303,7 +1366,7 @@ Links connected by a joint will never collide 16 100 343 - 66 + 67 @@ -1324,121 +1387,107 @@ Links connected by a joint will never collide moment_y - - - - 12 - 30 - 120 - 26 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - - 149 - 30 - 120 - 26 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 - - - kgm^2 - - - - - + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + + + + @@ -1617,7 +1666,7 @@ Links connected by a joint will never collide 18 174 343 - 66 + 67 @@ -1638,62 +1687,56 @@ Links connected by a joint will never collide moment_z - - - - 79 - 30 - 118 - 26 - - - - - - - - 10 - 15 - - - - - 10 - 18 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 - - - kgm^2 - - - - - + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 + + + kgm^2 + + + + + + @@ -1706,7 +1749,10 @@ Links connected by a joint will never collide collision - + + + false + 16 @@ -1729,140 +1775,240 @@ Links connected by a joint will never collide - + - 16 - 6 - 455 + 18 + 48 + 148 + 21 + + + + include_surface_info + + + + + + 10 + 7 + 467 26 - - - - 70 - 24 - - - - - 75 - 30 - - + laser_retro - + + + false + + - + max_contacts - + + + false + + - + - Material + visual - - - - 18 - 12 - 567 - 655 - - - - true - - - - - 0 - 0 - 565 - 653 - - - - + + + + + laser_retro + + + + + + + false + + + + + + + transparency + + + + + + + false + + + + + + + visibility_flags + + + + + + + false + + + + + + + cast_shadows + + + + + + + + 660 + 610 + + + + true + + + + + 0 + 0 + 661 + 614 + + + + + + - - - - - 90 - 24 - - - - - 95 - 30 - - - - Reset - - - - - - - - 90 - 24 - - - - - 95 - 30 - - - - Apply - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Ok - - - - + + + collision_laser_retro_cb + toggled(bool) + collision_laser_retro_sp + setEnabled(bool) + + + 333 + 58 + + + 451 + 58 + + + + + collison_max_contacts_cb + toggled(bool) + collision_max_contacts_sp + setEnabled(bool) + + + 569 + 58 + + + 686 + 58 + + + + + include_surface_info_cb + toggled(bool) + collision_scroll + setEnabled(bool) + + + 358 + 97 + + + 597 + 416 + + + + + visual_laser_retro_cb + toggled(bool) + visual_laser_retro_sp + setEnabled(bool) + + + 328 + 59 + + + 438 + 59 + + + + + visual_transparency_cb + toggled(bool) + visual_transparency_sp + setEnabled(bool) + + + 549 + 59 + + + 659 + 59 + + + + + visual_visibility_flags_cb + toggled(bool) + visual_visibility_flags_sp + setEnabled(bool) + + + 772 + 59 + + + 886 + 59 + + + + diff --git a/robot_descriptor/forms/surface.ui b/robot_descriptor/forms/surface.ui index b2103d0..530cd4b 100644 --- a/robot_descriptor/forms/surface.ui +++ b/robot_descriptor/forms/surface.ui @@ -7,7 +7,7 @@ 0 0 600 - 816 + 810 @@ -116,6 +116,9 @@ + + true + 0 @@ -123,878 +126,672 @@ - 1 + 2 + + + false + + + false + + + false friction - - - - 10 - 14 - 533 - 162 - - - - - 0 - 160 - - - - - 16777215 - 170 - - - - torsional - - - true - - - false - - - - - - - 0 - 24 - - - - - 70 - 16777215 - - - - coefficient - - - - - - - - 0 - 24 - - - - - 90 - 16777215 - - - - Torsional friction coefficient, unitless maximum ratio of + + + + + + + + true + + + false + + + + + + + 0 + 160 + + + + + 533 + 170 + + + + torsional + + + true + + + false + + + + + + + 0 + 24 + + + + + 70 + 16777215 + + + + coefficient + + + + + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Torsional friction coefficient, unitless maximum ratio of tangential stress to normal stress. - - - - - - - - 180 - 120 - - - - - 210 - 16777215 - - - - Torsional friction parameters for ODE - - - ode - - - true - - - - - 16 - 30 - 57 - 15 - - - - slip - - - - - - 56 - 26 - 111 - 24 - - - - force dependent slip for torsional friction, - equivalent to inverse of viscous damping coefficient - with units of rad/s/(Nm). + + + + + + + + 180 + 120 + + + + + 210 + 16777215 + + + + Torsional friction parameters for ODE + + + ode + + + true + + + + + 16 + 30 + 35 + 16 + + + + slip + + + + + + 60 + 28 + 111 + 24 + + + + force dependent slip for torsional friction, + equivalent to inverse of viscous damping coefficient + with units of rad/s/(Nm). A slip value of 0 is infinitely viscous - - - - - - - - - 0 - 24 - - - - - 130 - 16777215 - - - - If this flag is true, - torsional friction is calculated using the "patch_radius" parameter. - If this flag is set to false, - "surface_radius" (R) and contact depth (d) + + + + + + + + + 0 + 24 + + + + + 130 + 16777215 + + + + If this flag is true, + torsional friction is calculated using the "patch_radius" parameter. + If this flag is set to false, + "surface_radius" (R) and contact depth (d) are used to compute the patch radius as sqrt(R*d). - - - use_patch_radius - - - - - - - - 0 - 24 - - - - - 80 - 16777215 - - - - patch_radius - - - - - - - - 0 - 24 - - - - - 90 - 16777215 - - - - Radius of contact patch surface - - - - - - - - 0 - 24 - - - - - 130 - 16777215 - - - - surface_radius - - - - - - - - 0 - 24 - - - - - 90 - 16777215 - - - - Surface radius on the point of contact - - - - - - - - - 14 - 186 - 541 - 205 - - - - - 0 - 205 - - - - - 16777215 - 220 - - - - ODE - - - true - - - false - - - - - 100 - 34 - 62 - 24 - - - - Coefficient of friction in first friction pyramid direction, - the unitless maximum ratio of force in first friction pyramid - direction to normal force. - - - - - - 102 - 74 - 62 - 24 - - - - Coefficient of friction in second friction pyramid direction, - the unitless maximum ratio of force in second friction pyramid + + + use_patch_radius + + + + + + + + 0 + 24 + + + + + 80 + 16777215 + + + + patch_radius + + + + + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Radius of contact patch surface + + + + + + + + 0 + 24 + + + + + 130 + 16777215 + + + + surface_radius + + + + + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Surface radius on the point of contact + + + + + + + + + + + 0 + 205 + + + + + 505 + 220 + + + + ODE + + + true + + + false + + + + + + mu + + + + + + + false + + + Coefficient of friction in first friction pyramid direction, + the unitless maximum ratio of force in first friction pyramid direction to normal force. - - - - - - 18 - 104 - 493 - 66 - - - - - 500 - 465 - - - - unit vector specifying first friction pyramid direction in - collision-fixed reference frame. - If the friction pyramid model is in use, - and this value is set to a unit vector for one of the - colliding surfaces - - - fdir1 - - - true - - - - - - - 27 - 16777215 - - - - x - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 27 - 16777215 - - - - y - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 27 - 27 - - - - z - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - - 10 - 38 - 85 - 21 - - - - mu - - - - - - 10 - 74 - 85 - 21 - - - - mu2 - - - - - - 218 - 44 - 85 - 21 - - - - slip1 - - - - - - 214 - 84 - 85 - 21 - - - - slip2 - - - - - - 312 - 42 - 62 - 24 - - - - Force dependent slip in first friction pyramid direction, -equivalent to inverse of viscous damping coefficient - with units of m/s/N. + + + + + + + slip1 + + + + + + + false + + + Force dependent slip in first friction pyramid direction, +equivalent to inverse of viscous damping coefficient + with units of m/s/N. A slip value of 0 is infinitely viscous - - - - - - 314 - 82 - 62 - 24 - - - - Force dependent slip in second friction pyramid direction, - equivalent to inverse of viscous damping coefficient - with units of m/s/N. + + + + + + + mu2 + + + + + + + false + + + Coefficient of friction in second friction pyramid direction, + the unitless maximum ratio of force in second friction pyramid + direction to normal force. + + + + + + + slip2 + + + + + + + false + + + Force dependent slip in second friction pyramid direction, + equivalent to inverse of viscous damping coefficient + with units of m/s/N. A slip value of 0 is infinitely viscous. - - - - - - - 12 - 400 - 549 - 138 - - - - bullet - - - true - - - false - - - - - - friction - - - - - - - Coefficient of friction in first friction pyramid direction, - the unitless maximum ratio of force in first friction pyramid + + + + + + + + 500 + 465 + + + + unit vector specifying first friction pyramid direction in + collision-fixed reference frame. + If the friction pyramid model is in use, + and this value is set to a unit vector for one of the + colliding surfaces + + + fdir1 + + + true + + + false + + + + + + + 27 + 16777215 + + + + x + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 27 + 16777215 + + + + y + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 27 + 27 + + + + z + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + 508 + 16777215 + + + + bullet + + + true + + + false + + + + + + friction + + + + + + + false + + + Coefficient of friction in first friction pyramid direction, + the unitless maximum ratio of force in first friction pyramid direction to normal force - - - - - - - friction2 - - - - - - - Coefficient of friction in second friction pyramid direction, - the unitless maximum ratio of force in second friction pyramid + + + + + + + friction2 + + + + + + + false + + + Coefficient of friction in second friction pyramid direction, + the unitless maximum ratio of force in second friction pyramid direction to normal force - - - - - - - rolling_friction - - - - - - - Coefficient of rolling friction - - - - - - - - 500 - 465 - - - - Unit vector specifying first friction pyramid direction in + + + + + + + rolling_friction + + + + + + + false + + + Coefficient of rolling friction + + + + + + + + 500 + 465 + + + + Unit vector specifying first friction pyramid direction in collision-fixed reference frame - - - fdir1 - - - true - - - - - - - 27 - 16777215 - - - - x - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 27 - 16777215 - - - - y - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 27 - 27 - - - - z - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - + + + fdir1 + + + true + + + false + + + + + + + 27 + 16777215 + + + + x + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 27 + 16777215 + + + + y + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 27 + 27 + + + + z + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + contact - + - - - - 220 - 16777215 - - - - Flag to disable contact force generation, while still allowing collision checks and contact visualization to occur - - - collide_without_contact - - - - - - - - 220 - 16777215 - - - - collide_without_contact_bitmask - - - - - - - - 50 - 24 - - - - - 120 - 16777215 - - - - Bitmask for collision filtering when collide_without_contact is on - - - - - - - - 120 - 16777215 - - - - collide_bitmask - - - - - - - - 50 - 24 - - - - - 120 - 16777215 - - - - Bitmask for collision filtering. This will override collide_without_contact. Parsed as 16-bit unsigned integer - - - 65535 - - - - - - - - 0 - 24 - - - - - 120 - 16777215 - - - - category_bitmask - - - - - - - - 50 - 24 - - - - - 120 - 16777215 - - - - Bitmask for category of collision filtering. -Collision happens if ((category1 & collision2) | (category2 & collision1)) is not zero. -If not specified, the category_bitmask should be interpreted as being the same as collide_bitmask. -Parsed as 16-bit unsigned integer - - - 65535 - - - - - - - - 120 - 16777215 - - - - poissons_ratio - - - - - - - - 50 - 24 - - - - - 120 - 16777215 - - - - Poisson's ratio is the unitless ratio between transverse and axial strain. - This value must lie between (-1, 0.5). Defaults to 0.3 for typical steel. - Note typical silicone elastomers have Poisson's ratio near 0.49 ~ 0.50 - - - - - - - - 120 - 16777215 - - - - elastic_modulus - - - - - - - - 50 - 24 - - - - - 120 - 16777215 - - - - Young's Modulus in SI derived unit Pascal. - Defaults to -1. If value is less or equal to zero, - contact using elastic modulus (with Poisson's Ratio) is disabled. - - - - - + - ode + true @@ -1002,262 +799,453 @@ Parsed as 16-bit unsigned integer false - + - + + + + 220 + 16777215 + + + + Flag to disable contact force generation, while still allowing collision checks and contact visualization to occur + + + collide_without_contact + + + + + + + + 220 + 16777215 + + - soft_cfm + collide_without_contact_bitmask - - + + + + false + + + + 50 + 24 + + + + + 120 + 16777215 + + - Soft constraint force mixing + Bitmask for collision filtering when collide_without_contact is on - - + + + + + 120 + 16777215 + + - kd + collide_bitmask - - + + + + false + + + + 50 + 24 + + + + + 120 + 16777215 + + - dynamically "damping"-equivalent coefficient for contact joints + Bitmask for collision filtering. This will override collide_without_contact. Parsed as 16-bit unsigned integer + + + 65535 - - + + + + + 0 + 24 + + + + + 150 + 16777215 + + - soft_erp + category_bitmask - - + + + + false + + + + 50 + 24 + + + + + 120 + 16777215 + + - Soft error reduction parameter + Bitmask for category of collision filtering. +Collision happens if ((category1 & collision2) | (category2 & collision1)) is not zero. +If not specified, the category_bitmask should be interpreted as being the same as collide_bitmask. +Parsed as 16-bit unsigned integer + + + 65535 - - + + + + + 120 + 16777215 + + - max_vel + poissons_ratio - - + + + + false + + + + 50 + 24 + + + + + 120 + 16777215 + + - dynamically "damping"-equivalent coefficient for contact joints + Poisson's ratio is the unitless ratio between transverse and axial strain. + This value must lie between (-1, 0.5). Defaults to 0.3 for typical steel. + Note typical silicone elastomers have Poisson's ratio near 0.49 ~ 0.50 - - + + + + + 120 + 16777215 + + - kp + elastic_modulus - - - - dynamically "stiffness"-equivalent coefficient for contact joints + + + + false - - 2000000000000.000000000000000 + + + 50 + 24 + + + + + 120 + 16777215 + + + + Young's Modulus in SI derived unit Pascal. + Defaults to -1. If value is less or equal to zero, + contact using elastic modulus (with Poisson's Ratio) is disabled. - - - - min_depth + + + + ode + + + true + + + false + + + + + soft_cfm + + + + + + + false + + + Soft constraint force mixing + + + + + + + kd + + + + + + + false + + + dynamically "damping"-equivalent coefficient for contact joints + + + + + + + soft_erp + + + + + + + false + + + Soft error reduction parameter + + + + + + + max_vel + + + + + + + false + + + dynamically "damping"-equivalent coefficient for contact joints + + + + + + + kp + + + + + + + false + + + dynamically "stiffness"-equivalent coefficient for contact joints + + + 2000000000000.000000000000000 + + + + + + + min_depth + + + + + + + false + + + minimum allowable depth before contact correction impulse is applied + + + + - - - - minimum allowable depth before contact correction impulse is applied + + + + + 500 + 155 + + + + bullet + + + true + + false + + + + + + soft_cfm + + + + + + + false + + + Soft constraint force mixing + + + + + + + soft_erp + + + + + + + false + + + see ode + + + + + + + kp + + + + + + + split_impulse_penetration_threshold + + + + + + + false + + + see ode + + + 2000000000000.000000000000000 + + + + + + + imilar to ODE's max_vel implementation + + + + + + + kd + + + + + + + false + + + see ode + + + + + + + split_impulse + + + + - - - - - 551 - 155 - - - - bullet - - - true - - - false - - - - - 10 - 86 - 117 - 21 - - - - kp - - - - - - 133 - 25 - 146 - 24 - - - - Soft constraint force mixing - - - - - - 10 - 56 - 117 - 21 - - - - soft_erp - - - - - - 133 - 55 - 146 - 24 - - - - see ode - - - - - - 285 - 26 - 117 - 21 - - - - kd - - - - - - 408 - 25 - 117 - 24 - - - - see ode - - - - - - 133 - 85 - 146 - 24 - - - - see ode - - - 2000000000000.000000000000000 - - - - - - 10 - 26 - 117 - 21 - - - - soft_cfm - - - - - - 292 - 60 - 159 - 21 - - - - split_impulse - - - - - - 10 - 124 - 217 - 15 - - - - split_impulse_penetration_threshold - - - - - - 236 - 120 - 71 - 24 - - - - imilar to ODE's max_vel implementation - - - - diff --git a/robot_descriptor/forms/world.ui b/robot_descriptor/forms/world.ui index 466b3ee..74c7644 100644 --- a/robot_descriptor/forms/world.ui +++ b/robot_descriptor/forms/world.ui @@ -2001,16 +2001,6 @@ of degrees - - - - - 16777215 - 100 - - - - @@ -3028,6 +3018,16 @@ of degrees + + + + + 16777215 + 100 + + + + diff --git a/robot_descriptor/model_editor.py b/robot_descriptor/model_editor.py index 486710d..d93b670 100644 --- a/robot_descriptor/model_editor.py +++ b/robot_descriptor/model_editor.py @@ -58,8 +58,6 @@ def tree_setup(self,link_hierarchy,item): return - - #+=============================== #start command diff --git a/robot_descriptor/sdf_elements/collision.py b/robot_descriptor/sdf_elements/collision.py index e69de29..72f7b82 100644 --- a/robot_descriptor/sdf_elements/collision.py +++ b/robot_descriptor/sdf_elements/collision.py @@ -0,0 +1,92 @@ +from ..RD_utils import initialize_element_tree +from .. import common +from . import surface +import copy +import os +import xml.etree.ElementTree as ET +import FreeCADGui + + +class collision_properties: + def __init__(self,ui): + self.ui=ui +#laser retro + @property + def laser_retro(self): + return self.ui.collision_laser_retro_sp.value() + @laser_retro.setter + def laser_retro(self,value): + self.ui.collision_retro_sp.setValue(value) + +#max contacts + @property + def max_contacts(self): + return self.ui.collision_max_contacts_sp.value() + @max_contacts + def max_contacts(self,value): + self.ui.collision_max_contacts_sp.setValue(value) + +#checkboxes + @property + def collision_laser_retro_cb(self): + return self.ui.collision_laser_retro_cb.isChecked() + + @property + def collison_max_contacts_cb(self): + return self.ui.collison_max_contacts_cb.isChecked() + + + +class collison: + def __init__(self,parent_ui): + #model editor ui + self.ui=parent_ui + self.tag='collision' + self.parennt_path='' + self.properties=collision_properties(self.ui) + self.file_name='collision.sdf' + self.collision_elem=initialize_element_tree.convdict_2_tree(self.file_name).get_element + #surface element + self.surface_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"surface.ui")) + self.surface_elem=surface.surface(self.surface_ui) + #add widget to parent + self.ui.collision_scroll.setWidget(self.surface_ui.widget) + + self.configUI() + + def configUI(self): + self.ui.collision_max_contacts_sp.valueChanged.connect( + lambda collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"max_contacts",False,self.properties.max_contacts) + ) + self.ui.collision_laser_retro_sp.valueChanged.connect( + lambda collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"laser_retro",False,self.properties.laser_retro) + ) + + def updateUI(self): + data=["max_contacts","laser_retro"] + for item in data: + setattr(self.properties,item,common.get_xml_data(self.collision_elem,item,False)) + + def update_elem(self,elem:ET.Element): + surf=elem.find("surface") + if surf is not None: + self.surface_elem.update_elem(surf) + elem.remove(surf) + self.collision_elem=elem + + def reset(self): + pass + + @property + def element(self): + t_collision_elem=copy.deepcopy(self.collision_elem) + if not self.properties.collision_laser_retro_cb: + t_collision_elem.remove("laser_retro") + + if not self.properties.collison_max_contacts_cb: + t_collision_elem.remove("max_contacts") + + t_surface=self.surface_elem.element + + return t_collision_elem.append(t_surface) + \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/light.py b/robot_descriptor/sdf_elements/light.py index eb0f3c1..5f9c10b 100644 --- a/robot_descriptor/sdf_elements/light.py +++ b/robot_descriptor/sdf_elements/light.py @@ -1,3 +1,4 @@ +from typing import Any import xml.etree.ElementTree as ET from PySide import QtCore from PySide.QtGui import QMessageBox @@ -273,7 +274,7 @@ def configUI(self): #type self.ui.light_type.currentTextChanged.connect(self.on_type) #intensity - self.ui.intensity_sp.valueChanged.connect(self.on_intensity) + self.ui.intensity_sp.valueChanged.connect(lambda : common.set_xml_data(self._current_light_element,"intensity",False,self.properties.intensity)) #shadows self.ui.cast_shadows_check_b.stateChanged.connect(self.on_cast_shadows) #visualize @@ -403,9 +404,6 @@ def on_type(self): else: self.ui.direction_groupbox.setEnabled(False) - def on_intensity(self): - common.set_xml_data(self._current_light_element,"intensity",False,self.properties.intensity) - def on_cast_shadows(self): common.set_xml_data(self._current_light_element,"cast_shadows",False,self.properties.cast_shadows) diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py index 86cbe00..1551f11 100644 --- a/robot_descriptor/sdf_elements/link.py +++ b/robot_descriptor/sdf_elements/link.py @@ -1,7 +1,7 @@ import FreeCAD from .. import common from ..RD_utils import initialize_element_tree - +import copy from PySide import QtCore class link_properties: @@ -74,6 +74,173 @@ def angular(self): @angular.setter def angular(self,value): self.ui.link_angular_vel_decay_sp.setValue(value) + +#inertial +#fam -> fluid added mass +#xx + @property + def fam_xx(self): + return self.ui.fam_xx_sp.value() + @fam_xx.setter + def fam_xx(self,value): + self.ui.fam_xx_sp.setValue(value) +#xy + @property + def fam_xy(self): + return self.ui.fam_xy_sp.value() + @fam_xy.setter + def fam_xy(self,value): + self.ui.fam_xy_sp.setValue(value) +#xz + @property + def fam_xz(self): + return self.ui.fam_xz_sp.value() + @fam_xz.setter + def fam_xz(self,value): + self.ui.fam_xz_sp.setValue(value) + +#p + @property + def fam_xp(self): + return self.ui.fam_xp_sp.value() + @fam_xp.setter + def fam_xp(self,value): + self.ui.fam_xp_sp.setValue(value) + +#xq + @property + def fam_xq(self): + return self.ui.fam_xq_sp.value() + + @fam_xq.setter + def fam_xq(self,value): + self.ui.fam_xq_sp.setValue(value) + +#xr + @property + def fam_xr(self): + return self.ui.value() + @fam_xr.setter + def fam_xr(self,value): + self.ui.fam_xr_sp.setValue(value) + +#yy + @property + def fam_yy(self): + return self.ui.fam_yy_sp.value() + @fam_yy.setter + def fam_yy(self,val): + self.ui.fam_yy_sp.setValue(val) + +#yz + @property + def fam_yz(self): + return self.ui.fam_yz_sp.value() + @fam_yz.setter + def fam_yz(self,val): + self.ui.fam_yz_sp.setValue(val) + +#yp + @property + def fam_yp(self): + return self.ui.fam_yp_sp.value() + @fam_yp.setter + def fam_yp(self,value): + self.ui.fam_yp_sp.setValue(value) + +#yq + @property + def fam_yq(self): + return self.ui.fam_yq_sp.value() + @fam_yq.setter + def fam_yq(self,val): + self.ui.fam_yq.setValue(val) +#yr + @property + def fam_yr(self): + return self.ui.fam_yr_sp.value() + @fam_yr.setter + def fam_yr(self,val): + self.ui.fam_yr_sp.setValue(val) + +#zz + @property + def fam_zz(self): + return self.ui.fam_zz_sp.value() + @fam_zz.setter + def fam_zz(self,value): + self.ui.fam_zz_sp.setValue(value) +#zp + @property + def fam_zp(self): + return self.ui.fam_zp_sp.value() + @fam_zp.setter + def fam_zp(self,val): + self.ui.fam_zp_sp.setValue(val) + +#zq + @property + def fam_zq(self): + return self.ui.fam_zq_sp.value() + @fam_zq.setter + def fam_zp(self,val): + self.ui.fam_zq_sp.setValue(val) + +#zr + @property + def fam_zr(self): + return self.ui.fam_zr_sp.value() + @fam_zr.setter + def fam_zr(self,val): + return self.ui.fam_zr_sp.setValue(val) + +#pp + @property + def fam_pp(self): + return self.ui.fam_pp_sp.value() + @fam_pp.setter + def fam_pp(self,value): + self.ui.fam_pp_sp.setValue(value) + +#pq + @property + def fam_pq(self): + return self.ui.fam_pq_sp.value() + @fam_pq.setter + def fam_pq(self,val): + self.ui.fam_pq_sp.setValue(val) + +#pr + @property + def fam_pr(self): + return self.ui.fam_pr_sp.value() + @fam_pr.setter + def fam_pr(self,val): + self.ui.fam_pr_sp.setValue(val) +#qq + @property + def fam_qq(self): + return self.ui.fam_qq_sp.value() + @fam_qq.setter + def fam_qq(self,val): + self.ui.fam_qq_sp.setValue(val) + +#qr + @property + def fam_qr(self): + return self.ui.fam_qr_sp.value() + @fam_qr.setter + def fam_qr(self,val): + self.ui.fam_qr_sp.setValue(val) + +#rr + @property + def fam_rr(self): + return self.ui.fam_rr_sp.value() + @fam_rr.setter + def fam_rr(self,val): + self.ui.fam_rr_sp.setValue(val) + #====================== #link #==================== @@ -85,7 +252,10 @@ def __init__(self,ui,elem_struct): #models will be store as children of sdf self.parent_path=['sdf','model'] self.properties=link_properties(self.ui) - self.link_element=initialize_element_tree.convdict_2_tree(self.file_name) + self._inertial_element=initialize_element_tree.convdict_2_tree("inertial.sdf").get_element + + self.link_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element + # self.link_element.append(self._inertial_element) self._root_dict=elem_struct self.configUI() @@ -96,7 +266,44 @@ def configUI(self): self.ui.link_kinematic_checkbox.stateChanged.conned(self.onKinematic) self.ui.velocity_decay_linear_sp.clicked.connect(self.onLinear) self.ui.link_angular_vel_decay_sp.clicked.connect(self.onAngular) + #inertial + # fam=self.link_element.find(".//inertia/fluid_added_mass") + # fam every time the lmbda is called fam gets updated + self.ui.fam_xx_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xx',False,self.properties.fam_xx) ) + self.ui.fam_xy_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xy',False,self.properties.fam_xy) ) + self.ui.fam_xz_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xz',False,self.properties.fam_xz) ) + + self.ui.fam_xp_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xp',False,self.properties.fam_xp) ) + self.ui.fam_xq_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xq',False,self.properties.fam_xq) ) + self.ui.fam_xr_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xr',False,self.properties.fam_xr) ) + + #y + self.ui.fam_yy_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yy',False,self.properties.fam_yy)) + self.ui.fam_yz_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yz',False,self.properties.fam_yz)) + self.ui.fam_yp_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yp',False,self.properties.fam_yp)) + self.ui.fam_yq_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yq',False,self.properties.fam_yq)) + self.ui.fam_yr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yr',False,self.properties.fam_yr)) + + #z + self.ui.fam_zz_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zz',False,self.properties.fam_zz)) + self.ui.fam_zp_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zp',False,self.properties.fam_zp)) + self.ui.fam_zq_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zq',False,self.properties.fam_zq)) + self.ui.fam_zr_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zr',False,self.properties.fam_zr)) + + #p + self.ui.fam_pp_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pp',False,self.properties.fam_pp)) + self.ui.fam_pq_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pq',False,self.properties.fam_pq)) + self.ui.fam_pr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pr',False,self.properties.fam_pr)) + + self.ui.fam_qq_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qq',False,self.properties.fam_qq)) + self.ui.fam_qr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qr',False,self.properties.fam_qr)) + self.ui.fam_rr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'rr',False,self.properties.fam_rr)) + + + + +#end configUI def onGravity(self): common.set_xml_data(self.link_element,'gravity',False,self.properties.gravity) @@ -123,12 +330,31 @@ def UpdateUi(self,element): self.properties.kinematic= common.get_xml_data(element,'kinematic') self.properties.linear=common.set_xml_data(element,'linear') self.properties.angular=common.set_xml_data(element,'angular') - + fam=self._inertial_element.find(".//inertia/fluid_added_mass") + elem_ui_pairs={"xx":"fam_xx_sp","xy":"fam_xy_sp","xz":"fam_xz_sp","xp":"fam_xp_sp","xq":"fam_xq_sp","xr":"fam_xr_sp", + "yy":"fam_yy_sp","yz":"fam_yz_sp","yp":"fam_yp_sp","yq":"fam_yq_sp","yr":"fam_yr_sp","zz":"fam_zz_sp", + "zp":"fam_zp_sp","zq":"fam_zq_sp","zr":"fam_zr_sp","pp":"fam_pp_sp","pr":"fam_pr_sp","pq":"fam_pq_sp", + "qq":"fam_qq_sp","qr":"fam_qr_sp","rr":"fam_rr_sp"} + for tag in elem_ui_pairs.keys(): + setattr(self.properties,elem_ui_pairs[tag],common.get_xml_data(fam,tag,False)) + #this needs to reset the data of all links in the model #how will this information be extracted def reset(self,default=True): - if default: - self.link_element=initialize_element_tree.convdict_2_tree(self.file_name) - else: - elem_dict=common.parse_dict(self._root_dict,self.parent_path+[self.tag]) - \ No newline at end of file + pass + @property + def element(self): + t_link_elem=copy.deepcopy(self.link_element) + + if not self.ui.link_state_groupbox.isChecked(): + for tag in ["gravity","enable_wind","self_collide","kinematic"]: + t_link_elem.remove(t_link_elem.find(tag)) + + if self.ui.link_velocity_decay_groupbox.isChecked(): + t_link_elem.remove(t_link_elem.find("velocity_decay")) + + t_inertial_elem=copy.deepcopy(self._inertial_element) + if self.ui.self.link_elementfluid_added_mass_groupbox.isChecked(): + t_inertial_elem.remove(t_inertial_elem.find("fluid_added_mass")) + + return t_link_elem.append(t_inertial_elem) \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/material.py b/robot_descriptor/sdf_elements/material.py index 6719ed6..46cc52a 100644 --- a/robot_descriptor/sdf_elements/material.py +++ b/robot_descriptor/sdf_elements/material.py @@ -10,7 +10,6 @@ import xml.etree.ElementTree as ET import FreeCAD ,FreeCADGui - #matreial class material_properties: def __init__(self,ui) -> None: @@ -46,16 +45,6 @@ def normal_map(self): def normal_map(self,text): self.ui.material_normal_map_input.setText(text) -#this checkebox is not part of the sdf data its just used to enable and disable the normal_map input -# so no need to convert bool to strinf - @property - def normal_map_checkbox(self): - return str('true') if self.ui.normal_map_checkBox.isChecked() else str('false') - - @normal_map_checkbox.setter - def normal_map_checkbox(self,state): - self.ui.normal_map_checkBox.setState(QtCore.Qt.Checked) if state else self.ui.normal_map_checkBox.setState(QtCore.Qt.Unchecked) - #render order @@ -84,10 +73,10 @@ def lighting(self): return str('false') @lighting.setter def lighting(self,state): - if state is True: - self.ui.material_lighting_checkbox.setState(QtCore.Qt.Checked) + if state =='true': + self.ui.material_lighting_checkbox.setCheckState(QtCore.Qt.Checked) else: - self.ui.material_lighting_checkbox.setState(QtCore.Qt.Unchecked) + self.ui.material_lighting_checkbox.setCheckState(QtCore.Qt.Unchecked) #ambient @@ -369,7 +358,7 @@ def metal_emissive_map_cb(self): return self.ui.metal_emissive_map_checkBox.isChecked() @property def metal_normal_map_cb(self): - return self.ui.normal_map_groupBox.isChecked() + return self.ui.metal_normal_map_groupBox.isChecked() @property def metal_light_map_cb(self): @@ -411,7 +400,7 @@ def pbr_enabled(self): #metal cb @property def metal_enabled(self): - return self.ui.material_matal_groupbox.isChecked() + return self.ui.material_metal_groupbox.isChecked() #speculat cb @property def specular_enabled(self): @@ -444,11 +433,14 @@ def configUI(self): self.ui.material_script_uri_input.textEdited.connect(self.on_uri) self.ui.material_script_name.textEdited.connect(self.on_uri_name) self.ui.shader_type.currentTextChanged.connect(self.on_shader_type) - self.ui.normal_map_checkBox.stateChanged.connect(self.on_normal_map_state) self.ui.material_normal_map_input.textEdited.connect(self.on_normal_map) self.ui.material_render_order_sp.valueChanged.connect(self.on_material_render_ord) self.ui.material_shininess_sp.valueChanged.connect(self.on_shininess) + self.ui.material_lighting_checkbox.stateChanged.connect( + lambda : common.set_xml_data(self._material_element,"lighting",False,self.properties.lighting) + ) + #ambient self.ui.material_ambient_R_sp.valueChanged.connect(self.on_ambient) self.ui.material_ambient_G_sp.valueChanged.connect(self.on_ambient) @@ -476,83 +468,155 @@ def configUI(self): self.ui.material_specular_color_pkr.clicked.connect(self.on_specular_color_pkr) self.ui.material_emissive_color_pkr.clicked.connect(self.on_emissive_color_pkr) + #pbr #metal #properties under the metal element - metal=self._material_element.find('.//pbr/metal') - self.ui.metal_albedo_map_lineEdit.textEdited.connect( - lambda :common.set_xml_data(metal,'albedo_map',False,self.properties.metal_albedo_map)) + self.ui.metal_albedo_map_lineEdit.textEdited.connect(self.on_metal_albedo_map) - self.ui.metal_roughness_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(metal,'roughness_map',False,self.properties.metal_roughness_map)) - self.ui.metal_roughness_lineEdit.textEdited.connect(lambda :common.set_xml_data(metal, - "roughness",False,self.properties.metal_roughness)) + self.ui.metal_roughness_map_lineEdit.textEdited.connect(self.on_metal_roughness_map) + self.ui.metal_roughness_lineEdit.textEdited.connect(self.on_metal_roughness) - self.ui.metalness_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(metal,"metalness_map",False,self.properties.metalness_map)) + self.ui.metalness_map_lineEdit.textEdited.connect(self.on_metalness_map) - self.ui.metalness_sp.valueChanged.connect(lambda : - common.set_xml_data(metal,"metalness",False,self.properties.metalness)) + self.ui.metalness_sp.valueChanged.connect(self.on_metalness) - self.ui.metal_environment_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(metal,"environment_map",False,self.properties.metal_environment_map)) + self.ui.metal_environment_map_lineEdit.textEdited.connect(self.on_metal_environment_map) - self.ui.metal_ambient_occlusion_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(metal,"ambient_occlusion_map",False,self.properties.metal_ambient_occlusion_map)) + self.ui.metal_ambient_occlusion_map_lineEdit.textEdited.connect(self.on_metal_ambient_occlusion_map) - self.ui.metal_emissive_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(metal,"emissive_map",False,self.properties.metal_emissive_map)) + self.ui.metal_emissive_map_lineEdit.textEdited.connect(self.on_metal_emissive_map) - self.ui.metal_light_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(metal,"light_map",False,self.properties.metal_light_map)) + self.ui.metal_light_map_lineEdit.textEdited.connect(self.on_metal_light_map) - self.ui.metal_uv_set_sp.valueChanged.connect(lambda : - common.set_xml_data(metal,"light_map",True,{"uv_set":self.properties.metal_uv_set})) + self.ui.metal_uv_set_sp.valueChanged.connect(self.on_metal_uv_set) - self.ui.metal_normal_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(metal,"normal_map",False,self.properties.metal_normal_map)) - self.ui.metal_normal_map_type_comboBox.currentTextChanged.connect(lambda : - common.set_xml_data(metal,"normal_map",True,{"type":self.properties.metal_normal_map_type})) + self.ui.metal_normal_map_lineEdit.textEdited.connect(self.on_metal_normal_map) + self.ui.metal_normal_map_type_comboBox.currentTextChanged.connect(self.on_metal_normal_map_type) #specular #elements under the specular subelement specular=self._material_element.find(".//pbr/specular") - self.ui.specular_albedo_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(specular,"albedo_map",False,self.properties.specular_albedo_map)) + self.ui.specular_albedo_map_lineEdit.textEdited.connect(self.on_specular_albdedo_map) - self.ui.specular_map_lineEdit.textEdited.connect(lambda : - common.set_xml_data(specular,"specular_map",False,self.properties.specular_map)) + self.ui.specular_map_lineEdit.textEdited.connect(self.on_specular_map) - self.ui.specular_glossiness_sp.valueChanged.connect(lambda : - common.set_xml_data(specular,"glossiness",False,self.properties.specular_glossiness)) + self.ui.specular_glossiness_sp.valueChanged.connect(self.on_specular_glossiness) - self.ui.specular_environment_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(specular,"environment_map",False,self.properties.specular_environment_map) - ) - self.ui.specular_ambient_occlusion_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(specular,"ambient_occlusion_map",False,self.properties.specular_ambient_occlusion_map) - ) - self.ui.specular_emissive_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(specular,"emissive_map",False,self.properties.specular_emissive_map) - ) - self.ui.specular_glossiness_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(specular,"glossiness_map",False,self.properties.specular_glossiness_map) - ) - self.ui.specular_light_map_lineEdit.textEdited.connect( - lambda :common.set_xml_data(specular,"light_map",False,self.properties.specular_light_map) - ) - self.ui.specular_uv_set_sp.valueChanged.connect( - lambda : common.set_xml_data(specular,"light_map",True,{"uv_set":self.properties.specular_uv_set}) - ) - self.ui.specular_normal_map_lineEdit.textEdited.connect( - lambda : common.set_xml_data(specular,"normal_map",False,self.properties.specular_normal_map) + self.ui.specular_environment_map_lineEdit.textEdited.connect(self.on_specular_environment_map) + self.ui.specular_ambient_occlusion_map_lineEdit.textEdited.connect(self.on_specular_ambient_occlusion_map) + self.ui.specular_emissive_map_lineEdit.textEdited.connect(self.on_specular_emissive_map) + self.ui.specular_glossiness_map_lineEdit.textEdited.connect(self.on_specular_glossiness_map) + self.ui.specular_light_map_lineEdit.textEdited.connect(self.on_specular_light_map) + + self.ui.specular_uv_set_sp.valueChanged.connect(self.on_specular_uv_set) + + self.ui.specular_normal_map_lineEdit.textEdited.connect(self.on_specular_normal_map ) - self.ui.specular_normal_map_type_comboBox.currentTextChanged.connect( - lambda : common.set_xml_data(specular,"normal_map",True,{"type":self.properties.specular_normal_map_type}) + self.ui.specular_normal_map_type_comboBox.currentTextChanged.connect(self.on_specular_normal_map_type ) - +#callbacks + #metal + def on_metal_albedo_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,'albedo_map',False,self.properties.metal_albedo_map) + + def on_metal_roughness_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,'roughness_map',False,self.properties.metal_roughness_map) + + def on_metal_roughness(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"roughness",False,self.properties.metal_roughness) + + + def on_metalness_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"metalness_map",False,self.properties.metalness_map) + + def on_metalness(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"metalness",False,self.properties.metalness) + + def on_metal_environment_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"environment_map",False,self.properties.metal_environment_map) + + def on_metal_ambient_occlusion_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"ambient_occlusion_map",False,self.properties.metal_ambient_occlusion_map) + + def on_metal_emissive_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"emissive_map",False,self.properties.metal_emissive_map) + def on_metal_light_map(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"light_map",False,self.properties.metal_light_map) + + def on_metal_uv_set(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"light_map",True,{"uv_set":self.properties.metal_uv_set}) + + + def on_metal_normal_map(self): + metal=self._material_element.find(' common.set_xml_data(specular,"albedo_map",False,self.properties.specular_albedo_map).//pbr/metal') + common.set_xml_data(metal,"normal_map",False,self.properties.metal_normal_map) + + + def on_metal_normal_map_type(self): + metal=self._material_element.find('.//pbr/metal') + common.set_xml_data(metal,"normal_map",True,{"type":self.properties.metal_normal_map_type}) + + #specular + + def on_specular_albdedo_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"albedo_map",False,self.properties.specular_albedo_map) + + def on_specular_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"specular_map",False,self.properties.specular_map) + + def on_specular_glossiness(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"glossiness",False,self.properties.specular_glossiness) + + + def on_specular_environment_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"environment_map",False,self.properties.specular_environment_map) + + def on_specular_ambient_occlusion_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"ambient_occlusion_map",False,self.properties.specular_ambient_occlusion_map) + + def on_specular_emissive_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"emissive_map",False,self.properties.specular_emissive_map) + + def on_specular_glossiness_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"glossiness_map",False,self.properties.specular_glossiness_map) + + def on_specular_light_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"light_map",False,self.properties.specular_light_map) + + def on_specular_uv_set(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"light_map",True,{"uv_set":self.properties.specular_uv_set}) + + def on_specular_normal_map(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"normal_map",False,self.properties.specular_normal_map) + + def on_specular_normal_map_type(self): + specular=self._material_element.find(".//pbr/specular") + common.set_xml_data(specular,"normal_map",True,{"type":self.properties.specular_normal_map_type}) + + def on_uri(self): common.set_xml_data(self._material_element,'uri',False,self.properties.script_uri) @@ -562,12 +626,6 @@ def on_uri_name(self): def on_shader_type(self): common.set_xml_data(self._material_element,'shader',True,{'type':self.properties.shader_type}) -#enable and disable normal map - def on_normal_map_state(self): - if self.properties.normal_map_checkbox: - self.ui.material_normal_map_input.setEnabled(True) - else: - self.ui.material_normal_map_input.setEnabled(False) #normal map def on_normal_map(self): @@ -619,6 +677,7 @@ def updateUi(self): self.properties.diffuse=common.get_xml_data(self._material_element,'diffuse',False) self.properties.specular=common.get_xml_data(self._material_element,'specular',False) self.properties.emissive=common.get_xml_data(self._material_element,'emissive',False) + self.properties.lighting=common.get_xml_data(self._material_element,"lighting",False) #pbr #metal metal=self._material_element.find('.//pbr/metal') @@ -711,7 +770,8 @@ def element(self): temp_el.remove(temp_el.find('.//emissive')) #logic for materials related to pbr - if self.properties.pbr_enabled and temp_el.find('pbr') is not None: + pbr=temp_el.find('pbr') + if self.properties.pbr_enabled and pbr is not None: metal=temp_el.find('.//pbr/metal') if self.properties.metal_enabled and metal is not None: #{tag : property} @@ -725,7 +785,7 @@ def element(self): metal.remove(metal.find('.//'+tag)) else: if metal is not None: - temp_el.remove(metal) + temp_el.find('.//pbr').remove(metal) #related to specular specular=temp_el.find(".//pbr/specular") if self.properties.specular_enabled and specular is not None: @@ -741,6 +801,9 @@ def element(self): specular.remove(specular.find('.//'+tag)) else: if specular is not None: - temp_el.remove(specular) + temp_el.find('.//pbr').remove(specular) + else: + if pbr is not None: + temp_el.remove(pbr) return temp_el \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/surface.py b/robot_descriptor/sdf_elements/surface.py new file mode 100644 index 0000000..2cf8cf2 --- /dev/null +++ b/robot_descriptor/sdf_elements/surface.py @@ -0,0 +1,795 @@ +from ..RD_utils import initialize_element_tree +from .. import common +from PySide2 import QtGui,QtCore +import copy +import xml.etree.ElementTree as ET + +class surface_properties: + def __init__(self,ui): + self.ui=ui + +#restitution_coefficient + @property + def restitution_coefficient(self): + return self.ui.collision_restitution_coefficient_sp.value() + @restitution_coefficient.setter + def restitution_coefficient(self,value): + self.ui.collision_restitution_coefficient_sp.setValue(value) + +#threshold + @property + def threshold(self): + return self.ui.collision_bounce_threshold_sp.value() + @threshold.setter + def threshold(self,value): + self.ui.collision_bounce_threshold_sp.setValue(value) + +#friction + #torsional + #coefficient + @property + def coefficient(self): + return self.ui.torsional_coeff_sp.value() + @coefficient.setter + def coefficient(self,value): + self.ui.torsional_coeff_sp.setValue(value) + + #use_patch_radius + @property + def use_patch_radius(self): + return str('true') if self.ui.use_patch_radius_cb.isChecked() else str('false') + @use_patch_radius.setter + def use_patch_radius(self,state): + self.ui.use_patch_radius_cb.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.use_patch_radius_cb.seCheckState(QtCore.Qt.Unchecked) + + #patch_radius + @property + def patch_radius(self): + return self.ui.torsional_patch_radius_sp.value() + @patch_radius.setter + def patch_radius(self,value): + self.ui.torsional_patch_radius_sp.setValue(value) + + #surface_radius + @property + def surface_radius(self): + return self.torsional_surface_radius_sp.value() + @surface_radius.setter + def surface_radius(self,value): + self.ui.torsional_surface_radius_sp.setValue() + + #slip + @property + def torsional_slip(self): + self.ui.torsional_ode_slip_sp.value() + + @torsional_slip.setter + def torsional_slip(self,value): + self.ui.torsional_ode_slip_sp.setValue(value) + +#ode + #mu + @property + def friction_ode_mu(self): + return self.ui.surface_ode_mu_sp.value() + @friction_ode_mu.setter + def friction_ode_mu(self,value): + self.ui.surface_ode_mu_sp.setValue(value) + + #mu2 + @property + def friction_ode_mu2(self): + return self.ui.surface_ode_mu2_sp.value() + @friction_ode_mu2.setter + def friction_ode_mu2(self,value): + self.ui.surface_ode_mu2_sp.setValue(value) + + #fdir1 + @property + def friction_ode_fdir1(self): + return [self.ui.surface_ode_fdir1_x_sp.value(),self.ui.surface_ode_fdir1_y_sp.value(),self.ui.surface_ode_fdir1_z_sp.value()] + + @friction_ode_fdir1.setter + def friction_ode_fdir1(self,vals): + self.ui.surface_ode_fdir1_x_sp.setValue(vals[0]) + self.ui.surface_ode_fdir1_y_sp.setValue(vals[1]) + self.ui.surface_ode_fdir1_z_sp.setValue(vals[2]) + + #slip1 + @property + def friction_ode_slip1(self): + return self.ui.surface_ode_slip1_sp.value() + @friction_ode_slip1.setter + def friction_ode_slip1(self,value): + self.ui.surface_ode_slip1_sp.setValue(value) + + #slip2 + @property + def friction_ode_slip2(self): + return self.ui.surface_ode_slip2_sp.value() + @friction_ode_slip2.setter + def friction_ode_slip2(self,value): + self.ui.surface_ode_slip2_sp.setValue(value) + + +#bullet + #friction + @property + def friction_bullet_friction(self): + return self.ui.surface_bullet_friction_sp.value() + @friction_bullet_friction.setter + def friction_bullet_friction(self,value): + self.ui.surface_bullet_friction_sp.setValue(value) + + #friction2 + @property + def friction_bullet_friction2(self): + return self.ui.surface_bullet_friction2_sp.value() + @friction_bullet_friction2.setter + def friction_bullet_friction2(self,value): + self.ui.surface_bullet_friction2_sp.setValue(value) + + #rolling_friction + @property + def friction_bullet_rolling_friction(self): + return self.ui.surface_bullet_rolling_friction_sp.value() + @friction_bullet_rolling_friction.setter + def friction_bullet_rolling_friction(self,value): + self.ui.surface_bullet_rolling_friction_sp.setValue(value) + + @property + def friction_bullet_fdir1(self): + return [self.ui.surface_bullet_fdir1_x_sp.value(),self.ui.surface_bullet_fdir1_x_sp.value(),self.ui.surface_bullet_fdir1_x_sp.value()] + + @friction_bullet_fdir1.setter + def friction_bullet_fdir1(self,vals): + self.ui.surface_bullet_fdir1_x_sp.setValue(vals[0]) + self.ui.surface_bullet_fdir1_x_sp.setValue(vals[1]) + self.ui.surface_bullet_fdir1_x_sp.setValue(vals[2]) + + +#contact + @property + def collide_without_contact(self): + return str('true') if self.ui.contact_collide_without_contact_cb.isChecked() else str('false') + @collide_without_contact.setter + def collide_without_contact(self,state): + self.ui.contact_collide_without_contact_cb.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.contact_collide_without_contact_cb.setCheckState(QtCore.Qt.Unchecked) + + #collide_without_contact_bitmask + @property + def collide_without_contact_bitmask(self): + return self.ui.contact_collide_without_contact_bitmask_sp.value() + @collide_without_contact_bitmask.setter + def collide_without_contact_bitmask(self,val): + self.ui.contact_collide_without_contact_bitmask_sp.setValue(val) + + @property + def collide_bitmask(self): + return self.ui.contact_collide_bitmask_sp.value() + @collide_bitmask.setter + def collide_bitmask(self,value): + self.ui.contact_collide_bitmask_sp.setValue(value) + + @property + def category_bitmask(self): + return self.ui.contact_category_bitmask_sp.value() + @category_bitmask.setter + def category_bitmask(self,value): + self.ui.contact_category_bitmask_sp.setValue(value) + + @property + def poissons_ratio(self): + return self.ui.contact_poissons_ratio_sp.value() + @poissons_ratio.setter + def poissons_ratio(self,value): + self.ui.contact_poissons_ratio_sp.setValue(value) + + @property + def elastic_modulus(self): + return self.ui.contact_elastic_modulus_sp.value() + @elastic_modulus.setter + def elastic_modulus(self,value): + self.ui.contact_elastic_modulus_sp.setValue(value) + #ode + + @property + def contact_ode_soft_cfm(self): + return self.ui.contact_ode_soft_cfm_sp.value() + @contact_ode_soft_cfm.setter + def contact_ode_soft_cfm(self,value): + self.ui.contact_ode_soft_cfm_sp.setValue(value) + + @property + def contact_ode_soft_erp(self): + return self.ui.contact_ode_soft_erp_sp.value() + @contact_ode_soft_erp.setter + def contact_ode_soft_erp(self,value): + self.ui.contact_ode_soft_erp_sp.setValue(value) + + @property + def contact_ode_kp(self): + return self.ui.contact_ode_kp_sp.value() + @contact_ode_kp.setter + def contact_ode_kp(self,value): + self.ui.contact_ode_kp_sp.setValue(value) + + @property + def contact_ode_kd(self): + return self.ui.contact_ode_kd_sp.value() + @contact_ode_kd.setter + def contact_ode_kd(self,value): + self.ui.contact_ode_kd_sp.setValue(value) + + @property + def contact_ode_max_vel(self): + return self.ui.contact_ode_max_vel_sp.value() + @contact_ode_max_vel.setter + def contact_ode_max_vel(self,value): + self.ui.contact_ode_max_vel_sp.setValue(value) + + @property + def contact_ode_min_depth(self): + return self.ui.contact_ode_min_depth_sp.value() + @contact_ode_min_depth.setter + def contact_ode_min_depth(self,value): + self.ui.contact_ode_min_depth_sp.setValue(value) + + #bullet + @property + def contact_bullet_soft_cfm(self): + return self.ui.contact_bullet_soft_cfm_sp.value() + @contact_bullet_soft_cfm.setter + def contact_bullet_soft_cfm(self,value): + self.ui.contact_bullet_soft_cfm_sp.setValue(value) + + @property + def contact_bullet_soft_erp(self): + return self.ui.contact_bullet_soft_erp_sp.value() + @contact_bullet_soft_erp.setter + def contact_bullet_soft_erp(self,value): + self.ui.contact_bullet_soft_erp_sp.setValue(value) + + @property + def contact_bullet_kp(self): + return self.ui.contact_bullet_kp_sp.value() + @contact_bullet_kp.setter + def contact_bullet_kp(self,value): + self.ui.contact_bullet_kp_sp.setValue(value) + + @property + def contact_bullet_kd(self): + return self.ui.contact_bullet_kd_sp.value() + @contact_bullet_kd.setter + def contact_bullet_kd(self,value): + self.ui.contact_bullet_kd_sp.setValue(value) + + @property + def contact_bullet_split_impulse(self): + return str('true') if self.ui.contact_bullet_split_impulse_cb.isChecked() else str('false') + @contact_bullet_split_impulse.setter + def contact_bullet_split_impulse(self,state): + self.ui.contact_bullet_split_impulse_cb.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.contact_bullet_split_impulse_cb.setCheckState(QtCore.Qt.Unchecked) + + @property + def split_impulse_penetration_threshold(self): + return self.ui.split_impulse_penetration_threshold_sp.value() + @split_impulse_penetration_threshold.setter + def split_impulse_penetration_threshold(self,value): + self.ui.split_impulse_penetration_threshold_sp.setValue(value) + +#soft contact + @property + def bone_attachment(self): + return self.ui.soft_contact_bone_attachment_sp.value() + @bone_attachment.setter + def bone_attachment(self,value): + self.ui.soft_contact_bone_attachment_sp.setValue(value) + + + @property + def stiffness(self): + return self.ui.soft_contact_stiffness_sp.value() + @stiffness.setter + def stiffness(self,value): + self.ui.soft_contact_stiffness_sp.setValue(value) + + @property + def damping(self): + return self.ui.soft_body_damping_sp.value() + @damping.setter + def damping(self,value): + self.ui.soft_body_damping_sp.setValue(value) + + @property + def flesh_mass_fraction(self): + self.ui.soft_contact_flesh_mass_fraction_sp.value() + @flesh_mass_fraction.setter + def flesh_mass_fraction(self,value): + self.ui.soft_contact_flesh_mass_fraction_sp.setValue(value) + +#========================================= +#_cb +#============================================ + #control checkboxes +#friction + @property + def surface_friction_mu_cb(self): + return self.ui.surface_friction_mu_cb.isChecked() + + @property + def surface_ode_mu2_cb(self): + return self.ui.surface_ode_mu2_cb.isChecked() + + @property + def surface_ode_slip1_cb(self): + return self.ui.surface_ode_slip1_cb.isChecked() + + @property + def surface_ode_slip2_cb(self): + return self.ui.surface_ode_slip2_cb.isChecked() + + @property + def surface_bullet_friction_cb(self): + return self.ui.surface_bullet_friction_cb.isChecked() + + @property + def surface_bullet_friction2_cb(self): + return self.ui.surface_bullet_friction2_cb.isChecked() + + @property + def surface_bullet_rolling_friction_cb(self): + return self.ui.surface_bullet_rolling_friction_cb.isChecked() + + @property + def ode_frdir1_groupbox(self): + return self.ui.ode_frdir1_groupbox.isChecked() + @property + def bullet_frdir1_groupbox(self): + return self.ui.bullet_frdir1_groupbox.isChecked() + + +#contact + @property + def contact_collide_without_contact_bitmask_cb(self): + return self.ui.contact_collide_without_contact_bitmask_cb.isChecked() + + @property + def contact_collide_bitmask_cb(self): + return self.ui.contact_collide_bitmask_cb.isChecked() + + @property + def contact_category_bitmask_cb(self): + return self.ui.contact_category_bitmask_cb.isChecked() + + @property + def contact_poissons_ratio_cb(self): + return self.ui.contact_poissons_ratio_cb.isChecked() + + @property + def contact_ode_soft_cfm_cb(self): + return self.ui.contact_ode_soft_cfm_cb.isChecked() + + @property + def contact_ode_soft_erp_cb(self): + return self.ui.contact_ode_soft_erp_cb.isChecked() + + @property + def contact_ode_kp_cb(self): + return self.ui.contact_ode_kp_cb.isChecked() + + @property + def contact_ode_kd_cb(self): + return self.ui.contact_ode_kd_cb.isChecked() + + @property + def contact_ode_max_vel_cb(self): + return self.ui.contact_ode_max_vel_cb.isChecked() + + @property + def contact_ode_min_depth_cb(self): + return self.ui.contact_ode_min_depth_cb.isChecked() + + @property + def contact_bullet_soft_cfm_cb(self): + return self.ui.contact_bullet_soft_cfm_cb.isChecked() + + @property + def contact_bullet_soft_erp_cb(self): + return self.ui.contact_bullet_soft_erp_cb.isChecked() + + @property + def contact_bullet_kp_cb(self): + return self.ui.contact_bullet_kp_cb.isChecked() + + @property + def contact_bullet_kd_cb(self): + return self.ui.contact_bullet_kd_cb.isChecked() + + +#======================================= +#=======surface =================== +#================================ + +class surface: + def __init__(self,ui) -> None: + self.ui=ui + self.properties=surface_properties(self.ui) + self.file_name="surface.sdf" + self.tag="surface" + self.surface_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element + self.configUI() + + def configUI(self): + #bounce + # bounce=self.surface_element.find('bounce') + self.ui.collision_restitution_coefficient_sp.valueChanged.connect(lambda bounce=self.surface_element.find('bounce'): + common.set_xml_data(bounce,"restitution_coefficient",False,self.properties.restitution_coefficient)) + + self.ui.collision_bounce_threshold_sp.valueChanged.connect(lambda bounce=self.surface_element.find('bounce'): + common.set_xml_data(bounce,"threshold",False,self.properties.threshold)) + + #torsional + # torsional=self.surface_element.find(".//friction/torsional") + self.ui.torsional_coeff_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + common.set_xml_data(torsional,"coefficient",False,self.properties.coefficient)) + self.ui.use_patch_radius_cb.stateChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + common.set_xml_data(torsional,"use_patch_radius",False,self.properties.use_patch_radius)) + + self.ui.torsional_patch_radius_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + common.set_xml_data(torsional,"patch_radius",False,self.properties.patch_radius)) + + self.ui.torsional_surface_radius_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + common.set_xml_data(torsional,"surface_radius",False,self.properties.surface_radius)) + + self.ui.torsional_ode_slip_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + common.set_xml_data(torsional,"slip",False,self.properties.torsional_slip)) + + #frictional_ode + # frictional_ode=self.surface_element.find(".//friction/ode") + + self.ui.surface_ode_mu_sp.valueChanged.connect(lambda frictional_ode=self.surface_element.find(".//friction/ode"): + common.set_xml_data(frictional_ode,"mu",False,self.properties.friction_ode_mu)) + + self.ui.surface_ode_mu2_sp.valueChanged.connect( + lambda frictional_ode=self.surface_element.find(".//friction/ode"): + common.set_xml_data(frictional_ode,"mu2",False,self.properties.friction_ode_mu2) + ) + + self.ui.surface_ode_slip1_sp.valuChanged.connect( + lambda frictional_ode=self.surface_element.find(".//friction/ode"): + common.set_xml_data(frictional_ode,"slip1",False,self.properties.friction_ode_slip1) + ) + + self.ui.surface_ode_slip2_sp.valueChanged.connect( + lambda frictional_ode=self.surface_element.find(".//friction/ode"): + common.set_xml_data(frictional_ode,"slip2",False,self.properties.friction_ode_slip2) + ) + + self.ui.surface_ode_fdir1_x_sp.valueChanged.connect(self.ode_fdir1) + self.ui.surface_ode_fdir1_y_sp.valueChanged.connect(self.ode_fdir1) + self.ui.surface_ode_fdir1_z_sp.valueChanged.connect(self.ode_fdir1) + + #frictional_bullet + # frictional_bullet=self.surface_element.find(".//fiction/bullet") + self.ui.surface_bullet_friction_sp.valueChanged.connect( + lambda frictional_bullet=self.surface_element.find(".//fiction/bullet"): + common.set_xml_data(frictional_bullet,"friction",False,self.properties.friction_bullet_friction)) + self.ui.surface_bullet_friction2_sp.valueChanged.connect( + lambda frictional_bullet=self.surface_element.find(".//fiction/bullet"): + common.set_xml_data(frictional_bullet,"friction2",False,self.properties.friction_bullet_friction2) + ) + + self.ui.surface_bullet_rolling_friction_sp.valueChanged.connect( + lambda frictional_bullet=self.surface_element.find(".//fiction/bullet"): + common.set_xml_data(frictional_bullet,"rolling_friction",False,self.properties.friction_bullet_rolling_friction) + ) + + + self.ui.surface_bullet_fdir1_x_sp.valueChanged.connect(self.bullet_fdir1) + self.ui.surface_bullet_fdir1_y_sp.valueChanged.connect(self.bullet_fdir1) + self.ui.surface_bullet_fdir1_z_sp.valueChanged.connect(self.bullet_fdir1) + + #contact + # contact=self.surface_element.find(".//contact") + self.ui.contact_collide_without_contact_cb.stateChanged.connect(self.on_contact_collide_without_contact) + + self.ui.contact_collide_without_contact_bitmask_sp.valueChanged.connect(self.on_contact_collide_without_contact_bitmask) + + self.ui.contact_collide_bitmask_sp.valueChanged.connect(self.on_contact_collide_bitmask) + + self.ui.contact_category_bitmask_sp.valueChanged.connect(self.on_contact_category_bitmask) + self.ui.contact_poissons_ratio_sp.valueChanged.connect(self.on_contact_poissons_ratio) + self.ui.contact_elastic_modulus_sp.valueChanged.connect(self.on_contact_elastic_modulus) + + #ode + + self.ui.contact_ode_soft_cfm_sp.valueChanged.connect(self.on_contact_ode_soft_cfm) + self.ui.contact_ode_soft_erp_sp.valueChanged.coneect(self.on_contact_ode_soft_erp) + self.ui.contact_ode_kp_sp.valueChanged.connect(self.on_contact_ode_kp) + self.ui.contact_ode_kd_sp.valueChanged.connect(self.on_contact_ode_kd) + self.ui.contact_ode_max_vel_sp.valueChanged.connect(self.on_contact_ode_max_vel) + self.ui.contact_ode_min_depth_sp.valueChanged.connect(self.on_contact_ode_min_depth) + + #bullet + # contact_bullet=self.surface_element.find(".//contact/bullet") + self.ui.contact_bullet_soft_cfm_sp.valueChanged.connect(self.on_contact_bullet_soft_cfm) + self.ui.contact_bullet_soft_erp_sp.valueChanged.connect(self.on_contact_bullet_soft_erp) + self.ui.contact_bullet_kp_sp.valueChanged.connect(self.on_contact_bullet_kp) + self.ui.split_impulse_penetration_threshold_sp.valueChanged.connect(self.on_split_impulse_penetration_threshold) + self.ui.contact_bullet_kd_sp.valueChanged.connect(self.on_contact_bullet_kd) + self.ui.contact_bullet_split_impulse_cb.stateChanged.connect(self.on_contact_bullet_split_impulse) + + #soft contact + # soft_contact=self.surface_element.find(".//surface/soft_contact") + self.ui.soft_contact_bone_attachment_sp.valueChanged.connect(self.on_soft_contact_bone_attachment) + self.ui.soft_contact_stiffness_sp.valueChanged.connect(self.on_soft_contact_stiffness) + self.ui.soft_body_damping_sp.valueChanged.connect(self.on_soft_body_damping) + self.ui.soft_contact_flesh_mass_fraction_sp.valueChanged.connect(self.on_soft_contact_flesh_mass_fraction) + + #contact + #bullet + def on_contact_bullet_soft_cfm(self): + contact_bullet=self.surface_element.find(".//contact/bullet") + common.set_xml_data(contact_bullet,"soft_cfm",False,self.properties.contact_bullet_soft_cfm) + + def on_contact_bullet_soft_erp(self): + contact_bullet=self.surface_element.find(".//contact/bullet") + common.set_xml_data(contact_bullet,"soft_erp",False,self.properties.contact_bullet_soft_erp) + + def on_contact_bullet_kp(self): + contact_bullet=self.surface_element.find(".//contact/bullet") + common.set_xml_data(contact_bullet,"kp",False,self.properties.contact_bullet_kp) + + def on_split_impulse_penetration_threshold(self): + contact_bullet=self.surface_element.find(".//contact/bullet") + common.set_xml_data(contact_bullet,"split_impulse_penetration_threshold",False,self.properties.split_impulse_penetration_threshold) + + def on_contact_bullet_kd(self): + contact_bullet=self.surface_element.find(".//contact/bullet") + common.set_xml_data(contact_bullet,"kd",False,self.properties.contact_bullet_kd) + + def on_contact_bullet_split_impulse(self): + contact_bullet=self.surface_element.find(".//contact/bullet") + common.set_xml_data(contact_bullet,"split_impulse",False,self.properties.contact_bullet_split_impulse) + + #soft contact + def on_soft_contact_bone_attachment(self): + soft_contact=self.surface_element.find(".//surface/soft_contact") + common.set_xml_data(soft_contact,"bone_attachment",False,self.properties.bone_attachment) + + def on_soft_contact_stiffness(self): + soft_contact=self.surface_element.find(".//surface/soft_contact") + common.set_xml_data(soft_contact,"stiffness",False,self.properties.stiffness) + + def on_soft_body_damping(self): + soft_contact=self.surface_element.find(".//surface/soft_contact") + common.set_xml_data(soft_contact,"damping",False,self.properties.damping) + + def on_soft_contact_flesh_mass_fraction(self): + soft_contact=self.surface_element.find(".//surface/soft_contact") + common.set_xml_data(soft_contact,"flesh_mass_fraction",False,self.properties.flesh_mass_fraction) + + #ode + + def on_contact_ode_soft_cfm(self): + contact_ode=self.surface_element.find(".//contact/ode") + common.set_xml_data(contact_ode,"soft_cfm",False,self.properties.contact_ode_soft_cfm) + + def on_contact_ode_soft_erp(self): + contact_ode=self.surface_element.find(".//contact/ode") + common.set_xml_data(contact_ode,"soft_erp",False,self.properties.contact_ode_soft_erp) + + def on_contact_ode_kp(self): + contact_ode=self.surface_element.find(".//contact/ode") + common.set_xml_data(contact_ode,"kp",False,self.properties.contact_ode_kp) + + def on_contact_ode_kd(self): + contact_ode=self.surface_element.find(".//contact/ode") + common.set_xml_data(contact_ode,"kd",False,self.properties.contact_ode_kd) + + def on_contact_ode_max_vel(self): + contact_ode=self.surface_element.find(".//contact/ode") + common.set_xml_data(contact_ode,"max_vel",False,self.properties.contact_ode_max_vel) + + def on_contact_ode_min_depth(self): + contact_ode=self.surface_element.find(".//contact/ode") + common.set_xml_data(contact_ode,"min_depth",False,self.properties.contact_ode_min_depth) + + #friction + #ode + def ode_fdir1(self): + frictional_ode=self.surface_element.find(".//friction/ode") + common.set_xml_data(frictional_ode,"fdir1",False,self.properties.friction_ode_fdir1) + #bullet + + def bullet_fdir1(self): + frictional_bullet=self.surface_element.find(".//fiction/bullet") + common.set_xml_data(frictional_bullet,"fdir1",False,self.properties.friction_bullet_fdir1) + + #contact + def on_contact_collide_without_contact(self): + contact=self.surface_element.find(".//contact") + common.set_xml_data(contact,"collide_without_contact",False,self.properties.collide_without_contact) + + def on_contact_collide_without_contact_bitmask(self): + contact=self.surface_element.find(".//contact") + common.set_xml_data(contact,"collide_without_contact_bitmask",False,self.properties.collide_without_contact_bitmask) + + def on_contact_collide_bitmask(self): + contact=self.surface_element.find(".//contact") + common.set_xml_data(contact,"collide_bitmask",False,self.properties.collide_bitmask) + + def on_contact_category_bitmask(self): + contact=self.surface_element.find(".//contact") + common.set_xml_data(contact,"category_bitmask",False,self.properties.category_bitmask) + def on_contact_poissons_ratio(self): + contact=self.surface_element.find(".//contact") + common.set_xml_data(contact,"poissons_ratio",False,self.properties.poissons_ratio) + + def on_contact_elastic_modulus(self): + contact=self.surface_element.find(".//contact") + common.set_xml_data(contact,"elastic_modulus",False,self.properties.elastic_modulus) + + + def updateUI(self): + #bounce + bounce=self.surface_element.find('bounce') + #{tag : property} + bounce_pairs={"restitution_coefficient":"restitution_coefficient", + "threshold":"threshold"} + for tag in bounce_pairs.keys(): + setattr(self.properties,bounce_pairs[tag],common.get_xml_data(bounce,tag,False)) + + #torsional + torsional=self.surface_element.find(".//friction/torsional") + #{tag property} + torsional_pairs={"coefficient":"coefficient","use_patch_radius":"use_patch_radius", + "patch_radius":"patch_radius","surface_radius":"surface_radius","slip":"torsional_slip"} + for tag in torsional_pairs.keys(): + setattr(self.properties,torsional_pairs[tag],common.set_xml_data(torsional,tag,False)) + + #friction + #ode + frictional_ode=self.surface_element.find(".//friction/ode") + friction_ode_pairs={"mu":"friction_ode_mu","mu2":"friction_ode_mu2","slip1":"friction_ode_slip1", + "slip2":"friction_ode_slip2","fdir1":"friction_ode_fdir1"} + for tag in friction_ode_pairs.keys(): + setattr(self.properties,friction_ode_pairs[tag],common.get_xml_data(frictional_ode,tag,False)) + + #bullet + frictional_bullet=self.surface_element.find(".//fiction/bullet") + friction_bullet_pairs={"friction":"friction_bullet_friction","friction2":"friction_bullet_friction2", + "rolling_friction":"friction_bullet_rolling_friction","fdir1":"friction_bullet_fdir1"} + for tag in friction_bullet_pairs.keys(): + setattr(self.properties,friction_bullet_pairs[tag],common.get_xml_data(frictional_bullet,tag,False)) + + #contact + #contact + contact=self.surface_element.find(".//contact") + contact_pairs={"collide_without_contact":"collide_without_contact","collide_without_contact_bitmask":"collide_without_contact_bitmask", + "category_bitmask":"category_bitmask","poissons_ratio":"poissons_ratio", + "elastic_modulus":"elastic_modulus"} + for tag in contact_pairs.keys(): + setattr(self.properties,contact_pairs[tag],common.get_xml_data(contact,tag,False)) + + + #ode + contact_ode=self.surface_element.find(".//contact/ode") + contact_ode_pairs={"soft_cfm":"contact_ode_soft_cfm","soft_erp":"contact_ode_soft_erp", + "kp":"contact_ode_kp","kd":"contact_ode_kd","max_vel":"contact_ode_max_vel", + "min_depth":"contact_ode_min_depth"} + for tag in contact_ode_pairs.keys(): + setattr(self.properties,contact_ode_pairs[tag],common.get_xml_data(contact_ode,tag,False)) + + #bullet + contact_bullet=self.surface_element.find(".//contact/bullet") + contact_bullet_pairs={"soft_cfm":"contact_bullet_soft_cfm","soft_erp":"contact_bullet_soft_erp", + "kp":"contact_bullet_kp","kd":"contact_bullet_kd","split_impulse":"contact_bullet_split_impulse", + "split_impulse_penetration_threshold":"split_impulse_penetration_threshold"} + for tag in contact_bullet_pairs.keys(): + setattr(self.properties,contact_bullet_pairs[tag],common.get_xml_data(contact_bullet,tag,False)) + + #soft contact + soft_contact=self.surface_element.find(".//surface/soft_contact") + #since properties have the same name as the pairs no need for pairs + soft_contact_tags=["bone_attachment","stiffness","damping","flesh_mass_fraction"] + for tag in soft_contact_tags: + setattr(self.properties,tag,common.get_xml_data(soft_contact,tag,False)) + + def reset(self): + pass + + def update_elem(self,elem:ET.Element): + self.surface_element=elem + + #return element + @property + def element(self): + t_surface_elem=copy.deepcopy(self.surface_element) + #modify bounce + if not self.ui.collision_bounce_groupbox.isChecked(): + t_surface_elem.remove(t_surface_elem.find("bounce")) + + #friction + friction=t_surface_elem.find(".//friction") + if self.ui.surface_friction_groupBox.isChecked(): + #tor countrysion + torsion=friction.find("torsional") + if self.ui.friction_torsional_groupBox.isChecked(): + if not self.ui.torsional_ode_groupbox.isChecked(): + torsion.remove(torsion.find("ode")) + else: + friction.remove(friction.find(torsion)) + #end torsion + + #ode + friction_ode=friction.find("ode") + if self.ui.friction_ode_groupbox.isChecked(): + + elems_attrb_pair={"mu":"surface_friction_mu_cb","mu2":"surface_ode_mu2_cb","slip1":"surface_ode_slip1_cb","slip2":"surface_ode_slip2_cb" + ,"fdir1":"ode_frdir1_groupbox"} + for tag in elems_attrb_pair.keys(): + #remove element if its not enabled + if not getattr(self.properties,elems_attrb_pair[tag]): + friction_ode.remove(friction_ode.find(tag)) + else: + friction.remove(friction.find(friction_ode)) + #end ode + + #bullet + friction_bullet=friction.find("bullet") + if self.ui.surface_friction_bullet_groupbox.ischecked(): + bullet_pairs={"friction":"surface_bullet_friction_cb","friction2":"surface_bullet_friction2_cb","rolling_friction":"surface_bullet_rolling_friction_cb" + ,"fdir1":"bullet_frdir1_groupbox"} + for tag in bullet_pairs.keys(): + if not getattr(self.properties,bullet_pairs[tag]): + friction_bullet.remove(friction_bullet.find(tag)) + else: + friction.remove(friction_bullet) + #end bullet + else: + #remove friction if its not enabled + t_surface_elem.remove(t_surface_elem.find(friction)) + + #end friction + + #contact + contact=t_surface_elem.find("contact") + if self.ui.surface_contact_groupbox.isChecked(): + contact_pairs={"collide_without_contact_bitmask":"contact_collide_without_contact_bitmask_cb","collide_bitmask":"contact_collide_bitmask_cb", + "category_bitmask":"contact_category_bitmask_cb","poissons_ratio":"contact_poissons_ratio_cb","elastic_modulus":"contact_elastic_modulus_cb"} + for tag in contact_pairs.keys(): + if not getattr(self.properties,contact_pairs[tag]): + contact.remove(contact.find(tag)) + #ode + contact_ode=contact.find("ode") + if self.ui.contact_ode_groupbox.isChecked(): + ode_pairs={"soft_cfm":"contact_ode_soft_cfm_cb","soft_erp":"contact_ode_soft_erp_cb","kp":"contact_ode_kp_cb","kd":"contact_ode_kd_cb", + "max_vel":"contact_ode_max_vel_cb","min_depth":"contact_ode_min_depth_cb"} + for tag in ode_pairs.keys(): + if not getattr(self.properties,ode_pairs[tag]): + contact_ode.remove(contact_ode.find(tag)) + else: + contact.remove(contact.find(contact_ode)) + #end ode + + #bullet + contact_bullet=contact.find("bullet") + if self.ui.contact_bullet_groupbox.isChecked(): + bullet_pairs={"soft_cfm":"contact_bullet_soft_cfm_cb","soft_erp":"contact_bullet_soft_erp_cb","kp":"contact_bullet_kp_cb","kd":"contact_bullet_kd_cb"} + for tag in bullet_pairs.keys(): + if not getattr(self.properties,bullet_pairs[tag]): + contact_bullet.remove(tag) + else: + contact.remove(contact.find(contact_bullet)) + #end bullet + else: + t_surface_elem.remove(t_surface_elem.find(contact)) + #end contact + + #soft contact + if not self.ui.soft_contact_dart_groupbox.isChecked(): + t_surface_elem.remove(t_surface_elem.find("soft_contact")) + + return t_surface_elem \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/visual.py b/robot_descriptor/sdf_elements/visual.py new file mode 100644 index 0000000..b79c055 --- /dev/null +++ b/robot_descriptor/sdf_elements/visual.py @@ -0,0 +1,115 @@ +from .. import common +import copy +import FreeCAD,FreeCADGui +from PySide2 import QtCore +from ..RD_utils import initialize_element_tree +import xml.etree.ElementTree as ET +import os + +from . import material + +class visual_properties: + def __init__(self,ui): + self.ui=ui +#shadows + @property + def cast_shadows(self): + return str('true') if self.ui.visual_cast_shadows_checkBox.isCheked() else str('false') + @cast_shadows.setter + def cast_shadows(self,state): + self.ui.visual_laser_retro_sp.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.visual_cast_shadows_checkBox.setCheckState(QtCore.Qt.Unchecked) + +#transparency + @property + def transparency(self): + return self.ui.visual_transparency_sp.value() + @transparency.setter + def transparency(self,val): + self.ui.visual_transparency_sp.setValue(val) +#laser retro + @property + def laser_retro(self): + return self.ui.visual_laser_retro_sp.value() + @laser_retro.setter + def laser_retro(self,value): + self.ui.visual_laser_retro_sp.setValu(value) + +#visibility flags + @property + def visibility_flags(self): + return self.ui.visual_visibility_flags_sp.value() + @visibility_flags.setter + def visibility_flags(self,value): + self.ui.visual_visibility_flags_sp.setValue() + +#check boxes + @property + def visual_laser_retro_cb(self): + return self.ui.visual_laser_retro_cb.isChecked() + + @property + def visual_transparency_cb(self): + return self.ui.visual_transparency_cb.isChecked() + + @property + def visual_visibility_flags_cb(self): + return self.ui.visual_visibility_flags_cb.isChecked() + + +#============= +#==================== +class visual: + def __init__(self,parent_ui): + self.ui=parent_ui + self.file_name="visual.sdf" + self._visual_elem=initialize_element_tree.convdict_2_tree(self.file_name).get_element + self.properties=visual_properties(self.ui) + #maertial + self._material_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"material_ui")) + self._material_elem=material.material(self._material_ui) + #add widget to parent widget + self.ui.material_scroll.setWidget(self._material_ui.widget) + + def configUI(self): + self.ui.visual_laser_retro_sp.valueChanged.connect(self.on_laser_retro) + self.ui.visual_transparency_sp.valueChanged.connect(self.on_transparency) + self.ui.visual_visibility_flags_sp.valueChanged.connect(self.on_visibility_flags) + self.ui.visual_cast_shadows_checkBox.stateChanged.connect(self.on_cast_shadows) + + def on_laser_retro(self): + common.set_xml_data(self._visual_elem,"laser_retro",False,self.properties.laser_retro) + + def on_transparency(self): + common.set_xml_data(self._visual_elem,"transparency",False,self.properties.transparency) + + def on_visibility_flags(self): + common.set_xml_data(self._visual_elem,"visibility_flags",False,self.properties.visibility_flags) + + def on_cast_shadows(self): + common.set_xml_data(self._visual_elem,"cast_shadows",False,self.properties.cast_shadows) + + + def updateUI(self): + self.properties.laser_retro=common.get_xml_data(self._visual_elem,"laser_retro",False) + self.properties.transparency=common.get_xml_data(self._visual_elem,"transparency",False) + self.properties.visibility_flags=common.get_xml_data(self._visual_elem,"visibility_flags",False) + self.properties.cast_shadows=common.get_xml_data(self._visual_elem,"cast_shadows",False) + + def update_elem(self,new_elem:ET.Element): + mat=new_elem.find("material") + if mat is not None: + self._material_elem.update_elem(mat) + new_elem.remove(mat) + self._visual_elem=new_elem + + @property + def element(self): + t_visual_elem=copy.deepcopy(self._visual_elem) + visual_pairs={"laser_retro":"visual_laser_retro_","transparency":"visual_transparency_cb","visibility_flags":"visual_visibility_flags_cb"} + for tag in visual_pairs.keys(): + if not getattr(self.properties,visual_pairs[tag]): + t_visual_elem.remove(t_visual_elem.find(tag)) + + return t_visual_elem.append(self._material_elem.element) + + \ No newline at end of file From d3852027045984e12891bea7aaa73274ad3225a7 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Thu, 18 Jan 2024 21:49:55 +0300 Subject: [PATCH 5/9] fixed ui update issues --- robot_descriptor/RD_utils/parse_asm4_model.py | 2 +- robot_descriptor/forms/model_editor.ui | 11 +- robot_descriptor/forms/surface.ui | 363 +++++++++++++++++- robot_descriptor/model_editor.py | 37 +- robot_descriptor/sdf_elements/collision.py | 9 +- robot_descriptor/sdf_elements/link.py | 74 ++-- robot_descriptor/sdf_elements/material.py | 22 +- robot_descriptor/sdf_elements/road.py | 249 +++++++----- robot_descriptor/sdf_elements/surface.py | 59 +-- robot_descriptor/sdf_elements/visual.py | 16 +- 10 files changed, 639 insertions(+), 203 deletions(-) diff --git a/robot_descriptor/RD_utils/parse_asm4_model.py b/robot_descriptor/RD_utils/parse_asm4_model.py index 04699d6..6723934 100644 --- a/robot_descriptor/RD_utils/parse_asm4_model.py +++ b/robot_descriptor/RD_utils/parse_asm4_model.py @@ -14,7 +14,7 @@ def read_assembly(): #get all objects of type part feature objs=FreeCAD.ActiveDocument.findObjects("Part::Feature") - #get objects in the parts group + #get objects in the parts group parts=FreeCAD.ActiveDocument.Parts.Group #get fasteners since fasteners might not be accesed through links #remove objects in parts , coordinate systems diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui index 70e5e77..01b504d 100644 --- a/robot_descriptor/forms/model_editor.ui +++ b/robot_descriptor/forms/model_editor.ui @@ -102,7 +102,7 @@ - 1 + 2 @@ -1864,6 +1864,9 @@ Links connected by a joint will never collide + + false + visibility_flags @@ -1874,6 +1877,12 @@ Links connected by a joint will never collide false + + 900000000 + + + QAbstractSpinBox::DefaultStepType + diff --git a/robot_descriptor/forms/surface.ui b/robot_descriptor/forms/surface.ui index 530cd4b..d2af11e 100644 --- a/robot_descriptor/forms/surface.ui +++ b/robot_descriptor/forms/surface.ui @@ -126,7 +126,7 @@ - 2 + 1 false @@ -301,7 +301,7 @@ - 0 + 95 24 @@ -401,7 +401,7 @@ - + mu @@ -1086,7 +1086,7 @@ Parsed as 16-bit unsigned integer false - dynamically "damping"-equivalent coefficient for contact joints + maximum contact correction velocity truncation term. @@ -1347,5 +1347,358 @@ Parsed as 16-bit unsigned integer - + + + surface_ode_mu_cb + toggled(bool) + surface_ode_mu_sp + setEnabled(bool) + + + 121 + 425 + + + 240 + 425 + + + + + surface_ode_mu2_cb + toggled(bool) + surface_ode_mu2_sp + setEnabled(bool) + + + 121 + 455 + + + 240 + 455 + + + + + surface_ode_slip1_cb + toggled(bool) + surface_ode_slip1_sp + setEnabled(bool) + + + 359 + 425 + + + 478 + 425 + + + + + surface_ode_slip2_cb + toggled(bool) + surface_ode_slip2_sp + setEnabled(bool) + + + 359 + 455 + + + 478 + 455 + + + + + surface_bullet_friction_cb + toggled(bool) + surface_bullet_friction_sp + setEnabled(bool) + + + 98 + 636 + + + 169 + 636 + + + + + surface_bullet_friction2_cb + toggled(bool) + surface_bullet_friction2_sp + setEnabled(bool) + + + 244 + 636 + + + 318 + 636 + + + + + surface_bullet_rolling_friction_cb + toggled(bool) + surface_bullet_rolling_friction_sp + setEnabled(bool) + + + 411 + 636 + + + 503 + 636 + + + + + contact_collide_without_contact_bitmask_cb + toggled(bool) + contact_collide_without_contact_bitmask_sp + setEnabled(bool) + + + 162 + 253 + + + 434 + 253 + + + + + contact_poissons_ratio_cb + toggled(bool) + contact_poissons_ratio_sp + setEnabled(bool) + + + 112 + 343 + + + 434 + 343 + + + + + contact_collide_bitmask_cb + toggled(bool) + contact_collide_bitmask_sp + setEnabled(bool) + + + 112 + 283 + + + 434 + 283 + + + + + contact_category_bitmask_cb + toggled(bool) + contact_category_bitmask_sp + setEnabled(bool) + + + 127 + 313 + + + 434 + 313 + + + + + contact_elastic_modulus_cb + toggled(bool) + contact_elastic_modulus_sp + setEnabled(bool) + + + 112 + 373 + + + 434 + 373 + + + + + contact_ode_soft_cfm_cb + toggled(bool) + contact_ode_soft_cfm_sp + setEnabled(bool) + + + 115 + 446 + + + 245 + 446 + + + + + contact_ode_soft_erp_cb + toggled(bool) + contact_ode_soft_erp_sp + setEnabled(bool) + + + 115 + 489 + + + 245 + 489 + + + + + contact_ode_kp_cb + toggled(bool) + contact_ode_kp_sp + setEnabled(bool) + + + 115 + 532 + + + 245 + 532 + + + + + contact_ode_kd_cb + toggled(bool) + contact_ode_kd_sp + setEnabled(bool) + + + 375 + 446 + + + 483 + 446 + + + + + contact_ode_max_vel_cb + toggled(bool) + contact_ode_max_vel_sp + setEnabled(bool) + + + 375 + 489 + + + 483 + 489 + + + + + contact_ode_min_depth_cb + toggled(bool) + contact_ode_min_depth_sp + setEnabled(bool) + + + 375 + 532 + + + 483 + 532 + + + + + contact_bullet_soft_cfm_cb + toggled(bool) + contact_bullet_soft_cfm_sp + setEnabled(bool) + + + 102 + 623 + + + 219 + 623 + + + + + contact_bullet_kp_cb + toggled(bool) + contact_bullet_kp_sp + setEnabled(bool) + + + 102 + 691 + + + 219 + 691 + + + + + contact_bullet_soft_erp_cb + toggled(bool) + contact_bullet_soft_erp_sp + setEnabled(bool) + + + 102 + 657 + + + 219 + 657 + + + + + contact_bullet_kd_cb + toggled(bool) + contact_bullet_kd_sp + setEnabled(bool) + + + 350 + 623 + + + 474 + 623 + + + + diff --git a/robot_descriptor/model_editor.py b/robot_descriptor/model_editor.py index d93b670..e583c86 100644 --- a/robot_descriptor/model_editor.py +++ b/robot_descriptor/model_editor.py @@ -1,22 +1,28 @@ +from typing import Any import FreeCAD import FreeCADGui import robot_descriptor.common as common import os + from .RD_utils import parse_asm4_model -from PySide.QtGui import QStandardItemModel,QStandardItem,QHeaderView +from PySide.QtGui import QStandardItemModel,QStandardItem +from PySide.QtCore import Qt #start standard item class standard_item(QStandardItem): - def __init__(self,text,elements): + def __init__(self,text,type='link'): super().__init__() # data to describe the model - self.link_elem=elements[0] - self.collision_elem=elements[1] - self.material_elem=elements[2] + self.text=text + self.type=type #set the text to be displayed self.setText(text) self.setEditable(False) + + def data(self, role: int = ...) -> Any: + if role==Qt.DisplayRole: + return self.text #end standard Item #============================================== @@ -30,17 +36,32 @@ def __init__(self,elem_struct): if self.links_hierarchy is None: return self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) + + #subelements + from .sdf_elements import link + #link + self.link=link.link(self.ModelEditorUi) + #visual + from .sdf_elements import visual + self.visual=visual.visual(self.ModelEditorUi) + #collision + from .sdf_elements import collision + self.collision=collision.collison(self.ModelEditorUi) + + self.link_model=QStandardItemModel() self.link_model.setColumnCount(1) self.root_node=self.link_model.invisibleRootItem() self.tree_setup(self.links_hierarchy["children"],self.root_node) + + self.current_elems=[] + self.elems={} + # start header related self.ModelEditorUi.link_tree.setHeaderHidden(False) self.link_model.setHorizontalHeaderLabels(["Model Tree"]) #set the tree to resize automatically based on the display requirements - header = self.ModelEditorUi.link_tree.header() - header.setSectionResizeMode(QHeaderView.ResizeToContents) #end header related self.ModelEditorUi.link_tree.setModel(self.link_model) @@ -72,7 +93,7 @@ def GetResources(self): "ToolTip" : "Edit link and joint properties"} def Activated(self): - if hasattr(FreeCAD.ActiveDocument,"Assembly"): + if hasattr(FreeCAD.ActiveDocument,"Assembly") or hasattr(FreeCAD.ActiveDocument,"Model"): doc=FreeCAD.ActiveDocument self._root_dict=doc.Robot_Description.Proxy.element_dict self.edits=ModelEditor(self._root_dict) diff --git a/robot_descriptor/sdf_elements/collision.py b/robot_descriptor/sdf_elements/collision.py index 72f7b82..cafc777 100644 --- a/robot_descriptor/sdf_elements/collision.py +++ b/robot_descriptor/sdf_elements/collision.py @@ -16,13 +16,13 @@ def laser_retro(self): return self.ui.collision_laser_retro_sp.value() @laser_retro.setter def laser_retro(self,value): - self.ui.collision_retro_sp.setValue(value) + self.ui.collision_laser_retro_sp.setValue(value) #max contacts @property def max_contacts(self): return self.ui.collision_max_contacts_sp.value() - @max_contacts + @max_contacts.setter def max_contacts(self,value): self.ui.collision_max_contacts_sp.setValue(value) @@ -53,13 +53,14 @@ def __init__(self,parent_ui): self.ui.collision_scroll.setWidget(self.surface_ui.widget) self.configUI() + self.updateUI() def configUI(self): self.ui.collision_max_contacts_sp.valueChanged.connect( - lambda collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"max_contacts",False,self.properties.max_contacts) + lambda value,collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"max_contacts",False,self.properties.max_contacts) ) self.ui.collision_laser_retro_sp.valueChanged.connect( - lambda collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"laser_retro",False,self.properties.laser_retro) + lambda value,collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"laser_retro",False,self.properties.laser_retro) ) def updateUI(self): diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py index 1551f11..d4b513d 100644 --- a/robot_descriptor/sdf_elements/link.py +++ b/robot_descriptor/sdf_elements/link.py @@ -21,7 +21,7 @@ def gravity(self): @gravity.setter def gravity(self,state): if state=='true': - self.ui.link_gravity_checkbox.setCheckState(QtCore.Qt.Ckecked) + self.ui.link_gravity_checkbox.setCheckState(QtCore.Qt.Checked) else: self.ui.link_gravity_checkbox.setCheckState(QtCore.Qt.Unchecked) @@ -245,7 +245,7 @@ def fam_rr(self,val): #link #==================== class link: - def __init__(self,ui,elem_struct): + def __init__(self,ui,elem_struct=None): self.ui=ui self.file_name='link.sdf' self.tag='link' @@ -258,47 +258,48 @@ def __init__(self,ui,elem_struct): # self.link_element.append(self._inertial_element) self._root_dict=elem_struct self.configUI() + self.UpdateUi() def configUI(self): self.ui.link_gravity_checkbox.stateChanged.connect(self.onGravity) - self.ui.link_enable_wind_checkbox.stateCahanged.connect(self.onEnableWind) - self.ui.ink_self_collide_checkbox.stateChanged.connect(self.onSelfCollide) - self.ui.link_kinematic_checkbox.stateChanged.conned(self.onKinematic) - self.ui.velocity_decay_linear_sp.clicked.connect(self.onLinear) - self.ui.link_angular_vel_decay_sp.clicked.connect(self.onAngular) + self.ui.link_enable_wind_checkbox.stateChanged.connect(self.onEnableWind) + self.ui.link_self_collide_checkbox.stateChanged.connect(self.onSelfCollide) + self.ui.link_kinematic_checkbox.stateChanged.connect(self.onKinematic) + self.ui.velocity_decay_linear_sp.valueChanged.connect(self.onLinear) + self.ui.link_angular_vel_decay_sp.valueChanged.connect(self.onAngular) #inertial # fam=self.link_element.find(".//inertia/fluid_added_mass") # fam every time the lmbda is called fam gets updated - self.ui.fam_xx_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xx',False,self.properties.fam_xx) ) - self.ui.fam_xy_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xy',False,self.properties.fam_xy) ) - self.ui.fam_xz_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xz',False,self.properties.fam_xz) ) + self.ui.fam_xx_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xx',False,self.properties.fam_xx) ) + self.ui.fam_xy_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xy',False,self.properties.fam_xy) ) + self.ui.fam_xz_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xz',False,self.properties.fam_xz) ) - self.ui.fam_xp_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xp',False,self.properties.fam_xp) ) - self.ui.fam_xq_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xq',False,self.properties.fam_xq) ) - self.ui.fam_xr_sp.valuechanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xr',False,self.properties.fam_xr) ) + self.ui.fam_xp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xp',False,self.properties.fam_xp) ) + self.ui.fam_xq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xq',False,self.properties.fam_xq) ) + self.ui.fam_xr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xr',False,self.properties.fam_xr) ) #y - self.ui.fam_yy_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yy',False,self.properties.fam_yy)) - self.ui.fam_yz_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yz',False,self.properties.fam_yz)) + self.ui.fam_yy_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yy',False,self.properties.fam_yy)) + self.ui.fam_yz_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yz',False,self.properties.fam_yz)) - self.ui.fam_yp_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yp',False,self.properties.fam_yp)) - self.ui.fam_yq_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yq',False,self.properties.fam_yq)) - self.ui.fam_yr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yr',False,self.properties.fam_yr)) + self.ui.fam_yp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yp',False,self.properties.fam_yp)) + self.ui.fam_yq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yq',False,self.properties.fam_yq)) + self.ui.fam_yr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yr',False,self.properties.fam_yr)) #z - self.ui.fam_zz_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zz',False,self.properties.fam_zz)) - self.ui.fam_zp_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zp',False,self.properties.fam_zp)) - self.ui.fam_zq_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zq',False,self.properties.fam_zq)) - self.ui.fam_zr_sp.valueChanged.conneect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zr',False,self.properties.fam_zr)) + self.ui.fam_zz_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zz',False,self.properties.fam_zz)) + self.ui.fam_zp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zp',False,self.properties.fam_zp)) + self.ui.fam_zq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zq',False,self.properties.fam_zq)) + self.ui.fam_zr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zr',False,self.properties.fam_zr)) #p - self.ui.fam_pp_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pp',False,self.properties.fam_pp)) - self.ui.fam_pq_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pq',False,self.properties.fam_pq)) - self.ui.fam_pr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pr',False,self.properties.fam_pr)) + self.ui.fam_pp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pp',False,self.properties.fam_pp)) + self.ui.fam_pq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pq',False,self.properties.fam_pq)) + self.ui.fam_pr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pr',False,self.properties.fam_pr)) - self.ui.fam_qq_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qq',False,self.properties.fam_qq)) - self.ui.fam_qr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qr',False,self.properties.fam_qr)) - self.ui.fam_rr_sp.valueChanged.connect(lambda fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'rr',False,self.properties.fam_rr)) + self.ui.fam_qq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qq',False,self.properties.fam_qq)) + self.ui.fam_qr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qr',False,self.properties.fam_qr)) + self.ui.fam_rr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'rr',False,self.properties.fam_rr)) @@ -319,18 +320,19 @@ def onKinematic(self): def onLinear(self): common.set_xml_data(self.link_element,'linear',False,self.properties.linear) - def onAgular(self): + def onAngular(self): common.set_xml_data(self.link_element,'angular',False,self.properties.angular) #element to be updaed sent to the list - def UpdateUi(self,element): + def UpdateUi(self): + element=self.link_element self.properties.gravity=common.get_xml_data(element,'gravity',False) - self.properties.enable_wind=common.get_xml_data(self.element,'enable_wind',False) + self.properties.enable_wind=common.get_xml_data(element,'enable_wind',False) self.properties.self_collide=common.get_xml_data(element,'self_collide',False) - self.properties.kinematic= common.get_xml_data(element,'kinematic') - self.properties.linear=common.set_xml_data(element,'linear') - self.properties.angular=common.set_xml_data(element,'angular') - fam=self._inertial_element.find(".//inertia/fluid_added_mass") + self.properties.kinematic= common.get_xml_data(element,'kinematic',False) + self.properties.linear=common.get_xml_data(element,'linear',False) + self.properties.angular=common.get_xml_data(element,'angular',False) + fam=self._inertial_element.find(".//fluid_added_mass") elem_ui_pairs={"xx":"fam_xx_sp","xy":"fam_xy_sp","xz":"fam_xz_sp","xp":"fam_xp_sp","xq":"fam_xq_sp","xr":"fam_xr_sp", "yy":"fam_yy_sp","yz":"fam_yz_sp","yp":"fam_yp_sp","yq":"fam_yq_sp","yr":"fam_yr_sp","zz":"fam_zz_sp", "zp":"fam_zp_sp","zq":"fam_zq_sp","zr":"fam_zr_sp","pp":"fam_pp_sp","pr":"fam_pr_sp","pq":"fam_pq_sp", @@ -354,7 +356,7 @@ def element(self): t_link_elem.remove(t_link_elem.find("velocity_decay")) t_inertial_elem=copy.deepcopy(self._inertial_element) - if self.ui.self.link_elementfluid_added_mass_groupbox.isChecked(): + if self.ui.fluid_added_mass_groupbox.isChecked(): t_inertial_elem.remove(t_inertial_elem.find("fluid_added_mass")) return t_link_elem.append(t_inertial_elem) \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/material.py b/robot_descriptor/sdf_elements/material.py index 46cc52a..5cd8f2b 100644 --- a/robot_descriptor/sdf_elements/material.py +++ b/robot_descriptor/sdf_elements/material.py @@ -416,18 +416,18 @@ def specular_enabled(self): class material(common.color_pickr): #since material has multiple parents let the parent class # the parent and parent path data - def __init__(self,ui,ParentPath) -> None: + def __init__(self,ui) -> None: super().__init__() self.ui=ui #use the road tag since material will be implemented as part of the road element self.tag='road' - self.parent_path=ParentPath + self.parent_path='' self.file_name='material.sdf' self._material_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element self.properties=material_properties(self.ui) self.configUI() - self.reset(default=False) + # self.reset(default=False) def configUI(self): self.ui.material_script_uri_input.textEdited.connect(self.on_uri) @@ -711,21 +711,7 @@ def updateUi(self): self.set_widget_color('emissive',self.ui.material_emissive_color_pkr) def reset(self,default=True): - if default: - self._material_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element - else: - doc=FreeCAD.ActiveDocument - _root_dict=doc.Robot_Description.Proxy.element_dict - #since material does not exist independently find the parent - el_dict=common.parse_dict(_root_dict,self.parent_path) - if el_dict is not None: - #find the material element in parent element - elem=ET.fromstring(el_dict['elem_str']).find('.//material') - #make check since material might not always be included in the final element tree - # since its optional - if elem is not None: - self.merge_elements(self._material_element,elem) - self.updateUi() + pass #merger diff --git a/robot_descriptor/sdf_elements/road.py b/robot_descriptor/sdf_elements/road.py index 98ad00a..19f1259 100644 --- a/robot_descriptor/sdf_elements/road.py +++ b/robot_descriptor/sdf_elements/road.py @@ -1,68 +1,109 @@ from .. import common from ..RD_utils import initialize_element_tree -import copy -from PySide import QtGui,QtCore -import re +import copy +from PySide import QtGui, QtCore +import re import math import csv + # import Spreadsheet import os -import xml.etree.ElementTree as ET -import FreeCAD ,FreeCADGui -#======================================== -#road properties -#======================================== +import xml.etree.ElementTree as ET +import FreeCAD, FreeCADGui + + +# ======================================== +# road properties +# ======================================== class road_properties: - def __init__(self,ui) -> None: - self.ui=ui -#name property + def __init__(self, ui) -> None: + self.ui = ui + + # name property @property def name(self): return self.ui.road_name.text() + @name.setter - def name(self,text): + def name(self, text): self.ui.road_name.setText(text) -#width + # width @property def width(self): return self.ui.road_width_sp.value() + @width.setter - def width(self,value): + def width(self, value): self.ui.road_width_sp.setValue(value) -#================================================= -#================================================= -#road -#================================================== -#================================================= -class road(): - def __init__(self,ui): - self.ui=ui - self.parent_path=['sdf','world'] - self.tag='road' - self.file_name='road.sdf' - self._road_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element - self._road_properties=road_properties(self.ui) - #material element - from . import material - self.material_widget=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"material.ui")) - self._material=material.material(self.material_widget,self.parent_path+[self.tag]) + +# ================================================= +# ================================================= +# road +# ================================================== +# ================================================= +from . import material + + +class road_material(material.material): + def __init__(self, ui): + self.ui = ui - #disable unused material ui elements + super().__init__(self.ui) + #redefine parent path + self.parent_path = ["sdf", "world", "road"] + self.reset(default=False) + + def reset(self, default=True): + if default: + self._material_element = initialize_element_tree.convdict_2_tree( + self.file_name + ).get_element + else: + doc = FreeCAD.ActiveDocument + _root_dict = doc.Robot_Description.Proxy.element_dict + # since material does not exist independently find the parent + el_dict = common.parse_dict(_root_dict, self.parent_path) + if el_dict is not None: + # find the material element in parent element + elem = ET.fromstring(el_dict["elem_str"]).find(".//material") + # make check since material might not always be included in the final element tree + # since its optional + if elem is not None: + self.merge_elements(self._material_element, elem) + self.updateUi() + + +class road: + def __init__(self, ui): + self.ui = ui + self.parent_path = ["sdf", "world"] + self.tag = "road" + self.file_name = "road.sdf" + self._road_element = initialize_element_tree.convdict_2_tree( + self.file_name + ).get_element + self._road_properties = road_properties(self.ui) + # material element + self.material_widget = FreeCADGui.PySideUic.loadUi( + os.path.join(common.UI_PATH, "material.ui") + ) + self._material = road_material(self.material_widget) + + # disable unused material ui elements self.material_widget.material_pbr_groupbox.setEnabled(False) self.material_widget.material_double_sided_checkBox.setEnabled(False) - self.point_element=copy.deepcopy(self._road_element.find('.//point')) - #disable the scroll widget - + self.point_element = copy.deepcopy(self._road_element.find(".//point")) + # disable the scroll widget + self.ui.road_scroll.setWidget(self.material_widget.widget) self.ui.road_scroll.setEnabled(False) - - - #configure the Ui and callbacks + + # configure the Ui and callbacks self.configUI() self.reset(default=False) - + def configUI(self): self.ui.road_name.textEdited.connect(self.on_road_name) self.ui.road_width_sp.valueChanged.connect(self.on_road_width) @@ -70,85 +111,103 @@ def configUI(self): self.ui.enable_road_checkbox.clicked.connect(self.on_road_checkbox) def on_road_checkbox(self): - state=self.ui.enable_road_checkbox.isChecked() + state = self.ui.enable_road_checkbox.isChecked() if state: self.ui.road_scroll.setEnabled(True) else: self.ui.road_scroll.setEnabled(False) - + def on_road_reset(self): self.reset(default=True) - print('road resets applied\n') - + print("road resets applied\n") + def on_road_name(self): - common.set_xml_data(self._road_element,'road',True,{'name':self._road_properties.name}) - + common.set_xml_data( + self._road_element, "road", True, {"name": self._road_properties.name} + ) + def on_road_width(self): - common.set_xml_data(self._road_element,'width',False,self._road_properties.width) - + common.set_xml_data( + self._road_element, "width", False, self._road_properties.width + ) + def get_sheet_data(self): - #get spread sheet with points data - sheet=FreeCAD.ActiveDocument.points - data_cells=sheet.getNonEmptyCells() - #ensure all point data is available since a vector 3 is required - #all filled cells need to be a multiple of 3 - if len(data_cells)%3 !=0: - FreeCAD.Console.PrintUserWarning("some data is missing \n points not updated\n") + # get spread sheet with points data + sheet = FreeCAD.ActiveDocument.points + data_cells = sheet.getNonEmptyCells() + # ensure all point data is available since a vector 3 is required + # all filled cells need to be a multiple of 3 + if len(data_cells) % 3 != 0: + FreeCAD.Console.PrintUserWarning( + "some data is missing \n points not updated\n" + ) else: - #remove all points previously available in the tree - for point in self._road_element.iter('point'): + # remove all points previously available in the tree + for point in self._road_element.iter("point"): self._road_element.remove(point) - #use list comprehension to extract spreadsheet items 3 at a time - #produces - #start from 3 since the first 3 are the labels - for row in [ [sheet.getContents(data_cells[i]), sheet.getContents(data_cells[i+1]), sheet.getContents(data_cells[i+2])] - for i in range(3,len(data_cells),3)]: - point=copy.deepcopy(self.point_element) - point.text=' '.join(map(str,row)) + # use list comprehension to extract spreadsheet items 3 at a time + # produces + # start from 3 since the first 3 are the labels + for row in [ + [ + sheet.getContents(data_cells[i]), + sheet.getContents(data_cells[i + 1]), + sheet.getContents(data_cells[i + 2]), + ] + for i in range(3, len(data_cells), 3) + ]: + point = copy.deepcopy(self.point_element) + point.text = " ".join(map(str, row)) self._road_element.append(point) - - + def updateUI(self): - self._road_properties.name=common.get_xml_data(self._road_element,['road','name'],True) - self._road_properties.width=common.get_xml_data(self._road_element,'width',False) - - - def reset(self,default=True): + self._road_properties.name = common.get_xml_data( + self._road_element, ["road", "name"], True + ) + self._road_properties.width = common.get_xml_data( + self._road_element, "width", False + ) + + def reset(self, default=True): if default: - self._road_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element + self._road_element = initialize_element_tree.convdict_2_tree( + self.file_name + ).get_element self._material.reset(default=True) - self._road_properties.point=None + self._road_properties.point = None else: - doc=FreeCAD.ActiveDocument - _root_dict=doc.Robot_Description.Proxy.element_dict - el_dict=common.parse_dict(_root_dict,self.parent_path+[self.tag]) + doc = FreeCAD.ActiveDocument + _root_dict = doc.Robot_Description.Proxy.element_dict + el_dict = common.parse_dict(_root_dict, self.parent_path + [self.tag]) if el_dict is not None: - elem=ET.fromstring(el_dict['elem_str']) - self._road_element=elem - #remove material from the element - mat=self._road_element.find('.//material') - #material is an optional element hence might not be included - + elem = ET.fromstring(el_dict["elem_str"]) + self._road_element = elem + # remove material from the element + mat = self._road_element.find(".//material") + # material is an optional element hence might not be included + if mat is not None: self._road_element.remove(mat) self._material.reset(default=False) - - #remove unused material elements - self._material._material_element.remove(self._material._material_element.find('.//pbr')) - self._material._material_element.remove(self._material._material_element.find('.//double_sided')) - - self.updateUI() - + + # remove unused material elements + self._material._material_element.remove( + self._material._material_element.find(".//pbr") + ) + self._material._material_element.remove( + self._material._material_element.find(".//double_sided") + ) + + self.updateUI() + @property def element(self): - #update data in sheet before export + # update data in sheet before export self.get_sheet_data() - - _elem=copy.deepcopy(self._road_element) - #check if materialis enabled + + _elem = copy.deepcopy(self._road_element) + # check if materialis enabled if self.ui.include_material_info.isChecked(): - mat_el=self._material.element + mat_el = self._material.element _elem.append(mat_el) return _elem - - diff --git a/robot_descriptor/sdf_elements/surface.py b/robot_descriptor/sdf_elements/surface.py index 2cf8cf2..05dee29 100644 --- a/robot_descriptor/sdf_elements/surface.py +++ b/robot_descriptor/sdf_elements/surface.py @@ -53,10 +53,10 @@ def patch_radius(self,value): #surface_radius @property def surface_radius(self): - return self.torsional_surface_radius_sp.value() + return self.ui.torsional_surface_radius_sp.value() @surface_radius.setter def surface_radius(self,value): - self.ui.torsional_surface_radius_sp.setValue() + self.ui.torsional_surface_radius_sp.setValue(value) #slip @property @@ -314,8 +314,8 @@ def flesh_mass_fraction(self,value): #control checkboxes #friction @property - def surface_friction_mu_cb(self): - return self.ui.surface_friction_mu_cb.isChecked() + def surface_ode_mu_cb(self): + return self.ui.surface_ode_mu_cb.isChecked() @property def surface_ode_mu2_cb(self): @@ -419,50 +419,51 @@ def __init__(self,ui) -> None: self.tag="surface" self.surface_element=initialize_element_tree.convdict_2_tree(self.file_name).get_element self.configUI() + self.updateUI() def configUI(self): #bounce # bounce=self.surface_element.find('bounce') - self.ui.collision_restitution_coefficient_sp.valueChanged.connect(lambda bounce=self.surface_element.find('bounce'): + self.ui.collision_restitution_coefficient_sp.valueChanged.connect(lambda val,bounce=self.surface_element.find('bounce'): common.set_xml_data(bounce,"restitution_coefficient",False,self.properties.restitution_coefficient)) - self.ui.collision_bounce_threshold_sp.valueChanged.connect(lambda bounce=self.surface_element.find('bounce'): + self.ui.collision_bounce_threshold_sp.valueChanged.connect(lambda val,bounce=self.surface_element.find('bounce'): common.set_xml_data(bounce,"threshold",False,self.properties.threshold)) #torsional # torsional=self.surface_element.find(".//friction/torsional") - self.ui.torsional_coeff_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + self.ui.torsional_coeff_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): common.set_xml_data(torsional,"coefficient",False,self.properties.coefficient)) - self.ui.use_patch_radius_cb.stateChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + self.ui.use_patch_radius_cb.stateChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): common.set_xml_data(torsional,"use_patch_radius",False,self.properties.use_patch_radius)) - self.ui.torsional_patch_radius_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + self.ui.torsional_patch_radius_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): common.set_xml_data(torsional,"patch_radius",False,self.properties.patch_radius)) - self.ui.torsional_surface_radius_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + self.ui.torsional_surface_radius_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): common.set_xml_data(torsional,"surface_radius",False,self.properties.surface_radius)) - self.ui.torsional_ode_slip_sp.valueChanged.connect(lambda torsional=self.surface_element.find(".//friction/torsional"): + self.ui.torsional_ode_slip_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): common.set_xml_data(torsional,"slip",False,self.properties.torsional_slip)) #frictional_ode # frictional_ode=self.surface_element.find(".//friction/ode") - self.ui.surface_ode_mu_sp.valueChanged.connect(lambda frictional_ode=self.surface_element.find(".//friction/ode"): + self.ui.surface_ode_mu_sp.valueChanged.connect(lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): common.set_xml_data(frictional_ode,"mu",False,self.properties.friction_ode_mu)) self.ui.surface_ode_mu2_sp.valueChanged.connect( - lambda frictional_ode=self.surface_element.find(".//friction/ode"): + lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): common.set_xml_data(frictional_ode,"mu2",False,self.properties.friction_ode_mu2) ) - self.ui.surface_ode_slip1_sp.valuChanged.connect( - lambda frictional_ode=self.surface_element.find(".//friction/ode"): + self.ui.surface_ode_slip1_sp.valueChanged.connect( + lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): common.set_xml_data(frictional_ode,"slip1",False,self.properties.friction_ode_slip1) ) self.ui.surface_ode_slip2_sp.valueChanged.connect( - lambda frictional_ode=self.surface_element.find(".//friction/ode"): + lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): common.set_xml_data(frictional_ode,"slip2",False,self.properties.friction_ode_slip2) ) @@ -473,15 +474,15 @@ def configUI(self): #frictional_bullet # frictional_bullet=self.surface_element.find(".//fiction/bullet") self.ui.surface_bullet_friction_sp.valueChanged.connect( - lambda frictional_bullet=self.surface_element.find(".//fiction/bullet"): + lambda val,frictional_bullet=self.surface_element.find(".//friction/bullet"): common.set_xml_data(frictional_bullet,"friction",False,self.properties.friction_bullet_friction)) self.ui.surface_bullet_friction2_sp.valueChanged.connect( - lambda frictional_bullet=self.surface_element.find(".//fiction/bullet"): + lambda val,frictional_bullet=self.surface_element.find(".//friction/bullet"): common.set_xml_data(frictional_bullet,"friction2",False,self.properties.friction_bullet_friction2) ) self.ui.surface_bullet_rolling_friction_sp.valueChanged.connect( - lambda frictional_bullet=self.surface_element.find(".//fiction/bullet"): + lambda val,frictional_bullet=self.surface_element.find(".//friction/bullet"): common.set_xml_data(frictional_bullet,"rolling_friction",False,self.properties.friction_bullet_rolling_friction) ) @@ -505,7 +506,7 @@ def configUI(self): #ode self.ui.contact_ode_soft_cfm_sp.valueChanged.connect(self.on_contact_ode_soft_cfm) - self.ui.contact_ode_soft_erp_sp.valueChanged.coneect(self.on_contact_ode_soft_erp) + self.ui.contact_ode_soft_erp_sp.valueChanged.connect(self.on_contact_ode_soft_erp) self.ui.contact_ode_kp_sp.valueChanged.connect(self.on_contact_ode_kp) self.ui.contact_ode_kd_sp.valueChanged.connect(self.on_contact_ode_kd) self.ui.contact_ode_max_vel_sp.valueChanged.connect(self.on_contact_ode_max_vel) @@ -555,19 +556,19 @@ def on_contact_bullet_split_impulse(self): #soft contact def on_soft_contact_bone_attachment(self): - soft_contact=self.surface_element.find(".//surface/soft_contact") + soft_contact=self.surface_element.find(".//soft_contact") common.set_xml_data(soft_contact,"bone_attachment",False,self.properties.bone_attachment) def on_soft_contact_stiffness(self): - soft_contact=self.surface_element.find(".//surface/soft_contact") + soft_contact=self.surface_element.find(".//soft_contact") common.set_xml_data(soft_contact,"stiffness",False,self.properties.stiffness) def on_soft_body_damping(self): - soft_contact=self.surface_element.find(".//surface/soft_contact") + soft_contact=self.surface_element.find(".//soft_contact") common.set_xml_data(soft_contact,"damping",False,self.properties.damping) def on_soft_contact_flesh_mass_fraction(self): - soft_contact=self.surface_element.find(".//surface/soft_contact") + soft_contact=self.surface_element.find(".//soft_contact") common.set_xml_data(soft_contact,"flesh_mass_fraction",False,self.properties.flesh_mass_fraction) #ode @@ -604,7 +605,7 @@ def ode_fdir1(self): #bullet def bullet_fdir1(self): - frictional_bullet=self.surface_element.find(".//fiction/bullet") + frictional_bullet=self.surface_element.find(".//friction/bullet") common.set_xml_data(frictional_bullet,"fdir1",False,self.properties.friction_bullet_fdir1) #contact @@ -647,7 +648,7 @@ def updateUI(self): torsional_pairs={"coefficient":"coefficient","use_patch_radius":"use_patch_radius", "patch_radius":"patch_radius","surface_radius":"surface_radius","slip":"torsional_slip"} for tag in torsional_pairs.keys(): - setattr(self.properties,torsional_pairs[tag],common.set_xml_data(torsional,tag,False)) + setattr(self.properties,torsional_pairs[tag],common.get_xml_data(torsional,tag,False)) #friction #ode @@ -658,7 +659,7 @@ def updateUI(self): setattr(self.properties,friction_ode_pairs[tag],common.get_xml_data(frictional_ode,tag,False)) #bullet - frictional_bullet=self.surface_element.find(".//fiction/bullet") + frictional_bullet=self.surface_element.find(".//friction/bullet") friction_bullet_pairs={"friction":"friction_bullet_friction","friction2":"friction_bullet_friction2", "rolling_friction":"friction_bullet_rolling_friction","fdir1":"friction_bullet_fdir1"} for tag in friction_bullet_pairs.keys(): @@ -691,7 +692,7 @@ def updateUI(self): setattr(self.properties,contact_bullet_pairs[tag],common.get_xml_data(contact_bullet,tag,False)) #soft contact - soft_contact=self.surface_element.find(".//surface/soft_contact") + soft_contact=self.surface_element.find(".//soft_contact") #since properties have the same name as the pairs no need for pairs soft_contact_tags=["bone_attachment","stiffness","damping","flesh_mass_fraction"] for tag in soft_contact_tags: @@ -727,7 +728,7 @@ def element(self): friction_ode=friction.find("ode") if self.ui.friction_ode_groupbox.isChecked(): - elems_attrb_pair={"mu":"surface_friction_mu_cb","mu2":"surface_ode_mu2_cb","slip1":"surface_ode_slip1_cb","slip2":"surface_ode_slip2_cb" + elems_attrb_pair={"mu":"surface_ode_mu_cb","mu2":"surface_ode_mu2_cb","slip1":"surface_ode_slip1_cb","slip2":"surface_ode_slip2_cb" ,"fdir1":"ode_frdir1_groupbox"} for tag in elems_attrb_pair.keys(): #remove element if its not enabled diff --git a/robot_descriptor/sdf_elements/visual.py b/robot_descriptor/sdf_elements/visual.py index b79c055..e9aee3f 100644 --- a/robot_descriptor/sdf_elements/visual.py +++ b/robot_descriptor/sdf_elements/visual.py @@ -17,7 +17,7 @@ def cast_shadows(self): return str('true') if self.ui.visual_cast_shadows_checkBox.isCheked() else str('false') @cast_shadows.setter def cast_shadows(self,state): - self.ui.visual_laser_retro_sp.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.visual_cast_shadows_checkBox.setCheckState(QtCore.Qt.Unchecked) + self.ui.visual_cast_shadows_checkBox.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.visual_cast_shadows_checkBox.setCheckState(QtCore.Qt.Unchecked) #transparency @property @@ -32,7 +32,7 @@ def laser_retro(self): return self.ui.visual_laser_retro_sp.value() @laser_retro.setter def laser_retro(self,value): - self.ui.visual_laser_retro_sp.setValu(value) + self.ui.visual_laser_retro_sp.setValue(value) #visibility flags @property @@ -40,7 +40,8 @@ def visibility_flags(self): return self.ui.visual_visibility_flags_sp.value() @visibility_flags.setter def visibility_flags(self,value): - self.ui.visual_visibility_flags_sp.setValue() + print(value) + self.ui.visual_visibility_flags_sp.setValue(value) #check boxes @property @@ -65,10 +66,11 @@ def __init__(self,parent_ui): self._visual_elem=initialize_element_tree.convdict_2_tree(self.file_name).get_element self.properties=visual_properties(self.ui) #maertial - self._material_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"material_ui")) + self._material_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"material.ui")) self._material_elem=material.material(self._material_ui) #add widget to parent widget self.ui.material_scroll.setWidget(self._material_ui.widget) + self.updateUI() def configUI(self): self.ui.visual_laser_retro_sp.valueChanged.connect(self.on_laser_retro) @@ -92,7 +94,9 @@ def on_cast_shadows(self): def updateUI(self): self.properties.laser_retro=common.get_xml_data(self._visual_elem,"laser_retro",False) self.properties.transparency=common.get_xml_data(self._visual_elem,"transparency",False) - self.properties.visibility_flags=common.get_xml_data(self._visual_elem,"visibility_flags",False) + #this causes an overflow so dont update for now , ui is also disabled , + # t + # self.properties.visibility_flags=common.get_xml_data(self._visual_elem,"visibility_flags",False) self.properties.cast_shadows=common.get_xml_data(self._visual_elem,"cast_shadows",False) def update_elem(self,new_elem:ET.Element): @@ -105,7 +109,7 @@ def update_elem(self,new_elem:ET.Element): @property def element(self): t_visual_elem=copy.deepcopy(self._visual_elem) - visual_pairs={"laser_retro":"visual_laser_retro_","transparency":"visual_transparency_cb","visibility_flags":"visual_visibility_flags_cb"} + visual_pairs={"laser_retro":"visual_laser_retro_cb","transparency":"visual_transparency_cb","visibility_flags":"visual_visibility_flags_cb"} for tag in visual_pairs.keys(): if not getattr(self.properties,visual_pairs[tag]): t_visual_elem.remove(t_visual_elem.find(tag)) From 25a3fc12f677aba79f9474ac8abad0127323b220 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Sat, 20 Jan 2024 08:56:22 +0300 Subject: [PATCH 6/9] link info stored for each link --- robot_descriptor/RD_utils/parse_asm4_model.py | 29 +- robot_descriptor/forms/model_editor.ui | 2472 ++++++++--------- robot_descriptor/forms/surface.ui | 11 +- robot_descriptor/icons/link16.png | Bin 0 -> 559 bytes robot_descriptor/icons/ref16.png | Bin 0 -> 481 bytes robot_descriptor/model_editor.py | 109 +- robot_descriptor/sdf_elements/collision.py | 20 +- robot_descriptor/sdf_elements/link.py | 19 +- robot_descriptor/sdf_elements/material.py | 7 + robot_descriptor/sdf_elements/surface.py | 6 +- robot_descriptor/sdf_elements/visual.py | 18 +- 11 files changed, 1391 insertions(+), 1300 deletions(-) create mode 100644 robot_descriptor/icons/link16.png create mode 100644 robot_descriptor/icons/ref16.png diff --git a/robot_descriptor/RD_utils/parse_asm4_model.py b/robot_descriptor/RD_utils/parse_asm4_model.py index 6723934..288e491 100644 --- a/robot_descriptor/RD_utils/parse_asm4_model.py +++ b/robot_descriptor/RD_utils/parse_asm4_model.py @@ -35,9 +35,13 @@ def read_assembly(): #this will store a list of dictionaries def create_structure(data,dest): #check the parent objects + #since data is a list of dictionaries + #for every element int he list check if its parent is dest children=[child for child in data if child["parent"]==dest["name"]] + #return of no children are found if len (children)==0: return + #append the children to the current item for ch in children: dest["children"].append(ch) create_structure(data,ch) @@ -46,7 +50,11 @@ def create_structure(data,dest): link_data=[] #create the root parent structured_data={} + + #links that have been iterated and not references + non_refs=[] for child in links: + name=child.Label #attachedTo returns a string of the format 'Parent Assembly#LCS_Origin' hence #hence separating by the the '#' and taking the first element will be the parent @@ -54,19 +62,34 @@ def create_structure(data,dest): parent,attachement=child.AttachedTo.split('#') #returned type has '#' preceeding the coordinate remove it attached_by=child.AttachedBy.replace('#','') - link_data.append({"link":child,"name":name,"parent":parent,"attached_to":attachement,"attached_by":attached_by,'children':[]}) - # + if hasattr(child,"LinkedObject") : + #get links which refer to the same document + ref=[r for r in non_refs if r.LinkedObject.Document ==child.LinkedObject.Document] + if len(ref)==1: + #set type as reference i.e its a copy of a link that already exists in the assembly + link_data.append({"ref_label":ref[0].Label,"type":"ref","link":child,"name":name,"parent":parent,"attached_to":attachement,"attached_by":attached_by,'children':[]}) + elif len(ref)==0: + link_data.append({"ref_label":None,"type":"link","link":child,"name":name,"parent":parent,"attached_to":attachement,"attached_by":attached_by,'children':[]}) + non_refs.append(child) + else: + FreeCAD.Console.PrintDeveloperError("parse_asm4:error getting refs no than 1 were found, this is a bug \n") + return + else: + #add fasterners and other too + link_data.append({"ref_label":None,"type":"link","link":child,"name":name,"parent":parent,"attached_to":attachement,"attached_by":attached_by,'children':[]}) + #create a hierarchial data if hasattr(child,"LinkedObject"): if hasattr(child.LinkedObject.Document,"Assembly"): FreeCAD.Console.PrintError("Sub assemblies not supported yet \n") return None root_lcs=FreeCAD.ActiveDocument.findObjects("PartDesign::CoordinateSystem") - structured_data={"link":None,'name':"Parent Assembly","attachment":None,"coordinate_systems":root_lcs,"children":[]} + structured_data={"ref_label":None,"type":"link","link":None,'name':"Parent Assembly","attachment":None,"coordinate_systems":root_lcs,"children":[]} #this will just create a hierarchial data representation create_structure(link_data,structured_data) del link_data + del non_refs return structured_data diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui index 01b504d..af15860 100644 --- a/robot_descriptor/forms/model_editor.ui +++ b/robot_descriptor/forms/model_editor.ui @@ -6,7 +6,7 @@ 0 0 - 959 + 1028 775 @@ -102,7 +102,7 @@ - 2 + 0 @@ -127,13 +127,13 @@ 12 42 215 - 91 + 100 215 - 91 + 100 @@ -196,13 +196,13 @@ Links connected by a joint will never collide 12 140 217 - 98 + 110 217 - 98 + 110 @@ -285,15 +285,15 @@ Links connected by a joint will never collide 14 - 244 + 264 213 - 63 + 70 213 - 63 + 70 @@ -305,8 +305,8 @@ Links connected by a joint will never collide false - - + + auto @@ -320,10 +320,16 @@ Links connected by a joint will never collide 234 6 - 433 - 707 + 463 + 675 + + + 414 + 675 + + true @@ -331,8 +337,8 @@ Links connected by a joint will never collide 0 - 0 - 417 + -245 + 447 918 @@ -372,1026 +378,101 @@ Links connected by a joint will never collide false - - - - 12 - 30 - 370 - 190 - - - - - 370 - 190 - - - - - 372 - 190 - - - - x_axis - - - - - 18 - 28 - 344 - 66 - - - - - 340 - 66 - - - - - 344 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - linear_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to linear acceleration in the X axis, in kg - - - kg - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to linear acceleration in the Y axis, and vice-versa, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - Added mass in the X axis due to linear acceleration in the Z axis, and vice-versa, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - - 12 - 108 - 345 - 66 - - - - - 343 - 66 - - - - - 345 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - angular_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to angular acceleration about the X axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m - - - kgm - - - 1000.000000000000000 - - - - - - - - - - 12 - 226 - 370 - 190 - - - - - 370 - 190 - - - - - 372 - 190 - - - - y_axis - - - - - 8 - 30 - 343 - 66 - - - - - 343 - 66 - - - - - 344 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - linear_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to linear acceleration in the Y axis, in kg - - - kg - - - 1000.000000000000000 - - - - - - - - 10 - 15 - - - - - 10 - 18 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to linear acceleration in the Z axis, and vice-versa, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - - 12 - 108 - 345 - 66 - - - - - 343 - 66 - - - - - 345 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - angular_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to angular acceleration about the X axis, and vice-versa, in kg * m - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - - - 12 - 422 - 370 - 190 - - - - - 370 - 190 - - - - - 372 - 190 - - - - z_axis - - - - - 8 - 30 - 343 - 66 - - - - - 343 - 66 - - - - - 344 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - linear_acceleration - - - - - 81 - 32 - 139 - 26 - + + + + + + 370 + 200 + - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to linear acceleration in the Z axis, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - - - 12 - 108 - 345 - 66 - - - - - 343 - 66 - - - - - 345 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - angular_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to angular acceleration about the X axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - - - 12 - 618 - 370 - 255 - - - - - 370 - 255 - - - - - 372 - 265 - - - - moment - - - - - 16 - 100 - 343 - 67 - - - - - 343 - 66 - - - - - 345 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - moment_y - - - - + + + 372 + 190 + + + + x_axis + + + + + 18 + 28 + 344 + 75 + + + + + 340 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + - + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to linear acceleration in the X axis, in kg + + + kg + + + 1000.000000000000000 + + + + + 12 @@ -1413,7 +494,7 @@ Links connected by a joint will never collide - + 90 @@ -1427,22 +508,18 @@ Links connected by a joint will never collide - Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 + Added mass in the X axis due to linear acceleration in the Y axis, and vice-versa, in kg. - kgm^2 + kg 1000.000000000000000 - - - - - + 12 @@ -1464,7 +541,78 @@ Links connected by a joint will never collide - + + + + 90 + 24 + + + + Added mass in the X axis due to linear acceleration in the Z axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + 12 + 108 + 345 + 75 + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + 90 @@ -1478,230 +626,75 @@ Links connected by a joint will never collide - Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 + Added mass in the X axis due to angular acceleration about the X axis, and vice-versa, in kg * m. - kgm^2 + kgm + + + 1000.000000000000000 - - - - - - - - 12 - 28 - 345 - 66 - - - - - 343 - 66 - - - - - 345 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - moment_x - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the X axis due to angular acceleration about the X axis, in kg * m^2. - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m^2 - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2. - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - - 18 - 174 - 343 - 67 - - - - - 343 - 66 - - - - - 344 - 67 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - moment_z - - - - - + - 10 - 15 + 12 + 24 - 10 - 18 + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 @@ -1713,7 +706,7 @@ Links connected by a joint will never collide - + 90 @@ -1727,18 +720,973 @@ Links connected by a joint will never collide - Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 + Added mass in the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m - kgm^2 + kgm + + + 1000.000000000000000 - - - - + + + + + + + + 370 + 205 + + + + + 372 + 190 + + + + y_axis + + + + + + + 343 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to linear acceleration in the Y axis, in kg + + + kg + + + 1000.000000000000000 + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to linear acceleration in the Z axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the X axis, and vice-versa, in kg * m + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + + + + + + + 370 + 190 + + + + + 372 + 190 + + + + z_axis + + + + + + + 343 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + 81 + 32 + 139 + 26 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to linear acceleration in the Z axis, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the X axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + + + + + + + 370 + 255 + + + + + 372 + 300 + + + + moment + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_x + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the X axis, in kg * m^2. + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2. + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_y + + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + + + + + + + + + + + 343 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_z + + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 + + + kgm^2 + + + + + + + + + + + + @@ -1908,7 +1856,7 @@ Links connected by a joint will never collide 0 0 - 661 + 676 614 diff --git a/robot_descriptor/forms/surface.ui b/robot_descriptor/forms/surface.ui index d2af11e..4c5d486 100644 --- a/robot_descriptor/forms/surface.ui +++ b/robot_descriptor/forms/surface.ui @@ -126,7 +126,7 @@ - 1 + 2 false @@ -1283,6 +1283,9 @@ Parsed as 16-bit unsigned integer N/m + + 1000.000000000000000 + @@ -1300,6 +1303,9 @@ Parsed as 16-bit unsigned integer N/m + + 1000.000000000000000 + @@ -1317,6 +1323,9 @@ Parsed as 16-bit unsigned integer N/m/s + + 1000.000000000000000 + diff --git a/robot_descriptor/icons/link16.png b/robot_descriptor/icons/link16.png new file mode 100644 index 0000000000000000000000000000000000000000..2adfcbb96b124c1713033c4f1fbafe1ee79b5d1d GIT binary patch literal 559 zcmV+~0?_@5P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10lY~> zK~y-6jgdV}Q&AX(pYPsku12B^EDl{Dg50)9LNE@R4o!ClM}j5@0~-sn^!D5se!{>+ z2nnMb6OIxz!7%uf@Yi0{*tn7~7$O2L@sKn}Rr1o!F^v<=hXdUTf!O8_E>Uu4BvX3i9(3UpYP z-Y8(GHuDXmDB_$3-z<>EWf6#C4=A@q_!ui_8>Yc^S-@hVfVmUR0tSJkyT^PYPT+bx zv`RTLOlL-Dta`kv?sNCU1mD^XeU3xmKyH1K@9|G?@KKflHpcj>O2zf)Z+^m6fdY`< z4A=lTZjdtEQh0uNK-#;+XM{V)Lg5Y2QW<9#NdA8pkTzt17YbozoZad^vm!KSMri!a zlNF^DS62L@UQt*R%T&oQ9k(zQhD7Kn1?<)43AH>x_!0{n`c)`cOKvMX2?IFl&_t&pP1{c_0a xSulX8DqRCyIK0jyReVuC9sJpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10d7e| zK~y-6osvr{L~$6#fA2XnhHPB3n$b+NVzQDY3FDGdR=$N|VWAWYWMLs$_y}w@7um89 zieaL$(8=x%9kGe^ixvFFc*`)xr!K7~gl(b!7Z?$_;DC z00?0?u}IX~mi1~)qXqy1tVGVOgQ}&fy0Qmmt#&6bbBGg0Wd-p3I>~D4)W7L!FgSSa z{p#%AKv@J@YNWAE)9$~G2cJBZ+u-O+b8AOe0%fGmIi_tJ<3P1RtJgS$x?%tnd8|62 zKWdE$oHZf_iQk|4XP}}O1J=rIC|MB_3RehkD2G5(QGA>8;BG6>@~dRLG1q0C` z71@1A`rX7hh7P9_fg3lh*n#wzUR`n{0HhPWu3{*DWf8r+I|;nkBK Any: if role==Qt.DisplayRole: return self.text + + if role==Qt.DecorationRole: + if self.type=='link': + return link_img + elif self.type=='ref': + return ref_img + else: + return + #end standard Item #============================================== @@ -40,23 +55,29 @@ def __init__(self,elem_struct): #subelements from .sdf_elements import link #link - self.link=link.link(self.ModelEditorUi) + self._link=link.link(self.ModelEditorUi) #visual from .sdf_elements import visual - self.visual=visual.visual(self.ModelEditorUi) + self._visual=visual.visual(self.ModelEditorUi) #collision from .sdf_elements import collision - self.collision=collision.collison(self.ModelEditorUi) + self._collision=collision.collison(self.ModelEditorUi) + self.current_elems=[] + #dictionary of all links and their associated elements + #{link name: [link,collison,visual], ...} + self.elems={} + #used for creating refernces for item of type ref + self.referenced_elems={} + #create model self.link_model=QStandardItemModel() self.link_model.setColumnCount(1) self.root_node=self.link_model.invisibleRootItem() - self.tree_setup(self.links_hierarchy["children"],self.root_node) + self.model_tree_config(self.links_hierarchy["children"],self.root_node) - - self.current_elems=[] - self.elems={} + #add callback + self.config() # start header related self.ModelEditorUi.link_tree.setHeaderHidden(False) @@ -68,16 +89,64 @@ def __init__(self,elem_struct): self.ModelEditorUi.exec() - #create the tree structure - def tree_setup(self,link_hierarchy,item): - #iterate throuhg all children create items and the to tree - for child in link_hierarchy: - row=standard_item(child["name"]) - - item.appendRow(row) - self.tree_setup(child["children"],row) - return +#end __init__() + + def config(self): + self.ModelEditorUi.link_tree.clicked[QModelIndex].connect(self.on_tree_item) + def on_tree_item(self,index): + item = self.link_model.itemFromIndex(index) + label=item.data(Qt.DisplayRole) + #update data related to elems + self.current_elems=self.elems[label] + self._link.update_elem(self.current_elems[0]) + self._collision.update_elem(self.current_elems[1]) + self._visual.update_elem(self.current_elems[2]) + + + def model_tree_config(self,link_str,std_itm): + ref_links=[] + #create the tree view structure + def setup(link_hierarchy,item): + #iterate throuhg all children create items and the to tree + #seee parse_asm4_model.py + for child in link_hierarchy: + name=child["name"] + row=standard_item(child["name"],child['type']) + item.appendRow(row) + #make reference to the index of referenced link + #This assumes the link already exists in the referenced_elems dictionary + if child['type']=='ref': + # row.ref_idx=self.referenced_elems[child["ref_label"]] + # #refer to the data in the refered link + # #since the links are similar + # #this can be updated by right clicking on the tree element and clicking break reference + # self.elems[child['name']]=self.elems[child["ref_label"]] + + #just update the ref_links since the link might not be defined yet + ref_links.append([row,child["ref_label"],name]) + #store index to referred link + elif child['type']=='link': + #add to referenced elements + self.referenced_elems[child['name']]=self.link_model.indexFromItem(row) + # get data and store it in corresponding list + link_elem=copy.deepcopy(self._link.get_default_elem()) + collision_elem=copy.deepcopy(self._collision.get_default_elem()) + visual_elem=copy.deepcopy(self._visual.get_default_elem()) + #update element data + self.elems[child['name']]=[link_elem,collision_elem,visual_elem] + else: + pass + #deb + #### + #recursion + setup(child["children"],row) + return + setup(link_str,std_itm) + #add ref_link related data + for item,ref_label,name in ref_links: + item.ref_idx=self.referenced_elems[ref_label] + self.elems[name]=self.elems[ref_label] #+=============================== diff --git a/robot_descriptor/sdf_elements/collision.py b/robot_descriptor/sdf_elements/collision.py index cafc777..652c76f 100644 --- a/robot_descriptor/sdf_elements/collision.py +++ b/robot_descriptor/sdf_elements/collision.py @@ -48,13 +48,18 @@ def __init__(self,parent_ui): self.collision_elem=initialize_element_tree.convdict_2_tree(self.file_name).get_element #surface element self.surface_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"surface.ui")) - self.surface_elem=surface.surface(self.surface_ui) + self.surface_cls=surface.surface(self.surface_ui) #add widget to parent self.ui.collision_scroll.setWidget(self.surface_ui.widget) self.configUI() self.updateUI() + def get_default_elem(self): + default_el=copy.deepcopy(self.collision_elem) + default_el.append(self.surface_cls.get_default_elem()) + return default_el + def configUI(self): self.ui.collision_max_contacts_sp.valueChanged.connect( lambda value,collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"max_contacts",False,self.properties.max_contacts) @@ -71,9 +76,12 @@ def updateUI(self): def update_elem(self,elem:ET.Element): surf=elem.find("surface") if surf is not None: - self.surface_elem.update_elem(surf) - elem.remove(surf) + self.surface_cls.update_elem(surf) self.collision_elem=elem + else: + print("collision surf is none \n") + #update ui after element updates + self.updateUI() def reset(self): pass @@ -87,7 +95,9 @@ def element(self): if not self.properties.collison_max_contacts_cb: t_collision_elem.remove("max_contacts") - t_surface=self.surface_elem.element + t_surface=self.surface_cls.element - return t_collision_elem.append(t_surface) + if t_collision_elem.find('surface') is None: + t_collision_elem.append(t_surface) + return t_collision_elem \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py index d4b513d..d8927a7 100644 --- a/robot_descriptor/sdf_elements/link.py +++ b/robot_descriptor/sdf_elements/link.py @@ -3,6 +3,7 @@ from ..RD_utils import initialize_element_tree import copy from PySide import QtCore +import xml.etree.ElementTree as ET class link_properties: def __init__(self,ui) -> None: @@ -259,6 +260,18 @@ def __init__(self,ui,elem_struct=None): self._root_dict=elem_struct self.configUI() self.UpdateUi() + + def get_default_elem(self): + default_el=copy.deepcopy(self.link_element) + default_el.append(copy.deepcopy(self._inertial_element)) + return default_el + + def update_elem(self,new_elem:ET.Element): + inertial=new_elem.find("inertial") + if inertial is not None: + self.link_element=new_elem + self._inertial_element=inertial + self.UpdateUi() def configUI(self): self.ui.link_gravity_checkbox.stateChanged.connect(self.onGravity) @@ -358,5 +371,7 @@ def element(self): t_inertial_elem=copy.deepcopy(self._inertial_element) if self.ui.fluid_added_mass_groupbox.isChecked(): t_inertial_elem.remove(t_inertial_elem.find("fluid_added_mass")) - - return t_link_elem.append(t_inertial_elem) \ No newline at end of file + + if t_link_elem.find("inertial") is None: + t_link_elem.append(t_inertial_elem) + return t_link_elem \ No newline at end of file diff --git a/robot_descriptor/sdf_elements/material.py b/robot_descriptor/sdf_elements/material.py index 5cd8f2b..cc53680 100644 --- a/robot_descriptor/sdf_elements/material.py +++ b/robot_descriptor/sdf_elements/material.py @@ -429,6 +429,13 @@ def __init__(self,ui) -> None: self.configUI() # self.reset(default=False) + def get_default_elem(self): + return copy.deepcopy(self._material_element) + + def update_elem(self,new_elem:ET.Element): + self._material_element=new_elem + self.updateUi() + def configUI(self): self.ui.material_script_uri_input.textEdited.connect(self.on_uri) self.ui.material_script_name.textEdited.connect(self.on_uri_name) diff --git a/robot_descriptor/sdf_elements/surface.py b/robot_descriptor/sdf_elements/surface.py index 05dee29..30467d7 100644 --- a/robot_descriptor/sdf_elements/surface.py +++ b/robot_descriptor/sdf_elements/surface.py @@ -303,7 +303,7 @@ def damping(self,value): @property def flesh_mass_fraction(self): - self.ui.soft_contact_flesh_mass_fraction_sp.value() + return self.ui.soft_contact_flesh_mass_fraction_sp.value() @flesh_mass_fraction.setter def flesh_mass_fraction(self,value): self.ui.soft_contact_flesh_mass_fraction_sp.setValue(value) @@ -421,6 +421,9 @@ def __init__(self,ui) -> None: self.configUI() self.updateUI() + def get_default_elem(self): + return copy.deepcopy(self.surface_element) + def configUI(self): #bounce # bounce=self.surface_element.find('bounce') @@ -703,6 +706,7 @@ def reset(self): def update_elem(self,elem:ET.Element): self.surface_element=elem + self.updateUI() #return element @property diff --git a/robot_descriptor/sdf_elements/visual.py b/robot_descriptor/sdf_elements/visual.py index e9aee3f..99bfd47 100644 --- a/robot_descriptor/sdf_elements/visual.py +++ b/robot_descriptor/sdf_elements/visual.py @@ -67,11 +67,16 @@ def __init__(self,parent_ui): self.properties=visual_properties(self.ui) #maertial self._material_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"material.ui")) - self._material_elem=material.material(self._material_ui) + self._material_cls=material.material(self._material_ui) #add widget to parent widget self.ui.material_scroll.setWidget(self._material_ui.widget) self.updateUI() - + + def get_default_elem(self): + default_el=copy.deepcopy(self._visual_elem) + default_el.append(self._material_cls.get_default_elem()) + return default_el + def configUI(self): self.ui.visual_laser_retro_sp.valueChanged.connect(self.on_laser_retro) self.ui.visual_transparency_sp.valueChanged.connect(self.on_transparency) @@ -102,9 +107,9 @@ def updateUI(self): def update_elem(self,new_elem:ET.Element): mat=new_elem.find("material") if mat is not None: - self._material_elem.update_elem(mat) - new_elem.remove(mat) + self._material_cls.update_elem(mat) self._visual_elem=new_elem + self.updateUI() @property def element(self): @@ -113,7 +118,8 @@ def element(self): for tag in visual_pairs.keys(): if not getattr(self.properties,visual_pairs[tag]): t_visual_elem.remove(t_visual_elem.find(tag)) - - return t_visual_elem.append(self._material_elem.element) + if t_visual_elem.find("material") is None: + t_visual_elem.append(self._material_cls.element) + return t_visual_elem \ No newline at end of file From 16046578fd812a36474a233605906ccc10a1bc40 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Mon, 22 Jan 2024 09:19:34 +0300 Subject: [PATCH 7/9] using stacked widget to manage ui's --- robot_descriptor/forms/collision.ui | 147 ++ robot_descriptor/forms/link.ui | 1617 +++++++++++++++++ robot_descriptor/forms/model_editor.ui | 1869 +------------------- robot_descriptor/forms/surface.ui | 802 ++++----- robot_descriptor/forms/visual.ui | 153 ++ robot_descriptor/icons/link16.png | Bin 559 -> 600 bytes robot_descriptor/icons/link32.png | Bin 0 -> 1354 bytes robot_descriptor/icons/ref16.png | Bin 481 -> 424 bytes robot_descriptor/icons/ref32.png | Bin 0 -> 703 bytes robot_descriptor/model_editor.py | 130 +- robot_descriptor/sdf_elements/collision.py | 4 +- robot_descriptor/sdf_elements/link.py | 20 +- 12 files changed, 2450 insertions(+), 2292 deletions(-) create mode 100644 robot_descriptor/forms/collision.ui create mode 100644 robot_descriptor/forms/link.ui create mode 100644 robot_descriptor/forms/visual.ui create mode 100644 robot_descriptor/icons/link32.png create mode 100644 robot_descriptor/icons/ref32.png diff --git a/robot_descriptor/forms/collision.ui b/robot_descriptor/forms/collision.ui new file mode 100644 index 0000000..506c6da --- /dev/null +++ b/robot_descriptor/forms/collision.ui @@ -0,0 +1,147 @@ + + + collision + + + + 0 + 0 + 662 + 682 + + + + collision + + + + + + + 644 + 650 + + + + + + + + + laser_retro + + + + + + + false + + + + + + + max_contacts + + + + + + + false + + + + + + + + + include_surface_info + + + + + + + false + + + + 16777215 + 587 + + + + true + + + + + 0 + 0 + 624 + 585 + + + + + + + + + + + + + + collision_laser_retro_cb + toggled(bool) + collision_laser_retro_sp + setEnabled(bool) + + + 94 + 30 + + + 252 + 30 + + + + + collison_max_contacts_cb + toggled(bool) + collision_max_contacts_sp + setEnabled(bool) + + + 409 + 30 + + + 567 + 30 + + + + + include_surface_info_cb + toggled(bool) + collision_scroll + setEnabled(bool) + + + 330 + 60 + + + 330 + 415 + + + + + diff --git a/robot_descriptor/forms/link.ui b/robot_descriptor/forms/link.ui new file mode 100644 index 0000000..a09496d --- /dev/null +++ b/robot_descriptor/forms/link.ui @@ -0,0 +1,1617 @@ + + + link + + + + 0 + 0 + 715 + 668 + + + + link + + + + + + + 697 + 650 + + + + + 16777215 + 650 + + + + + + + + 215 + 100 + + + + + 16777215 + 110 + + + + link states + + + true + + + true + + + + + + If true, the link is affected by gravity + + + gravity + + + + + + + If true, the link is affected by the wind + + + enable_wind + + + + + + + If true, the link is kinematic only + + + kinematic + + + + + + + If true, the link can collide with other links in the model. +Two links within a model will collide if link1.self_collide OR link2.self_collide. +Links connected by a joint will never collide + + + self_collide + + + + + + + + + + + 414 + 600 + + + + true + + + + + 0 + 0 + 440 + 918 + + + + + + + false + + + + 348 + 900 + + + + + 413 + 950 + + + + This link's fluid added mass matrix about the link's origin. + This matrix represents the inertia of the fluid that is dislocated when the + body moves. Added mass should be zero if the density of the surrounding + fluid is negligible with respect to the body's density. + The 6x6 matrix is symmetric, therefore only 21 unique elements can be set. + The elements of the matrix follow the [x, y, z, p, q, r] notation, where + [x, y, z] correspond to translation and [p, q, r] to rotation + + + fluid_added_mass + + + true + + + false + + + + + + + 370 + 200 + + + + + 372 + 190 + + + + x_axis + + + + + 18 + 28 + 344 + 75 + + + + + 340 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to linear acceleration in the X axis, in kg + + + kg + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to linear acceleration in the Y axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + Added mass in the X axis due to linear acceleration in the Z axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + 12 + 108 + 345 + 75 + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the X axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m + + + kgm + + + 1000.000000000000000 + + + + + + + + + + + + 370 + 205 + + + + + 372 + 190 + + + + y_axis + + + + + + + 343 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to linear acceleration in the Y axis, in kg + + + kg + + + 1000.000000000000000 + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to linear acceleration in the Z axis, and vice-versa, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the X axis, and vice-versa, in kg * m + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + + + + + + + 370 + 190 + + + + + 372 + 190 + + + + z_axis + + + + + + + 343 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + linear_acceleration + + + + + 81 + 32 + 139 + 26 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to linear acceleration in the Z axis, in kg. + + + kg + + + 1000.000000000000000 + + + + + + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + angular_acceleration + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the X axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass in the Z axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. + + + kgm + + + 1000.000000000000000 + + + + + + + + + + + + + + 370 + 255 + + + + + 372 + 300 + + + + moment + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_x + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + x + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the X axis, in kg * m^2. + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2. + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + + + 343 + 75 + + + + + 345 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_y + + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + y + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 + + + kgm^2 + + + 1000.000000000000000 + + + + + + + + + + + + 12 + 24 + + + + + 15 + 30 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 + + + kgm^2 + + + + + + + + + + + + + 343 + 75 + + + + + 344 + 78 + + + + Added mass in the X axis due to linear acceleration in the x,y,z axes + + + moment_z + + + + + + + + + 10 + 15 + + + + + 10 + 18 + + + + z + + + Qt::AlignCenter + + + + + + + + 90 + 24 + + + + + 100 + 30 + + + + Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 + + + kgm^2 + + + + + + + + + + + + + + + + + + + + + + + 217 + 110 + + + + + 16777215 + 120 + + + + Exponential damping of the link's velocity. + + + velocity_decay + + + true + + + false + + + + + + + 35 + 15 + + + + + 45 + 16 + + + + linear + + + + + + + 5 + + + 1000.000000000000000 + + + + + + + + 50 + 25 + + + + + 55 + 27 + + + + angular + + + + + + + 5 + + + 1000.000000000000000 + + + + + + + + + + false + + + + 213 + 70 + + + + + 16777215 + 70 + + + + inertial + + + true + + + false + + + + + + auto + + + + + + + + + + Qt::Vertical + + + + 20 + 481 + + + + + + + + + + + + diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui index af15860..9ddd4ad 100644 --- a/robot_descriptor/forms/model_editor.ui +++ b/robot_descriptor/forms/model_editor.ui @@ -6,8 +6,8 @@ 0 0 - 1028 - 775 + 1030 + 764 @@ -81,7 +81,7 @@ - 250 + 350 800 @@ -91,14 +91,14 @@ - 685 + 695 530 700 - 720 + 800 @@ -108,1674 +108,27 @@ link - - - - 6 - 2 - 107 - 25 - - - - __link_name__ - - - - - - 12 - 42 - 215 - 100 - - - - - 215 - 100 - - - - link states - - - true - - - false - - - - - - If true, the link is affected by gravity - - - gravity - - - - - - - If true, the link is affected by the wind - - - enable_wind - - - - - - - If true, the link is kinematic only - - - kinematic - - - - - - - If true, the link can collide with other links in the model. -Two links within a model will collide if link1.self_collide OR link2.self_collide. -Links connected by a joint will never collide - - - self_collide - - - - - - - - - 12 - 140 - 217 - 110 - - - - - 217 - 110 - - - - Exponential damping of the link's velocity. - - - velocity_decay - - - true - - - false - - - - - - - 35 - 15 - - - - - 45 - 16 - - - - linear - - - - - - - 5 - - - 1000.000000000000000 - - - - - - - - 50 - 25 - - - - - 55 - 27 - - - - angular - - - - - - - 5 - - - 1000.000000000000000 - - - - - - - - false - - - - 14 - 264 - 213 - 70 - - - - - 213 - 70 - - - - inertial - - - true - - - false - - - - - - auto - - - - - - - - - 234 - 6 - 463 - 675 - - - - - 414 - 675 - - - - true - - - - - 0 - -245 - 447 - 918 - - - - - - - false - - - - 348 - 900 - - - - - 413 - 950 - - - - This link's fluid added mass matrix about the link's origin. - This matrix represents the inertia of the fluid that is dislocated when the - body moves. Added mass should be zero if the density of the surrounding - fluid is negligible with respect to the body's density. - The 6x6 matrix is symmetric, therefore only 21 unique elements can be set. - The elements of the matrix follow the [x, y, z, p, q, r] notation, where - [x, y, z] correspond to translation and [p, q, r] to rotation - - - fluid_added_mass - - - true - - - false - - - - - - - 370 - 200 - - - - - 372 - 190 - - - - x_axis - - - - - 18 - 28 - 344 - 75 - - - - - 340 - 75 - - - - - 344 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - linear_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to linear acceleration in the X axis, in kg - - - kg - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to linear acceleration in the Y axis, and vice-versa, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - Added mass in the X axis due to linear acceleration in the Z axis, and vice-versa, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - - 12 - 108 - 345 - 75 - - - - - 343 - 75 - - - - - 345 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - angular_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to angular acceleration about the X axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m - - - kgm - - - 1000.000000000000000 - - - - - - - - - - - - 370 - 205 - - - - - 372 - 190 - - - - y_axis - - - - - - - 343 - 75 - - - - - 344 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - linear_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to linear acceleration in the Y axis, in kg - - - kg - - - 1000.000000000000000 - - - - - - - - 10 - 15 - - - - - 10 - 18 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to linear acceleration in the Z axis, and vice-versa, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - - - - 343 - 75 - - - - - 345 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - angular_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to angular acceleration about the X axis, and vice-versa, in kg * m - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - - - - - - - 370 - 190 - - - - - 372 - 190 - - - - z_axis - - - - - - - 343 - 75 - - - - - 344 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - linear_acceleration - - - - - 81 - 32 - 139 - 26 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to linear acceleration in the Z axis, in kg. - - - kg - - - 1000.000000000000000 - - - - - - - - - - - - 343 - 75 - - - - - 345 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - angular_acceleration - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to angular acceleration about the X axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to angular acceleration about the Y axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass in the Z axis due to angular acceleration about the Z axis, and vice-versa, in kg * m. - - - kgm - - - 1000.000000000000000 - - - - - - - - - - - - - - 370 - 255 - - - - - 372 - 300 - - - - moment - - - - - - - 343 - 75 - - - - - 345 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - moment_x - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - x - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the X axis due to angular acceleration about the X axis, in kg * m^2. - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the X axis due to angular acceleration about the Y axis, and vice-versa, in kg * m^2 - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the X axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2. - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - - - - 343 - 75 - - - - - 345 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - moment_y - - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - y - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the Y axis due to angular acceleration about the Y axis, in kg * m^2 - - - kgm^2 - - - 1000.000000000000000 - - - - - - - - - - - - 12 - 24 - - - - - 15 - 30 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the Y axis due to angular acceleration about the Z axis, and vice-versa, in kg * m^2 - - - kgm^2 - - - - - - - - - - - - - 343 - 75 - - - - - 344 - 78 - - - - Added mass in the X axis due to linear acceleration in the x,y,z axes - - - moment_z - - - - - - - - - 10 - 15 - - - - - 10 - 18 - - - - z - - - Qt::AlignCenter - - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Added mass moment about the Z axis due to angular acceleration about the Z axis, in kg * m^2 - - - kgm^2 - - - - - - - - - - - - - - - - - + + + + + + + + collision - - - false - - - - 16 - 76 - 629 - 603 - - - - true - - - - - 0 - 0 - 627 - 601 - - - - - - - - 18 - 48 - 148 - 21 - - - - include_surface_info - - - - - - 10 - 7 - 467 - 26 - - - - - - - laser_retro - - - - - - - false - - - - - - - max_contacts - - - - - - - false - - - - - + + + + + + + + @@ -1783,84 +136,9 @@ Links connected by a joint will never collide - - - laser_retro - - - - - - - false - - - - - - - transparency - - - - - - - false - - - - - - - false - - - visibility_flags - - - - - - - false - - - 900000000 - - - QAbstractSpinBox::DefaultStepType - - - - - - - cast_shadows - - - - - - - - 660 - 610 - - - - true - - - - - 0 - 0 - 676 - 614 - - - + + + @@ -1870,102 +148,5 @@ Links connected by a joint will never collide - - - collision_laser_retro_cb - toggled(bool) - collision_laser_retro_sp - setEnabled(bool) - - - 333 - 58 - - - 451 - 58 - - - - - collison_max_contacts_cb - toggled(bool) - collision_max_contacts_sp - setEnabled(bool) - - - 569 - 58 - - - 686 - 58 - - - - - include_surface_info_cb - toggled(bool) - collision_scroll - setEnabled(bool) - - - 358 - 97 - - - 597 - 416 - - - - - visual_laser_retro_cb - toggled(bool) - visual_laser_retro_sp - setEnabled(bool) - - - 328 - 59 - - - 438 - 59 - - - - - visual_transparency_cb - toggled(bool) - visual_transparency_sp - setEnabled(bool) - - - 549 - 59 - - - 659 - 59 - - - - - visual_visibility_flags_cb - toggled(bool) - visual_visibility_flags_sp - setEnabled(bool) - - - 772 - 59 - - - 886 - 59 - - - - + diff --git a/robot_descriptor/forms/surface.ui b/robot_descriptor/forms/surface.ui index 4c5d486..0e09f58 100644 --- a/robot_descriptor/forms/surface.ui +++ b/robot_descriptor/forms/surface.ui @@ -126,7 +126,7 @@ - 2 + 1 false @@ -154,22 +154,16 @@ false - - - - - 0 - 160 - - + + - 533 - 170 + 508 + 16777215 - torsional + bullet true @@ -177,200 +171,169 @@ false - + - - - - 0 - 24 - - - - - 70 - 16777215 - - + - coefficient + friction - - - - 0 - 24 - - - - - 90 - 16777215 - + + + false - Torsional friction coefficient, unitless maximum ratio of - tangential stress to normal stress. + Coefficient of friction in first friction pyramid direction, + the unitless maximum ratio of force in first friction pyramid + direction to normal force - - - - - 180 - 120 - - - - - 210 - 16777215 - - - - Torsional friction parameters for ODE - - - ode - - - true + + + + friction2 - - - - 16 - 30 - 35 - 16 - - - - slip - - - - - - 60 - 28 - 111 - 24 - - - - force dependent slip for torsional friction, - equivalent to inverse of viscous damping coefficient - with units of rad/s/(Nm). - A slip value of 0 is infinitely viscous - - - - - - - 0 - 24 - - - - - 130 - 16777215 - + + + + false - If this flag is true, - torsional friction is calculated using the "patch_radius" parameter. - If this flag is set to false, - "surface_radius" (R) and contact depth (d) - are used to compute the patch radius as sqrt(R*d). - - - use_patch_radius + Coefficient of friction in second friction pyramid direction, + the unitless maximum ratio of force in second friction pyramid + direction to normal force - - - - - 95 - 24 - - - - - 80 - 16777215 - - + + - patch_radius + rolling_friction - - - - - 0 - 24 - - - - - 90 - 16777215 - + + + + false - Radius of contact patch surface + Coefficient of rolling friction - - - - - 0 - 24 - - + + - 130 - 16777215 + 500 + 465 - - surface_radius + + Unit vector specifying first friction pyramid direction in + collision-fixed reference frame - - - - - - - 0 - 24 - + + fdir1 - - - 90 - 16777215 - + + true - - Surface radius on the point of contact + + false + + + + + + 27 + 16777215 + + + + x + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 27 + 16777215 + + + + y + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 24 + + + + + 27 + 27 + + + + z + + + Qt::AlignCenter + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + + @@ -593,16 +556,22 @@ equivalent to inverse of viscous damping coefficient - - + + + + + 0 + 160 + + - 508 - 16777215 + 533 + 170 - bullet + torsional true @@ -610,169 +579,182 @@ equivalent to inverse of viscous damping coefficient false - + - + + + + 0 + 24 + + + + + 70 + 16777215 + + - friction + coefficient - - + + + + 0 + 24 + + + + + 90 + 16777215 + + + + Torsional friction coefficient, unitless maximum ratio of + tangential stress to normal stress. + + + + + + + ode + + + true + + false + + + + 24 + 62 + 57 + 15 + + + + slip + + + + + + 95 + 58 + 83 + 23 + + + + + + + + + + 0 + 24 + + + + + 130 + 16777215 + + - Coefficient of friction in first friction pyramid direction, - the unitless maximum ratio of force in first friction pyramid - direction to normal force + If this flag is true, + torsional friction is calculated using the "patch_radius" parameter. + If this flag is set to false, + "surface_radius" (R) and contact depth (d) + are used to compute the patch radius as sqrt(R*d). - - - - - friction2 + use_patch_radius - - - - false + + + + + 95 + 24 + - - Coefficient of friction in second friction pyramid direction, - the unitless maximum ratio of force in second friction pyramid - direction to normal force + + + 80 + 16777215 + - - - - - rolling_friction + patch_radius - - - - false + + + + + 0 + 24 + + + + + 90 + 16777215 + - Coefficient of rolling friction + Radius of contact patch surface - - + + + + + 0 + 24 + + - 500 - 465 + 130 + 16777215 - - Unit vector specifying first friction pyramid direction in - collision-fixed reference frame + + surface_radius - - fdir1 + + + + + + + 0 + 24 + - - true + + + 90 + 16777215 + - - false + + Surface radius on the point of contact - - - - - - 27 - 16777215 - - - - x - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 27 - 16777215 - - - - y - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 24 - - - - - 27 - 27 - - - - z - - - Qt::AlignCenter - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - - @@ -1106,7 +1088,7 @@ Parsed as 16-bit unsigned integer dynamically "stiffness"-equivalent coefficient for contact joints - 2000000000000.000000000000000 + 10000000000000.000000000000000 @@ -1205,7 +1187,7 @@ Parsed as 16-bit unsigned integer see ode - 2000000000000.000000000000000 + 10000000000000.000000000000000 @@ -1252,98 +1234,120 @@ Parsed as 16-bit unsigned integer soft_contact - - - - 12 - 14 - 359 - 156 - - - - soft_contact - - - true - - - - - - bone_attachment - - - - - - - This is variable k_v in the soft contacts paper. Its unit is N/m - - - N/m - - - 1000.000000000000000 - - - - - - - stiffness - - - - - - - This is variable k_e in the soft contacts paper - - - N/m - - - 1000.000000000000000 - - - - - - - damping - - - - - - - Viscous damping of point velocity in body frame - - - N/m/s - - - 1000.000000000000000 - - - - - - - flesh_mass_fraction - - - - - - - Fraction of mass to be distributed among deformable nodes - - - - - + + + + + soft_contact + + + true + + + + + + bone_attachment + + + + + + + This is variable k_v in the soft contacts paper. Its unit is N/m + + + N/m + + + 1000.000000000000000 + + + + + + + stiffness + + + + + + + This is variable k_e in the soft contacts paper + + + N/m + + + 1000.000000000000000 + + + + + + + damping + + + + + + + Viscous damping of point velocity in body frame + + + N/m/s + + + 1000.000000000000000 + + + + + + + flesh_mass_fraction + + + + + + + Fraction of mass to be distributed among deformable nodes + + + + + + + + + + Qt::Horizontal + + + + 248 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 448 + + + + + diff --git a/robot_descriptor/forms/visual.ui b/robot_descriptor/forms/visual.ui new file mode 100644 index 0000000..36d67fa --- /dev/null +++ b/robot_descriptor/forms/visual.ui @@ -0,0 +1,153 @@ + + + Form + + + + 0 + 0 + 730 + 700 + + + + + 695 + 700 + + + + Form + + + + + + + + + laser_retro + + + + + + + false + + + + + + + transparency + + + + + + + false + + + + + + + false + + + visibility_flags + + + + + + + false + + + 900000000 + + + QAbstractSpinBox::DefaultStepType + + + + + + + cast_shadows + + + + + + + + 660 + 600 + + + + + 16777215 + 607 + + + + true + + + + + 0 + 0 + 692 + 605 + + + + + + + + + + + + + + visual_laser_retro_cb + toggled(bool) + visual_laser_retro_sp + setEnabled(bool) + + + 73 + 29 + + + 189 + 29 + + + + + visual_transparency_cb + toggled(bool) + visual_transparency_sp + setEnabled(bool) + + + 306 + 29 + + + 423 + 29 + + + + + diff --git a/robot_descriptor/icons/link16.png b/robot_descriptor/icons/link16.png index 2adfcbb96b124c1713033c4f1fbafe1ee79b5d1d..b1c7113807efe58cbcea75643a43cc0d2ec424a8 100644 GIT binary patch delta 516 zcmV+f0{i{11lR#4V#1UFUB~CXn%(4y|-d+ z32`wl#Es2?pi$!JY)mu`PRtIPIG9RX$)z`vP}*pOxcGw(juLb*K(*x_1`U#Oi=6d6 z&vV{<$tSAHZl?OQ8kfDlE{W(NRh>`gog#qjMo=sI2M{fTEPsQ(MRWj_`IKu9?@Cbj zyhPA6=hLqJ48ZsOSiGV0sE+O^s84#w0wcp|*SWJTD_0(ApkGYK+EcHNsxi|b-@|fM z`b78~DtJ>UbhEzx9MuPD*M7L|dZ}_9=vj@KVl+(9itf1zd`;z@dv(uCXv@5aHdmbf zp`q1Usd5b%4}Xlt>gLgIkXofa**CIAT2DZZ@A?>T0b_DB4^1yaYg?I4bfk zwC(JZ*|_OxycU>9y7v9{g<5g?CL$xj&)DhAmCRau9(^_Y8iOc5I>2Lyj1h_0VK9IZ zI1DVb2Xm#$C?dBc2%OZwxldv6pEpnzfSm99u`Tcof!h&ql7qRAonZL;nQEoVW1vr9 z3g}nZAA!qfT>HaL@TLHuTJ~L|!70=%uEi->meu$l46p(3L&%lemMc>L0000^AcEYsNJ20Unhs5O z2S1nvh?=c7=FUQLgRiew=%)OuGr_>`z8Ir2J2G&$~=YK#BxYz{u>JqdK)8Kk^ zmkmn*B8XpP#ad?06r>7tSeM=?V5m0p4WlUHoCe=4kj7;Zh++>Yw?+6ED`*?0!F5@{ zVxoY#6U_n!fuy^~d?HTZdOWmBIWkOVMrf>hysGYV_rnC=+6{ezzf?Pj6tW`7KeZo=G6v*JA?v5X z0Fo_gVh5IiBj6>_t&pP1{c_0aSulX8DqRCyIK0jyReVuC9sJV diff --git a/robot_descriptor/icons/link32.png b/robot_descriptor/icons/link32.png new file mode 100644 index 0000000000000000000000000000000000000000..42a4bbd9dfdb2bed1d9a954b8589fba83a27575a GIT binary patch literal 1354 zcmV-Q1-1H#P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H11lLJK zK~z|UwU%3KR8na>VlWsJB9RCd3M~bMDbvf8i%(7rF(!rweF02NB;kpR zK9HDbOpFg2(Fcvj`lQgglunNY+A_6`BA^g7$Sp_#(<1HAIdhf|oswFsoPoNYR`$RD z{r_iW?RB=OD*s0uJ#=(tk;!iMVWBZ<`98lPCblvXIzMusjJE;Tb*B^$_Dk*``hX<8GiWnJlr?NuZSGmo6b3!>1pi0$7w^?--aURiRKQV~?9UU~=~J z2&KR+QMQ$*TR&y@Zhsh0$5T;7J_c46XLtj6eOxQho=D6Rb#_=H4J+!ZPK~vvBksN= z=*K|+gpAA^_a3-cG&D3=^QX?f1k6>{XU&5g)|O0`q~oa%(}|XiK{?TAGzXjn5M$=w zcMlwi9hp-k_F+X9tMWK-r~rB~fGFO5RUqBm{7{j2O(2VbUJHL$P_FB`Q-EavzUs+> z4IDjmbf$XdFz__che~8cB-|O4U!2kH3{~Lj#Xqli6lB14UE8s;U*+%lE#GK;MSZ9v zD8I8YwHDX|fXM!6G@2{OKygN22G#?EzOuQpc70n=ZaUsv=^Ob5C<1A*XHR_}ppYgM zU}rvivocck?J&^U=+5s;1fO)`{;|X`iNUSs7yh02KU^;NZ&Pq*XUER%LJg@;H{=&T6nKc{N z{4o+M-w-~Funz!VcXf4jIRGb;$;mz@225AwQ-ba$d-yo=!+m9_Kyl2i5;0^a!xZt!(z@n%d!Ec_ulvpxCTth z+LK-z>o7%%094c;3%{p<18Jce=6piP2nO zA%Nzrp9(h6o=D8{9Bl%Y0KMu{H+sUAA8&mZ_#C(_SbZZg&(ZA+UF%;fH>^Dw)PSfe zU0q#HuBWd_VI9yX_>uBRxIO409dS1#XcBOMS1KY^9|YwZfNW3Sc7=5UcSQV6g^0H& zQ>z618gNi)x^V0IM?tv&($dmm7iaV`P$ICiJW};mQ1bDZyAsg^`3aZxob{t;#J$3v zFrcduN`TuFP4@ku#P&q0+=#@1X}}L+`_*ge3KIt~meD7NQt2M<_osDj(kz5ln3;5ai60Qh`e}52h z0PDbK2QpXAou36%0yUR@Ie+fa1&`l-(>F9UShp|sY*o=Off>MATkNXk_3N%as5s;Y zk?Xn>i!<5+tjw>U0lHC&5LN?o^XuK7tN?;GncI4%Z;qpdOZn6XTa!C#=r9rfk3<9PA1>gwL{6dsPh0N*V3g%C*pQ~&?~ M07*qoM6N<$g8H3xrvLx| literal 0 HcmV?d00001 diff --git a/robot_descriptor/icons/ref16.png b/robot_descriptor/icons/ref16.png index f1c8fd07b34b334d6f082d3a7fecce7116c15ca2..e1a9c47d5bc6da8aee2ba96a3c29594f1c0ba858 100644 GIT binary patch delta 339 zcmV-Z0j&Pv1E>R#UVk-7L_t(Ijh)j!OI%S91@PY(|2BeOLF~k44OpfyU`P{4<0T%AzWY^<9+N<$Lc^UGbv(LI78xtKejC8^+2wSTTBVxb-cEe z7yqEqzNM8uc}&$}?hY~C6+WBvRx5v3kj#{Yoh*E;-GxG{4(nY?dwFE0(P9l1r@IcpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10!&Fn zK~z|U#g{*56JZ#KpZ9E)CTc}$1qH1l2nDN6{8t_9;NT#oibY%uxJm`Vx~f<=mx7Dn z&~73qB6QHA5eNU!T+~*BVnGnPi72LuNt4$h#=FK`dUsxOzb)T;@Ao`>d2@FWRVBLz=O=wAeF(dOO&+?ZX{LuR zohvUixo(}3C^?1@27%Rx2dtHCbP(6i;ARHWavEVG zAUHr2;ZXTQZGn`WMY)ETugXn|tXW*ZlzxP(fr72PsV(qQHUeXg_5VwTEXmpe$_-#; z9pC`x>D75>fwUY(Ianw72yq>^FZ?@P$|aYZ<$xLB3rZGYKd_?4^$+;Yxyr?b0+Vt8 zgP6kx^9YZDy9h~&d?2p*zg1J-0b3n{*HRA(Z1TGNg3OL_xErD&?)T|HqECva>_2FU{ z+J6OmZSW^VIN<|cK)6nU?QY;;KLMrZ&lBz=MUK*`Igjv1zyL9w_R?fM4NaK^)}b6@ zr{4Am_nnf!GihNdKY-`N*;i|5f=+1$nkfIP8Ez!p5?Dez@Rb%O8VR=qpbfa^WAFkJ l$nzHAa--qk=dC#4{08Xlq Any: if role==Qt.DisplayRole: @@ -37,32 +108,26 @@ def data(self, role: int = ...) -> Any: return ref_img else: return - + #end standard Item #============================================== + + #model editor class ModelEditor: def __init__(self,elem_struct): # find all objects of type 'App::Link' #doc=FreeCAD.ActiveDocument + + self._elem_struct=elem_struct self.links_hierarchy=parse_asm4_model.read_assembly() if self.links_hierarchy is None: return self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) - #subelements - from .sdf_elements import link - #link - self._link=link.link(self.ModelEditorUi) - #visual - from .sdf_elements import visual - self._visual=visual.visual(self.ModelEditorUi) - #collision - from .sdf_elements import collision - self._collision=collision.collison(self.ModelEditorUi) - + #subelements self.current_elems=[] #dictionary of all links and their associated elements #{link name: [link,collison,visual], ...} @@ -75,7 +140,7 @@ def __init__(self,elem_struct): self.link_model.setColumnCount(1) self.root_node=self.link_model.invisibleRootItem() self.model_tree_config(self.links_hierarchy["children"],self.root_node) - + self.ModelEditorUi.link_tree.setSelectionMode(self.ModelEditorUi.link_tree.SingleSelection) #add callback self.config() @@ -86,22 +151,17 @@ def __init__(self,elem_struct): #end header related self.ModelEditorUi.link_tree.setModel(self.link_model) - self.ModelEditorUi.exec() #end __init__() def config(self): self.ModelEditorUi.link_tree.clicked[QModelIndex].connect(self.on_tree_item) - + def on_tree_item(self,index): item = self.link_model.itemFromIndex(index) - label=item.data(Qt.DisplayRole) - #update data related to elems - self.current_elems=self.elems[label] - self._link.update_elem(self.current_elems[0]) - self._collision.update_elem(self.current_elems[1]) - self._visual.update_elem(self.current_elems[2]) + # label=item.data(Qt.DisplayRole) + item.selected() def model_tree_config(self,link_str,std_itm): @@ -112,7 +172,7 @@ def setup(link_hierarchy,item): #seee parse_asm4_model.py for child in link_hierarchy: name=child["name"] - row=standard_item(child["name"],child['type']) + row=ModelItem(self.ModelEditorUi,child["name"],child['type']) item.appendRow(row) #make reference to the index of referenced link #This assumes the link already exists in the referenced_elems dictionary @@ -128,13 +188,8 @@ def setup(link_hierarchy,item): #store index to referred link elif child['type']=='link': #add to referenced elements - self.referenced_elems[child['name']]=self.link_model.indexFromItem(row) - # get data and store it in corresponding list - link_elem=copy.deepcopy(self._link.get_default_elem()) - collision_elem=copy.deepcopy(self._collision.get_default_elem()) - visual_elem=copy.deepcopy(self._visual.get_default_elem()) - #update element data - self.elems[child['name']]=[link_elem,collision_elem,visual_elem] + self.referenced_elems[child['name']]=row + else: pass #deb @@ -145,9 +200,8 @@ def setup(link_hierarchy,item): setup(link_str,std_itm) #add ref_link related data for item,ref_label,name in ref_links: - item.ref_idx=self.referenced_elems[ref_label] - self.elems[name]=self.elems[ref_label] - + # item.ref_idx=self.referenced_elems[ref_label] + item.create_ref(self.referenced_elems[ref_label]) #+=============================== #start command diff --git a/robot_descriptor/sdf_elements/collision.py b/robot_descriptor/sdf_elements/collision.py index 652c76f..36da718 100644 --- a/robot_descriptor/sdf_elements/collision.py +++ b/robot_descriptor/sdf_elements/collision.py @@ -4,7 +4,7 @@ import copy import os import xml.etree.ElementTree as ET -import FreeCADGui +import FreeCADGui ,FreeCAD class collision_properties: @@ -79,7 +79,7 @@ def update_elem(self,elem:ET.Element): self.surface_cls.update_elem(surf) self.collision_elem=elem else: - print("collision surf is none \n") + FreeCAD.Console.PrintDeveloperWarning("collision surf is none \n") #update ui after element updates self.updateUI() diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py index d8927a7..4367555 100644 --- a/robot_descriptor/sdf_elements/link.py +++ b/robot_descriptor/sdf_elements/link.py @@ -4,6 +4,9 @@ import copy from PySide import QtCore import xml.etree.ElementTree as ET +import FreeCADGui +import os + class link_properties: def __init__(self,ui) -> None: @@ -29,7 +32,7 @@ def gravity(self,state): #enable wind @property def enable_wind(self): - state=self.ui.link_enable_wind_checkbox.isChecked(QtCore.Qt.Checked) + state=self.ui.link_enable_wind_checkbox.isChecked() if state: return str('true') else: @@ -37,10 +40,9 @@ def enable_wind(self): @enable_wind.setter def enable_wind(self,state): - if state=='true': - self.ui.link_enable_wind_checkbox.setCheckState(QtCore.Qt.Ckecked) - else: - self.ui.link_enable_wind_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.ui.link_enable_wind_checkbox.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.link_enable_wind_checkbox.setCheckState(QtCore.Qt.Unchecked) + + #self_collide @property @@ -49,7 +51,7 @@ def self_collide(self): @self_collide.setter def self_collide(self,state): - self.ui.link_self_collide_checkbox.setCheckState(QtCore.Qt.Ckecked) if state=='true' else self.ui.link_self_collide_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.ui.link_self_collide_checkbox.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.link_self_collide_checkbox.setCheckState(QtCore.Qt.Unchecked) #kinematic @property @@ -57,7 +59,7 @@ def kinematic(self): return str('true') if self.ui.link_kinematic_checkbox.isChecked() else str('false') @kinematic.setter def kinematic(self,state): - self.ui.link_kinematic_checkbox.setCheckState(QtCore.Qt.Ckecked) if state=='true' else self.ui.link_kinematic_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.ui.link_kinematic_checkbox.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.link_kinematic_checkbox.setCheckState(QtCore.Qt.Unchecked) #velocity decay #linear @@ -246,8 +248,8 @@ def fam_rr(self,val): #link #==================== class link: - def __init__(self,ui,elem_struct=None): - self.ui=ui + def __init__(self,parent_ui,elem_struct=None): + self.ui=parent_ui self.file_name='link.sdf' self.tag='link' #models will be store as children of sdf From a0c9fc5ebe71f15d3142517242488da9c6ea6bd0 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Sat, 27 Jan 2024 13:22:39 +0300 Subject: [PATCH 8/9] imporoved how selections are handled --- robot_descriptor/common.py | 2 +- robot_descriptor/forms/model_editor.ui | 152 --------------------- robot_descriptor/forms/surface.ui | 2 +- robot_descriptor/model_editor.py | 140 +++++++++++-------- robot_descriptor/sdf_elements/collision.py | 39 +++--- robot_descriptor/sdf_elements/link.py | 65 +++++---- robot_descriptor/sdf_elements/material.py | 10 +- robot_descriptor/sdf_elements/surface.py | 57 ++++---- robot_descriptor/sdf_elements/visual.py | 32 ++--- robot_descriptor/sdf_elements/world.py | 2 +- 10 files changed, 184 insertions(+), 317 deletions(-) delete mode 100644 robot_descriptor/forms/model_editor.ui diff --git a/robot_descriptor/common.py b/robot_descriptor/common.py index 86ca60a..2952876 100644 --- a/robot_descriptor/common.py +++ b/robot_descriptor/common.py @@ -78,7 +78,7 @@ def set_xml_data(element:ET.Element,tag:str,Is_Attribute:bool,value:Union[dict,f #no need for a loop try: elem=elem_iter.__next__() - except: + except Exception: return None # ensure no dictionaries are sent for non attributes if Is_Attribute is False and isinstance(value,dict) is False: diff --git a/robot_descriptor/forms/model_editor.ui b/robot_descriptor/forms/model_editor.ui deleted file mode 100644 index 9ddd4ad..0000000 --- a/robot_descriptor/forms/model_editor.ui +++ /dev/null @@ -1,152 +0,0 @@ - - - model_editor - - - - 0 - 0 - 1030 - 764 - - - - Model Editor - - - - - - - 90 - 24 - - - - - 100 - 30 - - - - Ok - - - - - - - - 90 - 24 - - - - - 95 - 30 - - - - Apply - - - - - - - - 90 - 24 - - - - - 95 - 30 - - - - Reset - - - - - - - - 216 - 716 - - - - - 350 - 800 - - - - - - - - - 695 - 530 - - - - - 700 - 800 - - - - 0 - - - - link - - - - - - - - - - - - - collision - - - - - - - - - - - - - visual - - - - - - - - - - - - - - - - - diff --git a/robot_descriptor/forms/surface.ui b/robot_descriptor/forms/surface.ui index 0e09f58..145d935 100644 --- a/robot_descriptor/forms/surface.ui +++ b/robot_descriptor/forms/surface.ui @@ -126,7 +126,7 @@ - 1 + 0 false diff --git a/robot_descriptor/model_editor.py b/robot_descriptor/model_editor.py index f2f6889..bc142bb 100644 --- a/robot_descriptor/model_editor.py +++ b/robot_descriptor/model_editor.py @@ -5,12 +5,14 @@ import os from PySide2 import QtGui import copy +from .RD_utils import initialize_element_tree import xml.etree.ElementTree as ET from .RD_utils import parse_asm4_model from PySide2.QtGui import QStandardItemModel,QStandardItem -from PySide2.QtCore import Qt,QModelIndex,QItemSelectionModel +from PySide2.QtWidgets import QTreeView,QDialog,QSplitter,QGridLayout,QTabWidget,QHBoxLayout,QWidget +from PySide2.QtCore import QSize, Qt,QModelIndex,QItemSelectionModel,Signal from .sdf_elements import link from .sdf_elements import visual from .sdf_elements import collision @@ -21,7 +23,7 @@ #start standard item class ModelItem(QStandardItem): - def __init__(self,Model_editor_ui,text,type='link'): + def __init__(self,model_editor_cls,text,type='link'): super().__init__() # data to describe the model @@ -31,13 +33,10 @@ def __init__(self,Model_editor_ui,text,type='link'): #set the text to be displayed self.setText(text) self.setEditable(False) + self.model_cls=model_editor_cls #this is the parent ui - self.Model_editor_ui=Model_editor_ui - #element ui's - self.collision_ui=None - self.link_ui=None - self.visual_ui=None - + # self.Model_editor_ui=self.model_cls.Model_editor_ui + #Tasks # 1. Implement function to # i. calculate inertia and write the info to the inertial element ,this might be @@ -53,50 +52,38 @@ def __init__(self,Model_editor_ui,text,type='link'): #linked if self.type !='ref': self.break_ref() + + def init_elements(self): + self.collision_element=initialize_element_tree.convdict_2_tree('collision.sdf').get_element + self._link_element=initialize_element_tree.convdict_2_tree('link.sdf').get_element + self._inertial_element=initialize_element_tree.convdict_2_tree("inertial.sdf").get_element + self.surface_element=initialize_element_tree.convdict_2_tree("surface.sdf").get_element + self._visual_element=initialize_element_tree.convdict_2_tree("visual.sdf").get_element + self._material_element=initialize_element_tree.convdict_2_tree('material.sdf').get_element + def create_ref(self,item): - #item will refer to data stored in the reference source - if self.collision_ui is not None and self.visual_ui is not None and self.link_ui is not None: - self.Model_editor_ui.ModelEditorCollisionStack.removeWidget(self.collision_ui) - self.Model_editor_ui.ModelEditorLinkStack.removeWidget.removeWidget(self.link_ui) - self.Model_editor_ui.ModelEditorVisualStack.removeWidget.removeWidget(self.visual_ui) - - self._link=item._link - self._visual=item._visual - self._collision=item._collision - self.collision_idx=item.collision_idx - self.link_idx=item.link_idx - self.visual_idx=item.visual_idx - self.type='ref' + + self.collision_element=item.collision_element + self._link_element=item._link_element + self._inertial_element=item._inertial_element + self.surface_element=item.surface_element + self._visual_element=item._visual_element + self._material_element=item._material_element self.emitDataChanged() - def break_ref(self): - #this will be called when reference is to broken - self.collision_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'collision.ui')) - self.collision_idx=self.Model_editor_ui.ModelEditorCollisionStack.addWidget(self.collision_ui) - - self.link_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'link.ui')) - self.link_idx=self.Model_editor_ui.ModelEditorLinkStack.addWidget(self.link_ui) - - self.visual_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'visual.ui')) - self.visual_idx=self.Model_editor_ui.ModelEditorVisualStack.addWidget(self.visual_ui) - #link - self._link=link.link(self.link_ui) - #visual - self._visual=visual.visual(self.visual_ui) - #collision - self._collision=collision.collison(self.collision_ui) - self.type='link' + self.init_elements() self.emitDataChanged() def selected(self): #this will called when an item is clicked - #it will basically add its ui to the model editor widget - self.Model_editor_ui.ModelEditorLinkStack.setCurrentIndex(self.link_idx) - self.Model_editor_ui.ModelEditorCollisionStack.setCurrentIndex(self.collision_idx) - self.Model_editor_ui.ModelEditorVisualStack.setCurrentIndex(self.visual_idx) + #update elements + self.model_cls._link.update_elements(self) + self.model_cls._visual.update_elements(self) + self.model_cls._collision.update_elements(self) + def data(self, role: int = ...) -> Any: if role==Qt.DisplayRole: return self.text @@ -115,17 +102,19 @@ def data(self, role: int = ...) -> Any: #model editor -class ModelEditor: +class ModelEditor(QWidget): + + def __init__(self,elem_struct): # find all objects of type 'App::Link' #doc=FreeCAD.ActiveDocument - + super(ModelEditor,self).__init__() self._elem_struct=elem_struct self.links_hierarchy=parse_asm4_model.read_assembly() if self.links_hierarchy is None: return - self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) + # self.ModelEditorUi=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'model_editor.ui')) #subelements self.current_elems=[] @@ -134,29 +123,72 @@ def __init__(self,elem_struct): self.elems={} #used for creating refernces for item of type ref self.referenced_elems={} + #ui's + self.collision_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'collision.ui')) + self.link_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'link.ui')) + self.visual_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,'visual.ui')) + #end ui's + #elements + self._link=link.link(self.link_ui) + self._visual=visual.visual(self.visual_ui) + self._collision=collision.collison(self.collision_ui) + #end elements + + self.setUpUI() #create model self.link_model=QStandardItemModel() self.link_model.setColumnCount(1) self.root_node=self.link_model.invisibleRootItem() self.model_tree_config(self.links_hierarchy["children"],self.root_node) - self.ModelEditorUi.link_tree.setSelectionMode(self.ModelEditorUi.link_tree.SingleSelection) + #add callback self.config() - # start header related - self.ModelEditorUi.link_tree.setHeaderHidden(False) + # start header related self.link_model.setHorizontalHeaderLabels(["Model Tree"]) #set the tree to resize automatically based on the display requirements #end header related - self.ModelEditorUi.link_tree.setModel(self.link_model) - self.ModelEditorUi.exec() - + #set view model + self.view.setModel(self.link_model) + mdl_idx0=self.link_model.index(0,0,self.view.rootIndex()) + self.view.selectionModel().select(mdl_idx0,QItemSelectionModel.Select) + #display dialog + self.show() #end __init__() - + + + def sizeHint(self) -> QSize: + return QSize(1030,764) + + def setUpUI(self): + self.setWindowTitle("ModelEditor") + #splitter + self.splitter=QSplitter(self) + self.splitter.setOrientation(Qt.Horizontal) + #create the treeview + self.view=QTreeView(self.splitter) + self.view.setHeaderHidden(False) + self.view.setSelectionMode(self.view.SingleSelection) + #set layout of the main dialog + grid=QGridLayout() + self.setLayout(grid) + grid.addWidget(self.splitter) + #create the tab widget + tab=QTabWidget(self.splitter) + tab.addTab(self.link_ui,"link") + tab.addTab(self.collision_ui,"collision") + tab.addTab(self.visual_ui,"visual") + + self.splitter.addWidget(self.view) + self.splitter.addWidget(tab) + + + def config(self): - self.ModelEditorUi.link_tree.clicked[QModelIndex].connect(self.on_tree_item) + self.view.clicked[QModelIndex].connect(self.on_tree_item) + def on_tree_item(self,index): item = self.link_model.itemFromIndex(index) @@ -172,7 +204,7 @@ def setup(link_hierarchy,item): #seee parse_asm4_model.py for child in link_hierarchy: name=child["name"] - row=ModelItem(self.ModelEditorUi,child["name"],child['type']) + row=ModelItem(self,child["name"],child['type']) item.appendRow(row) #make reference to the index of referenced link #This assumes the link already exists in the referenced_elems dictionary diff --git a/robot_descriptor/sdf_elements/collision.py b/robot_descriptor/sdf_elements/collision.py index 36da718..7533bab 100644 --- a/robot_descriptor/sdf_elements/collision.py +++ b/robot_descriptor/sdf_elements/collision.py @@ -38,7 +38,7 @@ def collison_max_contacts_cb(self): class collison: - def __init__(self,parent_ui): + def __init__(self,parent_ui=None): #model editor ui self.ui=parent_ui self.tag='collision' @@ -49,39 +49,34 @@ def __init__(self,parent_ui): #surface element self.surface_ui=FreeCADGui.PySideUic.loadUi(os.path.join(common.UI_PATH,"surface.ui")) self.surface_cls=surface.surface(self.surface_ui) - #add widget to parent - self.ui.collision_scroll.setWidget(self.surface_ui.widget) - + self.ui.collision_scroll.setWidget(self.surface_ui) self.configUI() self.updateUI() - def get_default_elem(self): - default_el=copy.deepcopy(self.collision_elem) - default_el.append(self.surface_cls.get_default_elem()) - return default_el - + def update_elements(self,item): + self.collision_elem=item.collision_element + self.surface_cls.update_element(item) + self.updateUI() + def configUI(self): - self.ui.collision_max_contacts_sp.valueChanged.connect( - lambda value,collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"max_contacts",False,self.properties.max_contacts) - ) + self.ui.collision_max_contacts_sp.valueChanged.connect(self.on_max_contacts) self.ui.collision_laser_retro_sp.valueChanged.connect( - lambda value,collision_elem=self.collision_elem: common.set_xml_data(collision_elem,"laser_retro",False,self.properties.laser_retro) + lambda value: common.set_xml_data(self.collision_elem,"laser_retro",False,self.properties.laser_retro) ) +#callabcks + + def on_max_contacts(self): + common.set_xml_data(self.collision_elem,"max_contacts",False,self.properties.max_contacts) + +#end callbacks + def updateUI(self): data=["max_contacts","laser_retro"] for item in data: setattr(self.properties,item,common.get_xml_data(self.collision_elem,item,False)) - def update_elem(self,elem:ET.Element): - surf=elem.find("surface") - if surf is not None: - self.surface_cls.update_elem(surf) - self.collision_elem=elem - else: - FreeCAD.Console.PrintDeveloperWarning("collision surf is none \n") - #update ui after element updates - self.updateUI() + def reset(self): pass diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py index 4367555..ddf39f7 100644 --- a/robot_descriptor/sdf_elements/link.py +++ b/robot_descriptor/sdf_elements/link.py @@ -6,7 +6,8 @@ import xml.etree.ElementTree as ET import FreeCADGui import os - +from PySide2.QtWidgets import QTreeView +from PySide2.QtGui import QStandardItemModel class link_properties: def __init__(self,ui) -> None: @@ -252,6 +253,7 @@ def __init__(self,parent_ui,elem_struct=None): self.ui=parent_ui self.file_name='link.sdf' self.tag='link' + #models will be store as children of sdf self.parent_path=['sdf','model'] self.properties=link_properties(self.ui) @@ -262,17 +264,12 @@ def __init__(self,parent_ui,elem_struct=None): self._root_dict=elem_struct self.configUI() self.UpdateUi() - - def get_default_elem(self): - default_el=copy.deepcopy(self.link_element) - default_el.append(copy.deepcopy(self._inertial_element)) - return default_el - - def update_elem(self,new_elem:ET.Element): - inertial=new_elem.find("inertial") - if inertial is not None: - self.link_element=new_elem - self._inertial_element=inertial +# this will be called for the item + + def update_elements(self,item): + self.link_element=item._link_element + self._inertial_element=item._inertial_element + #update the ui after reset self.UpdateUi() def configUI(self): @@ -283,38 +280,38 @@ def configUI(self): self.ui.velocity_decay_linear_sp.valueChanged.connect(self.onLinear) self.ui.link_angular_vel_decay_sp.valueChanged.connect(self.onAngular) #inertial - # fam=self.link_element.find(".//inertia/fluid_added_mass") + # fam=self._inertial_element.find(".//fluid_added_mass") # fam every time the lmbda is called fam gets updated - self.ui.fam_xx_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xx',False,self.properties.fam_xx) ) - self.ui.fam_xy_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xy',False,self.properties.fam_xy) ) - self.ui.fam_xz_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xz',False,self.properties.fam_xz) ) + self.ui.fam_xx_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xx',False,self.properties.fam_xx) ) + self.ui.fam_xy_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xy',False,self.properties.fam_xy) ) + self.ui.fam_xz_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xz',False,self.properties.fam_xz) ) - self.ui.fam_xp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xp',False,self.properties.fam_xp) ) - self.ui.fam_xq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xq',False,self.properties.fam_xq) ) - self.ui.fam_xr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'xr',False,self.properties.fam_xr) ) + self.ui.fam_xp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xp',False,self.properties.fam_xp) ) + self.ui.fam_xq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xq',False,self.properties.fam_xq) ) + self.ui.fam_xr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xr',False,self.properties.fam_xr) ) #y - self.ui.fam_yy_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yy',False,self.properties.fam_yy)) - self.ui.fam_yz_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yz',False,self.properties.fam_yz)) + self.ui.fam_yy_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yy',False,self.properties.fam_yy)) + self.ui.fam_yz_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yz',False,self.properties.fam_yz)) - self.ui.fam_yp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yp',False,self.properties.fam_yp)) - self.ui.fam_yq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yq',False,self.properties.fam_yq)) - self.ui.fam_yr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"):common.set_xml_data(fam,'yr',False,self.properties.fam_yr)) + self.ui.fam_yp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yp',False,self.properties.fam_yp)) + self.ui.fam_yq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yq',False,self.properties.fam_yq)) + self.ui.fam_yr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yr',False,self.properties.fam_yr)) #z - self.ui.fam_zz_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zz',False,self.properties.fam_zz)) - self.ui.fam_zp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zp',False,self.properties.fam_zp)) - self.ui.fam_zq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zq',False,self.properties.fam_zq)) - self.ui.fam_zr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'zr',False,self.properties.fam_zr)) + self.ui.fam_zz_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zz',False,self.properties.fam_zz)) + self.ui.fam_zp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zp',False,self.properties.fam_zp)) + self.ui.fam_zq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zq',False,self.properties.fam_zq)) + self.ui.fam_zr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zr',False,self.properties.fam_zr)) #p - self.ui.fam_pp_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pp',False,self.properties.fam_pp)) - self.ui.fam_pq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pq',False,self.properties.fam_pq)) - self.ui.fam_pr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'pr',False,self.properties.fam_pr)) + self.ui.fam_pp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'pp',False,self.properties.fam_pp)) + self.ui.fam_pq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'pq',False,self.properties.fam_pq)) + self.ui.fam_pr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'pr',False,self.properties.fam_pr)) - self.ui.fam_qq_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qq',False,self.properties.fam_qq)) - self.ui.fam_qr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'qr',False,self.properties.fam_qr)) - self.ui.fam_rr_sp.valueChanged.connect(lambda val,fam=self.link_element.find(".//inertia/fluid_added_mass"): common.set_xml_data(fam,'rr',False,self.properties.fam_rr)) + self.ui.fam_qq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'qq',False,self.properties.fam_qq)) + self.ui.fam_qr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'qr',False,self.properties.fam_qr)) + self.ui.fam_rr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'rr',False,self.properties.fam_rr)) diff --git a/robot_descriptor/sdf_elements/material.py b/robot_descriptor/sdf_elements/material.py index cc53680..e4d05d8 100644 --- a/robot_descriptor/sdf_elements/material.py +++ b/robot_descriptor/sdf_elements/material.py @@ -210,8 +210,7 @@ def metal_light_map(self,text): #metal_uv_set @property def metal_uv_set(self): - def metal_uv_set(self): - return self.ui.metal_uv_set_sp.value() + return self.ui.metal_uv_set_sp.value() @metal_uv_set.setter def metal_uv_set(self,value): self.ui.metal_uv_set_sp.setValue(value) @@ -429,11 +428,8 @@ def __init__(self,ui) -> None: self.configUI() # self.reset(default=False) - def get_default_elem(self): - return copy.deepcopy(self._material_element) - - def update_elem(self,new_elem:ET.Element): - self._material_element=new_elem + def update_elements(self,item): + self._material_element=item._material_element self.updateUi() def configUI(self): diff --git a/robot_descriptor/sdf_elements/surface.py b/robot_descriptor/sdf_elements/surface.py index 30467d7..97a4162 100644 --- a/robot_descriptor/sdf_elements/surface.py +++ b/robot_descriptor/sdf_elements/surface.py @@ -421,8 +421,6 @@ def __init__(self,ui) -> None: self.configUI() self.updateUI() - def get_default_elem(self): - return copy.deepcopy(self.surface_element) def configUI(self): #bounce @@ -435,39 +433,39 @@ def configUI(self): #torsional # torsional=self.surface_element.find(".//friction/torsional") - self.ui.torsional_coeff_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): - common.set_xml_data(torsional,"coefficient",False,self.properties.coefficient)) - self.ui.use_patch_radius_cb.stateChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): - common.set_xml_data(torsional,"use_patch_radius",False,self.properties.use_patch_radius)) + self.ui.torsional_coeff_sp.valueChanged.connect(lambda val: + common.set_xml_data(self.surface_element.find(".//friction/torsional"),"coefficient",False,self.properties.coefficient)) + self.ui.use_patch_radius_cb.stateChanged.connect(lambda val: + common.set_xml_data(self.surface_element.find(".//friction/torsional"),"use_patch_radius",False,self.properties.use_patch_radius)) - self.ui.torsional_patch_radius_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): - common.set_xml_data(torsional,"patch_radius",False,self.properties.patch_radius)) + self.ui.torsional_patch_radius_sp.valueChanged.connect(lambda val: + common.set_xml_data(self.surface_element.find(".//friction/torsional"),"patch_radius",False,self.properties.patch_radius)) - self.ui.torsional_surface_radius_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): - common.set_xml_data(torsional,"surface_radius",False,self.properties.surface_radius)) + self.ui.torsional_surface_radius_sp.valueChanged.connect(lambda val: + common.set_xml_data(self.surface_element.find(".//friction/torsional"),"surface_radius",False,self.properties.surface_radius)) - self.ui.torsional_ode_slip_sp.valueChanged.connect(lambda val,torsional=self.surface_element.find(".//friction/torsional"): - common.set_xml_data(torsional,"slip",False,self.properties.torsional_slip)) + self.ui.torsional_ode_slip_sp.valueChanged.connect(lambda val: + common.set_xml_data(self.surface_element.find(".//friction/torsional"),"slip",False,self.properties.torsional_slip)) #frictional_ode # frictional_ode=self.surface_element.find(".//friction/ode") - self.ui.surface_ode_mu_sp.valueChanged.connect(lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): - common.set_xml_data(frictional_ode,"mu",False,self.properties.friction_ode_mu)) + self.ui.surface_ode_mu_sp.valueChanged.connect(lambda val: + common.set_xml_data(self.surface_element.find(".//friction/ode"),"mu",False,self.properties.friction_ode_mu)) self.ui.surface_ode_mu2_sp.valueChanged.connect( - lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): - common.set_xml_data(frictional_ode,"mu2",False,self.properties.friction_ode_mu2) + lambda val: + common.set_xml_data(self.surface_element.find(".//friction/ode"),"mu2",False,self.properties.friction_ode_mu2) ) self.ui.surface_ode_slip1_sp.valueChanged.connect( - lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): - common.set_xml_data(frictional_ode,"slip1",False,self.properties.friction_ode_slip1) + lambda val: + common.set_xml_data(self.surface_element.find(".//friction/ode"),"slip1",False,self.properties.friction_ode_slip1) ) self.ui.surface_ode_slip2_sp.valueChanged.connect( - lambda val,frictional_ode=self.surface_element.find(".//friction/ode"): - common.set_xml_data(frictional_ode,"slip2",False,self.properties.friction_ode_slip2) + lambda val: + common.set_xml_data(self.surface_element.find(".//friction/ode"),"slip2",False,self.properties.friction_ode_slip2) ) self.ui.surface_ode_fdir1_x_sp.valueChanged.connect(self.ode_fdir1) @@ -477,16 +475,16 @@ def configUI(self): #frictional_bullet # frictional_bullet=self.surface_element.find(".//fiction/bullet") self.ui.surface_bullet_friction_sp.valueChanged.connect( - lambda val,frictional_bullet=self.surface_element.find(".//friction/bullet"): - common.set_xml_data(frictional_bullet,"friction",False,self.properties.friction_bullet_friction)) + lambda val: + common.set_xml_data(self.surface_element.find(".//friction/bullet"),"friction",False,self.properties.friction_bullet_friction)) self.ui.surface_bullet_friction2_sp.valueChanged.connect( - lambda val,frictional_bullet=self.surface_element.find(".//friction/bullet"): - common.set_xml_data(frictional_bullet,"friction2",False,self.properties.friction_bullet_friction2) + lambda val: + common.set_xml_data(self.surface_element.find(".//friction/bullet"),"friction2",False,self.properties.friction_bullet_friction2) ) self.ui.surface_bullet_rolling_friction_sp.valueChanged.connect( - lambda val,frictional_bullet=self.surface_element.find(".//friction/bullet"): - common.set_xml_data(frictional_bullet,"rolling_friction",False,self.properties.friction_bullet_rolling_friction) + lambda val: + common.set_xml_data(self.surface_element.find(".//friction/bullet"),"rolling_friction",False,self.properties.friction_bullet_rolling_friction) ) @@ -621,6 +619,7 @@ def on_contact_collide_without_contact_bitmask(self): common.set_xml_data(contact,"collide_without_contact_bitmask",False,self.properties.collide_without_contact_bitmask) def on_contact_collide_bitmask(self): + contact=self.surface_element.find(".//contact") common.set_xml_data(contact,"collide_bitmask",False,self.properties.collide_bitmask) @@ -672,7 +671,7 @@ def updateUI(self): #contact contact=self.surface_element.find(".//contact") contact_pairs={"collide_without_contact":"collide_without_contact","collide_without_contact_bitmask":"collide_without_contact_bitmask", - "category_bitmask":"category_bitmask","poissons_ratio":"poissons_ratio", + "category_bitmask":"category_bitmask","poissons_ratio":"poissons_ratio","collide_bitmask":"collide_bitmask", "elastic_modulus":"elastic_modulus"} for tag in contact_pairs.keys(): setattr(self.properties,contact_pairs[tag],common.get_xml_data(contact,tag,False)) @@ -704,8 +703,8 @@ def updateUI(self): def reset(self): pass - def update_elem(self,elem:ET.Element): - self.surface_element=elem + def update_element(self,item): + self.surface_element=item.surface_element self.updateUI() #return element diff --git a/robot_descriptor/sdf_elements/visual.py b/robot_descriptor/sdf_elements/visual.py index 99bfd47..16ef662 100644 --- a/robot_descriptor/sdf_elements/visual.py +++ b/robot_descriptor/sdf_elements/visual.py @@ -14,7 +14,7 @@ def __init__(self,ui): #shadows @property def cast_shadows(self): - return str('true') if self.ui.visual_cast_shadows_checkBox.isCheked() else str('false') + return str('true') if self.ui.visual_cast_shadows_checkBox.isChecked() else str('false') @cast_shadows.setter def cast_shadows(self,state): self.ui.visual_cast_shadows_checkBox.setCheckState(QtCore.Qt.Checked) if state=='true' else self.ui.visual_cast_shadows_checkBox.setCheckState(QtCore.Qt.Unchecked) @@ -70,13 +70,11 @@ def __init__(self,parent_ui): self._material_cls=material.material(self._material_ui) #add widget to parent widget self.ui.material_scroll.setWidget(self._material_ui.widget) + self.configUI() self.updateUI() - - def get_default_elem(self): - default_el=copy.deepcopy(self._visual_elem) - default_el.append(self._material_cls.get_default_elem()) - return default_el - + + + def configUI(self): self.ui.visual_laser_retro_sp.valueChanged.connect(self.on_laser_retro) self.ui.visual_transparency_sp.valueChanged.connect(self.on_transparency) @@ -84,16 +82,20 @@ def configUI(self): self.ui.visual_cast_shadows_checkBox.stateChanged.connect(self.on_cast_shadows) def on_laser_retro(self): - common.set_xml_data(self._visual_elem,"laser_retro",False,self.properties.laser_retro) + element=self._visual_elem + common.set_xml_data(element,"laser_retro",False,self.properties.laser_retro) def on_transparency(self): - common.set_xml_data(self._visual_elem,"transparency",False,self.properties.transparency) + element=self._visual_elem + common.set_xml_data(element,"transparency",False,self.properties.transparency) def on_visibility_flags(self): - common.set_xml_data(self._visual_elem,"visibility_flags",False,self.properties.visibility_flags) + element=self._visual_elem + common.set_xml_data(element,"visibility_flags",False,self.properties.visibility_flags) def on_cast_shadows(self): - common.set_xml_data(self._visual_elem,"cast_shadows",False,self.properties.cast_shadows) + element=self._visual_elem + common.set_xml_data(element,"cast_shadows",False,self.properties.cast_shadows) def updateUI(self): @@ -104,11 +106,9 @@ def updateUI(self): # self.properties.visibility_flags=common.get_xml_data(self._visual_elem,"visibility_flags",False) self.properties.cast_shadows=common.get_xml_data(self._visual_elem,"cast_shadows",False) - def update_elem(self,new_elem:ET.Element): - mat=new_elem.find("material") - if mat is not None: - self._material_cls.update_elem(mat) - self._visual_elem=new_elem + def update_elements(self,item): + self._visual_elem=item._visual_element + self._material_cls.update_elements(item) self.updateUI() @property diff --git a/robot_descriptor/sdf_elements/world.py b/robot_descriptor/sdf_elements/world.py index dc5154b..f825281 100644 --- a/robot_descriptor/sdf_elements/world.py +++ b/robot_descriptor/sdf_elements/world.py @@ -104,7 +104,7 @@ def wind(self,wind_vec:list)->bool: #------------------------------------------------------ class world(): def __init__(self): - super(world,self).__init__() + self.parent_path=["sdf"] self.tag='world' self.file_name="world.sdf" From cb768e44e547d8efe1b38fba600671d1e3dab8e6 Mon Sep 17 00:00:00 2001 From: Joseph Mbayi Date: Tue, 6 Feb 2024 08:42:52 +0300 Subject: [PATCH 9/9] changed lamda functions --- robot_descriptor/RD_utils/parse_asm4_model.py | 3 ++ robot_descriptor/icons/link24.png | Bin 0 -> 747 bytes robot_descriptor/icons/ref24.png | Bin 0 -> 544 bytes robot_descriptor/model_editor.py | 17 ++++--- robot_descriptor/sdf_elements/link.py | 44 +++++++++--------- 5 files changed, 37 insertions(+), 27 deletions(-) create mode 100644 robot_descriptor/icons/link24.png create mode 100644 robot_descriptor/icons/ref24.png diff --git a/robot_descriptor/RD_utils/parse_asm4_model.py b/robot_descriptor/RD_utils/parse_asm4_model.py index 288e491..45381e5 100644 --- a/robot_descriptor/RD_utils/parse_asm4_model.py +++ b/robot_descriptor/RD_utils/parse_asm4_model.py @@ -93,3 +93,6 @@ def create_structure(data,dest): return structured_data +def get_pose_info(): + pass + diff --git a/robot_descriptor/icons/link24.png b/robot_descriptor/icons/link24.png new file mode 100644 index 0000000000000000000000000000000000000000..77ecc245f415a3d21a2fc276d2927ba429cd1142 GIT binary patch literal 747 zcmVpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10(eP8 zK~zYIwUj?hQ&AMgf9LUDiAjOiDrLh&2p}T3)%tmIx-9N=Kz1MyemT#TaG?Q}83`a^C&A<@gy3{>!n z#t1e7S1r8OGwABtDeV&;Xar}nkg^_oP{43myp`{lC2-MGps&v1Wb!=^@q?t|g#3B) zMFN8c9N0=(Hb9^WWTvneAu|C?TI3=CD;#W4$oOzBQw^wO^mx?=4S=I zD4Z{nJq6kX5N3WBxKZqYn+V2{>MZt%K)}z>9{^dbQQ%~fK<5^=7T{Y6_{{-v#J7q) z?7^=(GX0%s4j@W;#lwqu7{C8%>w=)CJ&ZTy0ye&iB*BNE4QZU{b=2K%!}tV=48`2SMnpQhyb)% z;A1Is6FaVuo5Q(Win1sH@Kxb>F+mKmEbM0jI)~G@6Z4G#m)sC=HbJnXa4|)FO$d8L z!EkXd?bI9!UQq(OTaYKf3t&o-MnU@pO=VfUS?ZIkC}1t5CM1~spe-QZ1$o}X!t`#8 diw5jR{RKlu?ulX8-lqTn002ovPDHLkV1mPrMyLP) literal 0 HcmV?d00001 diff --git a/robot_descriptor/icons/ref24.png b/robot_descriptor/icons/ref24.png new file mode 100644 index 0000000000000000000000000000000000000000..a4a3599436b6cb4dd0691462bc1175bd7adabf0e GIT binary patch literal 544 zcmV+*0^j|KP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10j)_y zK~zYIwbeUoltC26@!xr~cmY8Sq85TEXd{Zr#t0D!f|b~KA&mjQfMp~WegG|O?ZiT` zFqVpqHX3swyHT+eEyTjwMi7%@kt}Y^Zr;shA9!JyIrD$!%sIRhnW>v9HneLt_7l-P zgNp0wX3WJcZs%~%@{ynT-~dsYukE*hR&;aV>S+M-e4{c2)!*@GRN3)Q^TnZaBfS9pxR66i{$iw5!~Yh6)2ZYb2&4To^G zF|4!(d9&6X!h<2YxVUeyfTX$fC+!I}KtJo&H4^*DjSrnPqpxAf(7NjC5S*PPBT z|1UIWFw!)>=d0n4;OUXyhE!L>S=pwIU+;a@yscV_{)RCFIk9F`X3D2}vgT*jOlB%F z)0*FVM{~-~(zwj!3=TVlUBXy%2ej3x{9GEdtVRv?N^kY&Os5;yXHeKDJlkqGjUq4j i=#Qyx7?i&Uo77+aou>zQ1F>@e0000 Any: #model editor -class ModelEditor(QWidget): +class ModelEditor(QDialog): def __init__(self,elem_struct): @@ -152,10 +156,11 @@ def __init__(self,elem_struct): #set view model self.view.setModel(self.link_model) + #select the first item mdl_idx0=self.link_model.index(0,0,self.view.rootIndex()) self.view.selectionModel().select(mdl_idx0,QItemSelectionModel.Select) #display dialog - self.show() + self.exec_() #end __init__() diff --git a/robot_descriptor/sdf_elements/link.py b/robot_descriptor/sdf_elements/link.py index ddf39f7..47bf6e8 100644 --- a/robot_descriptor/sdf_elements/link.py +++ b/robot_descriptor/sdf_elements/link.py @@ -282,36 +282,38 @@ def configUI(self): #inertial # fam=self._inertial_element.find(".//fluid_added_mass") # fam every time the lmbda is called fam gets updated - self.ui.fam_xx_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xx',False,self.properties.fam_xx) ) - self.ui.fam_xy_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xy',False,self.properties.fam_xy) ) - self.ui.fam_xz_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xz',False,self.properties.fam_xz) ) + #the lambda expression captures self ,therefore updates made to all local variables of self will reflected for + # each lambda call + self.ui.fam_xx_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'xx',False,self.properties.fam_xx) ) + self.ui.fam_xy_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'xy',False,self.properties.fam_xy) ) + self.ui.fam_xz_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'xz',False,self.properties.fam_xz) ) - self.ui.fam_xp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xp',False,self.properties.fam_xp) ) - self.ui.fam_xq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xq',False,self.properties.fam_xq) ) - self.ui.fam_xr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'xr',False,self.properties.fam_xr) ) + self.ui.fam_xp_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'xp',False,self.properties.fam_xp) ) + self.ui.fam_xq_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'xq',False,self.properties.fam_xq) ) + self.ui.fam_xr_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'xr',False,self.properties.fam_xr) ) #y - self.ui.fam_yy_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yy',False,self.properties.fam_yy)) - self.ui.fam_yz_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yz',False,self.properties.fam_yz)) + self.ui.fam_yy_sp.valueChanged.connect(lambda val:common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'yy',False,self.properties.fam_yy)) + self.ui.fam_yz_sp.valueChanged.connect(lambda val:common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'yz',False,self.properties.fam_yz)) - self.ui.fam_yp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yp',False,self.properties.fam_yp)) - self.ui.fam_yq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yq',False,self.properties.fam_yq)) - self.ui.fam_yr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"):common.set_xml_data(fam,'yr',False,self.properties.fam_yr)) + self.ui.fam_yp_sp.valueChanged.connect(lambda val:common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'yp',False,self.properties.fam_yp)) + self.ui.fam_yq_sp.valueChanged.connect(lambda val:common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'yq',False,self.properties.fam_yq)) + self.ui.fam_yr_sp.valueChanged.connect(lambda val:common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'yr',False,self.properties.fam_yr)) #z - self.ui.fam_zz_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zz',False,self.properties.fam_zz)) - self.ui.fam_zp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zp',False,self.properties.fam_zp)) - self.ui.fam_zq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zq',False,self.properties.fam_zq)) - self.ui.fam_zr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'zr',False,self.properties.fam_zr)) + self.ui.fam_zz_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'zz',False,self.properties.fam_zz)) + self.ui.fam_zp_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'zp',False,self.properties.fam_zp)) + self.ui.fam_zq_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'zq',False,self.properties.fam_zq)) + self.ui.fam_zr_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'zr',False,self.properties.fam_zr)) #p - self.ui.fam_pp_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'pp',False,self.properties.fam_pp)) - self.ui.fam_pq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'pq',False,self.properties.fam_pq)) - self.ui.fam_pr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'pr',False,self.properties.fam_pr)) + self.ui.fam_pp_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'pp',False,self.properties.fam_pp)) + self.ui.fam_pq_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'pq',False,self.properties.fam_pq)) + self.ui.fam_pr_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'pr',False,self.properties.fam_pr)) - self.ui.fam_qq_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'qq',False,self.properties.fam_qq)) - self.ui.fam_qr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'qr',False,self.properties.fam_qr)) - self.ui.fam_rr_sp.valueChanged.connect(lambda val,fam=self._inertial_element.find(".//fluid_added_mass"): common.set_xml_data(fam,'rr',False,self.properties.fam_rr)) + self.ui.fam_qq_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'qq',False,self.properties.fam_qq)) + self.ui.fam_qr_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'qr',False,self.properties.fam_qr)) + self.ui.fam_rr_sp.valueChanged.connect(lambda val: common.set_xml_data(self._inertial_element.find(".//fluid_added_mass"),'rr',False,self.properties.fam_rr))