class_docstr: A Transform3d object encapsulates a batch of N 3D transformations, and knows
  how to transform points and normal vectors. Suppose that t is a Transform3d;
  then we can do the following:
  
  .. code-block:: python
  
      N = len(t)
      points = torch.randn(N, P, 3)
      normals = torch.randn(N, P, 3)
      points_transformed = t.transform_points(points)    # => (N, P, 3)
      normals_transformed = t.transform_normals(normals)  # => (N, P, 3)
  
  
  BROADCASTING
  Transform3d objects supports broadcasting. Suppose that t1 and tN are
  Transform3d objects with len(t1) == 1 and len(tN) == N respectively. Then we
  can broadcast transforms like this:
  
  .. code-block:: python
  
      t1.transform_points(torch.randn(P, 3))     # => (P, 3)
      t1.transform_points(torch.randn(1, P, 3))  # => (1, P, 3)
      t1.transform_points(torch.randn(M, P, 3))  # => (M, P, 3)
      tN.transform_points(torch.randn(P, 3))     # => (N, P, 3)
      tN.transform_points(torch.randn(1, P, 3))  # => (N, P, 3)
  
  
  COMBINING TRANSFORMS
  Transform3d objects can be combined in two ways: composing and stacking.
  Composing is function composition. Given Transform3d objects t1, t2, t3,
  the following all compute the same thing:
  
  .. code-block:: python
  
      y1 = t3.transform_points(t2.transform_points(t1.transform_points(x)))
      y2 = t1.compose(t2).compose(t3).transform_points(x)
      y3 = t1.compose(t2, t3).transform_points(x)
  
  
  Composing transforms should broadcast.
  
  .. code-block:: python
  
      if len(t1) == 1 and len(t2) == N, then len(t1.compose(t2)) == N.
  
  We can also stack a sequence of Transform3d objects, which represents
  composition along the batch dimension; then the following should compute the
  same thing.
  
  .. code-block:: python
  
      N, M = len(tN), len(tM)
      xN = torch.randn(N, P, 3)
      xM = torch.randn(M, P, 3)
      y1 = torch.cat([tN.transform_points(xN), tM.transform_points(xM)], dim=0)
      y2 = tN.stack(tM).transform_points(torch.cat([xN, xM], dim=0))
  
  BUILDING TRANSFORMS
  We provide convenience methods for easily building Transform3d objects
  as compositions of basic transforms.
  
  .. code-block:: python
  
      # Scale by 0.5, then translate by (1, 2, 3)
      t1 = Transform3d().scale(0.5).translate(1, 2, 3)
  
      # Scale each axis by a different amount, then translate, then scale
      t2 = Transform3d().scale(1, 3, 3).translate(2, 3, 1).scale(2.0)
  
      t3 = t1.compose(t2)
      tN = t1.stack(t3, t3)
  
  
  BACKPROP THROUGH TRANSFORMS
  When building transforms, we can also parameterize them by Torch tensors;
  in this case we can backprop through the construction and application of
  Transform objects, so they could be learned via gradient descent or
  predicted by a neural network.
  
  .. code-block:: python
  
      s1_params = torch.randn(N, requires_grad=True)
      t_params = torch.randn(N, 3, requires_grad=True)
      s2_params = torch.randn(N, 3, requires_grad=True)
  
      t = Transform3d().scale(s1_params).translate(t_params).scale(s2_params)
      x = torch.randn(N, 3)
      y = t.transform_points(x)
      loss = compute_loss(y)
      loss.backward()
  
      with torch.no_grad():
          s1_params -= lr * s1_params.grad
          t_params -= lr * t_params.grad
          s2_params -= lr * s2_params.grad
  
  CONVENTIONS
  We adopt a right-hand coordinate system, meaning that rotation about an axis
  with a positive angle results in a counter clockwise rotation.
  
  This class assumes that transformations are applied on inputs which
  are row vectors. The internal representation of the Nx4x4 transformation
  matrix is of the form:
  
  .. code-block:: python
  
      M = [
              [Rxx, Ryx, Rzx, 0],
              [Rxy, Ryy, Rzy, 0],
              [Rxz, Ryz, Rzz, 0],
              [Tx,  Ty,  Tz,  1],
          ]
  
  To apply the transformation to points, which are row vectors, the latter are
  converted to homogeneous (4D) coordinates and right-multiplied by the M matrix:
  
  .. code-block:: python
  
      points = [[0, 1, 2]]  # (1 x 3) xyz coordinates of a point
      [transformed_points, 1] ∝ [points, 1] @ M
