Пример #1
0
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
const ChVector<> M113a_Suspension::GetLocation(PointId which) {
    ChVector<> point;

    switch (which) {
        case ARM:
            point = ChVector<>(0.213, -0.12, 0.199);
            break;
        case ARM_WHEEL:
            point = ChVector<>(0, -0.12, 0);
            break;
        case ARM_CHASSIS:
            point = ChVector<>(0.232, -0.12, 0.217);
            break;
        case SHOCK_A:
            point = ChVector<>(0, -0.12, 0);
            break;
        case SHOCK_C:
            point = ChVector<>(0, -0.12, 1);
            break;
        default:
            point = ChVector<>(0, 0, 0);
            break;
    }

    if (m_side == RIGHT)
        point.y() *= -1;

    return point;
}
Пример #2
0
int ChLinkDistance::Initialize(std::shared_ptr<ChBodyFrame> mbody1,
                               std::shared_ptr<ChBodyFrame> mbody2,
                               bool pos_are_relative,
                               ChVector<> mpos1,
                               ChVector<> mpos2,
                               bool auto_distance,
                               double mdistance) {
    Body1 = mbody1.get();
    Body2 = mbody2.get();
    Cx.SetVariables(&Body1->Variables(), &Body2->Variables());

    if (pos_are_relative) {
        pos1 = mpos1;
        pos2 = mpos2;
    } else {
        pos1 = Body1->TransformPointParentToLocal(mpos1);
        pos2 = Body2->TransformPointParentToLocal(mpos2);
    }

    ChVector<> AbsDist = Body1->TransformPointLocalToParent(pos1) - Body2->TransformPointLocalToParent(pos2);
    curr_dist = AbsDist.Length();

    if (auto_distance) {
        distance = curr_dist;
    } else {
        distance = mdistance;
    }

    return true;
}
Пример #3
0
// 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;
}
Пример #4
0
void ChLinkDistance::Update (double mytime)
{
    // Inherit time changes of parent class (ChLink), basically doing nothing :)
    ChLink::UpdateTime(mytime);

		// compute jacobians
	ChVector<> AbsDist = Body1->Point_Body2World(&pos1)-Body2->Point_Body2World(&pos2);
	curr_dist          = AbsDist.Length();
	ChVector<> D2abs   = Vnorm(AbsDist);
	ChVector<> D2relB  = Body2->Dir_World2Body(&D2abs);
	ChVector<> D2relA  = Body1->Dir_World2Body(&D2abs);

	ChVector<> CqAx =  D2abs;
	ChVector<> CqBx = -D2abs;
	
	ChVector<> CqAr = -Vcross(D2relA,pos1);
	ChVector<> CqBr =  Vcross(D2relB,pos2);

	Cx.Get_Cq_a()->ElementN(0)=(float)CqAx.x;
	Cx.Get_Cq_a()->ElementN(1)=(float)CqAx.y;
	Cx.Get_Cq_a()->ElementN(2)=(float)CqAx.z;
	Cx.Get_Cq_a()->ElementN(3)=(float)CqAr.x;
	Cx.Get_Cq_a()->ElementN(4)=(float)CqAr.y;
	Cx.Get_Cq_a()->ElementN(5)=(float)CqAr.z;

	Cx.Get_Cq_b()->ElementN(0)=(float)CqBx.x;
	Cx.Get_Cq_b()->ElementN(1)=(float)CqBx.y;
	Cx.Get_Cq_b()->ElementN(2)=(float)CqBx.z;
	Cx.Get_Cq_b()->ElementN(3)=(float)CqBr.x;
	Cx.Get_Cq_b()->ElementN(4)=(float)CqBr.y;
	Cx.Get_Cq_b()->ElementN(5)=(float)CqBr.z;

	//***TO DO***  C_dt? C_dtdt? (may be never used..)
}
Пример #5
0
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
const ChVector<> M113_Idler::GetLocation(PointId which) {
    ChVector<> point;

    switch (which) {
        case WHEEL:
            point = ChVector<>(0, 0, 0);
            break;
        case CARRIER:
            point = ChVector<>(0, -0.1, 0);
            break;
        case CARRIER_CHASSIS:
            point = ChVector<>(0, -0.2, 0);
            break;
        case TSDA_CARRIER:
            point = ChVector<>(0, -0.2, 0);
            break;
        case TSDA_CHASSIS:
            point = ChVector<>(0.5, -0.2, 0);
            break;
        default:
            point = ChVector<>(0, 0, 0);
            break;
    }

    if (GetVehicleSide() == RIGHT)
        point.y() *= -1;

    return point;
}
Пример #6
0
// 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;
}
Пример #7
0
// 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;
}
Пример #8
0
void ChModelBullet::GetAABB(ChVector<>& bbmin, ChVector<>& bbmax) const
{
	btVector3 btmin;
	btVector3 btmax;
	if (bt_collision_object->getCollisionShape())
		bt_collision_object->getCollisionShape()->getAabb( bt_collision_object->getWorldTransform(), btmin, btmax);
	bbmin.Set(btmin.x(), btmin.y(), btmin.z());
	bbmax.Set(btmax.x(), btmax.y(), btmax.z());
}
Пример #9
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);
}
Пример #10
0
// 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}
}
Пример #11
0
void WrdStyleSheet::GetStyleList(ChUINT2 in_unParagraphStyleIndex, ChVector<ChUINT2>& vecStyles) const
{
	ChUINT2 unStyleIndex = in_unParagraphStyleIndex;
	while (unStyleIndex != 0x0FFF)
    {
		vecStyles.push_back(unStyleIndex);
        const WrdStyle& style = getStyle(unStyleIndex);
        unStyleIndex = style.getBaseStyleIndex();
    }
	if (vecStyles.size() == 0 || vecStyles[vecStyles.size() - 1] != 0)
		vecStyles.push_back(0);
}
Пример #12
0
// 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);
}
Пример #13
0
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;
}
Пример #14
0
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;
}
Пример #15
0
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);
}
Пример #16
0
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);
    }
}
Пример #17
0
// -----------------------------------------------------------------------------
// 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());
}
Пример #18
0
int ChPathSteeringControllerXT::CalcCurvatureCode(ChVector<>& a, ChVector<>& b) {
    // a[] is a unit vector pointing to the left vehicle side
    // b[] is a unit vector pointing to the instantanous curve center 
    a.z() = 0;
    a.Normalize();
    b.z() = 0;
    b.Normalize();
    
    // In a left turn the distance between the two points will be nearly zero
    // in a right turn the distance will be around 2, at least > 1
    ChVector<> ab = a - b;
    double ltest = ab.Length();
    
    // What is a straight line? We define a threshold radius R_threshold
    // if the actual curvature is greater than 1/R_treshold, we are in a curve
    // otherwise we take this point as part of a straight line
    // m_pcurvature is always >= 0
    if(m_pcurvature <= 1.0/m_R_threshold) {
        return 0; // -> straight line
    }
    if(ltest < 1.0) {
        return 1;   // left bending curve
    }
    return -1; // right bending curve
}
Пример #19
0
int ChLinkDistance::Initialize(ChSharedPtr<ChBody>& mbody1,   ///< first body to link
						   ChSharedPtr<ChBody>& mbody2,		 ///< second body to link
						   bool pos_are_relative,///< true: following posit. are considered relative to bodies. false: pos.are absolute
						   ChVector<> mpos1,	 ///< position of distance endpoint, for 1st body (rel. or abs., see flag above)
						   ChVector<> mpos2,	 ///< position of distance endpoint, for 2nd body (rel. or abs., see flag above) 
						   bool auto_distance,///< if true, initializes the imposed distance as the distance between mpos1 and mpos2
						   double mdistance   ///< imposed distance (no need to define, if auto_distance=true.)
						   )
{
	this->Body1 = mbody1.get_ptr();
	this->Body2 = mbody2.get_ptr();
	this->Cx.SetVariables(&this->Body1->Variables(),&this->Body2->Variables());

	if (pos_are_relative)
	{
		this->pos1 = mpos1;
		this->pos2 = mpos2;
	}
	else
	{
		this->pos1 = this->Body1->Point_World2Body(&mpos1);
		this->pos2 = this->Body2->Point_World2Body(&mpos2);
	}
	
	ChVector<> AbsDist = Body1->Point_Body2World(&pos1)-Body2->Point_Body2World(&pos2);
	this->curr_dist = AbsDist.Length();

	if (auto_distance)
	{
		this->distance = this->curr_dist;
	}
	else
	{
		this->distance = mdistance;
	}

	return true;
}
Пример #20
0
double ChPathSteeringControllerXT::CalcHeadingError(ChVector<>& a, ChVector<>& b) {
    double ang = 0.0;
    
    // test for velocity > 0
    m_vel.z() = 0;
    m_vel.Normalize();
    double speed = m_vel.Length();
    
    if(speed < 1) {
        // vehicle is standing still, we take the chassis orientation
        a.z() = 0;
        b.z() = 0;
        a.Normalize();
        b.Normalize();
    } else {
        // vehicle is running, we take the {x,y} velocity vector
        a = m_vel;
        b.z() = 0;
        b.Normalize();        
    }

    // it might happen to cruise against the path definition (end->begin instead of begin->end),
    // then the the tangent points backwards to driving direction
    // the distance |ab| is > 1 then
    ChVector<> ab = a - b;
    double ltest = ab.Length();

    ChVector<> vpc;
    if(ltest < 1) {
        vpc = Vcross(a,b);
    } else {
        vpc = Vcross(a,-b);
    }
    ang = std::asin(vpc.z());

    return ang;
}
Пример #21
0
void ChLinkSpring::Initialize(std::shared_ptr<ChBody> mbody1,
                              std::shared_ptr<ChBody> mbody2,
                              bool pos_are_relative,
                              ChVector<> mpos1,
                              ChVector<> mpos2,
                              bool auto_rest_length,
                              double mrest_length) {
    // First, initialize as all constraint with markers.
    // In this case, create the two markers also!.
    ChLinkMarkers::Initialize(mbody1, mbody2, CSYSNORM);

    if (pos_are_relative) {
        marker1->Impose_Rel_Coord(ChCoordsys<>(mpos1, QUNIT));
        marker2->Impose_Rel_Coord(ChCoordsys<>(mpos2, QUNIT));
    } else {
        marker1->Impose_Abs_Coord(ChCoordsys<>(mpos1, QUNIT));
        marker2->Impose_Abs_Coord(ChCoordsys<>(mpos2, QUNIT));
    }

    ChVector<> AbsDist = marker1->GetAbsCoord().pos - marker2->GetAbsCoord().pos;
    dist = AbsDist.Length();

    spr_restlength = auto_rest_length ? dist : mrest_length;
}
Пример #22
0
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;
}
Пример #23
0
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;
    }
}
Пример #24
0
// 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);
}
Пример #25
0
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..)
}
Пример #26
0
// -----------------------------------------------------------------------------
// 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;
}
Пример #27
0
void XlChartPlotSeries::classifySeries (XlChartBinaryReader& in_reader)
{
	//NOTE! modifies m_uCurrentIndex.
	//
    enum {undef = -2, aux, std, trend, xPos, xNeg, yPos, yNeg} type = undef;

    ChAutoPtr<XlHeader> pHeader(ChNEW XlHeader());
    ChSINT4  lPos = in_reader.getStream()->getPos();    

    if ( in_reader.nextSibling(*pHeader) )
    {    
        in_reader.getStream()->seek( pHeader->getLength() + XlRecord::HDR_SIZE, SsrwOO_CUR );
        // Open container and parse subordinates.
		// Find out about series type, 
		// also get main series group index or pick up aux series parent while parsing.
		in_reader.m_pParser->getHeader( *pHeader, in_reader.getSheetVersion() );
        if ( pHeader->getId() == XlChartBegin::ID )
        {
			ChSINT2 unAuxParentInd = -1;
			ChVector<SeriesDescription>* pList = NULL;	// tells about group type 
														// when completed
            while ( in_reader.nextSibling(*pHeader) )  
            {
                switch ( pHeader->getId() )
                {
                case XlChartSerToCrt::ID:		//order 1
                    {   
						ChAutoPtr<XlChartSerToCrt> pSerToCrt( ChNEW XlChartSerToCrt(*pHeader) );
						in_reader.getStream()->seek(XlRecord::HDR_SIZE, SsrwOO_CUR);
						in_reader.m_pParser->visit(*pSerToCrt);

						if (type == undef)
						{

							type = std;

							pList = ( pSerToCrt->getChartGroup() == 1 )? &m_secondaryGroupSeries :
																		 &m_mainGroupSeries;
						}
						break;
                    }
				case XlChartSerParent::ID:		//order 1
                    {   
						ChAutoPtr<XlChartSerParent> pSerParent( ChNEW XlChartSerParent(*pHeader) );
						in_reader.getStream()->seek(XlRecord::HDR_SIZE, SsrwOO_CUR);
						in_reader.m_pParser->visit(*pSerParent);

						if (type == undef)
						{
							type = aux;

							// this record seems to use 1 based indexes so subtract 1 to get 0 based
							unAuxParentInd = pSerParent->getSeriesNumber() - 1;
						}
						break;
                    }
				case XlChartSerAuxErrBar::ID:	//order 2
                    {   
						ChAutoPtr<XlChartSerAuxErrBar> pSerErr( ChNEW XlChartSerAuxErrBar(*pHeader) );
						in_reader.getStream()->seek(XlRecord::HDR_SIZE, SsrwOO_CUR);
						in_reader.m_pParser->visit(*pSerErr);

						if (type == aux)
						{
							switch ( pSerErr->getErrorBarType() )
							{
							case EB_XPLUS:
								{
									type = xPos;
									break;
								}
							case EB_XMINUS:
								{
									type = xNeg;
									break;
								}
							case EB_YPLUS:
								{
									type = yPos;
									break;
								}
							case EB_YMINUS:
								{
									type = yNeg;
									break;
								}
							}
						}
						break;
                    }
                case XlChartSerAuxTrend::ID:	//order 2
                    // no need to parse yet...
					if (type == aux)
					{
						type = trend;
					}
					// no break!
                    // step over the header as we didn't read anything.
                default:
                    in_reader.getStream()->seek( pHeader->getLength() + XlRecord::HDR_SIZE, SsrwOO_CUR );
                    break;
                }
            }
        
			switch (type)
			{
			default:	//
			case undef:	// incorrect file data
			case aux:	//
				{
					break;
				}
			case std:	// primary series
				{
					// standard series are simply appended to their list
					ChAutoPtr<SeriesDescription> pSeries( ChNEW SeriesDescription() );
					pSeries->m_primary.m_lLoc = lPos;
					pSeries->m_primary.m_unIndex = m_uCurrentIndex;
					pList->push_back(*pSeries);
					break;
				}
			case trend:	//
			case xPos:	//
			case xNeg:	// aux series
			case yPos:	//
			case yNeg:	//
				{
					// need to find the parent
					// ASSUMPTION: parent already exists.  If BIFF files define an auxillary
					// series before the parent series, this assumption is invalid and 
					// the result will be missing auxillary information.

					//Look in the main axis group first, then in the secondary axis group
					if (unAuxParentInd >= 0)
					{
						ChUINT2 iGroup;
						for (iGroup = 0; iGroup < 2; iGroup ++)
						{
							ChVector<SeriesDescription>* pList = iGroup == 0? &m_mainGroupSeries : 
																			  &m_secondaryGroupSeries;

							ChUINT2 iListItem;
							for (iListItem = 0; iListItem < pList->size(); iListItem ++)
							{
								if (pList->at(iListItem).m_primary.m_unIndex == unAuxParentInd)
								{
									switch (type)
									{
									case trend:
										{
											SeriesDesc desc;
											desc.m_lLoc = lPos;
											desc.m_unIndex = m_uCurrentIndex;
											pList->at(iListItem).m_trendlines.push_back(desc);
											break;
										}
									case xPos:
										pList->at(iListItem).m_ErrorXPos.m_lLoc = lPos;
										pList->at(iListItem).m_ErrorXPos.m_unIndex = m_uCurrentIndex;
										break;
									case xNeg:
										pList->at(iListItem).m_ErrorXNeg.m_lLoc = lPos;
										pList->at(iListItem).m_ErrorXNeg.m_unIndex = m_uCurrentIndex;
										break;
									case yPos:
										pList->at(iListItem).m_ErrorYPos.m_lLoc = lPos;
										pList->at(iListItem).m_ErrorYPos.m_unIndex = m_uCurrentIndex;
										break;
									case yNeg:
										pList->at(iListItem).m_ErrorYNeg.m_lLoc = lPos;
										pList->at(iListItem).m_ErrorYNeg.m_unIndex = m_uCurrentIndex;
										break;
									}
									iGroup = 2;	// break the group loop as we don't need to look in 
												// secondary series if we succeeded.

									break;		// break this list search
								}
							}
						}
					}
					break;
				}
			}
        }
    }
    m_uCurrentIndex ++;
}
Пример #28
0
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
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::Initialize(std::shared_ptr<ChBodyAuxRef> chassis, const ChVector<>& location) {
    // Express the suspension reference frame in the absolute coordinate system.
    ChFrame<> susp_to_abs(location);
    susp_to_abs.ConcatenatePreTransformation(chassis->GetFrame_REF_to_abs());

    // Transform all points and directions to absolute frame.
    std::vector<ChVector<> > points(NUM_POINTS);

    for (int i = 0; i < NUM_POINTS; i++) {
        ChVector<> rel_pos = GetLocation(static_cast<PointId>(i));
        points[i] = susp_to_abs.TransformPointLocalToParent(rel_pos);
    }

    // Create the trailing arm body. The reference frame of the arm body has its
    // x-axis aligned with the line between the arm-chassis connection point and
    // the arm-wheel connection point.
    ChVector<> y_dir = susp_to_abs.GetA().Get_A_Yaxis();
    ChVector<> u = susp_to_abs.GetPos() - points[ARM_CHASSIS];
    u.Normalize();
    ChVector<> w = Vcross(u, y_dir);
    w.Normalize();
    ChVector<> v = Vcross(w, u);
    ChMatrix33<> rot;
    rot.Set_A_axis(u, v, w);

    m_arm = std::shared_ptr<ChBody>(chassis->GetSystem()->NewBody());
    m_arm->SetNameString(m_name + "_arm");
    m_arm->SetPos(points[ARM]);
    m_arm->SetRot(rot);
    m_arm->SetMass(GetArmMass());
    m_arm->SetInertiaXX(GetArmInertia());
    chassis->GetSystem()->AddBody(m_arm);

    // Cache points and directions for arm visualization (expressed in the arm frame)
    m_pO = m_arm->TransformPointParentToLocal(susp_to_abs.GetPos());
    m_pA = m_arm->TransformPointParentToLocal(points[ARM]);
    m_pAW = m_arm->TransformPointParentToLocal(points[ARM_WHEEL]);
    m_pAC = m_arm->TransformPointParentToLocal(points[ARM_CHASSIS]);
    m_pAS = m_arm->TransformPointParentToLocal(points[SHOCK_A]);
    m_dY = m_arm->TransformDirectionParentToLocal(y_dir);

    // Create and initialize the revolute joint between arm and chassis.
    // The axis of rotation is the y axis of the suspension reference frame.
    m_revolute = std::make_shared<ChLinkLockRevolute>();
    m_revolute->SetNameString(m_name + "_revolute");
    m_revolute->Initialize(chassis, m_arm,
                           ChCoordsys<>(points[ARM_CHASSIS], susp_to_abs.GetRot() * Q_from_AngX(CH_C_PI_2)));
    chassis->GetSystem()->AddLink(m_revolute);

    // Create and initialize the rotational spring torque element.
    m_spring = std::make_shared<ChLinkRotSpringCB>();
    m_spring->SetNameString(m_name + "_spring");
    m_spring->Initialize(chassis, m_arm, ChCoordsys<>(points[ARM_CHASSIS], susp_to_abs.GetRot() * Q_from_AngX(CH_C_PI_2)));
    m_spring->RegisterTorqueFunctor(GetSpringTorqueFunctor());
    chassis->GetSystem()->AddLink(m_spring);

    // Create and initialize the translational shock force element.
    if (m_has_shock) {
        m_shock = std::make_shared<ChLinkSpringCB>();
        m_shock->SetNameString(m_name + "_shock");
        m_shock->Initialize(chassis, m_arm, false, points[SHOCK_C], points[SHOCK_A]);
        m_shock->RegisterForceFunctor(GetShockForceFunctor());
        chassis->GetSystem()->AddLink(m_shock);
    }

    // Invoke the base class implementation. This initializes the associated road wheel.
    // Note: we must call this here, after the m_arm body is created.
    ChRoadWheelAssembly::Initialize(chassis, location);
}
Пример #30
0
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;
}