code: def from_rotation_matrix(
      rotation_matrix: type_alias.TensorLike,
      name: str = "euler_from_rotation_matrix",
  ) -> tf.Tensor:
      """Converts rotation matrices to Euler angles.
  
      The rotation matrices are assumed to have been constructed by rotation around
      the $$x$$, then $$y$$, and finally the $$z$$ axis.
  
      Note:
        There is an infinite number of solutions to this problem. There are
      Gimbal locks when abs(rotation_matrix(2,0)) == 1, which are not handled.
  
      Note:
        In the following, A1 to An are optional batch dimensions.
  
      Args:
        rotation_matrix: A tensor of shape `[A1, ..., An, 3, 3]`, where the last two
          dimensions represent a rotation matrix.
        name: A name for this op that defaults to "euler_from_rotation_matrix".
  
      Returns:
        A tensor of shape `[A1, ..., An, 3]`, where the last dimension represents
        the three Euler angles.
  
      Raises:
        ValueError: If the shape of `rotation_matrix` is not supported.
      """
  
      def general_case(rotation_matrix, r20, eps_addition):
          """Handles the general case."""
          theta_y = -tf.asin(r20)
          sign_cos_theta_y = safe_ops.nonzero_sign(tf.cos(theta_y))
          r00 = rotation_matrix[..., 0, 0]
          r10 = rotation_matrix[..., 1, 0]
          r21 = rotation_matrix[..., 2, 1]
          r22 = rotation_matrix[..., 2, 2]
          r00 = safe_ops.nonzero_sign(r00) * eps_addition + r00
          r22 = safe_ops.nonzero_sign(r22) * eps_addition + r22
          # cos_theta_y evaluates to 0 on Gimbal locks, in which case the output of
          # this function will not be used.
          theta_z = tf.atan2(
              r10 * sign_cos_theta_y, r00 * sign_cos_theta_y
          )
          theta_x = tf.atan2(
              r21 * sign_cos_theta_y, r22 * sign_cos_theta_y
          )
          angles = tf.stack((theta_x, theta_y, theta_z), axis=-1)
          return angles
  
      def gimbal_lock(rotation_matrix, r20, eps_addition):
          """Handles Gimbal locks."""
          r01 = rotation_matrix[..., 0, 1]
          r02 = rotation_matrix[..., 0, 2]
          sign_r20 = safe_ops.nonzero_sign(r20)
          r02 = safe_ops.nonzero_sign(r02) * eps_addition + r02
          theta_x = tf.atan2(-sign_r20 * r01, -sign_r20 * r02)
          theta_y = -sign_r20 * tf.constant(
              math.pi / 2.0, dtype=r20.dtype
          )
          theta_z = tf.zeros_like(theta_x)
          angles = tf.stack((theta_x, theta_y, theta_z), axis=-1)
          return angles
  
      with tf.name_scope(name):
          rotation_matrix = tf.convert_to_tensor(value=rotation_matrix)
  
          shape.check_static(
              tensor=rotation_matrix,
              tensor_name="rotation_matrix",
              has_rank_greater_than=1,
              has_dim_equals=((-1, 3), (-2, 3)),
          )
          rotation_matrix = (
              rotation_matrix_3d.assert_rotation_matrix_normalized(
                  rotation_matrix
              )
          )
  
          r20 = rotation_matrix[..., 2, 0]
          eps_addition = asserts.select_eps_for_addition(
              rotation_matrix.dtype
          )
          general_solution = general_case(
              rotation_matrix, r20, eps_addition
          )
          gimbal_solution = gimbal_lock(
              rotation_matrix, r20, eps_addition
          )
          is_gimbal = tf.equal(tf.abs(r20), 1)
          gimbal_mask = tf.stack(
              (is_gimbal, is_gimbal, is_gimbal), axis=-1
          )
          return tf.where(
              gimbal_mask, gimbal_solution, general_solution
          )
  
file_path: graphics/tensorflow_graphics/geometry/transformation/euler.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import math
  import tensorflow
  from tensorflow_graphics.geometry.transformation import quaternion
  from tensorflow_graphics.geometry.transformation import rotation_matrix_3d
  from tensorflow_graphics.util import asserts
  from tensorflow_graphics.util import export_api
  from tensorflow_graphics.util import safe_ops
  from tensorflow_graphics.util import shape
  from tensorflow_graphics.util import type_alias
label_desc: Use image node_id 3 for calling a global function with example usage: from_rotation_matrix(rotation_matrix, name) and returns: angles, angles, tf