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