/// Initialization based on passing two vectors (point + dir) on the /// two bodies, they will represent the X axes of the two frames (Y and Z will /// be built from the X vector via Gram Schmidt orthonormalization). /// Use the other ChLinkMateGeneric::Initialize() if you want to set the two frames directly. public virtual void Initialize(ChBodyFrame mbody1, //< first body to link ChBodyFrame mbody2, //< second body to link bool pos_are_relative, //< true: following pos. are relative to bodies. ChVector mpt1, //< origin of slave frame 1, for 1st body (rel. or abs., see flag above) ChVector mpt2, //< origin of master frame 2, for 2nd body (rel. or abs., see flag above) ChVector mnorm1, //< X axis of slave plane, for 1st body (rel. or abs., see flag above) ChVector mnorm2 //< X axis of master plane, for 2nd body (rel. or abs., see flag above) ) { Debug.Assert(mbody1 != mbody2); this.Body1 = mbody1; this.Body2 = mbody2; // this.SetSystem(mbody1.GetSystem()); this.mask.SetTwoBodiesVariables(Body1.Variables(), Body2.Variables()); ChVector mx = new ChVector(0, 0, 0); ChVector my = new ChVector(0, 0, 0); ChVector mz = new ChVector(0, 0, 0); ChVector mN = new ChVector(0, 0, 0); ChMatrix33 <double> mrot = new ChMatrix33 <double>(); ChFrame <double> mfr1 = new ChFrame <double>(); ChFrame <double> mfr2 = new ChFrame <double>(); if (pos_are_relative) { mN = mnorm1; mN.DirToDxDyDz(ref mx, ref my, ref mz, new ChVector(0, 1, 0)); mrot.Set_A_axis(mx, my, mz); mfr1.SetRot(mrot); mfr1.SetPos(mpt1); mN = mnorm2; mN.DirToDxDyDz(ref mx, ref my, ref mz, new ChVector(0, 1, 0)); mrot.Set_A_axis(mx, my, mz); mfr2.SetRot(mrot); mfr2.SetPos(mpt2); } else { ChVector temp = ChVector.VECT_Z; // from abs to body-rel mN = this.Body1.TransformDirectionParentToLocal(mnorm1); mN.DirToDxDyDz(ref mx, ref my, ref mz, temp); mrot.Set_A_axis(mx, my, mz); mfr1.SetRot(mrot); mfr1.SetPos(this.Body1.TransformPointParentToLocal(mpt1)); mN = this.Body2.TransformDirectionParentToLocal(mnorm2); mN.DirToDxDyDz(ref mx, ref my, ref mz, temp); mrot.Set_A_axis(mx, my, mz); mfr2.SetRot(mrot); mfr2.SetPos(this.Body2.TransformPointParentToLocal(mpt2)); } this.frame1 = mfr1; this.frame2 = mfr2; }
public override void update(double mytime, bool update_assets) { // Inherit parent class: base.update(mytime, update_assets); // Override the rotational jacobian [Cq] and the rotational residual C, // by assuming an additional hidden frame that rotates about frame2: if (this.Body1 != null && this.Body2 != null) { ChFrame <double> aframe1 = ChFrame <double> .BitShiftRight(this.frame1, (this.Body1)); ChFrame <double> aframe2 = ChFrame <double> .BitShiftRight(this.frame2, (this.Body2)); ChFrame <double> aframe12 = new ChFrame <double>(); aframe2.TransformParentToLocal(aframe1, aframe12); ChFrame <double> aframe2rotating = new ChFrame <double>(); double aux_rotation; if (this.avoid_angle_drift) { aux_rotation = this.aux_dt + this.rot_offset; } else { // to have it aligned to current rot, to allow C=0. aux_rotation = aframe12.GetRot().Q_to_Rotv().z; } aframe2rotating.SetRot(aframe2.GetRot() * ChQuaternion.Q_from_AngAxis2(aux_rotation, ChVector.VECT_Z)); // TODO this needs to be addressed, with it it causes rotation problems, seems to work fine without the TransformParentToLocal? ChFrame <double> aframe12rotating = new ChFrame <double>(); // aframe2rotating.TransformParentToLocal(aframe1, aframe12rotating); ChMatrix33 <double> Jw1 = new ChMatrix33 <double>(); ChMatrix33 <double> Jw2 = new ChMatrix33 <double>(); ChMatrix33 <double> mtempM = new ChMatrix33 <double>(); ChMatrix33 <double> mtempQ = new ChMatrix33 <double>(); ChMatrix33 <double> abs_plane_rotating = aframe2rotating.GetA(); Jw1.nm.matrix.MatrTMultiply(abs_plane_rotating.nm.matrix, Body1.GetA().nm.matrix); Jw2.nm.matrix.MatrTMultiply(abs_plane_rotating.nm.matrix, Body2.GetA().nm.matrix); Jw2.nm.matrix.MatrNeg(); // TODO this also needs to be addressed, with it it causes rotation problems/ // Premultiply by Jw1 and Jw2 by 0.5*[Fp(q_resid)]' to get residual as imaginary part of a quaternion. /* mtempM.Set_X_matrix((aframe12rotating.GetRot().GetVector()) * 0.5); * mtempM[0, 0] = 0.5 * aframe12rotating.GetRot().e0; * mtempM[1, 1] = 0.5 * aframe12rotating.GetRot().e0; * mtempM[2, 2] = 0.5 * aframe12rotating.GetRot().e0; * mtempQ.MatrTMultiply(mtempM, Jw1); * Jw1 = mtempQ; * mtempQ.MatrTMultiply(mtempM, Jw2); * Jw2 = mtempQ;*/ int nc = 0; if (c_x) { nc++; } if (c_y) { nc++; } if (c_z) { nc++; } if (c_rx) { this.C.matrix.ElementN(nc) = aframe12rotating.GetRot().e1; this.mask.Constr_N(nc).Get_Cq_a().FillElem(0); this.mask.Constr_N(nc).Get_Cq_b().FillElem(0); this.mask.Constr_N(nc).Get_Cq_a().PasteClippedMatrix(Jw1.nm.matrix, 0, 0, 1, 3, 0, 3); this.mask.Constr_N(nc).Get_Cq_b().PasteClippedMatrix(Jw2.nm.matrix, 0, 0, 1, 3, 0, 3); nc++; } if (c_ry) { this.C.matrix.ElementN(nc) = aframe12rotating.GetRot().e2; this.mask.Constr_N(nc).Get_Cq_a().FillElem(0); this.mask.Constr_N(nc).Get_Cq_b().FillElem(0); this.mask.Constr_N(nc).Get_Cq_a().PasteClippedMatrix(Jw1.nm.matrix, 1, 0, 1, 3, 0, 3); this.mask.Constr_N(nc).Get_Cq_b().PasteClippedMatrix(Jw2.nm.matrix, 1, 0, 1, 3, 0, 3); nc++; } if (c_rz) { this.C.matrix.ElementN(nc) = aframe12rotating.GetRot().e3; this.mask.Constr_N(nc).Get_Cq_a().FillElem(0); this.mask.Constr_N(nc).Get_Cq_b().FillElem(0); this.mask.Constr_N(nc).Get_Cq_a().PasteClippedMatrix(Jw1.nm.matrix, 2, 0, 1, 3, 0, 3); this.mask.Constr_N(nc).Get_Cq_b().PasteClippedMatrix(Jw2.nm.matrix, 2, 0, 1, 3, 0, 3); nc++; } } }
public override void update(double mytime, bool update_assets) { // Inherit parent class: base.update(mytime, update_assets); // Override the rotational jacobian [Cq] and the rotational residual C, // by assuming an additional hidden frame that rotates about frame2: if (this.Body1 != null && this.Body2 != null) { ChFrame <double> aframe1 = this.frame1.BitShiftRight(this.Body1); ChFrame <double> aframe2 = this.frame2.BitShiftRight(this.Body2); ChFrame <double> aframe12 = new ChFrame <double>();// ChFrame<double>.FNULL; aframe2.TransformParentToLocal(aframe1, aframe12); ChFrame <double> aframe2rotating = new ChFrame <double>();// ChFrame<double>.FNULL; double aux_rotation; aux_rotation = m_func.Get_y(mytime) + rot_offset; aframe2rotating.SetRot(aframe2.GetRot() * ChQuaternion.Q_from_AngAxis2(aux_rotation, ChVector.VECT_Z)); ChFrame <double> aframe12rotating = new ChFrame <double>(); // aframe2rotating.TransformParentToLocal(aframe1, aframe12rotating); ChMatrix33 <double> Jw1 = new ChMatrix33 <double>(0), Jw2 = new ChMatrix33 <double>(0); ChMatrix33 <double> mtempM = new ChMatrix33 <double>(0), mtempQ = new ChMatrix33 <double>(0); ChMatrix33 <double> abs_plane_rotating = aframe2rotating.GetA(); Jw1.nm.matrix.MatrTMultiply(abs_plane_rotating.nm.matrix, Body1.GetA().nm.matrix); Jw2.nm.matrix.MatrTMultiply(abs_plane_rotating.nm.matrix, Body2.GetA().nm.matrix); Jw2.nm.matrix.MatrNeg(); // Premultiply by Jw1 and Jw2 by 0.5*[Fp(q_resid)]' to get residual as imaginary part of a quaternion. /* mtempM.Set_X_matrix((aframe12rotating.GetRot().GetVector()) * 0.5); * mtempM.nm.matrix[0, 0] = 0.5 * aframe12rotating.GetRot().e0; * mtempM.nm.matrix[1, 1] = 0.5 * aframe12rotating.GetRot().e0; * mtempM.nm.matrix[2, 2] = 0.5 * aframe12rotating.GetRot().e0; * mtempQ.nm.matrix.MatrTMultiply(mtempM.nm.matrix, Jw1.nm.matrix); * Jw1 = mtempQ; * mtempQ.nm.matrix.MatrTMultiply(mtempM.nm.matrix, Jw2.nm.matrix); * Jw2 = mtempQ;*/ int nc = 0; if (c_x) { nc++; } if (c_y) { nc++; } if (c_z) { nc++; } if (c_rx) { this.C.matrix.ElementN(nc) = aframe12rotating.GetRot().e1; this.mask.Constr_N(nc).Get_Cq_a().FillElem(0); this.mask.Constr_N(nc).Get_Cq_b().FillElem(0); this.mask.Constr_N(nc).Get_Cq_a().PasteClippedMatrix(Jw1.nm.matrix, 0, 0, 1, 3, 0, 3); this.mask.Constr_N(nc).Get_Cq_b().PasteClippedMatrix(Jw2.nm.matrix, 0, 0, 1, 3, 0, 3); nc++; } if (c_ry) { this.C.matrix.ElementN(nc) = aframe12rotating.GetRot().e2; this.mask.Constr_N(nc).Get_Cq_a().FillElem(0); this.mask.Constr_N(nc).Get_Cq_b().FillElem(0); this.mask.Constr_N(nc).Get_Cq_a().PasteClippedMatrix(Jw1.nm.matrix, 1, 0, 1, 3, 0, 3); this.mask.Constr_N(nc).Get_Cq_b().PasteClippedMatrix(Jw2.nm.matrix, 1, 0, 1, 3, 0, 3); nc++; } if (c_rz) { this.C.matrix.ElementN(nc) = aframe12rotating.GetRot().e3; this.mask.Constr_N(nc).Get_Cq_a().FillElem(0); this.mask.Constr_N(nc).Get_Cq_b().FillElem(0); this.mask.Constr_N(nc).Get_Cq_a().PasteClippedMatrix(Jw1.nm.matrix, 2, 0, 1, 3, 0, 3); this.mask.Constr_N(nc).Get_Cq_b().PasteClippedMatrix(Jw2.nm.matrix, 2, 0, 1, 3, 0, 3); nc++; } } }