Repository: sympy/sympy
Pull request: kinematic_equation returns zero if speeds are zero
earlier kinematic equations returned a non-zero vector if the speeds were zero. Now if the speeds are zero kinematic_equation returns a zero vector.

fixes #12600 

Problem statement:
kinematic_equations should return a zero vector if the speeds are all zero
This is currently the behavior:

```
moorepants@garuda:sympy(master)$ ipython --pdb
Python 3.5.3 |Continuum Analytics, Inc.| (default, Mar  6 2017, 11:58:13) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.0.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sympy as sm

In [2]: import sympy.physics.mechanics as me

In [3]: me.kinematic_equations((0, 0, 0), (sm.pi, sm.pi / 2, 0), 'body', '132')
Out[3]: [nan, 0, nan]
```

This expected output should be:

```
[0, 0, 0]
```

Hints from issue discussion:
Hello Sir, I am very much interested in contributing, but am new to open source. Where can I find this particular function kinematic_equation(), I opened sympy/physics/mechanics but could not find the function in the files. Can you please help me with this? I read that the code is present in sympy/core but could not find this
It is defined in sympy/physics/vector/functions.py.
q1d - (w1 * c3 + w3 * s3)/ c2 
This is what is returned
c2 is a function dealing with cos(q2)
q2 being Pi/2 makes c2 to become 0
x/ 0 is infinite which is getting to NaN

My line of thought was that if the speeds are all zero it supersedes any result due to the definition of coordinates that may result in a singularity. From a physical, instead of mathematical, perspective I think that makes sense.
@moorepants : Yes! But getting that mathematically will force us to equate infinity with 0. Binding a special case will look like a history text book rather than a mathematical equation.
Lets see If I can do anything
The function `kinematic_equations` is not some mathematical construct in SymPy. It's purpose is to provide the correct angular velocity given a variety of rotation types. If you tell the function that angular velocity is zero, then it should return the same, regardless of any mathematical rules.

Here is a little more context:

```
moorepants@garuda:mae297(master)$ ipython
Python 3.5.3 |Continuum Analytics, Inc.| (default, Mar  6 2017, 11:58:13) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.0.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sympy as sm

In [2]: import sympy.physics.mechanics as me

In [3]: N = me.ReferenceFrame('N')

In [4]: A = N.orientnew('A', 'body', (sm.pi, sm.pi / 2, 0), '132')

In [5]: A.dcm(N)
Out[5]: 
Matrix([
[ 0, -1,  0],
[-1,  0,  0],
[ 0,  0, -1]])

In [6]: A.ang_vel_in(N)
Out[6]: ---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/moorepants/miniconda3/lib/python3.5/site-packages/IPython/core/formatters.py in __call__(self, obj)
    664                 type_pprinters=self.type_printers,
    665                 deferred_pprinters=self.deferred_printers)
--> 666             printer.pretty(obj)
    667             printer.flush()
    668             return stream.getvalue()

/home/moorepants/miniconda3/lib/python3.5/site-packages/IPython/lib/pretty.py in pretty(self, obj)
    379                             if callable(meth):
    380                                 return meth(obj, self, cycle)
--> 381             return _default_pprint(obj, self, cycle)
    382         finally:
    383             self.end_group()

/home/moorepants/miniconda3/lib/python3.5/site-packages/IPython/lib/pretty.py in _default_pprint(obj, p, cycle)
    499     if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
    500         # A user-provided repr. Find newlines and replace them with p.break_()
--> 501         _repr_pprint(obj, p, cycle)
    502         return
    503     p.begin_group(1, '<')

/home/moorepants/miniconda3/lib/python3.5/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
    697     """A pprint that just redirects to the normal repr function."""
    698     # Find newlines and replace them with p.break_()
--> 699     output = repr(obj)
    700     for idx,output_line in enumerate(output.splitlines()):
    701         if idx:

/home/moorepants/miniconda3/lib/python3.5/site-packages/sympy/physics/vector/vector.py in __str__(self, printer)
    351             for j in 0, 1, 2:
    352                 # if the coef of the basis vector is 1, we skip the 1
--> 353                 if ar[i][0][j] == 1:
    354                     ol.append(' + ' + ar[i][1].str_vecs[j])
    355                 # if the coef of the basis vector is -1, we skip the 1

TypeError: 'NaN' object does not support indexing
```

The automatic calculation of angular velocity relies on `kinematic_equations`. This should simply return a zero vector for any non-time varying orientation. The error could be fixed in the `.orient` method or maybe it is appropriate for `kinematic_equations` to be aware of this.
Is this issue open?
Is this a closed issue or an open issue ? Please confirm . I am really confused as it is shown as open in list and closed when we look at it with different issue numbers.
It is an open issue. @smichr worked on it here: https://github.com/sympy/sympy/pull/12698 but I didn't think his solution was correct. These equations have to be solved explicitly for the derivative terms and rewriting the equations to avoid zeros on the denominator only postpones this issue.
I tried on this issue to fix. Someone please review it .

Commit message: kinematic_equation returns zero if speeds are zero

earlier kinematic equations returned a non-zero vector if the speeds were zero. Now if the speeds are zero kinematic_equation returns a zero vector.

Patch to review:
diff --git a/sympy/physics/vector/functions.py b/sympy/physics/vector/functions.py
index 814d2fc99724..6d3c105460b2 100644
--- a/sympy/physics/vector/functions.py
+++ b/sympy/physics/vector/functions.py
@@ -280,6 +280,8 @@ def kinematic_equations(speeds, coords, rot_type, rot_order=''):
         w1, w2, w3 = speeds
         s1, s2, s3 = [sin(q1), sin(q2), sin(q3)]
         c1, c2, c3 = [cos(q1), cos(q2), cos(q3)]
+        if w1==w2==w3==0:
+            return [0,0,0]
         if rot_type.lower() == 'body':
             if rot_order == '123':
                 return [q1d - (w1 * c3 - w2 * s3) / c2, q2d - w1 * s3 - w2 *


Code review comments:
diff_hunk: @@ -280,6 +280,8 @@ def kinematic_equations(speeds, coords, rot_type, rot_order=''):
         w1, w2, w3 = speeds
path: sympy/physics/vector/functions.py
text: @user1:
Could you move `w1, w2...` and the test `if w1 == w2...` to appear before `q1, q2, ...`?

Surround `==` with a single space.

`return [S.Zero]*3` since it's usually good form to return SymPy objects instead of Python objects.

@author:
sure.
How to edit the current PR?