Actuator (Docstrings)¶
Implementations of actuators for linked force and torque application.
- class sympy.physics.mechanics.actuator.ActuatorBase[source]¶
Abstract base class for all actuator classes to inherit from.
Notes
Instances of this class cannot be directly instantiated by users. However, it can be used to created custom actuator types through subclassing.
- abstract to_loads()[source]¶
Loads required by the equations of motion method classes.
Explanation
KanesMethod
requires a list ofPoint
-Vector
tuples to be passed to theloads
parameters of itskanes_equations
method when constructing the equations of motion. This method acts as a utility to produce the correctly-structred pairs of points and vectors required so that these can be easily concatenated with other items in the list of loads and passed toKanesMethod.kanes_equations
. These loads are also in the correct form to also be passed to the other equations of motion method classes, e.g.LagrangesMethod
.
- class sympy.physics.mechanics.actuator.CoulombKineticFriction(
- mu_k,
- f_n,
- pathway,
- *,
- v_s=None,
- sigma=None,
- mu_s=None,
Coulomb kinetic friction with Stribeck and viscous effects.
- Parameters:
f_n : sympifiable
The normal force between the surfaces. It should always be a non-negative scalar.
mu_k : sympifiable
The coefficient of kinetic friction.
pathway : PathwayBase
The pathway that the actuator follows.
v_s : sympifiable, optional
The Stribeck friction coefficient.
sigma : sympifiable, optional
The viscous friction coefficient.
mu_s : sympifiable, optional
The coefficient of static friction. Defaults to mu_k, meaning the Stribeck effect evaluates to 0 by default.
Explanation
This represents a Coulomb kinetic friction with the Stribeck and viscous effect, described by the function:
\[F = (\mu_k f_n + (\mu_s - \mu_k) f_n e^{-(\frac{v}{v_s})^2}) \text{sign}(v) + \sigma v\]where \(\mu_k\) is the coefficient of kinetic friction, \(\mu_s\) is the coefficient of static friction, \(f_n\) is the normal force, \(v\) is the relative velocity, \(v_s\) is the Stribeck friction coefficient, and \(\sigma\) is the viscous friction constant.
The default friction force is \(F = \mu_k f_n\). When specified, the actuator includes:
Stribeck effect: \((\mu_s - \mu_k) f_n e^{-(\frac{v}{v_s})^2}\)
Viscous effect: \(\sigma v\)
Notes
The actuator makes the following assumptions:
The actuator assumes relative motion is non-zero.
The normal force is assumed to be a non-negative scalar.
The resultant friction force is opposite to the velocity direction.
Each point in the pathway is fixed within separate objects that are sliding relative to each other. In other words, these two points are fixed in the mutually sliding objects.
This actuator has been tested for straightforward motions, like a block sliding on a surface.
The friction force is defined to always oppose the direction of relative velocity \(v\). Specifically:
The default Coulomb friction force \(\mu_k f_n \text{sign}(v)\) is opposite to \(v\).
The Stribeck effect \((\mu_s - \mu_k) f_n e^{-(\frac{v}{v_s})^2} \text{sign}(v)\) is also opposite to \(v\).
The viscous friction term \(\sigma v\) is opposite to \(v\).
Examples
The below example shows how to generate the loads produced by a Coulomb kinetic friction actuator in a mass-spring system with friction.
>>> import sympy as sm >>> from sympy.physics.mechanics import (dynamicsymbols, ReferenceFrame, Point, ... LinearPathway, CoulombKineticFriction, LinearSpring, KanesMethod, Particle)
>>> x, v = dynamicsymbols('x, v', real=True) >>> m, g, k, mu_k, mu_s, v_s, sigma = sm.symbols('m, g, k, mu_k, mu_s, v_s, sigma')
>>> N = ReferenceFrame('N') >>> O, P = Point('O'), Point('P') >>> O.set_vel(N, 0) >>> P.set_pos(O, x*N.x)
>>> pathway = LinearPathway(O, P) >>> friction = CoulombKineticFriction(mu_k, m*g, pathway, v_s=v_s, sigma=sigma, mu_s=mu_k) >>> spring = LinearSpring(k, pathway) >>> block = Particle('block', point=P, mass=m)
>>> kane = KanesMethod(N, (x,), (v,), kd_eqs=(x.diff() - v,)) >>> friction.to_loads() [(O, (g*m*mu_k*sign(sign(x(t))*Derivative(x(t), t)) + sigma*sign(x(t))*Derivative(x(t), t))*x(t)/Abs(x(t))*N.x), (P, (-g*m*mu_k*sign(sign(x(t))*Derivative(x(t), t)) - sigma*sign(x(t))*Derivative(x(t), t))*x(t)/Abs(x(t))*N.x)] >>> loads = friction.to_loads() + spring.to_loads() >>> fr, frstar = kane.kanes_equations([block], loads) >>> eom = fr + frstar >>> eom Matrix([[-k*x(t) - m*Derivative(v(t), t) + (-g*m*mu_k*sign(v(t)*sign(x(t))) - sigma*v(t)*sign(x(t)))*x(t)/Abs(x(t))]])
References
[Flores2023]Paulo Flores, Jorge Ambrosio, Hamid M. Lankarani, “Contact-impact events with friction in multibody dynamics: Back to basics”, Mechanism and Machine Theory, vol. 184, 2023. https://doi.org/10.1016/j.mechmachtheory.2023.105305.
[Rogner2017]I. Rogner, “Friction modelling for robotic applications with planar motion”, Chalmers University of Technology, Department of Electrical Engineering, 2017.
- property f_n¶
The normal force between the surfaces.
- property mu_k¶
The coefficient of kinetic friction.
- property mu_s¶
The coefficient of static friction.
- property sigma¶
The viscous friction coefficient.
- property v_s¶
The Stribeck friction coefficient.
- class sympy.physics.mechanics.actuator.DuffingSpring(
- linear_stiffness,
- nonlinear_stiffness,
- pathway,
- equilibrium_length=0,
A nonlinear spring based on the Duffing equation.
- Parameters:
linear_stiffness : Expr
The linear stiffness coefficient (beta).
nonlinear_stiffness : Expr
The nonlinear stiffness coefficient (alpha).
pathway : PathwayBase
The pathway that the actuator follows.
equilibrium_length : Expr, optional
The length at which the spring is in equilibrium (x).
Explanation
Here,
DuffingSpring
represents the force exerted by a nonlinear spring based on the Duffing equation: F = -beta*x-alpha*x**3, where x is the displacement from the equilibrium position, beta is the linear spring constant, and alpha is the coefficient for the nonlinear cubic term.- property force¶
The force produced by the Duffing spring.
- class sympy.physics.mechanics.actuator.ForceActuator(force, pathway)[source]¶
Force-producing actuator.
- Parameters:
force : Expr
The scalar expression defining the (expansile) force that the actuator produces.
pathway : PathwayBase
The pathway that the actuator follows. This must be an instance of a concrete subclass of
PathwayBase
, e.g.LinearPathway
.
Explanation
A
ForceActuator
is an actuator that produces a (expansile) force along its length.A force actuator uses a pathway instance to determine the direction and number of forces that it applies to a system. Consider the simplest case where a
LinearPathway
instance is used. This pathway is made up of two points that can move relative to each other, and results in a pair of equal and opposite forces acting on the endpoints. If the positive time-varying Euclidean distance between the two points is defined, then the “extension velocity” is the time derivative of this distance. The extension velocity is positive when the two points are moving away from each other and negative when moving closer to each other. The direction for the force acting on either point is determined by constructing a unit vector directed from the other point to this point. This establishes a sign convention such that a positive force magnitude tends to push the points apart, this is the meaning of “expansile” in this context. The following diagram shows the positive force sense and the distance between the points:P Q o<--- F --->o | | |<--l(t)--->|
Examples
To construct an actuator, an expression (or symbol) must be supplied to represent the force it can produce, alongside a pathway specifying its line of action. Let’s also create a global reference frame and spatially fix one of the points in it while setting the other to be positioned such that it can freely move in the frame’s x direction specified by the coordinate
q
.>>> from sympy import symbols >>> from sympy.physics.mechanics import (ForceActuator, LinearPathway, ... Point, ReferenceFrame) >>> from sympy.physics.vector import dynamicsymbols >>> N = ReferenceFrame('N') >>> q = dynamicsymbols('q') >>> force = symbols('F') >>> pA, pB = Point('pA'), Point('pB') >>> pA.set_vel(N, 0) >>> pB.set_pos(pA, q*N.x) >>> pB.pos_from(pA) q(t)*N.x >>> linear_pathway = LinearPathway(pA, pB) >>> actuator = ForceActuator(force, linear_pathway) >>> actuator ForceActuator(F, LinearPathway(pA, pB))
- property force¶
The magnitude of the force produced by the actuator.
- property pathway¶
The
Pathway
defining the actuator’s line of action.
- to_loads()[source]¶
Loads required by the equations of motion method classes.
Explanation
KanesMethod
requires a list ofPoint
-Vector
tuples to be passed to theloads
parameters of itskanes_equations
method when constructing the equations of motion. This method acts as a utility to produce the correctly-structred pairs of points and vectors required so that these can be easily concatenated with other items in the list of loads and passed toKanesMethod.kanes_equations
. These loads are also in the correct form to also be passed to the other equations of motion method classes, e.g.LagrangesMethod
.Examples
The below example shows how to generate the loads produced by a force actuator that follows a linear pathway. In this example we’ll assume that the force actuator is being used to model a simple linear spring. First, create a linear pathway between two points separated by the coordinate
q
in thex
direction of the global frameN
.>>> from sympy.physics.mechanics import (LinearPathway, Point, ... ReferenceFrame) >>> from sympy.physics.vector import dynamicsymbols >>> q = dynamicsymbols('q') >>> N = ReferenceFrame('N') >>> pA, pB = Point('pA'), Point('pB') >>> pB.set_pos(pA, q*N.x) >>> pathway = LinearPathway(pA, pB)
Now create a symbol
k
to describe the spring’s stiffness and instantiate a force actuator that produces a (contractile) force proportional to both the spring’s stiffness and the pathway’s length. Note that actuator classes use the sign convention that expansile forces are positive, so for a spring to produce a contractile force the spring force needs to be calculated as the negative for the stiffness multiplied by the length.>>> from sympy import symbols >>> from sympy.physics.mechanics import ForceActuator >>> stiffness = symbols('k') >>> spring_force = -stiffness*pathway.length >>> spring = ForceActuator(spring_force, pathway)
The forces produced by the spring can be generated in the list of loads form that
KanesMethod
(and other equations of motion methods) requires by calling theto_loads
method.>>> spring.to_loads() [(pA, k*q(t)*N.x), (pB, - k*q(t)*N.x)]
A simple linear damper can be modeled in a similar way. Create another symbol
c
to describe the dampers damping coefficient. This time instantiate a force actuator that produces a force proportional to both the damper’s damping coefficient and the pathway’s extension velocity. Note that the damping force is negative as it acts in the opposite direction to which the damper is changing in length.>>> damping_coefficient = symbols('c') >>> damping_force = -damping_coefficient*pathway.extension_velocity >>> damper = ForceActuator(damping_force, pathway)
Again, the forces produces by the damper can be generated by calling the
to_loads
method.>>> damper.to_loads() [(pA, c*Derivative(q(t), t)*N.x), (pB, - c*Derivative(q(t), t)*N.x)]
- class sympy.physics.mechanics.actuator.LinearDamper(damping, pathway)[source]¶
A damper whose force is a linear function of its extension velocity.
- Parameters:
damping : Expr
The damping constant.
pathway : PathwayBase
The pathway that the actuator follows. This must be an instance of a concrete subclass of
PathwayBase
, e.g.LinearPathway
.
Explanation
Note that the “linear” in the name
LinearDamper
refers to the fact that the damping force is a linear function of the damper’s rate of change in its length. I.e. for a linear damper with dampingc
and extension velocityv
, the damping force will be-c*v
, which is a linear function inv
. To create a damper that follows a linear, or straight, pathway between its two ends, aLinearPathway
instance needs to be passed to thepathway
parameter.A
LinearDamper
is a subclass ofForceActuator
and so follows the same sign conventions for length, extension velocity, and the direction of the forces it applies to its points of attachment on bodies. The sign convention for the direction of forces is such that, for the case where a linear damper is instantiated with aLinearPathway
instance as its pathway, they act to push the two ends of the damper away from one another. Because dampers produce a force that opposes the direction of change in length, when extension velocity is positive the scalar portions of the forces applied at the two endpoints are negative in order to flip the sign of the forces on the endpoints wen converted into vector quantities. When extension velocity is negative (i.e. when the damper is shortening), the scalar portions of the fofces applied are also negative so that the signs cancel producing forces on the endpoints that are in the same direction as the positive sign convention for the forces at the endpoints of the pathway (i.e. they act to push the endpoints away from one another). The following diagram shows the positive force sense and the distance between the points:P Q o<--- F --->o | | |<--l(t)--->|
Examples
To construct a linear damper, an expression (or symbol) must be supplied to represent the damping coefficient of the damper (we’ll use the symbol
c
), alongside a pathway specifying its line of action. Let’s also create a global reference frame and spatially fix one of the points in it while setting the other to be positioned such that it can freely move in the frame’s x direction specified by the coordinateq
. The velocity that the two points move away from one another can be specified by the coordinateu
whereu
is the first time derivative ofq
(i.e.,u = Derivative(q(t), t)
).>>> from sympy import symbols >>> from sympy.physics.mechanics import (LinearDamper, LinearPathway, ... Point, ReferenceFrame) >>> from sympy.physics.vector import dynamicsymbols >>> N = ReferenceFrame('N') >>> q = dynamicsymbols('q') >>> damping = symbols('c') >>> pA, pB = Point('pA'), Point('pB') >>> pA.set_vel(N, 0) >>> pB.set_pos(pA, q*N.x) >>> pB.pos_from(pA) q(t)*N.x >>> pB.vel(N) Derivative(q(t), t)*N.x >>> linear_pathway = LinearPathway(pA, pB) >>> damper = LinearDamper(damping, linear_pathway) >>> damper LinearDamper(c, LinearPathway(pA, pB))
This damper will produce a force that is proportional to both its damping coefficient and the pathway’s extension length. Note that this force is negative as SymPy’s sign convention for actuators is that negative forces are contractile and the damping force of the damper will oppose the direction of length change.
>>> damper.force -c*sqrt(q(t)**2)*Derivative(q(t), t)/q(t)
See also
ForceActuator
force-producing actuator (superclass of
LinearDamper
).LinearPathway
straight-line pathway between a pair of points.
- property damping¶
The damping constant for the linear damper.
- property force¶
The damping force produced by the linear damper.
- class sympy.physics.mechanics.actuator.LinearSpring(
- stiffness,
- pathway,
- equilibrium_length=0,
A spring with its spring force as a linear function of its length.
- Parameters:
stiffness : Expr
The spring constant.
pathway : PathwayBase
The pathway that the actuator follows. This must be an instance of a concrete subclass of
PathwayBase
, e.g.LinearPathway
.equilibrium_length : Expr, optional
The length at which the spring is in equilibrium, i.e. it produces no force. The default value is 0, i.e. the spring force is a linear function of the pathway’s length with no constant offset.
Explanation
Note that the “linear” in the name
LinearSpring
refers to the fact that the spring force is a linear function of the springs length. I.e. for a linear spring with stiffnessk
, distance between its ends ofx
, and an equilibrium length of0
, the spring force will be-k*x
, which is a linear function inx
. To create a spring that follows a linear, or straight, pathway between its two ends, aLinearPathway
instance needs to be passed to thepathway
parameter.A
LinearSpring
is a subclass ofForceActuator
and so follows the same sign conventions for length, extension velocity, and the direction of the forces it applies to its points of attachment on bodies. The sign convention for the direction of forces is such that, for the case where a linear spring is instantiated with aLinearPathway
instance as its pathway, they act to push the two ends of the spring away from one another. Because springs produces a contractile force and acts to pull the two ends together towards the equilibrium length when stretched, the scalar portion of the forces on the endpoint are negative in order to flip the sign of the forces on the endpoints when converted into vector quantities. The following diagram shows the positive force sense and the distance between the points:P Q o<--- F --->o | | |<--l(t)--->|
Examples
To construct a linear spring, an expression (or symbol) must be supplied to represent the stiffness (spring constant) of the spring, alongside a pathway specifying its line of action. Let’s also create a global reference frame and spatially fix one of the points in it while setting the other to be positioned such that it can freely move in the frame’s x direction specified by the coordinate
q
.>>> from sympy import symbols >>> from sympy.physics.mechanics import (LinearPathway, LinearSpring, ... Point, ReferenceFrame) >>> from sympy.physics.vector import dynamicsymbols >>> N = ReferenceFrame('N') >>> q = dynamicsymbols('q') >>> stiffness = symbols('k') >>> pA, pB = Point('pA'), Point('pB') >>> pA.set_vel(N, 0) >>> pB.set_pos(pA, q*N.x) >>> pB.pos_from(pA) q(t)*N.x >>> linear_pathway = LinearPathway(pA, pB) >>> spring = LinearSpring(stiffness, linear_pathway) >>> spring LinearSpring(k, LinearPathway(pA, pB))
This spring will produce a force that is proportional to both its stiffness and the pathway’s length. Note that this force is negative as SymPy’s sign convention for actuators is that negative forces are contractile.
>>> spring.force -k*sqrt(q(t)**2)
To create a linear spring with a non-zero equilibrium length, an expression (or symbol) can be passed to the
equilibrium_length
parameter on construction on aLinearSpring
instance. Let’s create a symboll
to denote a non-zero equilibrium length and create another linear spring.>>> l = symbols('l') >>> spring = LinearSpring(stiffness, linear_pathway, equilibrium_length=l) >>> spring LinearSpring(k, LinearPathway(pA, pB), equilibrium_length=l)
The spring force of this new spring is again proportional to both its stiffness and the pathway’s length. However, the spring will not produce any force when
q(t)
equalsl
. Note that the force will become expansile whenq(t)
is less thanl
, as expected.>>> spring.force -k*(-l + sqrt(q(t)**2))
See also
ForceActuator
force-producing actuator (superclass of
LinearSpring
).LinearPathway
straight-line pathway between a pair of points.
- property equilibrium_length¶
The length of the spring at which it produces no force.
- property force¶
The spring force produced by the linear spring.
- property stiffness¶
The spring constant for the linear spring.
- class sympy.physics.mechanics.actuator.TorqueActuator(
- torque,
- axis,
- target_frame,
- reaction_frame=None,
Torque-producing actuator.
- Parameters:
torque : Expr
The scalar expression defining the torque that the actuator produces.
axis : Vector
The axis about which the actuator applies torques.
target_frame : ReferenceFrame | RigidBody
The primary frame on which the actuator will apply the torque.
reaction_frame : ReferenceFrame | RigidBody | None
The secondary frame on which the actuator will apply the torque. Note that the (equal and opposite) reaction torque is applied to this frame.
Explanation
A
TorqueActuator
is an actuator that produces a pair of equal and opposite torques on a pair of bodies.Examples
To construct a torque actuator, an expression (or symbol) must be supplied to represent the torque it can produce, alongside a vector specifying the axis about which the torque will act, and a pair of frames on which the torque will act.
>>> from sympy import symbols >>> from sympy.physics.mechanics import (ReferenceFrame, RigidBody, ... TorqueActuator) >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> torque = symbols('T') >>> axis = N.z >>> parent = RigidBody('parent', frame=N) >>> child = RigidBody('child', frame=A) >>> bodies = (child, parent) >>> actuator = TorqueActuator(torque, axis, *bodies) >>> actuator TorqueActuator(T, axis=N.z, target_frame=A, reaction_frame=N)
Note that because torques actually act on frames, not bodies,
TorqueActuator
will extract the frame associated with aRigidBody
when one is passed instead of aReferenceFrame
.- classmethod at_pin_joint(torque, pin_joint)[source]¶
Alternate construtor to instantiate from a
PinJoint
instance.- Parameters:
torque : Expr
The scalar expression defining the torque that the actuator produces.
pin_joint : PinJoint
The pin joint, and by association the parent and child bodies, on which the torque actuator will act. The pair of bodies acted upon by the torque actuator are the parent and child bodies of the pin joint, with the child acting as the reaction body. The pin joint’s axis is used as the axis about which the torque actuator will apply its torque.
Examples
To create a pin joint the
PinJoint
class requires a name, parent body, and child body to be passed to its constructor. It is also possible to control the joint axis using thejoint_axis
keyword argument. In this example let’s use the parent body’s reference frame’s z-axis as the joint axis.>>> from sympy.physics.mechanics import (PinJoint, ReferenceFrame, ... RigidBody, TorqueActuator) >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> parent = RigidBody('parent', frame=N) >>> child = RigidBody('child', frame=A) >>> pin_joint = PinJoint( ... 'pin', ... parent, ... child, ... joint_axis=N.z, ... )
Let’s also create a symbol
T
that will represent the torque applied by the torque actuator.>>> from sympy import symbols >>> torque = symbols('T')
To create the torque actuator from the
torque
andpin_joint
variables previously instantiated, these can be passed to the alternate constructor class methodat_pin_joint
of theTorqueActuator
class. It should be noted that a positive torque will cause a positive displacement of the joint coordinate or that the torque is applied on the child body with a reaction torque on the parent.>>> actuator = TorqueActuator.at_pin_joint(torque, pin_joint) >>> actuator TorqueActuator(T, axis=N.z, target_frame=A, reaction_frame=N)
- property axis¶
The axis about which the torque acts.
- property reaction_frame¶
The primary reference frames on which the torque will act.
- property target_frame¶
The primary reference frames on which the torque will act.
- to_loads()[source]¶
Loads required by the equations of motion method classes.
Explanation
KanesMethod
requires a list ofPoint
-Vector
tuples to be passed to theloads
parameters of itskanes_equations
method when constructing the equations of motion. This method acts as a utility to produce the correctly-structred pairs of points and vectors required so that these can be easily concatenated with other items in the list of loads and passed toKanesMethod.kanes_equations
. These loads are also in the correct form to also be passed to the other equations of motion method classes, e.g.LagrangesMethod
.Examples
The below example shows how to generate the loads produced by a torque actuator that acts on a pair of bodies attached by a pin joint.
>>> from sympy import symbols >>> from sympy.physics.mechanics import (PinJoint, ReferenceFrame, ... RigidBody, TorqueActuator) >>> torque = symbols('T') >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> parent = RigidBody('parent', frame=N) >>> child = RigidBody('child', frame=A) >>> pin_joint = PinJoint( ... 'pin', ... parent, ... child, ... joint_axis=N.z, ... ) >>> actuator = TorqueActuator.at_pin_joint(torque, pin_joint)
The forces produces by the damper can be generated by calling the
to_loads
method.>>> actuator.to_loads() [(A, T*N.z), (N, - T*N.z)]
Alternatively, if a torque actuator is created without a reaction frame then the loads returned by the
to_loads
method will contain just the single load acting on the target frame.>>> actuator = TorqueActuator(torque, N.z, N) >>> actuator.to_loads() [(N, T*N.z)]
- property torque¶
The magnitude of the torque produced by the actuator.