class_docstr_tok: ["A","Transform3d","object","encapsulates","a","batch","of","N","3D","transformations",",","and","knows","how","to","transform","points","and","normal","vectors",".","Suppose","that","t","is","a","Transform3d",";","then","we","can","do","the","following",":","..","code-block",":",":","python","N","=","len","(","t",")","points","=","torch.randn","(","N",",","P",",","3",")","normals","=","torch.randn","(","N",",","P",",","3",")","points_transformed","=","t.transform_points","(","points",")","#","=",">","(","N",",","P",",","3",")","normals_transformed","=","t.transform_normals","(","normals",")","#","=",">","(","N",",","P",",","3",")","BROADCASTING","Transform3d","objects","supports","broadcasting",".","Suppose","that","t1","and","tN","are","Transform3d","objects","with","len","(","t1",")","==","1","and","len","(","tN",")","==","N","respectively",".","Then","we","can","broadcast","transforms","like","this",":","..","code-block",":",":","python","t1.transform_points","(","torch.randn","(","P",",","3",")",")","#","=",">","(","P",",","3",")","t1.transform_points","(","torch.randn","(","1",",","P",",","3",")",")","#","=",">","(","1",",","P",",","3",")","t1.transform_points","(","torch.randn","(","M",",","P",",","3",")",")","#","=",">","(","M",",","P",",","3",")","tN.transform_points","(","torch.randn","(","P",",","3",")",")","#","=",">","(","N",",","P",",","3",")","tN.transform_points","(","torch.randn","(","1",",","P",",","3",")",")","#","=",">","(","N",",","P",",","3",")","COMBINING","TRANSFORMS","Transform3d","objects","can","be","combined","in","two","ways",":","composing","and","stacking",".","Composing","is","function","composition",".","Given","Transform3d","objects","t1",",","t2",",","t3",",","the","following","all","compute","the","same","thing",":","..","code-block",":",":","python","y1","=","t3.transform_points","(","t2.transform_points","(","t1.transform_points","(","x",")",")",")","y2","=","t1.compose","(","t2",")",".compose","(","t3",")",".transform_points","(","x",")","y3","=","t1.compose","(","t2",",","t3",")",".transform_points","(","x",")","Composing","transforms","should","broadcast",".","..","code-block",":",":","python","if","len","(","t1",")","==","1","and","len","(","t2",")","==","N",",","then","len","(","t1.compose","(","t2",")",")","==","N.","We","can","also","stack","a","sequence","of","Transform3d","objects",",","which","represents","composition","along","the","batch","dimension",";","then","the","following","should","compute","the","same","thing",".","..","code-block",":",":","python","N",",","M","=","len","(","tN",")",",","len","(","tM",")","xN","=","torch.randn","(","N",",","P",",","3",")","xM","=","torch.randn","(","M",",","P",",","3",")","y1","=","torch.cat","(","[","tN.transform_points","(","xN",")",",","tM.transform_points","(","xM",")","]",",","dim=0",")","y2","=","tN.stack","(","tM",")",".transform_points","(","torch.cat","(","[","xN",",","xM","]",",","dim=0",")",")","BUILDING","TRANSFORMS","We","provide","convenience","methods","for","easily","building","Transform3d","objects","as","compositions","of","basic","transforms",".","..","code-block",":",":","python","#","Scale","by","0.5",",","then","translate","by","(","1",",","2",",","3",")","t1","=","Transform3d","(",")",".scale","(","0.5",")",".translate","(","1",",","2",",","3",")","#","Scale","each","axis","by","a","different","amount",",","then","translate",",","then","scale","t2","=","Transform3d","(",")",".scale","(","1",",","3",",","3",")",".translate","(","2",",","3",",","1",")",".scale","(","2.0",")","t3","=","t1.compose","(","t2",")","tN","=","t1.stack","(","t3",",","t3",")","BACKPROP","THROUGH","TRANSFORMS","When","building","transforms",",","we","can","also","parameterize","them","by","Torch","tensors",";","in","this","case","we","can","backprop","through","the","construction","and","application","of","Transform","objects",",","so","they","could","be","learned","via","gradient","descent","or","predicted","by","a","neural","network",".","..","code-block",":",":","python","s1_params","=","torch.randn","(","N",",","requires_grad=True",")","t_params","=","torch.randn","(","N",",","3",",","requires_grad=True",")","s2_params","=","torch.randn","(","N",",","3",",","requires_grad=True",")","t","=","Transform3d","(",")",".scale","(","s1_params",")",".translate","(","t_params",")",".scale","(","s2_params",")","x","=","torch.randn","(","N",",","3",")","y","=","t.transform_points","(","x",")","loss","=","compute_loss","(","y",")","loss.backward","(",")","with","torch.no_grad","(",")",":","s1_params","-=","lr","*","s1_params.grad","t_params","-=","lr","*","t_params.grad","s2_params","-=","lr","*","s2_params.grad","CONVENTIONS","We","adopt","a","right-hand","coordinate","system",",","meaning","that","rotation","about","an","axis","with","a","positive","angle","results","in","a","counter","clockwise","rotation",".","This","class","assumes","that","transformations","are","applied","on","inputs","which","are","row","vectors",".","The","internal","representation","of","the","Nx4x4","transformation","matrix","is","of","the","form",":","..","code-block",":",":","python","M","=","[","[","Rxx",",","Ryx",",","Rzx",",","0","]",",","[","Rxy",",","Ryy",",","Rzy",",","0","]",",","[","Rxz",",","Ryz",",","Rzz",",","0","]",",","[","Tx",",","Ty",",","Tz",",","1","]",",","]","To","apply","the","transformation","to","points",",","which","are","row","vectors",",","the","latter","are","converted","to","homogeneous","(","4D",")","coordinates","and","right-multiplied","by","the","M","matrix",":","..","code-block",":",":","python","points","=","[","[","0",",","1",",","2","]","]","#","(","1","x","3",")","xyz","coordinates","of","a","point","[","transformed_points",",","1","]","\u221d","[","points",",","1","]","@","M"]
code: def rotate(self, *args, **kwargs) -> "Transform3d":
      return self.compose(
          Rotate(*args, device=self.device, dtype=self.dtype, **kwargs)
      )
  
imports: import math
  import os
  import warnings
  from typing import List, Optional, Union
  import torch
  from ..common.datatypes import Device, get_device, make_device
  from ..common.workaround import _safe_det_3x3
  from .rotation_conversions import _axis_angle_rotation
  from .se3 import se3_log_map
label_desc: Use image node_id 14 for calling the Transform3d obj's underlying member method code with example usage: obj.rotate() and returns: self