public override SolverUpdateable GetBaseJoint() { LinearAxisMotor lam = new LinearAxisMotor(Ent1.Body, Ent2.Body, Ent2.GetPosition().ToBVector(), Ent2.GetPosition().ToBVector(), Axis.ToBVector()); lam.Settings.Mode = Mode ? MotorMode.Servomechanism : MotorMode.VelocityMotor; lam.Settings.Servo.Goal = 1; lam.Settings.Servo.SpringSettings.Stiffness = 300; lam.Settings.Servo.SpringSettings.Damping = 70; return lam; }
/// <summary> /// Constructs a new constraint which restricts two degrees of linear freedom and two degrees of angular freedom between two entities. /// This constructs the internal constraints, but does not configure them. Before using a constraint constructed in this manner, /// ensure that its active constituent constraints are properly configured. The entire group as well as all internal constraints are initially inactive (IsActive = false). /// </summary> public LineSliderJoint() { IsActive = false; PointOnLineJoint = new PointOnLineJoint(); AngularJoint = new RevoluteAngularJoint(); Limit = new LinearAxisLimit(); Motor = new LinearAxisMotor(); Add(PointOnLineJoint); Add(AngularJoint); Add(Limit); Add(Motor); }
/// <summary> /// Constructs a new constraint which restricts two degrees of linear freedom and all three degrees of angular freedom. /// This constructs the internal constraints, but does not configure them. Before using a constraint constructed in this manner, /// ensure that its active constituent constraints are properly configured. The entire group as well as all internal constraints are initially inactive (IsActive = false). /// </summary> public PrismaticJoint() { IsActive = false; PointOnLineJoint = new PointOnLineJoint(); AngularJoint = new NoRotationJoint(); Limit = new LinearAxisLimit(); Motor = new LinearAxisMotor(); Add(PointOnLineJoint); Add(AngularJoint); Add(Limit); Add(Motor); }
/// <summary> /// Constructs a new constraint which restricts one linear degree of freedom between two entities. /// This constructs the internal constraints, but does not configure them. Before using a constraint constructed in this manner, /// ensure that its active constituent constraints are properly configured. The entire group as well as all internal constraints are initially inactive (IsActive = false). /// </summary> public PlaneSliderJoint() { IsActive = false; PointOnPlaneJoint = new PointOnPlaneJoint(); LimitX = new LinearAxisLimit(); MotorX = new LinearAxisMotor(); LimitY = new LinearAxisLimit(); MotorY = new LinearAxisMotor(); Add(PointOnPlaneJoint); Add(LimitX); Add(MotorX); Add(LimitY); Add(MotorY); }
/// <summary> /// Constructs a new constraint which restricts two degrees of linear freedom and all three degrees of angular freedom. /// </summary> /// <param name="connectionA">First entity of the constraint pair.</param> /// <param name="connectionB">Second entity of the constraint pair.</param> /// <param name="lineAnchor">Location of the anchor for the line to be attached to connectionA in world space.</param> /// <param name="lineDirection">Axis in world space to be attached to connectionA along which connectionB can move.</param> /// <param name="pointAnchor">Location of the anchor for the point to be attached to connectionB in world space.</param> public PrismaticJoint(Entity connectionA, Entity connectionB, Vector3 lineAnchor, Vector3 lineDirection, Vector3 pointAnchor) { if (connectionA == null) connectionA = TwoEntityConstraint.WorldEntity; if (connectionB == null) connectionB = TwoEntityConstraint.WorldEntity; PointOnLineJoint = new PointOnLineJoint(connectionA, connectionB, lineAnchor, lineDirection, pointAnchor); AngularJoint = new NoRotationJoint(connectionA, connectionB); Limit = new LinearAxisLimit(connectionA, connectionB, lineAnchor, pointAnchor, lineDirection, 0, 0); Motor = new LinearAxisMotor(connectionA, connectionB, lineAnchor, pointAnchor, lineDirection); Limit.IsActive = false; Motor.IsActive = false; Add(PointOnLineJoint); Add(AngularJoint); Add(Limit); Add(Motor); }
/// <summary> /// Constructs a new constraint which restricts two degrees of linear freedom and two degrees of angular freedom between two entities. /// </summary> /// <param name="connectionA">First entity of the constraint pair.</param> /// <param name="connectionB">Second entity of the constraint pair.</param> /// <param name="lineAnchor">Location of the anchor for the line to be attached to connectionA in world space.</param> /// <param name="lineDirection">Axis in world space to be attached to connectionA along which connectionB can move and rotate.</param> /// <param name="pointAnchor">Location of the anchor for the point to be attached to connectionB in world space.</param> public LineSliderJoint(Entity connectionA, Entity connectionB, System.Numerics.Vector3 lineAnchor, System.Numerics.Vector3 lineDirection, System.Numerics.Vector3 pointAnchor) { if (connectionA == null) connectionA = TwoEntityConstraint.WorldEntity; if (connectionB == null) connectionB = TwoEntityConstraint.WorldEntity; PointOnLineJoint = new PointOnLineJoint(connectionA, connectionB, lineAnchor, lineDirection, pointAnchor); AngularJoint = new RevoluteAngularJoint(connectionA, connectionB, lineDirection); Limit = new LinearAxisLimit(connectionA, connectionB, lineAnchor, pointAnchor, lineDirection, 0, 0); Motor = new LinearAxisMotor(connectionA, connectionB, lineAnchor, pointAnchor, lineDirection); Limit.IsActive = false; Motor.IsActive = false; Add(PointOnLineJoint); Add(AngularJoint); Add(Limit); Add(Motor); }
/// <summary> /// Constructs a new constraint which restricts one linear degree of freedom between two entities. /// </summary> /// <param name="connectionA">First entity of the constraint pair.</param> /// <param name="connectionB">Second entity of the constraint pair.</param> /// <param name="planeAnchor">Location of the anchor for the plane to be attached to connectionA in world space.</param> /// <param name="planeNormal">Normal of the plane constraint in world space.</param> /// <param name="xAxis">Direction in world space along which the X axis LinearAxisLimit and LinearAxisMotor work. /// This is usually chosen to be perpendicular to the planeNormal and the yAxis.</param> /// <param name="yAxis">Direction in world space along which the Y axis LinearAxisLimit and LinearAxisMotor work. /// This is usually chosen to be perpendicular to the planeNormal and the xAxis.</param> /// <param name="pointAnchor">Location of the anchor for the point to be attached to connectionB in world space.</param> public PlaneSliderJoint(Entity connectionA, Entity connectionB, Vector3 planeAnchor, Vector3 planeNormal, Vector3 xAxis, Vector3 yAxis, Vector3 pointAnchor) { if (connectionA == null) connectionA = TwoEntityConstraint.WorldEntity; if (connectionB == null) connectionB = TwoEntityConstraint.WorldEntity; PointOnPlaneJoint = new PointOnPlaneJoint(connectionA, connectionB, planeAnchor, planeNormal, pointAnchor); LimitX = new LinearAxisLimit(connectionA, connectionB, planeAnchor, pointAnchor, xAxis, 0, 0); MotorX = new LinearAxisMotor(connectionA, connectionB, planeAnchor, pointAnchor, xAxis); LimitY = new LinearAxisLimit(connectionA, connectionB, planeAnchor, pointAnchor, yAxis, 0, 0); MotorY = new LinearAxisMotor(connectionA, connectionB, planeAnchor, pointAnchor, yAxis); LimitX.IsActive = false; MotorX.IsActive = false; LimitY.IsActive = false; MotorY.IsActive = false; Add(PointOnPlaneJoint); Add(LimitX); Add(MotorX); Add(LimitY); Add(MotorY); }
void AddBackWheel(Vector3 wheelOffset, Entity body) { var wheel = new Cylinder(body.Position + wheelOffset, .4f, .5f, 5f); wheel.Material.KineticFriction = 2.5f; wheel.Material.StaticFriction = 3.5f; wheel.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2); //Preventing the occasional pointless collision pair can speed things up. CollisionRules.AddRule(wheel, body, CollisionRule.NoBroadPhase); //Connect the wheel to the body. var pointOnLineJoint = new PointOnLineJoint(body, wheel, wheel.Position, Vector3.Down, wheel.Position); var suspensionLimit = new LinearAxisLimit(body, wheel, wheel.Position, wheel.Position, Vector3.Down, -1, 0); //This linear axis motor will give the suspension its springiness by pushing the wheels outward. var suspensionSpring = new LinearAxisMotor(body, wheel, wheel.Position, wheel.Position, Vector3.Down); suspensionSpring.Settings.Mode = MotorMode.Servomechanism; suspensionSpring.Settings.Servo.Goal = 0; suspensionSpring.Settings.Servo.SpringSettings.Stiffness = 300; suspensionSpring.Settings.Servo.SpringSettings.Damping = 70; var revoluteAngularJoint = new RevoluteAngularJoint(body, wheel, Vector3.Right); //Add the wheel and connection to the space. Space.Add(wheel); Space.Add(pointOnLineJoint); Space.Add(suspensionLimit); Space.Add(suspensionSpring); Space.Add(revoluteAngularJoint); }
Entity AddDriveWheel(Vector3 wheelOffset, Entity body, out RevoluteMotor drivingMotor, out RevoluteMotor steeringMotor) { var wheel = new Cylinder(body.Position + wheelOffset, .4f, .5f, 5f); wheel.Material.KineticFriction = 2.5f; wheel.Material.StaticFriction = 3.5f; wheel.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2); //Preventing the occasional pointless collision pair can speed things up. CollisionRules.AddRule(wheel, body, CollisionRule.NoBroadPhase); //Connect the wheel to the body. var pointOnLineJoint = new PointOnLineJoint(body, wheel, wheel.Position, Vector3.Down, wheel.Position); var suspensionLimit = new LinearAxisLimit(body, wheel, wheel.Position, wheel.Position, Vector3.Down, -1, 0); //This linear axis motor will give the suspension its springiness by pushing the wheels outward. var suspensionSpring = new LinearAxisMotor(body, wheel, wheel.Position, wheel.Position, Vector3.Down); suspensionSpring.Settings.Mode = MotorMode.Servomechanism; suspensionSpring.Settings.Servo.Goal = 0; suspensionSpring.Settings.Servo.SpringSettings.Stiffness = 300; suspensionSpring.Settings.Servo.SpringSettings.Damping = 70; var swivelHingeAngularJoint = new SwivelHingeAngularJoint(body, wheel, Vector3.Up, Vector3.Right); //Motorize the wheel. drivingMotor = new RevoluteMotor(body, wheel, Vector3.Left); drivingMotor.Settings.VelocityMotor.Softness = .3f; drivingMotor.Settings.MaximumForce = 100; //Let it roll when the user isn't giving specific commands. drivingMotor.IsActive = false; steeringMotor = new RevoluteMotor(body, wheel, Vector3.Up); steeringMotor.Settings.Mode = MotorMode.Servomechanism; //The constructor makes a guess about how to set up the constraint. //It can't always be right since it doesn't have all the information; //in this case, it chooses the basis and test axis incorrectly. //This leads to a 'flipping' behavior when the wheel is rolling //(the test axis is 'rolling' with the wheel, and passes over //a singularity which causes a flip). //To fix this, we configure the constraint directly. //The basis is aligned with how the wheel is set up; we choose 'up' as //the motorized axis, and right/forward to define the angle measurement plane. //The test axis is set to be perpendicular to the wheel's rotation so that //it only measures the steering angle. //If you're curious, the angle measurement is just a Math.Atan2. //The current world test axis is dotted against the two plane axes (Right and Forward here). //This gives an x and y value. These can be plugged into Atan2 just like when //you compute an angle on a normal 2d graph. steeringMotor.Basis.SetWorldAxes(Vector3.Up, Vector3.Right); steeringMotor.TestAxis = Vector3.Right; steeringMotor.Settings.Servo.BaseCorrectiveSpeed = 5; //The revolute motor is weaker than some other types of constraints and maintaining a goal in the presence of extremely fast rotation and integration issues. //Laying a revolute limit on top of it can help mitigate the problem. var steeringConstraint = new RevoluteLimit(body, wheel, Vector3.Up, Vector3.Right, -maximumTurnAngle, maximumTurnAngle); //Add the wheel and connection to the space. Space.Add(wheel); Space.Add(pointOnLineJoint); Space.Add(suspensionLimit); Space.Add(suspensionSpring); Space.Add(swivelHingeAngularJoint); Space.Add(drivingMotor); Space.Add(steeringMotor); Space.Add(steeringConstraint); return wheel; }
public TreadSegment(Vector3 segmentPosition, Entity body, TreadSegmentDescription treadSegmentDescription) { Entity = new Cylinder(segmentPosition, treadSegmentDescription.Width, treadSegmentDescription.Radius, treadSegmentDescription.Mass); Entity.Material.KineticFriction = treadSegmentDescription.Friction; Entity.Material.StaticFriction = treadSegmentDescription.Friction; Entity.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2); //Preventing the occasional pointless collision pair can speed things up. CollisionRules.AddRule(Entity, body, CollisionRule.NoBroadPhase); //Connect the wheel to the body. SuspensionAxisJoint = new PointOnLineJoint(body, Entity, Entity.Position, Vector3.Down, Entity.Position); SuspensionLengthLimit = new LinearAxisLimit(body, Entity, Entity.Position, Entity.Position, Vector3.Down, -treadSegmentDescription.SuspensionLength, 0); //This linear axis motor will give the suspension its springiness by pushing the wheels outward. SuspensionSpring = new LinearAxisMotor(body, Entity, Entity.Position, Entity.Position, Vector3.Down); SuspensionSpring.Settings.Mode = MotorMode.Servomechanism; SuspensionSpring.Settings.Servo.Goal = 0; SuspensionSpring.Settings.Servo.SpringSettings.Stiffness = treadSegmentDescription.SuspensionStiffness; SuspensionSpring.Settings.Servo.SpringSettings.Damping = treadSegmentDescription.SuspensionDamping; SuspensionAngularJoint = new RevoluteAngularJoint(body, Entity, Vector3.Right); //Make the joint extremely rigid. There are going to be extreme conditions when the wheels get up to speed; //we don't want the forces involved to torque the wheel off the frame! SuspensionAngularJoint.SpringSettings.Damping *= Entity.Mass * 50; SuspensionAngularJoint.SpringSettings.Stiffness *= Entity.Mass * 50; //Motorize the wheel. Motor = new RevoluteMotor(body, Entity, Vector3.Left); Motor.Settings.VelocityMotor.Softness = treadSegmentDescription.MotorSoftness; Motor.Settings.MaximumForce = treadSegmentDescription.MotorMaximumForce; }