Kano001's picture
Upload 3077 files
6a86ad5 verified
raw
history blame
24.9 kB
"""Tests for the ``sympy.physics.mechanics.pathway.py`` module."""
import pytest
from sympy import (
Rational,
Symbol,
cos,
pi,
sin,
sqrt,
)
from sympy.physics.mechanics import (
Force,
LinearPathway,
ObstacleSetPathway,
PathwayBase,
Point,
ReferenceFrame,
WrappingCylinder,
WrappingGeometryBase,
WrappingPathway,
WrappingSphere,
dynamicsymbols,
)
from sympy.simplify.simplify import simplify
def _simplify_loads(loads):
return [
load.__class__(load.location, load.vector.simplify())
for load in loads
]
class TestLinearPathway:
def test_is_pathway_base_subclass(self):
assert issubclass(LinearPathway, PathwayBase)
@staticmethod
@pytest.mark.parametrize(
'args, kwargs',
[
((Point('pA'), Point('pB')), {}),
]
)
def test_valid_constructor(args, kwargs):
pointA, pointB = args
instance = LinearPathway(*args, **kwargs)
assert isinstance(instance, LinearPathway)
assert hasattr(instance, 'attachments')
assert len(instance.attachments) == 2
assert instance.attachments[0] is pointA
assert instance.attachments[1] is pointB
assert isinstance(instance.attachments[0], Point)
assert instance.attachments[0].name == 'pA'
assert isinstance(instance.attachments[1], Point)
assert instance.attachments[1].name == 'pB'
@staticmethod
@pytest.mark.parametrize(
'attachments',
[
(Point('pA'), ),
(Point('pA'), Point('pB'), Point('pZ')),
]
)
def test_invalid_attachments_incorrect_number(attachments):
with pytest.raises(ValueError):
_ = LinearPathway(*attachments)
@staticmethod
@pytest.mark.parametrize(
'attachments',
[
(None, Point('pB')),
(Point('pA'), None),
]
)
def test_invalid_attachments_not_point(attachments):
with pytest.raises(TypeError):
_ = LinearPathway(*attachments)
@pytest.fixture(autouse=True)
def _linear_pathway_fixture(self):
self.N = ReferenceFrame('N')
self.pA = Point('pA')
self.pB = Point('pB')
self.pathway = LinearPathway(self.pA, self.pB)
self.q1 = dynamicsymbols('q1')
self.q2 = dynamicsymbols('q2')
self.q3 = dynamicsymbols('q3')
self.q1d = dynamicsymbols('q1', 1)
self.q2d = dynamicsymbols('q2', 1)
self.q3d = dynamicsymbols('q3', 1)
self.F = Symbol('F')
def test_properties_are_immutable(self):
instance = LinearPathway(self.pA, self.pB)
with pytest.raises(AttributeError):
instance.attachments = None
with pytest.raises(TypeError):
instance.attachments[0] = None
with pytest.raises(TypeError):
instance.attachments[1] = None
def test_repr(self):
pathway = LinearPathway(self.pA, self.pB)
expected = 'LinearPathway(pA, pB)'
assert repr(pathway) == expected
def test_static_pathway_length(self):
self.pB.set_pos(self.pA, 2*self.N.x)
assert self.pathway.length == 2
def test_static_pathway_extension_velocity(self):
self.pB.set_pos(self.pA, 2*self.N.x)
assert self.pathway.extension_velocity == 0
def test_static_pathway_to_loads(self):
self.pB.set_pos(self.pA, 2*self.N.x)
expected = [
(self.pA, - self.F*self.N.x),
(self.pB, self.F*self.N.x),
]
assert self.pathway.to_loads(self.F) == expected
def test_2D_pathway_length(self):
self.pB.set_pos(self.pA, 2*self.q1*self.N.x)
expected = 2*sqrt(self.q1**2)
assert self.pathway.length == expected
def test_2D_pathway_extension_velocity(self):
self.pB.set_pos(self.pA, 2*self.q1*self.N.x)
expected = 2*sqrt(self.q1**2)*self.q1d/self.q1
assert self.pathway.extension_velocity == expected
def test_2D_pathway_to_loads(self):
self.pB.set_pos(self.pA, 2*self.q1*self.N.x)
expected = [
(self.pA, - self.F*(self.q1 / sqrt(self.q1**2))*self.N.x),
(self.pB, self.F*(self.q1 / sqrt(self.q1**2))*self.N.x),
]
assert self.pathway.to_loads(self.F) == expected
def test_3D_pathway_length(self):
self.pB.set_pos(
self.pA,
self.q1*self.N.x - self.q2*self.N.y + 2*self.q3*self.N.z,
)
expected = sqrt(self.q1**2 + self.q2**2 + 4*self.q3**2)
assert simplify(self.pathway.length - expected) == 0
def test_3D_pathway_extension_velocity(self):
self.pB.set_pos(
self.pA,
self.q1*self.N.x - self.q2*self.N.y + 2*self.q3*self.N.z,
)
length = sqrt(self.q1**2 + self.q2**2 + 4*self.q3**2)
expected = (
self.q1*self.q1d/length
+ self.q2*self.q2d/length
+ 4*self.q3*self.q3d/length
)
assert simplify(self.pathway.extension_velocity - expected) == 0
def test_3D_pathway_to_loads(self):
self.pB.set_pos(
self.pA,
self.q1*self.N.x - self.q2*self.N.y + 2*self.q3*self.N.z,
)
length = sqrt(self.q1**2 + self.q2**2 + 4*self.q3**2)
pO_force = (
- self.F*self.q1*self.N.x/length
+ self.F*self.q2*self.N.y/length
- 2*self.F*self.q3*self.N.z/length
)
pI_force = (
self.F*self.q1*self.N.x/length
- self.F*self.q2*self.N.y/length
+ 2*self.F*self.q3*self.N.z/length
)
expected = [
(self.pA, pO_force),
(self.pB, pI_force),
]
assert self.pathway.to_loads(self.F) == expected
class TestObstacleSetPathway:
def test_is_pathway_base_subclass(self):
assert issubclass(ObstacleSetPathway, PathwayBase)
@staticmethod
@pytest.mark.parametrize(
'num_attachments, attachments',
[
(3, [Point(name) for name in ('pO', 'pA', 'pI')]),
(4, [Point(name) for name in ('pO', 'pA', 'pB', 'pI')]),
(5, [Point(name) for name in ('pO', 'pA', 'pB', 'pC', 'pI')]),
(6, [Point(name) for name in ('pO', 'pA', 'pB', 'pC', 'pD', 'pI')]),
]
)
def test_valid_constructor(num_attachments, attachments):
instance = ObstacleSetPathway(*attachments)
assert isinstance(instance, ObstacleSetPathway)
assert hasattr(instance, 'attachments')
assert len(instance.attachments) == num_attachments
for attachment in instance.attachments:
assert isinstance(attachment, Point)
@staticmethod
@pytest.mark.parametrize(
'attachments',
[[Point('pO')], [Point('pO'), Point('pI')]],
)
def test_invalid_constructor_attachments_incorrect_number(attachments):
with pytest.raises(ValueError):
_ = ObstacleSetPathway(*attachments)
@staticmethod
@pytest.mark.parametrize(
'attachments',
[
(None, Point('pA'), Point('pI')),
(Point('pO'), None, Point('pI')),
(Point('pO'), Point('pA'), None),
]
)
def test_invalid_constructor_attachments_not_point(attachments):
with pytest.raises(TypeError):
_ = WrappingPathway(*attachments) # type: ignore
def test_properties_are_immutable(self):
pathway = ObstacleSetPathway(Point('pO'), Point('pA'), Point('pI'))
with pytest.raises(AttributeError):
pathway.attachments = None # type: ignore
with pytest.raises(TypeError):
pathway.attachments[0] = None # type: ignore
with pytest.raises(TypeError):
pathway.attachments[1] = None # type: ignore
with pytest.raises(TypeError):
pathway.attachments[-1] = None # type: ignore
@staticmethod
@pytest.mark.parametrize(
'attachments, expected',
[
(
[Point(name) for name in ('pO', 'pA', 'pI')],
'ObstacleSetPathway(pO, pA, pI)'
),
(
[Point(name) for name in ('pO', 'pA', 'pB', 'pI')],
'ObstacleSetPathway(pO, pA, pB, pI)'
),
(
[Point(name) for name in ('pO', 'pA', 'pB', 'pC', 'pI')],
'ObstacleSetPathway(pO, pA, pB, pC, pI)'
),
]
)
def test_repr(attachments, expected):
pathway = ObstacleSetPathway(*attachments)
assert repr(pathway) == expected
@pytest.fixture(autouse=True)
def _obstacle_set_pathway_fixture(self):
self.N = ReferenceFrame('N')
self.pO = Point('pO')
self.pI = Point('pI')
self.pA = Point('pA')
self.pB = Point('pB')
self.q = dynamicsymbols('q')
self.qd = dynamicsymbols('q', 1)
self.F = Symbol('F')
def test_static_pathway_length(self):
self.pA.set_pos(self.pO, self.N.x)
self.pB.set_pos(self.pO, self.N.y)
self.pI.set_pos(self.pO, self.N.z)
pathway = ObstacleSetPathway(self.pO, self.pA, self.pB, self.pI)
assert pathway.length == 1 + 2 * sqrt(2)
def test_static_pathway_extension_velocity(self):
self.pA.set_pos(self.pO, self.N.x)
self.pB.set_pos(self.pO, self.N.y)
self.pI.set_pos(self.pO, self.N.z)
pathway = ObstacleSetPathway(self.pO, self.pA, self.pB, self.pI)
assert pathway.extension_velocity == 0
def test_static_pathway_to_loads(self):
self.pA.set_pos(self.pO, self.N.x)
self.pB.set_pos(self.pO, self.N.y)
self.pI.set_pos(self.pO, self.N.z)
pathway = ObstacleSetPathway(self.pO, self.pA, self.pB, self.pI)
expected = [
Force(self.pO, -self.F * self.N.x),
Force(self.pA, self.F * self.N.x),
Force(self.pA, self.F * sqrt(2) / 2 * (self.N.x - self.N.y)),
Force(self.pB, self.F * sqrt(2) / 2 * (self.N.y - self.N.x)),
Force(self.pB, self.F * sqrt(2) / 2 * (self.N.y - self.N.z)),
Force(self.pI, self.F * sqrt(2) / 2 * (self.N.z - self.N.y)),
]
assert pathway.to_loads(self.F) == expected
def test_2D_pathway_length(self):
self.pA.set_pos(self.pO, -(self.N.x + self.N.y))
self.pB.set_pos(
self.pO, cos(self.q) * self.N.x - (sin(self.q) + 1) * self.N.y
)
self.pI.set_pos(
self.pO, sin(self.q) * self.N.x + (cos(self.q) - 1) * self.N.y
)
pathway = ObstacleSetPathway(self.pO, self.pA, self.pB, self.pI)
expected = 2 * sqrt(2) + sqrt(2 + 2*cos(self.q))
assert (pathway.length - expected).simplify() == 0
def test_2D_pathway_extension_velocity(self):
self.pA.set_pos(self.pO, -(self.N.x + self.N.y))
self.pB.set_pos(
self.pO, cos(self.q) * self.N.x - (sin(self.q) + 1) * self.N.y
)
self.pI.set_pos(
self.pO, sin(self.q) * self.N.x + (cos(self.q) - 1) * self.N.y
)
pathway = ObstacleSetPathway(self.pO, self.pA, self.pB, self.pI)
expected = - (sqrt(2) * sin(self.q) * self.qd) / (2 * sqrt(cos(self.q) + 1))
assert (pathway.extension_velocity - expected).simplify() == 0
def test_2D_pathway_to_loads(self):
self.pA.set_pos(self.pO, -(self.N.x + self.N.y))
self.pB.set_pos(
self.pO, cos(self.q) * self.N.x - (sin(self.q) + 1) * self.N.y
)
self.pI.set_pos(
self.pO, sin(self.q) * self.N.x + (cos(self.q) - 1) * self.N.y
)
pathway = ObstacleSetPathway(self.pO, self.pA, self.pB, self.pI)
pO_pA_force_vec = sqrt(2) / 2 * (self.N.x + self.N.y)
pA_pB_force_vec = (
- sqrt(2 * cos(self.q) + 2) / 2 * self.N.x
+ sqrt(2) * sin(self.q) / (2 * sqrt(cos(self.q) + 1)) * self.N.y
)
pB_pI_force_vec = cos(self.q + pi/4) * self.N.x - sin(self.q + pi/4) * self.N.y
expected = [
Force(self.pO, self.F * pO_pA_force_vec),
Force(self.pA, -self.F * pO_pA_force_vec),
Force(self.pA, self.F * pA_pB_force_vec),
Force(self.pB, -self.F * pA_pB_force_vec),
Force(self.pB, self.F * pB_pI_force_vec),
Force(self.pI, -self.F * pB_pI_force_vec),
]
assert _simplify_loads(pathway.to_loads(self.F)) == expected
class TestWrappingPathway:
def test_is_pathway_base_subclass(self):
assert issubclass(WrappingPathway, PathwayBase)
@pytest.fixture(autouse=True)
def _wrapping_pathway_fixture(self):
self.pA = Point('pA')
self.pB = Point('pB')
self.r = Symbol('r', positive=True)
self.pO = Point('pO')
self.N = ReferenceFrame('N')
self.ax = self.N.z
self.sphere = WrappingSphere(self.r, self.pO)
self.cylinder = WrappingCylinder(self.r, self.pO, self.ax)
self.pathway = WrappingPathway(self.pA, self.pB, self.cylinder)
self.F = Symbol('F')
def test_valid_constructor(self):
instance = WrappingPathway(self.pA, self.pB, self.cylinder)
assert isinstance(instance, WrappingPathway)
assert hasattr(instance, 'attachments')
assert len(instance.attachments) == 2
assert isinstance(instance.attachments[0], Point)
assert instance.attachments[0] == self.pA
assert isinstance(instance.attachments[1], Point)
assert instance.attachments[1] == self.pB
assert hasattr(instance, 'geometry')
assert isinstance(instance.geometry, WrappingGeometryBase)
assert instance.geometry == self.cylinder
@pytest.mark.parametrize(
'attachments',
[
(Point('pA'), ),
(Point('pA'), Point('pB'), Point('pZ')),
]
)
def test_invalid_constructor_attachments_incorrect_number(self, attachments):
with pytest.raises(TypeError):
_ = WrappingPathway(*attachments, self.cylinder)
@staticmethod
@pytest.mark.parametrize(
'attachments',
[
(None, Point('pB')),
(Point('pA'), None),
]
)
def test_invalid_constructor_attachments_not_point(attachments):
with pytest.raises(TypeError):
_ = WrappingPathway(*attachments)
def test_invalid_constructor_geometry_is_not_supplied(self):
with pytest.raises(TypeError):
_ = WrappingPathway(self.pA, self.pB)
@pytest.mark.parametrize(
'geometry',
[
Symbol('r'),
dynamicsymbols('q'),
ReferenceFrame('N'),
ReferenceFrame('N').x,
]
)
def test_invalid_geometry_not_geometry(self, geometry):
with pytest.raises(TypeError):
_ = WrappingPathway(self.pA, self.pB, geometry)
def test_attachments_property_is_immutable(self):
with pytest.raises(TypeError):
self.pathway.attachments[0] = self.pB
with pytest.raises(TypeError):
self.pathway.attachments[1] = self.pA
def test_geometry_property_is_immutable(self):
with pytest.raises(AttributeError):
self.pathway.geometry = None
def test_repr(self):
expected = (
f'WrappingPathway(pA, pB, '
f'geometry={self.cylinder!r})'
)
assert repr(self.pathway) == expected
@staticmethod
def _expand_pos_to_vec(pos, frame):
return sum(mag*unit for (mag, unit) in zip(pos, frame))
@pytest.mark.parametrize(
'pA_vec, pB_vec, factor',
[
((1, 0, 0), (0, 1, 0), pi/2),
((0, 1, 0), (sqrt(2)/2, -sqrt(2)/2, 0), 3*pi/4),
((1, 0, 0), (Rational(1, 2), sqrt(3)/2, 0), pi/3),
]
)
def test_static_pathway_on_sphere_length(self, pA_vec, pB_vec, factor):
pA_vec = self._expand_pos_to_vec(pA_vec, self.N)
pB_vec = self._expand_pos_to_vec(pB_vec, self.N)
self.pA.set_pos(self.pO, self.r*pA_vec)
self.pB.set_pos(self.pO, self.r*pB_vec)
pathway = WrappingPathway(self.pA, self.pB, self.sphere)
expected = factor*self.r
assert simplify(pathway.length - expected) == 0
@pytest.mark.parametrize(
'pA_vec, pB_vec, factor',
[
((1, 0, 0), (0, 1, 0), Rational(1, 2)*pi),
((1, 0, 0), (-1, 0, 0), pi),
((-1, 0, 0), (1, 0, 0), pi),
((0, 1, 0), (sqrt(2)/2, -sqrt(2)/2, 0), 5*pi/4),
((1, 0, 0), (Rational(1, 2), sqrt(3)/2, 0), pi/3),
(
(0, 1, 0),
(sqrt(2)*Rational(1, 2), -sqrt(2)*Rational(1, 2), 1),
sqrt(1 + (Rational(5, 4)*pi)**2),
),
(
(1, 0, 0),
(Rational(1, 2), sqrt(3)*Rational(1, 2), 1),
sqrt(1 + (Rational(1, 3)*pi)**2),
),
]
)
def test_static_pathway_on_cylinder_length(self, pA_vec, pB_vec, factor):
pA_vec = self._expand_pos_to_vec(pA_vec, self.N)
pB_vec = self._expand_pos_to_vec(pB_vec, self.N)
self.pA.set_pos(self.pO, self.r*pA_vec)
self.pB.set_pos(self.pO, self.r*pB_vec)
pathway = WrappingPathway(self.pA, self.pB, self.cylinder)
expected = factor*sqrt(self.r**2)
assert simplify(pathway.length - expected) == 0
@pytest.mark.parametrize(
'pA_vec, pB_vec',
[
((1, 0, 0), (0, 1, 0)),
((0, 1, 0), (sqrt(2)*Rational(1, 2), -sqrt(2)*Rational(1, 2), 0)),
((1, 0, 0), (Rational(1, 2), sqrt(3)*Rational(1, 2), 0)),
]
)
def test_static_pathway_on_sphere_extension_velocity(self, pA_vec, pB_vec):
pA_vec = self._expand_pos_to_vec(pA_vec, self.N)
pB_vec = self._expand_pos_to_vec(pB_vec, self.N)
self.pA.set_pos(self.pO, self.r*pA_vec)
self.pB.set_pos(self.pO, self.r*pB_vec)
pathway = WrappingPathway(self.pA, self.pB, self.sphere)
assert pathway.extension_velocity == 0
@pytest.mark.parametrize(
'pA_vec, pB_vec',
[
((1, 0, 0), (0, 1, 0)),
((1, 0, 0), (-1, 0, 0)),
((-1, 0, 0), (1, 0, 0)),
((0, 1, 0), (sqrt(2)/2, -sqrt(2)/2, 0)),
((1, 0, 0), (Rational(1, 2), sqrt(3)/2, 0)),
((0, 1, 0), (sqrt(2)*Rational(1, 2), -sqrt(2)/2, 1)),
((1, 0, 0), (Rational(1, 2), sqrt(3)/2, 1)),
]
)
def test_static_pathway_on_cylinder_extension_velocity(self, pA_vec, pB_vec):
pA_vec = self._expand_pos_to_vec(pA_vec, self.N)
pB_vec = self._expand_pos_to_vec(pB_vec, self.N)
self.pA.set_pos(self.pO, self.r*pA_vec)
self.pB.set_pos(self.pO, self.r*pB_vec)
pathway = WrappingPathway(self.pA, self.pB, self.cylinder)
assert pathway.extension_velocity == 0
@pytest.mark.parametrize(
'pA_vec, pB_vec, pA_vec_expected, pB_vec_expected, pO_vec_expected',
(
((1, 0, 0), (0, 1, 0), (0, 1, 0), (1, 0, 0), (-1, -1, 0)),
(
(0, 1, 0),
(sqrt(2)/2, -sqrt(2)/2, 0),
(1, 0, 0),
(sqrt(2)/2, sqrt(2)/2, 0),
(-1 - sqrt(2)/2, -sqrt(2)/2, 0)
),
(
(1, 0, 0),
(Rational(1, 2), sqrt(3)/2, 0),
(0, 1, 0),
(sqrt(3)/2, -Rational(1, 2), 0),
(-sqrt(3)/2, Rational(1, 2) - 1, 0),
),
)
)
def test_static_pathway_on_sphere_to_loads(
self,
pA_vec,
pB_vec,
pA_vec_expected,
pB_vec_expected,
pO_vec_expected,
):
pA_vec = self._expand_pos_to_vec(pA_vec, self.N)
pB_vec = self._expand_pos_to_vec(pB_vec, self.N)
self.pA.set_pos(self.pO, self.r*pA_vec)
self.pB.set_pos(self.pO, self.r*pB_vec)
pathway = WrappingPathway(self.pA, self.pB, self.sphere)
pA_vec_expected = sum(
mag*unit for (mag, unit) in zip(pA_vec_expected, self.N)
)
pB_vec_expected = sum(
mag*unit for (mag, unit) in zip(pB_vec_expected, self.N)
)
pO_vec_expected = sum(
mag*unit for (mag, unit) in zip(pO_vec_expected, self.N)
)
expected = [
Force(self.pA, self.F*(self.r**3/sqrt(self.r**6))*pA_vec_expected),
Force(self.pB, self.F*(self.r**3/sqrt(self.r**6))*pB_vec_expected),
Force(self.pO, self.F*(self.r**3/sqrt(self.r**6))*pO_vec_expected),
]
assert pathway.to_loads(self.F) == expected
@pytest.mark.parametrize(
'pA_vec, pB_vec, pA_vec_expected, pB_vec_expected, pO_vec_expected',
(
((1, 0, 0), (0, 1, 0), (0, 1, 0), (1, 0, 0), (-1, -1, 0)),
((1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, 1, 0), (0, -2, 0)),
((-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, -1, 0), (0, 2, 0)),
(
(0, 1, 0),
(sqrt(2)/2, -sqrt(2)/2, 0),
(-1, 0, 0),
(-sqrt(2)/2, -sqrt(2)/2, 0),
(1 + sqrt(2)/2, sqrt(2)/2, 0)
),
(
(1, 0, 0),
(Rational(1, 2), sqrt(3)/2, 0),
(0, 1, 0),
(sqrt(3)/2, -Rational(1, 2), 0),
(-sqrt(3)/2, Rational(1, 2) - 1, 0),
),
(
(1, 0, 0),
(sqrt(2)/2, sqrt(2)/2, 0),
(0, 1, 0),
(sqrt(2)/2, -sqrt(2)/2, 0),
(-sqrt(2)/2, sqrt(2)/2 - 1, 0),
),
((0, 1, 0), (0, 1, 1), (0, 0, 1), (0, 0, -1), (0, 0, 0)),
(
(0, 1, 0),
(sqrt(2)/2, -sqrt(2)/2, 1),
(-5*pi/sqrt(16 + 25*pi**2), 0, 4/sqrt(16 + 25*pi**2)),
(
-5*sqrt(2)*pi/(2*sqrt(16 + 25*pi**2)),
-5*sqrt(2)*pi/(2*sqrt(16 + 25*pi**2)),
-4/sqrt(16 + 25*pi**2),
),
(
5*(sqrt(2) + 2)*pi/(2*sqrt(16 + 25*pi**2)),
5*sqrt(2)*pi/(2*sqrt(16 + 25*pi**2)),
0,
),
),
)
)
def test_static_pathway_on_cylinder_to_loads(
self,
pA_vec,
pB_vec,
pA_vec_expected,
pB_vec_expected,
pO_vec_expected,
):
pA_vec = self._expand_pos_to_vec(pA_vec, self.N)
pB_vec = self._expand_pos_to_vec(pB_vec, self.N)
self.pA.set_pos(self.pO, self.r*pA_vec)
self.pB.set_pos(self.pO, self.r*pB_vec)
pathway = WrappingPathway(self.pA, self.pB, self.cylinder)
pA_force_expected = self.F*self._expand_pos_to_vec(pA_vec_expected,
self.N)
pB_force_expected = self.F*self._expand_pos_to_vec(pB_vec_expected,
self.N)
pO_force_expected = self.F*self._expand_pos_to_vec(pO_vec_expected,
self.N)
expected = [
Force(self.pA, pA_force_expected),
Force(self.pB, pB_force_expected),
Force(self.pO, pO_force_expected),
]
assert _simplify_loads(pathway.to_loads(self.F)) == expected
def test_2D_pathway_on_cylinder_length(self):
q = dynamicsymbols('q')
pA_pos = self.r*self.N.x
pB_pos = self.r*(cos(q)*self.N.x + sin(q)*self.N.y)
self.pA.set_pos(self.pO, pA_pos)
self.pB.set_pos(self.pO, pB_pos)
expected = self.r*sqrt(q**2)
assert simplify(self.pathway.length - expected) == 0
def test_2D_pathway_on_cylinder_extension_velocity(self):
q = dynamicsymbols('q')
qd = dynamicsymbols('q', 1)
pA_pos = self.r*self.N.x
pB_pos = self.r*(cos(q)*self.N.x + sin(q)*self.N.y)
self.pA.set_pos(self.pO, pA_pos)
self.pB.set_pos(self.pO, pB_pos)
expected = self.r*(sqrt(q**2)/q)*qd
assert simplify(self.pathway.extension_velocity - expected) == 0
def test_2D_pathway_on_cylinder_to_loads(self):
q = dynamicsymbols('q')
pA_pos = self.r*self.N.x
pB_pos = self.r*(cos(q)*self.N.x + sin(q)*self.N.y)
self.pA.set_pos(self.pO, pA_pos)
self.pB.set_pos(self.pO, pB_pos)
pA_force = self.F*self.N.y
pB_force = self.F*(sin(q)*self.N.x - cos(q)*self.N.y)
pO_force = self.F*(-sin(q)*self.N.x + (cos(q) - 1)*self.N.y)
expected = [
Force(self.pA, pA_force),
Force(self.pB, pB_force),
Force(self.pO, pO_force),
]
loads = _simplify_loads(self.pathway.to_loads(self.F))
assert loads == expected