NetDEM v1.0
Loading...
Searching...
No Matches
11_contact_test_trimesh.cpp

This is an example of how to use the netdem library.

#include "cork_wrapper.hpp"
#include "igl_wrapper.hpp"
#include "particle.hpp"
#include "utils_math.hpp"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
using namespace netdem;
using namespace std;
void SaveDataset(string filename, VecXT<VecXT<double>> &data);
double GetContactVolume(STLModel &stl_a, STLModel &stl_b, double z_coord) {
auto va = stl_a.vertices;
auto fa = stl_a.facets;
auto vb = stl_b.vertices;
auto fb = stl_b.facets;
for (auto &vert : vb) {
vert[2] += z_coord;
}
CorkWrapper::MeshIntersect(va, fa, vb, fb, &vab, &fab);
return STLModel::GetVolume(vab, fab);
}
void ContactTestTrimesh(int potential_case, int surface_node_num) {
// load particle
sh.InitFromSTL("data/particle_template.stl");
sh.SetSize(1.0);
auto surf_stl = sh.GetSTLModel(surface_node_num);
sh.SetSurfaceNodes(surf_stl);
cout << "shape size: " << sh.GetSize() << endl;
Particle obj_p1 = Particle(&sh);
Particle obj_p2 = Particle(&sh);
cout << "particle created ... " << endl;
// try another particle configuration
obj_p1.SetRodrigues(0.3, 0, 1, 0);
obj_p2.SetRodrigues(1.2, 0, 1, 0);
// obtain a mesh representation of the nodes
auto facets = surf_stl.facets;
auto nodes = sh.GetSurfaceNodes();
for (auto &vert : nodes) {
vert = Math::Rotate(vert, obj_p1.quaternion);
}
STLModel stl_model_1(nodes, facets);
nodes = sh.GetSurfaceNodes();
for (auto &vert : nodes) {
vert = Math::Rotate(vert, obj_p2.quaternion);
}
STLModel stl_model_2(nodes, facets);
// solver settings
SolverSDFPP cnt_solver;
cnt_solver.potential_type = potential_case;
LinearSpring cnt_model(1, 1, 0, 0);
ContactPP *cnt = nullptr;
// gradually push particle 2 onto particle 1
double pos_z0 = 1.015;
for (int i = 0; i < 61; i++) {
obj_p1.ClearForce();
obj_p1.ClearMoment();
obj_p2.ClearForce();
obj_p2.ClearMoment();
obj_p2.SetPosition(0, 0, pos_z0 - i * 0.001);
cnt_solver.Init(&obj_p2, &obj_p1);
if (cnt_solver.Detect()) {
if (cnt == nullptr) {
cnt = new ContactPP(&obj_p2, &obj_p1);
cnt->SetCollisionModel(&cnt_model);
cnt_solver.ResolveInit(cnt, 1.0e-4);
} else {
cnt_solver.ResolveUpdate(cnt, 1.0e-4);
}
cnt->EvaluateForces(1.0e-4);
double len_n = 1.0 - obj_p2.pos[2];
double vol = GetContactVolume(stl_model_1, stl_model_2, obj_p2.pos[2]);
cout << len_n << ", " << cnt->collision_entries.size() << ", "
<< obj_p2.force[0] << ", " << obj_p2.force[1] << ", "
<< obj_p2.force[2] << ", " << obj_p2.moment[0] << ", "
<< obj_p2.moment[1] << ", " << obj_p2.moment[2] << ", " << vol
<< endl;
cnt_data.push_back({len_n, double(cnt->collision_entries.size()),
obj_p2.force[0], obj_p2.force[1], obj_p2.force[2],
obj_p2.moment[0], obj_p2.moment[1], obj_p2.moment[2],
vol});
}
}
for (int i = 0; i < 61; i++) {
obj_p1.ClearForce();
obj_p1.ClearMoment();
obj_p2.ClearForce();
obj_p2.ClearMoment();
obj_p2.SetPosition(0, 0, pos_z0 - 60 * 0.001 + i * 0.001);
cnt_solver.Init(&obj_p2, &obj_p1);
if (cnt_solver.Detect()) {
if (cnt == nullptr) {
cnt = new ContactPP(&obj_p2, &obj_p1);
cnt->SetCollisionModel(&cnt_model);
cnt_solver.ResolveInit(cnt, 1.0e-4);
} else {
cnt_solver.ResolveUpdate(cnt, 1.0e-4);
}
cnt->EvaluateForces(1.0e-4);
double len_n = 1.0 - obj_p2.pos[2];
double vol = GetContactVolume(stl_model_1, stl_model_2, obj_p2.pos[2]);
cout << len_n << ", " << cnt->collision_entries.size() << ", "
<< obj_p2.force[0] << ", " << obj_p2.force[1] << ", "
<< obj_p2.force[2] << ", " << obj_p2.moment[0] << ", "
<< obj_p2.moment[1] << ", " << obj_p2.moment[2] << ", " << vol
<< endl;
cnt_data.push_back({len_n, double(cnt->collision_entries.size()),
obj_p2.force[0], obj_p2.force[1], obj_p2.force[2],
obj_p2.moment[0], obj_p2.moment[1], obj_p2.moment[2],
vol});
}
}
string root_dir = "tmp/examples/sdf_dem/contact_test/";
filesystem::create_directories(root_dir);
switch (potential_case) {
case SolverSDFPP::PotentialType::linear:
SaveDataset(root_dir + "trimesh_linear.txt", cnt_data);
break;
case SolverSDFPP::PotentialType::hertz:
SaveDataset(root_dir + "trimesh_hertz.txt", cnt_data);
break;
default:
SaveDataset(root_dir + "trimesh_hertz.txt", cnt_data);
break;
}
stl_model_1.SaveAsSTL(root_dir + "p1.stl");
for (auto &vert : stl_model_2.vertices) {
vert[2] += pos_z0 - 60 * 0.001;
}
stl_model_2.SaveAsSTL(root_dir + "p2.stl");
if (cnt != nullptr) {
delete cnt;
cnt = nullptr;
}
}
A class representing a contact between two particles.
Definition contact_pp.hpp:20
void SetCollisionModel(ContactModel *const cnt_model)
Set the collision model used to calculate collision forces between particles.
Definition contact_pp.cpp:22
void ApplyToParticle()
Apply the contact forces and moments to the particles.
Definition contact_pp.cpp:48
VecXT< CollisionEntry > collision_entries
A list of CollisionEntry objects representing the collision geometries used by the contact model.
Definition contact_pp.hpp:47
void EvaluateForces(double dt)
Calculate and apply the contact forces and moments between particles.
Definition contact_pp.cpp:30
Contact model that uses linear spring elements to evaluate contact forces and moments.
Definition model_linear_spring.hpp:16
Definition particle.hpp:26
virtual void ClearMoment()
Clear all moments applied to the particle.
Definition particle.cpp:180
virtual void SetRodrigues(double angle, double axis_x, double axis_y, double axis_z)
Sets the orientation of the particle using a Rodrigues rotation vector.
Definition particle.cpp:95
virtual void SetPosition(double pos_x, double pos_y, double pos_z)
Sets the position of the particle.
Definition particle.cpp:83
Vec4d quaternion
The quaternion of the particle.
Definition particle.hpp:108
Vec3d pos
The position of the particle.
Definition particle.hpp:103
virtual void ClearForce()
Clear all forces applied to the particle.
Definition particle.cpp:174
Vec3d moment
The moment acting on the particle.
Definition particle.hpp:138
Vec3d force
The force acting on the particle.
Definition particle.hpp:133
Class for working with STL models.
Definition stl_model.hpp:17
VecXT< Vec3i > facets
A M by 3 matrix. Each row defines a facet, with the row elements being the indices of the vertices.
Definition stl_model.hpp:28
VecXT< Vec3d > vertices
A N by 3 matrix that defines the points on the 3D model surface.
Definition stl_model.hpp:22
virtual void SetSurfaceNodes(VecXT< Vec3d > const &nodes)
Set the surface nodes of the shape.
Definition shape.cpp:308
virtual void EnableSurfaceNodes()
Enable the use of surface nodes.
Definition shape.cpp:284
virtual VecXT< Vec3d > const & GetSurfaceNodes() const
Return surface nodes of the shape.
Definition shape.cpp:189
virtual double GetSize() const
Return shape size, which is defined as the diameter of equal-volume sphere.
Definition shape.cpp:116
Signed distance field-based contact solver.
Definition solver_sdf_pp.hpp:19
void ResolveUpdate(ContactPP *const cnt, double timestep) override
Updates the contact resolution for a contact point.
Definition solver_sdf_pp.cpp:191
int potential_type
Whether to solve both sides of the collision.
Definition solver_sdf_pp.hpp:31
bool Detect() override
Detects collisions between particles.
Definition solver_sdf_pp.cpp:73
void ResolveInit(ContactPP *const cnt, double timestep) override
Initializes the contact resolution for a contact point.
Definition solver_sdf_pp.cpp:163
void Init(Particle *const p1, Particle *const p2) override
Initializes the collision solver with two particles.
Definition solver_sdf_pp.cpp:18
A class representing a spherical harmonics object.
Definition shape_spherical_harmonics.hpp:24
void InitFromSTL(std::string const &file)
Initialize the SphericalHarmonics object from an STL file.
void SetSize(double d) override
Set the size of the SphericalHarmonics object.
Definition shape_spherical_harmonics.cpp:175
STLModel GetSTLModel(int num_nodes=200) override
Generate an STL model for the SphericalHarmonics object.
Definition shape_spherical_harmonics.cpp:184
Definition bond_entry.hpp:7
std::vector< T > VecXT
Definition utils_macros.hpp:31
len_n
Definition json_serilization.hpp:20
vol
Definition json_serilization.hpp:23