1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Radu Serban
13 // =============================================================================
14 //
15 // Chrono demonstration of using contact callbacks for smooth contacts
16 // (penalty-based).
17 //
18 // The global reference frame has Y up.
19 //
20 // =============================================================================
21
22 #include <cstdio>
23 #include <cmath>
24
25 #include "chrono/utils/ChUtilsCreators.h"
26 #include "chrono/physics/ChSystemSMC.h"
27
28 #include "chrono_irrlicht/ChIrrApp.h"
29
30 using namespace chrono;
31
32 // -----------------------------------------------------------------------------
33 // Callback class for contact reporting
34 // -----------------------------------------------------------------------------
35 class ContactReporter : public ChContactContainer::ReportContactCallback {
36 public:
ContactReporter(std::shared_ptr<ChBody> box1,std::shared_ptr<ChBody> box2)37 ContactReporter(std::shared_ptr<ChBody> box1, std::shared_ptr<ChBody> box2) : m_box1(box1), m_box2(box2) {}
38
39 private:
OnReportContact(const ChVector<> & pA,const ChVector<> & pB,const ChMatrix33<> & plane_coord,const double & distance,const double & eff_radius,const ChVector<> & cforce,const ChVector<> & ctorque,ChContactable * modA,ChContactable * modB)40 virtual bool OnReportContact(const ChVector<>& pA,
41 const ChVector<>& pB,
42 const ChMatrix33<>& plane_coord,
43 const double& distance,
44 const double& eff_radius,
45 const ChVector<>& cforce,
46 const ChVector<>& ctorque,
47 ChContactable* modA,
48 ChContactable* modB) override {
49 // Check if contact involves box1
50 if (modA == m_box1.get()) {
51 printf(" A contact on Box 1 at pos: %7.3f %7.3f %7.3f", pA.x(), pA.y(), pA.z());
52 } else if (modB == m_box1.get()) {
53 printf(" B contact on Box 1 at pos: %7.3f %7.3f %7.3f", pB.x(), pB.y(), pB.z());
54 }
55
56 // Check if contact involves box2
57 if (modA == m_box2.get()) {
58 printf(" A contact on Box 2 at pos: %7.3f %7.3f %7.3f", pA.x(), pA.y(), pA.z());
59 } else if (modB == m_box2.get()) {
60 printf(" B contact on Box 2 at pos: %7.3f %7.3f %7.3f", pB.x(), pB.y(), pB.z());
61 }
62
63 const ChVector<>& nrm = plane_coord.Get_A_Xaxis();
64 printf(" nrm: %7.3f, %7.3f %7.3f", nrm.x(), nrm.y(), nrm.z());
65 printf(" frc: %7.3f %7.3f %7.3f", cforce.x(), cforce.y(), cforce.z());
66 printf(" trq: %7.3f, %7.3f %7.3f", ctorque.x(), ctorque.y(), ctorque.z());
67 printf(" penetration: %8.4f eff. radius: %7.3f\n", distance, eff_radius);
68
69 return true;
70 }
71
72 std::shared_ptr<ChBody> m_box1;
73 std::shared_ptr<ChBody> m_box2;
74 };
75
76 // -----------------------------------------------------------------------------
77 // Callback class for modifying composite material
78 // -----------------------------------------------------------------------------
79 class ContactMaterial : public ChContactContainer::AddContactCallback {
80 public:
OnAddContact(const collision::ChCollisionInfo & contactinfo,ChMaterialComposite * const material)81 virtual void OnAddContact(const collision::ChCollisionInfo& contactinfo,
82 ChMaterialComposite* const material) override {
83 // Downcast to appropriate composite material type
84 auto mat = static_cast<ChMaterialCompositeSMC* const>(material);
85
86 // Set different friction for left/right halfs
87 float friction = (contactinfo.vpA.z() > 0) ? 0.3f : 0.8f;
88 mat->mu_eff = friction;
89 }
90 };
91
main(int argc,char * argv[])92 int main(int argc, char* argv[]) {
93 GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
94
95 // ----------------
96 // Parameters
97 // ----------------
98
99 float friction = 0.6f;
100
101 // -----------------
102 // Create the system
103 // -----------------
104
105 ChSystemSMC system;
106 system.Set_G_acc(ChVector<>(0, -10, 0));
107
108 // Set solver settings
109 system.SetSolverMaxIterations(100);
110 system.SetSolverForceTolerance(0);
111
112 // Change default collision effective radius of curvature
113 ////collision::ChCollisionInfo::SetDefaultEffectiveCurvatureRadius(1);
114
115 // --------------------------------------------------
116 // Create a contact material, shared among all bodies
117 // --------------------------------------------------
118
119 auto material = chrono_types::make_shared<ChMaterialSurfaceSMC>();
120 material->SetFriction(friction);
121
122 // ----------
123 // Add bodies
124 // ----------
125
126 auto container = std::shared_ptr<ChBody>(system.NewBody());
127 system.Add(container);
128 container->SetPos(ChVector<>(0, 0, 0));
129 container->SetBodyFixed(true);
130 container->SetIdentifier(-1);
131
132 container->SetCollide(true);
133 container->GetCollisionModel()->ClearModel();
134 utils::AddBoxGeometry(container.get(), material, ChVector<>(4, 0.5, 4), ChVector<>(0, -0.5, 0));
135 container->GetCollisionModel()->BuildModel();
136
137 container->AddAsset(chrono_types::make_shared<ChColorAsset>(ChColor(0.4f, 0.4f, 0.4f)));
138
139 auto box1 = std::shared_ptr<ChBody>(system.NewBody());
140 box1->SetMass(10);
141 box1->SetInertiaXX(ChVector<>(1, 1, 1));
142 box1->SetPos(ChVector<>(-1, 0.21, -1));
143 box1->SetPos_dt(ChVector<>(5, 0, 0));
144
145 box1->SetCollide(true);
146 box1->GetCollisionModel()->ClearModel();
147 utils::AddBoxGeometry(box1.get(), material, ChVector<>(0.4, 0.2, 0.1));
148 box1->GetCollisionModel()->BuildModel();
149
150 box1->AddAsset(chrono_types::make_shared<ChColorAsset>(ChColor(0.1f, 0.1f, 0.4f)));
151
152 system.AddBody(box1);
153
154 auto box2 = std::shared_ptr<ChBody>(system.NewBody());
155 box2->SetMass(10);
156 box2->SetInertiaXX(ChVector<>(1, 1, 1));
157 box2->SetPos(ChVector<>(-1, 0.21, +1));
158 box2->SetPos_dt(ChVector<>(5, 0, 0));
159
160 box2->SetCollide(true);
161 box2->GetCollisionModel()->ClearModel();
162 utils::AddBoxGeometry(box2.get(), material, ChVector<>(0.4, 0.2, 0.1));
163 box2->GetCollisionModel()->BuildModel();
164
165 box2->AddAsset(chrono_types::make_shared<ChColorAsset>(ChColor(0.4f, 0.1f, 0.1f)));
166
167 system.AddBody(box2);
168
169 // -------------------------------
170 // Create the visualization window
171 // -------------------------------
172
173 irrlicht::ChIrrApp application(&system, L"SMC callbacks", irr::core::dimension2d<irr::u32>(800, 600));
174 application.AddTypicalLogo();
175 application.AddTypicalSky();
176 application.AddTypicalLights();
177 application.AddTypicalCamera(irr::core::vector3df(4, 4, -6));
178
179 application.AssetBindAll();
180 application.AssetUpdateAll();
181
182 // ---------------
183 // Simulate system
184 // ---------------
185
186 auto creporter = chrono_types::make_shared<ContactReporter>(box1, box2);
187
188 auto cmaterial = chrono_types::make_shared<ContactMaterial>();
189 system.GetContactContainer()->RegisterAddContactCallback(cmaterial);
190
191 application.SetTimestep(1e-3);
192
193 while (application.GetDevice()->run()) {
194 application.BeginScene(true, true, irr::video::SColor(255, 140, 161, 192));
195 application.DrawAll();
196 irrlicht::tools::drawGrid(application.GetVideoDriver(), 0.5, 0.5, 12, 12,
197 ChCoordsys<>(ChVector<>(0, 0, 0), Q_from_AngX(CH_C_PI_2)));
198 irrlicht::tools::drawAllCOGs(system, application.GetVideoDriver(), 1.0);
199
200 application.DoStep();
201 application.EndScene();
202
203 // Process contacts
204 std::cout << system.GetChTime() << " " << system.GetNcontacts() << std::endl;
205 system.GetContactContainer()->ReportAllContacts(creporter);
206
207 // Cumulative contact force and torque on boxes (as applied to COM)
208 ChVector<> frc1 = box1->GetContactForce();
209 ChVector<> trq1 = box1->GetContactTorque();
210 printf(" Box 1 contact force at COM: %7.3f %7.3f %7.3f", frc1.x(), frc1.y(), frc1.z());
211 printf(" contact torque at COM: %7.3f %7.3f %7.3f\n", trq1.x(), trq1.y(), trq1.z());
212 ChVector<> frc2 = box2->GetContactForce();
213 ChVector<> trq2 = box2->GetContactTorque();
214 printf(" Box 2 contact force at COM: %7.3f %7.3f %7.3f", frc2.x(), frc2.y(), frc2.z());
215 printf(" contact torque at COM: %7.3f %7.3f %7.3f\n", trq2.x(), trq2.y(), trq2.z());
216 }
217
218 return 0;
219 }
220