// ----------------------------------------------------------------------------- // Calculate kinematics quantities (slip angle, longitudinal slip, camber angle, // and toe-in angle using the current state of the associated wheel body. // ----------------------------------------------------------------------------- void ChTire::CalculateKinematics(double time, const WheelState& state, const ChTerrain& terrain) { // Wheel normal (expressed in global frame) ChVector<> wheel_normal = state.rot.GetYaxis(); // Terrain normal at wheel location (expressed in global frame) ChVector<> Z_dir = terrain.GetNormal(state.pos.x(), state.pos.y()); // Longitudinal (heading) and lateral directions, in the terrain plane ChVector<> X_dir = Vcross(wheel_normal, Z_dir); X_dir.Normalize(); ChVector<> Y_dir = Vcross(Z_dir, X_dir); // Tire reference coordinate system ChMatrix33<> rot; rot.Set_A_axis(X_dir, Y_dir, Z_dir); ChCoordsys<> tire_csys(state.pos, rot.Get_A_quaternion()); // Express wheel linear velocity in tire frame ChVector<> V = tire_csys.TransformDirectionParentToLocal(state.lin_vel); // Express wheel normal in tire frame ChVector<> n = tire_csys.TransformDirectionParentToLocal(wheel_normal); // Slip angle double abs_Vx = std::abs(V.x()); double zero_Vx = 1e-4; m_slip_angle = (abs_Vx > zero_Vx) ? std::atan(V.y() / abs_Vx) : 0; // Longitudinal slip m_longitudinal_slip = (abs_Vx > zero_Vx) ? -(V.x() - state.omega * GetRadius()) / abs_Vx : 0; // Camber angle m_camber_angle = std::atan2(n.z(), n.y()); }
void ChLinkDistance::Update(double mytime, bool update_assets) { // Inherit time changes of parent class (ChLink), basically doing nothing :) ChLink::Update(mytime, update_assets); // compute jacobians ChVector<> AbsDist = Body1->TransformPointLocalToParent(pos1) - Body2->TransformPointLocalToParent(pos2); curr_dist = AbsDist.Length(); ChVector<> D2abs = Vnorm(AbsDist); ChVector<> D2relB = Body2->TransformDirectionParentToLocal(D2abs); ChVector<> D2relA = Body1->TransformDirectionParentToLocal(D2abs); ChVector<> CqAx = D2abs; ChVector<> CqBx = -D2abs; ChVector<> CqAr = -Vcross(D2relA, pos1); ChVector<> CqBr = Vcross(D2relB, pos2); Cx.Get_Cq_a()->ElementN(0) = CqAx.x(); Cx.Get_Cq_a()->ElementN(1) = CqAx.y(); Cx.Get_Cq_a()->ElementN(2) = CqAx.z(); Cx.Get_Cq_a()->ElementN(3) = CqAr.x(); Cx.Get_Cq_a()->ElementN(4) = CqAr.y(); Cx.Get_Cq_a()->ElementN(5) = CqAr.z(); Cx.Get_Cq_b()->ElementN(0) = CqBx.x(); Cx.Get_Cq_b()->ElementN(1) = CqBx.y(); Cx.Get_Cq_b()->ElementN(2) = CqBx.z(); Cx.Get_Cq_b()->ElementN(3) = CqBr.x(); Cx.Get_Cq_b()->ElementN(4) = CqBr.y(); Cx.Get_Cq_b()->ElementN(5) = CqBr.z(); //***TO DO*** C_dt? C_dtdt? (may be never used..) }
void ChMatterSPH::FillBox(const ChVector<> size, const double spacing, const double initial_density, const ChCoordsys<> boxcoords, const bool do_centeredcube, const double kernel_sfactor, const double randomness) { int samples_x = (int)(size.x() / spacing); int samples_y = (int)(size.y() / spacing); int samples_z = (int)(size.z() / spacing); int totsamples = 0; double mrandomness = randomness; if (do_centeredcube) mrandomness = randomness * 0.5; for (int ix = 0; ix < samples_x; ix++) for (int iy = 0; iy < samples_y; iy++) for (int iz = 0; iz < samples_z; iz++) { ChVector<> pos(ix * spacing - 0.5 * size.x(), iy * spacing - 0.5 * size.y(), iz * spacing - 0.5 * size.z()); pos += ChVector<>(mrandomness * ChRandom() * spacing, mrandomness * ChRandom() * spacing, mrandomness * ChRandom() * spacing); AddNode(boxcoords.TransformLocalToParent(pos)); totsamples++; if (do_centeredcube) { ChVector<> pos2 = pos + 0.5 * ChVector<>(spacing, spacing, spacing); pos2 += ChVector<>(mrandomness * ChRandom() * spacing, mrandomness * ChRandom() * spacing, mrandomness * ChRandom() * spacing); AddNode(boxcoords.TransformLocalToParent(pos2)); totsamples++; } } double mtotvol = size.x() * size.y() * size.z(); double mtotmass = mtotvol * initial_density; double nodemass = mtotmass / (double)totsamples; double kernelrad = kernel_sfactor * spacing; for (unsigned int ip = 0; ip < GetNnodes(); ip++) { // downcasting std::shared_ptr<ChNodeSPH> mnode(nodes[ip]); assert(mnode); mnode->SetKernelRadius(kernelrad); mnode->SetCollisionRadius(spacing * 0.05); mnode->SetMass(nodemass); } GetMaterial().Set_density(initial_density); }
// Get the X axis of a coordsystem, given the quaternion which // represents the alignment of the coordsystem. ChVector<double> VaxisXfromQuat(const ChQuaternion<double>& quat) { ChVector<double> res; res.x() = (pow(quat.e0(), 2) + pow(quat.e1(), 2)) * 2 - 1; res.y() = ((quat.e1() * quat.e2()) + (quat.e0() * quat.e3())) * 2; res.z() = ((quat.e1() * quat.e3()) - (quat.e0() * quat.e2())) * 2; return res; }
// ----------------------------------------------------------------------------- // Utility function for characterizing the geometric contact between a disc with // specified center location, normal direction, and radius and the terrain, // assumed to be specified as a height field (over the x-y domain). // This function returns false if no contact occurs. Otherwise, it sets the // contact points on the disc (ptD) and on the terrain (ptT), the normal contact // direction, and the resulting penetration depth (a positive value). // ----------------------------------------------------------------------------- bool ChTire::disc_terrain_contact(const ChTerrain& terrain, const ChVector<>& disc_center, const ChVector<>& disc_normal, double disc_radius, ChCoordsys<>& contact, double& depth) { // Find terrain height below disc center. There is no contact if the disc // center is below the terrain or farther away by more than its radius. double hc = terrain.GetHeight(disc_center.x(), disc_center.y()); if (disc_center.z() <= hc || disc_center.z() >= hc + disc_radius) return false; // Find the lowest point on the disc. There is no contact if the disc is // (almost) horizontal. ChVector<> dir1 = Vcross(disc_normal, ChVector<>(0, 0, 1)); double sinTilt2 = dir1.Length2(); if (sinTilt2 < 1e-3) return false; // Contact point (lowest point on disc). ChVector<> ptD = disc_center + disc_radius * Vcross(disc_normal, dir1 / sqrt(sinTilt2)); // Find terrain height at lowest point. No contact if lowest point is above // the terrain. double hp = terrain.GetHeight(ptD.x(), ptD.y()); if (ptD.z() > hp) return false; // Approximate the terrain with a plane. Define the projection of the lowest // point onto this plane as the contact point on the terrain. ChVector<> normal = terrain.GetNormal(ptD.x(), ptD.y()); ChVector<> longitudinal = Vcross(disc_normal, normal); longitudinal.Normalize(); ChVector<> lateral = Vcross(normal, longitudinal); ChMatrix33<> rot; rot.Set_A_axis(longitudinal, lateral, normal); contact.pos = ptD; contact.rot = rot.Get_A_quaternion(); depth = Vdot(ChVector<>(0, 0, hp - ptD.z()), normal); assert(depth > 0); return true; }
// Given the imaginary (vectorial) {e1 e2 e3} part of a quaternion time derivative, // find the entire quaternion q = {e0, e1, e2, e3}. // Note: singularities are possible. ChQuaternion<double> ImmQ_dt_complete(const ChQuaternion<double>& mq, const ChVector<double>& qimm_dt) { ChQuaternion<double> mqdt; mqdt.e1() = qimm_dt.x(); mqdt.e2() = qimm_dt.y(); mqdt.e3() = qimm_dt.z(); mqdt.e0() = (-mq.e1() * mqdt.e1() - mq.e2() * mqdt.e2() - mq.e3() * mqdt.e3()) / mq.e0(); return mqdt; }
// Given the imaginary (vectorial) {e1 e2 e3} part of a quaternion, // find the entire quaternion q = {e0, e1, e2, e3}. // Note: singularities are possible. ChQuaternion<double> ImmQ_complete(const ChVector<double>& qimm) { ChQuaternion<double> mq; mq.e1() = qimm.x(); mq.e2() = qimm.y(); mq.e3() = qimm.z(); mq.e0() = sqrt(1 - mq.e1() * mq.e1() - mq.e2() * mq.e2() - mq.e3() * mq.e3()); return mq; }
void Q_to_AngAxis(const ChQuaternion<double>& quat, double& angle, ChVector<double>& axis) { if (fabs(quat.e0()) < 0.99999999) { double arg = acos(quat.e0()); double invsine = 1 / sin(arg); ChVector<double> vtemp; vtemp.x() = invsine * quat.e1(); vtemp.y() = invsine * quat.e2(); vtemp.z() = invsine * quat.e3(); angle = 2 * arg; axis = Vnorm(vtemp); } else { axis.x() = 1; axis.y() = 0; axis.z() = 0; angle = 0; } }
void AddWall(std::shared_ptr<ChBody> body, const ChVector<>& dim, const ChVector<>& loc) { body->GetCollisionModel()->AddBox(dim.x(), dim.y(), dim.z(), loc); auto box = std::make_shared<ChBoxShape>(); box->GetBoxGeometry().Size = dim; box->GetBoxGeometry().Pos = loc; box->SetColor(ChColor(1, 0, 0)); box->SetFading(0.6f); body->AddAsset(box); }
// Get the quaternion time derivative from the vector of angular speed, with w specified in _local_ coords. ChQuaternion<double> Qdt_from_Wrel(const ChVector<double>& w, const ChQuaternion<double>& q) { ChQuaternion<double> qw; double half = 0.5; qw.e0() = 0; qw.e1() = w.x(); qw.e2() = w.y(); qw.e3() = w.z(); return Qscale(Qcross(q, qw), half); // {q_dt} = 1/2 {q}*{0,w_rel} }
// output any relevant test rig data here void drawWheelOutput() { ChVector<> cm = mwheel->wheel->GetPos(); char messageCM[100]; sprintf(messageCM, "CM pos, x: %4.4g, y: %4.4g, z: %4.4g", cm.x(), cm.y(), cm.z()); text_cmPos->setText(core::stringw(messageCM).c_str()); // wheel CM vel ChVector<> cmVel = mwheel->wheel->GetPos_dt(); char messageV[100]; sprintf(messageV, "CM vel, x: %4.4g, y: %4.4g, z: %4.4g", cmVel.x(), cmVel.y(), cmVel.z()); text_cmVel->setText(core::stringw(messageV).c_str()); // rxn. forces on spindle ChVector<> rxnF = mtester->spindle->Get_react_force(); char messageF[100]; sprintf(messageF, "spindle Rxn. F, x: %4.3g, y: %4.3g, z: %4.3g", rxnF.x(), rxnF.y(), rxnF.z()); text_spindleForces->setText(core::stringw(messageF).c_str()); // rxn. torques on spindle ChVector<> rxnT = mtester->spindle->Get_react_torque(); char messageT[100]; sprintf(messageT, "spindle Rxn. T, x: %4.3g, y: %4.3g, z: %4.3g", rxnT.x(), rxnT.y(), rxnT.z()); text_spindleTorque->setText(core::stringw(messageT).c_str()); }
// Get the quaternion from a source vector and a destination vector which specifies // the rotation from one to the other. The vectors do not need to be normalized. ChQuaternion<double> Q_from_Vect_to_Vect(const ChVector<double>& fr_vect, const ChVector<double>& to_vect) { const double ANGLE_TOLERANCE = 1e-6; ChQuaternion<double> quat; double halfang; double sinhalf; ChVector<double> axis; double lenXlen = fr_vect.Length() * to_vect.Length(); axis = fr_vect % to_vect; double sinangle = ChClamp(axis.Length() / lenXlen, -1.0, +1.0); double cosangle = ChClamp(fr_vect ^ to_vect / lenXlen, -1.0, +1.0); // Consider three cases: Parallel, Opposite, non-collinear if (std::abs(sinangle) == 0.0 && cosangle > 0) { // fr_vect & to_vect are parallel quat.e0() = 1.0; quat.e1() = 0.0; quat.e2() = 0.0; quat.e3() = 0.0; } else if (std::abs(sinangle) < ANGLE_TOLERANCE && cosangle < 0) { // fr_vect & to_vect are opposite, i.e. ~180 deg apart axis = fr_vect.GetOrthogonalVector() + (-to_vect).GetOrthogonalVector(); axis.Normalize(); quat.e0() = 0.0; quat.e1() = ChClamp(axis.x(), -1.0, +1.0); quat.e2() = ChClamp(axis.y(), -1.0, +1.0); quat.e3() = ChClamp(axis.z(), -1.0, +1.0); } else { // fr_vect & to_vect are not co-linear case axis.Normalize(); halfang = 0.5 * ChAtan2(sinangle, cosangle); sinhalf = sin(halfang); quat.e0() = cos(halfang); quat.e1() = ChClamp(axis.x(), -1.0, +1.0); quat.e2() = ChClamp(axis.y(), -1.0, +1.0); quat.e3() = ChClamp(axis.z(), -1.0, +1.0); } return (quat); }
ChVector<double> Q_to_NasaAngles(const ChQuaternion<double>& q1) { ChVector<double> mnasa; double sqw = q1.e0() * q1.e0(); double sqx = q1.e1() * q1.e1(); double sqy = q1.e2() * q1.e2(); double sqz = q1.e3() * q1.e3(); // heading mnasa.z() = atan2(2.0 * (q1.e1() * q1.e2() + q1.e3() * q1.e0()), (sqx - sqy - sqz + sqw)); // bank mnasa.y() = atan2(2.0 * (q1.e2() * q1.e3() + q1.e1() * q1.e0()), (-sqx - sqy + sqz + sqw)); // attitude mnasa.x() = asin(-2.0 * (q1.e1() * q1.e3() - q1.e2() * q1.e0())); return mnasa; }
// Get the quaternion from an angle of rotation and an axis, defined in _abs_ coords. // The axis is supposed to be fixed, i.e. it is constant during rotation. // The 'axis' vector must be normalized. ChQuaternion<double> Q_from_AngAxis(double angle, const ChVector<double>& axis) { ChQuaternion<double> quat; double halfang; double sinhalf; halfang = (angle * 0.5); sinhalf = sin(halfang); quat.e0() = cos(halfang); quat.e1() = axis.x() * sinhalf; quat.e2() = axis.y() * sinhalf; quat.e3() = axis.z() * sinhalf; return (quat); }
bool ChCascadeDoc::GetVolumeProperties(const TopoDS_Shape& mshape, ///< pass the shape here const double density, ///< pass the density here ChVector<>& center_position, ///< get the position center, respect to shape pos. ChVector<>& inertiaXX, ///< get the inertia diagonal terms ChVector<>& inertiaXY, ///< get the inertia extradiagonal terms double& volume, ///< get the volume double& mass ///< get the mass ) { if (mshape.IsNull()) return false; GProp_GProps mprops; GProp_GProps vprops; BRepGProp::VolumeProperties(mshape, mprops); BRepGProp::VolumeProperties(mshape, vprops); mprops.Add(mprops, density); mass = mprops.Mass(); volume = vprops.Mass(); gp_Pnt G = mprops.CentreOfMass(); gp_Mat I = mprops.MatrixOfInertia(); center_position.x() = G.X(); center_position.y() = G.Y(); center_position.z() = G.Z(); inertiaXX.x() = I(1, 1); inertiaXX.y() = I(2, 2); inertiaXX.z() = I(3, 3); inertiaXY.x() = I(1, 2); inertiaXY.y() = I(1, 3); inertiaXY.z() = I(2, 3); return true; }
ChQuaternion<double> Q_from_NasaAngles(const ChVector<double>& mang) { ChQuaternion<double> mq; double c1 = cos(mang.z() / 2); double s1 = sin(mang.z() / 2); double c2 = cos(mang.x() / 2); double s2 = sin(mang.x() / 2); double c3 = cos(mang.y() / 2); double s3 = sin(mang.y() / 2); double c1c2 = c1 * c2; double s1s2 = s1 * s2; mq.e0() = c1c2 * c3 + s1s2 * s3; mq.e1() = c1c2 * s3 - s1s2 * c3; mq.e2() = c1 * s2 * c3 + s1 * c2 * s3; mq.e3() = s1 * c2 * c3 - c1 * s2 * s3; return mq; }
void AddContainerWall(std::shared_ptr<ChBody> body, const ChVector<>& pos, const ChVector<>& size, bool visible = true) { ChVector<> hsize = 0.5 * size; body->GetCollisionModel()->AddBox(hsize.x(), hsize.y(), hsize.z(), pos); if (visible) { auto box = std::make_shared<ChBoxShape>(); box->GetBoxGeometry().Pos = pos; box->GetBoxGeometry().Size = hsize; box->SetColor(ChColor(1, 0, 0)); box->SetFading(0.6f); body->AddAsset(box); } }
// @param pSize particle radius // @param pDev multiplier added to ChRandom() // @param maxTorque max slider torque applied to wheel // @param maxParticles max number of particles to generate each spawning event MyEventReceiver(ChIrrApp* app, SoilbinWheel* wheel, TestMech* tester, ParticleGenerator* particleGenerator, double pSize = 0.02, double pDev = 0.02, double maxTorque = 100.0, int maxParticles = 50) { // store pointer to physical system & other stuff so we can tweak them by user keyboard this->mapp = app; // any rigid bodies that have their states modified by the GUI need to go here this->mwheel = wheel; this->mtester = tester; this->mgenerator = particleGenerator; // for getting output from the TM_Module module // initial checkbox values this->wheelLocked = true; this->makeParticles = false; this->wheelCollision = false; this->pVisible = true; this->wheelVisible = true; // initial values for the sliders this->particleSize0 = pSize; this->particleDev0 = pDev; this->maxTorque = maxTorque; this->nParticlesGenMax = maxParticles; // **** *** // create the GUI items here irr::s32 x0 = 740; irr::s32 y0 = 20; // box0 top left corner // create the tabs for the rig output: NOTE: GUI widget locations are all relative to the TabControl! gad_tabbed = mapp->GetIGUIEnvironment()->addTabControl(core::rect<s32>(x0, y0, x0 + 255, y0 + 440), 0, true, true); gad_tab_controls = gad_tabbed->addTab(L"Controls"); // static text will be printed w/ each checkbox or slider gad_text_wheelControls = mapp->GetIGUIEnvironment()->addStaticText( L"Wheel Control", core::rect<s32>(10, 10, 245, 150), true, true, gad_tab_controls); irr::s32 y1 = 165; // box1 top left corner gad_text_pControls = mapp->GetIGUIEnvironment()->addStaticText( L"Particle Control", core::rect<s32>(10, y1, 245, y1 + 230), true, true, gad_tab_controls); gad_tab_wheel = gad_tabbed->addTab(L"Wheel State"); gad_text_wheelState = mapp->GetIGUIEnvironment()->addStaticText(L"WS", core::rect<s32>(10, 10, 290, 250), true, true, gad_tab_wheel); gad_tab_soil = gad_tabbed->addTab(L"Soil State"); gad_text_soilState = mapp->GetIGUIEnvironment()->addStaticText(L"SS", core::rect<s32>(10, 10, 290, 250), true, true, gad_tab_soil); // **** GUI CONTROLS *** // -------- Wheel controls // ..add a GUI for wheel position lock ( id = 2110 ) checkbox_wheelLocked = app->GetIGUIEnvironment()->addCheckBox(wheelLocked, core::rect<s32>(20, 30, 35, 45), gad_tab_controls, 2110); text_wheelLocked = app->GetIGUIEnvironment()->addStaticText(L"Wheel Locked", core::rect<s32>(45, 30, 125, 45), false, false, gad_tab_controls); checkbox_wheelLocked->setVisible(true); text_wheelLocked->setVisible(true); this->mwheel->wheel->SetBodyFixed(wheelLocked); // set IC of checkbox this->mtester->truss->SetBodyFixed(wheelLocked); this->mtester->suspweight->SetBodyFixed(wheelLocked); // turn wheel visibility on/off, ie = 2115 ////checkbox_wheelVisible = app->GetIGUIEnvironment()->addCheckBox(wheelVisible, core::rect<s32>(180, 30, 195, ///45), //// gad_tab_controls, 2115); ////text_wheelVisible = app->GetIGUIEnvironment()->addStaticText(L"visible?", core::rect<s32>(205, 30, 290, 45), //// false, false, gad_tab_controls); // add a GUI for setting the wheel collision ( id = 2112 ) checkbox_wheelCollision = app->GetIGUIEnvironment()->addCheckBox( wheelCollision, core::rect<s32>(20, 60, 35, 75), gad_tab_controls, 2112); text_wheelCollision = app->GetIGUIEnvironment()->addStaticText( L"Wheel collide? ", core::rect<s32>(45, 60, 125, 75), false, false, gad_tab_controls); checkbox_wheelCollision->setVisible(true); text_wheelCollision->setVisible(true); this->mwheel->wheel->SetCollide(wheelCollision); // torque slider (id = 1103) scrollbar_torque = mapp->GetIGUIEnvironment()->addScrollBar(true, rect<s32>(20, 115, 150, 130), gad_tab_controls, 1103); scrollbar_torque->setMax(100); scrollbar_torque->setPos(50); text_torque = mapp->GetIGUIEnvironment()->addStaticText(L"Torque[N/m]: 0 ", rect<s32>(160, 115, 300, 130), false, false, gad_tab_controls); this->mtester->currTorque = 0; // set the IC of this slider // -------- Particle Controls // add a GUI for turning particle creation on/off ( id = 2111 ) checkbox_createParticles = app->GetIGUIEnvironment()->addCheckBox( makeParticles, core::rect<s32>(20, y1 + 20, 35, y1 + 35), gad_tab_controls, 2111); text_createParticles = app->GetIGUIEnvironment()->addStaticText( L"create Particles? ", core::rect<s32>(45, y1 + 20, 165, y1 + 35), false, false, gad_tab_controls); checkbox_createParticles->setVisible(true); text_createParticles->setVisible(true); // add a checkbox to make particle visibility turn on/off, id = 2114 ////checkbox_particlesVisible = app->GetIGUIEnvironment()->addCheckBox( //// pVisible, core::rect<s32>(180, y1 + 20, 195, y1 + 35), gad_tab_controls, 2114); ////text_particlesVisible = app->GetIGUIEnvironment()->addStaticText( //// L"visible?", core::rect<s32>(205, y1 + 20, 290, y1 + 35), false, false, gad_tab_controls); // create sliders to modify particle size/dev ( id = 1101) scrollbar_pSize = mapp->GetIGUIEnvironment()->addScrollBar(true, rect<s32>(20, y1 + 50, 150, y1 + 65), gad_tab_controls, 1101); scrollbar_pSize->setMax(100); scrollbar_pSize->setPos(50); char message[50]; sprintf(message, "p rad [m]: %g", particleSize0); text_pSize = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(message).c_str(), rect<s32>(160, y1 + 50, 300, y1 + 65), false, false, gad_tab_controls); this->currParticleSize = particleSize0; // set the IC // particle rad Deviation slider (id = 1102) scrollbar_pDev = mapp->GetIGUIEnvironment()->addScrollBar(true, rect<s32>(20, y1 + 80, 150, y1 + 95), gad_tab_controls, 1102); scrollbar_pDev->setMax(100); scrollbar_pDev->setPos(50); char message1[50]; sprintf(message1, "p dev.[m]: %g", particleDev0); text_pDev = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(message1).c_str(), rect<s32>(160, y1 + 80, 300, y1 + 95), false, false, gad_tab_controls); this->currParticleDev = particleDev0; // set the IC for the slider // nParticlesGen slider ( id = 1104) scrollbar_nParticlesGen = mapp->GetIGUIEnvironment()->addScrollBar(true, rect<s32>(20, y1 + 110, 150, y1 + 125), gad_tab_controls, 1104); scrollbar_nParticlesGen->setMax(100); scrollbar_nParticlesGen->setPos(50); this->currNparticlesGen = nParticlesGenMax / 2; // IC of this slider char message2[50]; sprintf(message2, "# p Gen: %d", this->currNparticlesGen); text_nParticlesGen = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(message2).c_str(), rect<s32>(160, y1 + 110, 300, y1 + 125), false, false, gad_tab_controls); // friction coefficient of particles, id = 1105 scrollbar_particleFriction = mapp->GetIGUIEnvironment()->addScrollBar( true, rect<s32>(20, y1 + 140, 150, y1 + 155), gad_tab_controls, 1105); scrollbar_particleFriction->setMax(100); scrollbar_particleFriction->setPos(33); this->currParticleFriction = 0.33; char message3[50]; sprintf(message3, "mu: %g", this->currParticleFriction); text_particleFriction = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(message3).c_str(), rect<s32>(160, y1 + 140, 300, y1 + 155), false, false, gad_tab_controls); // particle density, id = 1106 scrollbar_particleDensity = mapp->GetIGUIEnvironment()->addScrollBar( true, rect<s32>(20, y1 + 170, 150, y1 + 185), gad_tab_controls, 1106); scrollbar_particleDensity->setMax(100); scrollbar_particleDensity->setPos(50); this->avgDensity = this->mgenerator->getSphDensity(); char message4[50]; sprintf(message4, "rho [kg/m3]: %g", this->avgDensity); text_particleDensity = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(message4).c_str(), rect<s32>(160, y1 + 170, 300, y1 + 185), false, false, gad_tab_controls); // ******* GUI WHEEL STATE // wheel CM pos ChVector<> cm = mwheel->wheel->GetPos(); char message5[100]; sprintf(message5, "CM pos, x: %4.4g, y: %4.4g, z: %4.4g", cm.x(), cm.y(), cm.z()); text_cmPos = mapp->GetIGUIEnvironment()->addStaticText(core::stringw(message5).c_str(), rect<s32>(10, 30, 280, 45), false, false, gad_tab_wheel); // wheel CM vel ChVector<> cmVel = mwheel->wheel->GetPos_dt(); char messageV[100]; sprintf(messageV, "CM vel, x: %4.4g, y: %4.4g, z: %4.4g", cmVel.x(), cmVel.y(), cmVel.z()); text_cmVel = mapp->GetIGUIEnvironment()->addStaticText(core::stringw(message5).c_str(), rect<s32>(10, 60, 280, 75), false, false, gad_tab_wheel); // rxn. forces on spindle, in the local coordinate system ChVector<> rxnF = mtester->spindle->Get_react_force(); char messageF[100]; sprintf(messageF, "spindle Rxn. F, x: %4.3g, y: %4.3g, z: %4.3g", rxnF.x(), rxnF.y(), rxnF.z()); text_spindleForces = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(message5).c_str(), rect<s32>(10, 90, 280, 105), false, false, gad_tab_wheel); // rxn. torques on spindle, in local coordinate system ChVector<> rxnT = mtester->spindle->Get_react_torque(); char messageT[100]; sprintf(messageT, "spindle Rxn. T, x: %4.3g, y: %4.3g, z: %4.3g", rxnT.x(), rxnT.y(), rxnT.z()); text_spindleTorque = mapp->GetIGUIEnvironment()->addStaticText( core::stringw(messageT).c_str(), rect<s32>(10, 120, 280, 135), false, false, gad_tab_wheel); // ******* GUI PARTICLE STATE // average particle size: pRadMean // running/continuous std. dev: pRadStdDev // total particle mass: totalParticleMass // average particle mass: pMassMean // running/continuous std. dev of mass: pMassStdDev std::vector<double> particleStats = this->mgenerator->getStatistics(); char messageRad[100]; sprintf(messageRad, "p Rad mean, std. dev: %4.4g, %4.4g", particleStats[0], particleStats[1]); text_pRad = mapp->GetIGUIEnvironment()->addStaticText(core::stringw(messageRad).c_str(), rect<s32>(10, 30, 280, 45), false, false, gad_tab_soil); char messageMass[100]; sprintf(messageMass, "p mass mean, std. dev: %4.4g, %4.4g", particleStats[6], particleStats[7]); text_pMass = mapp->GetIGUIEnvironment()->addStaticText(core::stringw(messageMass).c_str(), rect<s32>(10, 60, 280, 75), false, false, gad_tab_soil); }
void ChMeshExporter::writeFrame(std::shared_ptr<ChMesh> my_mesh, char SaveAsBuffer[256], std::string MeshFileBuffer) { std::ofstream output; std::string SaveAsBuffer_string(SaveAsBuffer); SaveAsBuffer_string.erase(SaveAsBuffer_string.length() - 4, 4); std::cout << SaveAsBuffer_string << std::endl; snprintf(SaveAsBuffer, sizeof(char) * 256, ("%s"), (SaveAsBuffer_string + ".vtk").c_str()); output.open(SaveAsBuffer, std::ios::app); output << "# vtk DataFile Version 2.0" << std::endl; output << "Unstructured Grid Example" << std::endl; output << "ASCII" << std::endl; output << "DATASET UNSTRUCTURED_GRID" << std::endl; output << "POINTS " << my_mesh->GetNnodes() << " float\n"; for (unsigned int i = 0; i < my_mesh->GetNnodes(); i++) { auto node = std::dynamic_pointer_cast<ChNodeFEAxyz>(my_mesh->GetNode(i)); output << node->GetPos().x() << " " << node->GetPos().y() << " " << node->GetPos().z() << "\n"; } std::ifstream CopyFrom(MeshFileBuffer); output << CopyFrom.rdbuf(); int numCell = 0; for (unsigned int iele = 0; iele < my_mesh->GetNelements(); iele++) { if (auto element = std::dynamic_pointer_cast<ChElementCableANCF>(my_mesh->GetElement(iele))) numCell++; else if (auto element = std::dynamic_pointer_cast<ChElementShellANCF>(my_mesh->GetElement(iele))) numCell++; } output << "\nCELL_DATA " << numCell << "\n"; output << "SCALARS Deflection float 1\n"; output << "LOOKUP_TABLE default\n"; double scalar = 0; for (unsigned int iele = 0; iele < my_mesh->GetNelements(); iele++) { if (auto element = std::dynamic_pointer_cast<ChElementCableANCF>(my_mesh->GetElement(iele))) scalar = element->GetCurrLength() - element->GetRestLength(); else if (auto element = std::dynamic_pointer_cast<ChElementShellANCF>(my_mesh->GetElement(iele))) element->EvaluateDeflection(scalar); output << scalar + 1e-20 << "\n"; } output << "VECTORS Strain float\n"; ChVector<> StrainV; for (unsigned int iele = 0; iele < my_mesh->GetNelements(); iele++) { if (auto element = std::dynamic_pointer_cast<ChElementCableANCF>(my_mesh->GetElement(iele))) element->EvaluateSectionStrain(0.0, StrainV); else if (auto element = std::dynamic_pointer_cast<ChElementShellANCF>(my_mesh->GetElement(iele))) StrainV = element->EvaluateSectionStrains(); StrainV += ChVector<>(1e-20); output << StrainV.x() << " " << StrainV.y() << " " << StrainV.z() << "\n"; } output << "\nPOINT_DATA " << my_mesh->GetNnodes() << "\n"; output << "VECTORS Velocity float\n"; for (unsigned int i = 0; i < my_mesh->GetNnodes(); i++) { ChVector<> vel = std::dynamic_pointer_cast<ChNodeFEAxyz>(my_mesh->GetNode(i))->GetPos_dt(); vel += ChVector<>(1e-20); output << (double)vel.x() << " " << (double)vel.y() << " " << (double)vel.z() << "\n"; } output << "VECTORS Acceleration float\n"; for (unsigned int i = 0; i < my_mesh->GetNnodes(); i++) { ChVector<> acc = std::dynamic_pointer_cast<ChNodeFEAxyz>(my_mesh->GetNode(i))->GetPos_dtdt(); acc += ChVector<>(1e-20); output << (double)acc.x() << " " << (double)acc.y() << " " << (double)acc.z() << "\n"; } output.close(); } // namespace fea
bool ChOpenGLMesh::Initialize(chrono::ChTriangleMeshShape* tri_mesh, ChOpenGLMaterial mat) { if (GLReturnedError("Mesh::Initialize - on entry")) { return false; } if (!super::Initialize()) { return false; } int num_triangles = tri_mesh->GetMesh().getNumTriangles(); for (unsigned int i = 0; i < (unsigned)num_triangles; i++) { chrono::geometry::ChTriangle tri = tri_mesh->GetMesh().getTriangle(i); ChVector<> norm = tri.GetNormal(); ChVector<> v1 = tri.p1; ChVector<> v2 = tri.p2; ChVector<> v3 = tri.p3; this->vertex_indices.push_back(i * 3 + 0); this->vertex_indices.push_back(i * 3 + 1); this->vertex_indices.push_back(i * 3 + 2); glm::vec3 v, n; v = glm::vec3(v1.x(), v1.y(), v1.z()); n = glm::vec3(norm.x(), norm.y(), norm.z()); this->data.push_back(ChOpenGLVertexAttributesPN(v, n)); v = glm::vec3(v2.x(), v2.y(), v2.z()); this->data.push_back(ChOpenGLVertexAttributesPN(v, n)); v = glm::vec3(v3.x(), v3.y(), v3.z()); this->data.push_back(ChOpenGLVertexAttributesPN(v, n)); } ambient = mat.ambient_color; diffuse = mat.diffuse_color; specular = mat.specular_color; // // std::vector<ChVector<int> >& indices = // tri_mesh->GetMesh().getIndicesVertexes(); // std::vector<ChVector<double> >& vertices = // tri_mesh->GetMesh().getCoordsVertices(); // std::vector<ChVector<double> >& normals = // tri_mesh->GetMesh().getCoordsNormals(); // // this->vertex_indices.resize(indices.size() * 3); // for (unsigned int i = 0; i < indices.size(); i++) { // // this->vertex_indices[i * 3 + 0] = indices[i].x; // this->vertex_indices[i * 3 + 1] = indices[i].y; // this->vertex_indices[i * 3 + 2] = indices[i].z; // } // for (unsigned int i = 0; i < vertices.size(); i++) { // glm::vec3 n; // glm::vec3 v(vertices[i].x, vertices[i].y, vertices[i].z); // if (normals.size() > 0) { // n = glm::vec3(normals[i].x, normals[i].y, normals[i].z); // } else { // n = glm::vec3(1, 0, 0); // } // // this->data.push_back(ChOpenGLVertexAttributesPN(v, n)); // } PostInitialize(); if (GLReturnedError("ChOpenGLMesh::Initialize - on exit")) { return false; } return true; }