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 // Demonstration of actuating a translational joint with a ChLinkForce.
16 // The model is built with gravity acting in the negative Y direction.
17 //
18 // Recall that Irrlicht uses a left-hand frame, so everything is rendered with
19 // left and right flipped.
20 //
21 // =============================================================================
22
23 #include <cmath>
24
25 #include "chrono/physics/ChSystemNSC.h"
26 #include "chrono/physics/ChBody.h"
27 #include "chrono/assets/ChPointPointDrawing.h"
28
29 #include "chrono_irrlicht/ChIrrApp.h"
30
31 using namespace chrono;
32 using namespace chrono::irrlicht;
33
main(int argc,char * argv[])34 int main(int argc, char* argv[]) {
35 GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
36
37 ChSystemNSC system;
38 system.Set_G_acc(ChVector<>(0, 0, 0));
39
40 // Create the ground body
41 auto ground = chrono_types::make_shared<ChBody>();
42 system.AddBody(ground);
43 ground->SetIdentifier(-1);
44 ground->SetBodyFixed(true);
45 ground->SetCollide(false);
46
47 auto rail1 = chrono_types::make_shared<ChBoxShape>();
48 rail1->GetBoxGeometry().SetLengths(ChVector<>(8, 0.1, 0.1));
49 rail1->GetBoxGeometry().Pos = ChVector<>(0, 0, -1);
50 ground->AddAsset(rail1);
51
52 auto rail2 = chrono_types::make_shared<ChBoxShape>();
53 rail2->GetBoxGeometry().SetLengths(ChVector<>(8, 0.1, 0.1));
54 rail2->GetBoxGeometry().Pos = ChVector<>(0, 0, +1);
55 ground->AddAsset(rail2);
56
57 auto col = chrono_types::make_shared<ChColorAsset>();
58 col->SetColor(ChColor(0.6f, 0.6f, 0.6f));
59 ground->AddAsset(col);
60
61 // Create the slider bodies
62 auto slider1 = chrono_types::make_shared<ChBody>();
63 system.AddBody(slider1);
64 slider1->SetIdentifier(1);
65 slider1->SetBodyFixed(false);
66 slider1->SetCollide(false);
67 slider1->SetMass(1);
68 slider1->SetInertiaXX(ChVector<>(0.1, 0.1, 0.1));
69 slider1->SetPos(ChVector<>(-4, 0, -1));
70
71 auto cyl1 = chrono_types::make_shared<ChCylinderShape>();
72 cyl1->GetCylinderGeometry().p1 = ChVector<>(-0.2, 0, 0);
73 cyl1->GetCylinderGeometry().p2 = ChVector<>(+0.2, 0, 0);
74 cyl1->GetCylinderGeometry().rad = 0.2;
75 slider1->AddAsset(cyl1);
76
77 auto col1 = chrono_types::make_shared<ChColorAsset>();
78 col1->SetColor(ChColor(0.6f, 0, 0));
79 slider1->AddAsset(col1);
80
81 auto slider2 = chrono_types::make_shared<ChBody>();
82 system.AddBody(slider2);
83 slider2->SetIdentifier(1);
84 slider2->SetBodyFixed(false);
85 slider2->SetCollide(false);
86 slider2->SetMass(1);
87 slider2->SetInertiaXX(ChVector<>(0.1, 0.1, 01));
88 slider2->SetPos(ChVector<>(-4, 0, +1));
89
90 auto cyl2 = chrono_types::make_shared<ChCylinderShape>();
91 cyl2->GetCylinderGeometry().p1 = ChVector<>(-0.2, 0, 0);
92 cyl2->GetCylinderGeometry().p2 = ChVector<>(+0.2, 0, 0);
93 cyl2->GetCylinderGeometry().rad = 0.2;
94 slider2->AddAsset(cyl2);
95
96 auto col2 = chrono_types::make_shared<ChColorAsset>();
97 col2->SetColor(ChColor(0, 0, 0.6f));
98 slider2->AddAsset(col2);
99
100 // Create prismatic joints between ground and sliders
101 auto prismatic1 = chrono_types::make_shared<ChLinkLockPrismatic>();
102 prismatic1->Initialize(slider1, ground, ChCoordsys<>(ChVector<>(0, 0, -1), Q_from_AngY(CH_C_PI_2)));
103 system.AddLink(prismatic1);
104
105 auto prismatic2 = chrono_types::make_shared<ChLinkLockPrismatic>();
106 prismatic2->Initialize(slider2, ground, ChCoordsys<>(ChVector<>(0, 0, +1), Q_from_AngY(CH_C_PI_2)));
107 system.AddLink(prismatic2);
108
109 // Sine function
110 double freq = 1;
111 double ampl = 4;
112 ////double omg = 2 * CH_C_PI * freq;
113 auto mod = chrono_types::make_shared<ChFunction_Sine>(0.0, freq, ampl);
114
115 // Actuate first slider using a link force
116 prismatic1->GetForce_Z().SetActive(true);
117 prismatic1->GetForce_Z().SetF(1);
118 prismatic1->GetForce_Z().SetModulationF(mod);
119
120 // Actuate second slider using a body force
121 auto frc2 = chrono_types::make_shared<ChForce>();
122 frc2->SetF_x(mod);
123 slider2->AddForce(frc2);
124
125 // Create the Irrlicht application
126 ChIrrApp application(&system, L"Actuated prismatic joint", irr::core::dimension2d<irr::u32>(800, 600));
127 application.AddTypicalLogo();
128 application.AddTypicalSky();
129 application.AddTypicalLights();
130 application.AddTypicalCamera(irr::core::vector3df(-1, 1.5, -6));
131
132 application.AssetBindAll();
133 application.AssetUpdateAll();
134
135 application.SetTimestep(1e-3);
136
137 // Simulation loop
138 ////double x0 = slider1->GetPos().x();
139 while (application.GetDevice()->run()) {
140 ////double time = system.GetChTime();
141
142 // Output slider x position/velocity and analytical solution
143 ////double x = slider1->GetPos().x();
144 ////double x_d = slider1->GetPos_dt().x();
145 ////double xa = x0 + (ampl / omg) * (time - std::sin(omg * time) / omg);
146 ////double xa_d = (ampl / omg) * (1 - std::cos(omg * time));
147 ////std::cout << time << " " << x << " " << x_d << " " << xa << " " << xa_d << std::endl;
148
149 application.BeginScene();
150 application.DrawAll();
151 tools::drawAllLinkframes(system, application.GetVideoDriver(), 1.0);
152 application.DoStep();
153 application.EndScene();
154 }
155
156 return 0;
157 }
158