From 04ec1c8180733447988227c6e29862acf8d4b791 Mon Sep 17 00:00:00 2001 From: Yinoussa Adagolodjo Date: Fri, 15 Nov 2024 18:10:38 +0100 Subject: [PATCH] enhance and restructure FEM mesh handling and visualization Added new functions attach_mesh_with_springs, attach_3d_points_to_meca_with_barycentric_mapping, and add_finger_mesh_force_field_Object to modularize and simplify FEM mesh handling and visualization. Introduced show_mecha_visual for toggling visibility of mechanical objects and indices. Replaced addFEMObject with add_finger_mesh_force_field_Object for improved clarity and functionality. Updated tuto_5.py to utilize new FEM mesh functions, enabling better integration and enhanced visualization. Removed redundant code and refactored solver and geometry attachment logic for better maintainability. --- examples/python3/useful/header.py | 48 ++++++++++++++++--------------- tutorial/tuto_scenes/tuto_5.py | 18 +++++++++--- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/examples/python3/useful/header.py b/examples/python3/useful/header.py index a1068794..d353195e 100644 --- a/examples/python3/useful/header.py +++ b/examples/python3/useful/header.py @@ -17,7 +17,9 @@ import os from useful.params import ContactParameters as DefaultContactParams - +def show_mecha_visual(node, show=True): + node.showObject = show + node.showIndices = show def addHeader(parent_node, multithreading=False, inverse=False, is_constrained=False, is_contact=False, contact_params=None): """ @@ -152,44 +154,44 @@ def addSolverNode(parent_node, name='solverNode', template='CompressedRowSparseM return solver_node +def attach_mesh_with_springs(mesh_node, _box='-18 -15 -8 2 -3 8'): + mesh_node.addObject('BoxROI', name='ROI1', box=_box, drawBoxes='true') + mesh_node.addObject('RestShapeSpringsForceField', + points='@ROI1.indices', stiffness='1e12') + +def attach_3d_points_to_meca_with_barycentric_mapping(parent_node, name='node_name', + list_of_points=[" 0.0 0 0 15 0 0 30 0 0 45 0 0 60 0 0 66 0 0 81 0.0 0.0"]): + points_node = parent_node.addChild(name) + points_node.addObject('MechanicalObject', name=name+"_mo", position=list_of_points) + points_node.addObject('BarycentricMapping') + return points_node -def addFEMObject(parent_node, path, name='FEMFinger'): - finger_solver = addSolverNode(parent_node, name=name) +def add_finger_mesh_force_field_Object(parent_node, path): + parent_node.addObject('VisualStyle', displayFlags='showForceFields') + #finger_solver = addSolverNode(parent_node, name=name) # Load a VTK tetrahedral mesh and expose the resulting topology in the scene . - loader = finger_solver.addObject('MeshVTKLoader', name='loader', filename=f'{path}finger.vtk', + loader = parent_node.addObject('MeshVTKLoader', name='loader', filename=f'{path}finger.vtk', translation="-17.5 -12.5 7.5", rotation="0 180 0") - finger_solver.addObject('TetrahedronSetTopologyContainer', position=loader.position.getLinkPath(), + parent_node.addObject('TetrahedronSetTopologyContainer', position=loader.position.getLinkPath(), tetras=loader.tetras.getLinkPath(), name='container') # Create a MechanicalObject component to stores the DoFs of the model - finger_solver.addObject('MechanicalObject', template='Vec3', name='dofs') + parent_node.addObject('MechanicalObject', template='Vec3', name='dofs') # Gives a mass to the model - finger_solver.addObject('UniformMass', totalMass='0.075') + parent_node.addObject('UniformMass', totalMass='1.75') # Add a TetrahedronFEMForceField component which implement an elastic material model # solved using the Finite Element Method on # tetrahedrons. - finger_solver.addObject('TetrahedronFEMForceField', template='Vec3d', name='forceField', method='large', + parent_node.addObject('TetrahedronFEMForceField', template='Vec3d', name='forceField', method='large', poissonRatio='0.45', youngModulus='500') + attach_mesh_with_springs(parent_node) - finger_solver.addObject('BoxROI', name='ROI1', box='-18 -15 -8 2 -3 8', drawBoxes='true') - finger_solver.addObject('RestShapeSpringsForceField', - points='@ROI1.indices', stiffness='1e12') - ########################################## - # Cable points # - ########################################## # Mapped points inside the finger volume, these points attached to the FE model # are constrained to slide on the cable. - - FEMpos = [" 0.0 0 0 15 0 0 30 0 0 45 0 0 60 0 0 66 0 0 81 0.0 0.0"] - fem_points = finger_solver.addChild('femPoints') - fem_points.addObject('MechanicalObject', name="pointsInFEM", position=FEMpos, showObject="1", - showIndices="1") - fem_points.addObject('BarycentricMapping') - - return finger_solver, fem_points - + points_node = attach_3d_points_to_meca_with_barycentric_mapping(parent_node) + return points_node def addMappedPoints(parent_node, name="pointsInFEM", position=None, showObject="1", showIndices="1", femPos="0.0 0 0 15 0 0 30 0 0 45 0 0 60 0 0 66 0 0 81 0.0 0.0"): diff --git a/tutorial/tuto_scenes/tuto_5.py b/tutorial/tuto_scenes/tuto_5.py index b37662fb..b34767c1 100644 --- a/tutorial/tuto_scenes/tuto_5.py +++ b/tutorial/tuto_scenes/tuto_5.py @@ -9,7 +9,7 @@ __copyright__ = "(c) 2021,Inria" __date__ = "October, 26 2021" -from useful.header import addHeader, addSolverNode, addFEMObject +from useful.header import addHeader, addSolverNode, add_finger_mesh_force_field_Object, show_mecha_visual from useful.params import BeamPhysicsParametersNoInertia, BeamGeometryParameters, SimulationParameters from useful.params import Parameters from cosserat.CosseratBase import CosseratBase @@ -19,6 +19,7 @@ import os from math import pi from controller import FingerController +from geo_cosserat_cable_driven_cosserat_beam import show_mecha_visual _beam_radius = 0.5 _beam_length = 81. @@ -100,9 +101,18 @@ def onKeypressedEvent(self, event): def createScene(root_node): - addHeader(root_node, is_constrained=True) + addHeader(root_node, is_constrained=False) root_node.gravity = [0, -9.81, 0.] + # Add FEM finger node + finger_node = addSolverNode(root_node, name="finger_node") + # this function attach the geometry and force field to predefine solver node + # It also fixe finger regarding predefine box + attached_3d_points_fem_node = add_finger_mesh_force_field_Object(finger_node, path=path) + show_mecha_visual(attached_3d_points_fem_node, show=True) + + return root_node + solver_node = addSolverNode(root_node, name="cable_node", isConstrained=is_constrained) # create cosserat Beam @@ -110,12 +120,12 @@ def createScene(root_node): cosserat_frames_node = cosserat_beam.cosseratFrame # Finger node - femFingerNode = root_node.addChild('femFingerNode') + #femFingerNode = root_node.addChild('femFingerNode') """ Add FEM finger to the scene""" # finger_node, fem_points_node = Finger(femFingerNode, name="Finger", rotation=array([0.0, 180.0, 0.0]), # translation=array([-17.5, -12.5, 7.5]), path=path) - finger_node, fem_points_node = addFEMObject(root_node, path=path, name="Finger") + return root_node