001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.math.geometry; 006 007import edu.wpi.first.math.geometry.proto.Transform3dProto; 008import edu.wpi.first.math.geometry.struct.Transform3dStruct; 009import edu.wpi.first.util.protobuf.ProtobufSerializable; 010import edu.wpi.first.util.struct.StructSerializable; 011import java.util.Objects; 012 013/** Represents a transformation for a Pose3d in the pose's frame. */ 014public class Transform3d implements ProtobufSerializable, StructSerializable { 015 /** 016 * A preallocated Transform3d representing no transformation. 017 * 018 * <p>This exists to avoid allocations for common transformations. 019 */ 020 public static final Transform3d kZero = new Transform3d(); 021 022 private final Translation3d m_translation; 023 private final Rotation3d m_rotation; 024 025 /** 026 * Constructs the transform that maps the initial pose to the final pose. 027 * 028 * @param initial The initial pose for the transformation. 029 * @param last The final pose for the transformation. 030 */ 031 public Transform3d(Pose3d initial, Pose3d last) { 032 // We are rotating the difference between the translations 033 // using a clockwise rotation matrix. This transforms the global 034 // delta into a local delta (relative to the initial pose). 035 m_translation = 036 last.getTranslation() 037 .minus(initial.getTranslation()) 038 .rotateBy(initial.getRotation().unaryMinus()); 039 040 m_rotation = last.getRotation().minus(initial.getRotation()); 041 } 042 043 /** 044 * Constructs a transform with the given translation and rotation components. 045 * 046 * @param translation Translational component of the transform. 047 * @param rotation Rotational component of the transform. 048 */ 049 public Transform3d(Translation3d translation, Rotation3d rotation) { 050 m_translation = translation; 051 m_rotation = rotation; 052 } 053 054 /** 055 * Constructs a transform with x, y, and z translations instead of a separate Translation3d. 056 * 057 * @param x The x component of the translational component of the transform. 058 * @param y The y component of the translational component of the transform. 059 * @param z The z component of the translational component of the transform. 060 * @param rotation The rotational component of the transform. 061 */ 062 public Transform3d(double x, double y, double z, Rotation3d rotation) { 063 m_translation = new Translation3d(x, y, z); 064 m_rotation = rotation; 065 } 066 067 /** Constructs the identity transform -- maps an initial pose to itself. */ 068 public Transform3d() { 069 m_translation = Translation3d.kZero; 070 m_rotation = Rotation3d.kZero; 071 } 072 073 /** 074 * Multiplies the transform by the scalar. 075 * 076 * @param scalar The scalar. 077 * @return The scaled Transform3d. 078 */ 079 public Transform3d times(double scalar) { 080 return new Transform3d(m_translation.times(scalar), m_rotation.times(scalar)); 081 } 082 083 /** 084 * Divides the transform by the scalar. 085 * 086 * @param scalar The scalar. 087 * @return The scaled Transform3d. 088 */ 089 public Transform3d div(double scalar) { 090 return times(1.0 / scalar); 091 } 092 093 /** 094 * Composes two transformations. The second transform is applied relative to the orientation of 095 * the first. 096 * 097 * @param other The transform to compose with this one. 098 * @return The composition of the two transformations. 099 */ 100 public Transform3d plus(Transform3d other) { 101 return new Transform3d(Pose3d.kZero, Pose3d.kZero.transformBy(this).transformBy(other)); 102 } 103 104 /** 105 * Returns the translation component of the transformation. 106 * 107 * @return The translational component of the transform. 108 */ 109 public Translation3d getTranslation() { 110 return m_translation; 111 } 112 113 /** 114 * Returns the X component of the transformation's translation. 115 * 116 * @return The x component of the transformation's translation. 117 */ 118 public double getX() { 119 return m_translation.getX(); 120 } 121 122 /** 123 * Returns the Y component of the transformation's translation. 124 * 125 * @return The y component of the transformation's translation. 126 */ 127 public double getY() { 128 return m_translation.getY(); 129 } 130 131 /** 132 * Returns the Z component of the transformation's translation. 133 * 134 * @return The z component of the transformation's translation. 135 */ 136 public double getZ() { 137 return m_translation.getZ(); 138 } 139 140 /** 141 * Returns the rotational component of the transformation. 142 * 143 * @return Reference to the rotational component of the transform. 144 */ 145 public Rotation3d getRotation() { 146 return m_rotation; 147 } 148 149 /** 150 * Invert the transformation. This is useful for undoing a transformation. 151 * 152 * @return The inverted transformation. 153 */ 154 public Transform3d inverse() { 155 // We are rotating the difference between the translations 156 // using a clockwise rotation matrix. This transforms the global 157 // delta into a local delta (relative to the initial pose). 158 return new Transform3d( 159 getTranslation().unaryMinus().rotateBy(getRotation().unaryMinus()), 160 getRotation().unaryMinus()); 161 } 162 163 @Override 164 public String toString() { 165 return String.format("Transform3d(%s, %s)", m_translation, m_rotation); 166 } 167 168 /** 169 * Checks equality between this Transform3d and another object. 170 * 171 * @param obj The other object. 172 * @return Whether the two objects are equal or not. 173 */ 174 @Override 175 public boolean equals(Object obj) { 176 if (obj instanceof Transform3d) { 177 return ((Transform3d) obj).m_translation.equals(m_translation) 178 && ((Transform3d) obj).m_rotation.equals(m_rotation); 179 } 180 return false; 181 } 182 183 @Override 184 public int hashCode() { 185 return Objects.hash(m_translation, m_rotation); 186 } 187 188 /** Transform3d protobuf for serialization. */ 189 public static final Transform3dProto proto = new Transform3dProto(); 190 191 /** Transform3d struct for serialization. */ 192 public static final Transform3dStruct struct = new Transform3dStruct(); 193}