New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add zero velocity constraint in v1pt and v2pt #23359
Conversation
✅ Hi, I am the SymPy bot (v167). I'm here to help you write a release notes entry. Please read the guide on how to write release notes. Your release notes are in good order. Here is what the release notes will look like:
This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.11. Click here to see the pull request description that was parsed.
|
sympy/physics/mechanics/models.py
Outdated
@@ -197,6 +197,7 @@ def n_link_pendulum_on_cart(n=1, cart_force=True, joint_torques=False): | |||
frames.append(Bi) | |||
|
|||
Pi = points[-1].locatenew('P{}'.format(i + 1), l[i] * Bi.y) | |||
points[-1].set_vel(Bi, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing that we have to add this now, I'm not sure this is the solution we want. I thought that we only want to through an error if the velocity of the fixed point is such that it has a value and that value indicates it isn't fixed. So we should allow the velocity to 1) be undefined or 2) fixed in the shared frame. Having to set this velocity to zero is just going to be annoying for users.
sympy/physics/vector/point.py
Outdated
@@ -444,6 +444,9 @@ def v1pt_theory(self, otherpoint, outframe, interframe): | |||
_check_frame(outframe) | |||
_check_frame(interframe) | |||
self._check_point(otherpoint) | |||
if not otherpoint.vel(interframe) == 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given my comment above, this should be something like "if otherpoint velocity is defined and it isn't zero in the shared frame, then ...."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree. We could at most display a warning. The best option I see is to use try
except
to catch the ValueError
, when the velocity is not defined. This will result in something like:
other_point_is_valid = True
try:
if not otherpoint.vel(interframe)==0:
otherpoint_is_valid = False
except ValueError:
pass
if not other_point_is_valid:
raise ValueError(...)
Advantage is that this is a extensive test, which really checks whether the velocity is defined. Disadvantages: it uses try
except
and will possibly add {interframe: 0}
to the otherpoint._vel_dict' by calling
otherpoint.vel` (not sure if this is a disadvantage).
Shall I implement this solution? Or is there a better one? Also should I revert my previous commit, so the test files and model.py
will not be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is fine to do explicit checks over the try/except clause. Maybe preferred in this case.
We try to avoid warnings in SymPy, but we already have some for this particular piece of code. I think it is fine to throw an error if the velocity is defined and it is not constant. If it is not defined, the behavior should be as it is, don't do anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I also undo my previous changes to the other files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, unfortunately. I don't think we want to add this requirement that you have to set the velocity of the base point in the shared frame. It is really unnecessary. The alternative is, as @angadhn suggested, to set that velocity automatically for the user. It's probably ok to do that. So, if the velocity is undefined, set it to 0 and if it is defined and not zero, then throw an error. The only thing I'm hung up on that is that we don't set more than one velocity with any other methods. But I may be warmed up to the idea by now. If it throws an error if it is not constant and sets it to zero otherwise, I can't see a major issue, but then we wouldn't return that second velocity. But that method really shouldn't return a velocity, it should just set them. If you set the velocity to zero and make that very clear in the documentation, then that's probably fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will just revert my changes and implement the suggestion. For this one the velocity in that frame will only be set to 0
if it is already known that it is 0
.
e478566
to
7945460
Compare
Just cleaned up a bit and changed the implementation as well. However I found out that there is one big problem, namely that it will fail on cases where the velocity term contains a kde. This happens in the last example here, which can be replicated with the following code: from sympy.physics.vector import dynamicsymbols, Point, ReferenceFrame
from sympy import Symbol, cos, sin
N = ReferenceFrame('N')
u1, u2 = dynamicsymbols('u1 u2')
q1, q2 = dynamicsymbols('q1 q2')
l = Symbol('l')
R = Symbol('R')
C = N.orientnew('C', 'Axis', [q1, N.x])
C.set_ang_vel(N, u1 * N.x)
O = Point('O')
O.set_vel(N, 0)
Q = O.locatenew('Q', -l * C.z)
P = Q.locatenew('P', R * (cos(q2) * C.x + sin(q2) * C.y))
P.set_vel(C, R * u2 * (-sin(q2) * C.x + cos(q2) * C.y))
print(O.vel(C))
Q.v2pt_theory(O, N, C) An option would be to check that there are no derivative terms in the velocity, but personally I do not really like that solution. |
Another problem could be given if someone manages to define something double with different variable. |
@moorepants or @sidhu1012 what shall we do with this PR:
|
Hi @tjstienstra is there a reason to close this? It seems to have been forgotten, but looks like there are some aspects that may be desired. Or maybe its been addressed in other work? |
P = O.locatenew('P', q * B.x) | ||
assert P.pos_from(O) == q * B.x | ||
P = O.locatenew('P', q * B.x + q2 * B.y) | ||
assert P.pos_from(O) == q * B.x + q2 * B.y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this an error in the example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the next line sets the velocity as P.set_vel(B, qd * B.x + q2d * B.y)
References to other Issues or PRs
Fixes the problem presented in pull request 12322.
Brief description of what is fixed or changed
Add a check if the velocity of the
otherpoint
in the velocity theorems is indeed set to0
Other comments
Possibly also add a check for the acceleration theorems (i.e.
a1pt_theory
anda2pt_theory
).Release Notes
v1pt_theory
andv2pt_theory