Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wpimath] Make a class for a bound vector #7542

Closed
wants to merge 10 commits into from
191 changes: 191 additions & 0 deletions wpimath/src/main/java/edu/wpi/first/math/geometry/BoundVector2d.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package edu.wpi.first.math.geometry;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.wpi.first.math.geometry.struct.BoundVector2dStruct;
import edu.wpi.first.util.struct.StructSerializable;
import java.util.Objects;

/** Represents a bound vector in a vector field. Has an origin, and x/y component vectors. */
Copy link
Member

@calcmogul calcmogul Dec 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be defining a lot more terms. What's a "bound vector"? What are "component vectors"? When would someone use this class in their robot code?

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
public class BoundVector2d implements StructSerializable {
private final Translation2d m_position;
private final Translation2d m_components;

/**
* Constructs a vector with the specified position and component vectors.
*
* @param position The position of the vector.
* @param components The X/Y component vectors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "component vectors" here? This variable is poorly named. The two fields in a Translation2d are scalars, not vectors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A scalar only has a magnitude while a vector has both direction and magnitude right? The direction can be just the sign of a number, and isn't necessarily an angle. Translation2d.getX() and Translation2d.getY() would be vectors in their respective axes. This needs to be made more clear though.

Copy link
Member

@calcmogul calcmogul Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation2d is a 2D vector represented by <x, y>. We don't consider the elements x and y to also be vectors. If we did, what we actually have is a matrix (rank-2 tensor).

x and y in this case represent the magnitudes of the î and ĵ unit vectors.

*/
public BoundVector2d(
@JsonProperty(required = true, value = "position") Translation2d position,
@JsonProperty(required = true, value = "components") Translation2d components) {
this.m_position = position;
this.m_components = components;
}

/**
* Constructs a bound vector with the specified position, direction, and magnitude.
*
* @param position The position of the vector.
* @param direction The direction of the vector.
* @param magnitude The magnitude of the vector.
*/
public BoundVector2d(Translation2d position, Rotation2d direction, double magnitude) {
this(position, new Translation2d(magnitude, direction));
}

/**
* Constructs a vector from a start and end point.
*
* @param start The start point.
* @param end The end point.
* @return A new Vector2d with the correct position and components.
*/
public static BoundVector2d fromStartEndPoints(Translation2d start, Translation2d end) {
return new BoundVector2d(start, end.minus(start));
}

/**
* Returns the position of the vector.
*
* @return The position of the vector.
*/
@JsonProperty
public Translation2d getPosition() {
return m_position;
}

/**
* Returns the X component of the vector's position
*
* @return The Y component of the vector's position
*/
public double getXPos() {
TheComputer314 marked this conversation as resolved.
Show resolved Hide resolved
return m_position.getX();
}

/**
* Returns the Y component of the vector's position
*
* @return The Y component of the vector's position
*/
public double getYPos() {
TheComputer314 marked this conversation as resolved.
Show resolved Hide resolved
return m_position.getY();
}

/**
* Returns the components of the vector.
*
* @return The components of the vector.
*/
@JsonProperty
public Translation2d getComponents() {
return m_components;
}

/**
* Returns the X component of the vector.
*
* @return The X component of the vector.
*/
public double getXComponent() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really saving much typing over getComponents().getX(). At least Pose2d.getX() is a lot shorter than Pose2d.getTranslation().getX().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think we should still include this, it saves a little bit of typing even if it isn't much.

return m_components.getX();
}

/**
* Returns the Y component of the vector.
*
* @return The Y component of the vector.
*/
public double getYComponent() {
return m_components.getY();
}

/**
* Returns the magnitude of the vector.
*
* @return The magnitude of the vector.
*/
public double getMagnitude() {
return m_components.getNorm();
}

/**
* Returns the angle of the vector.
TheComputer314 marked this conversation as resolved.
Show resolved Hide resolved
*
* @return The angle of the vector.
*/
public Rotation2d getAngle() {
return m_components.getAngle();
}

/**
* Multiplies the magnitude of the vector by a scalar.
*
* @param scalar The scalar.
* @return The new scaled Vector2d.
*/
public BoundVector2d times(double scalar) {
return new BoundVector2d(m_position, m_components.times(scalar));
}

/**
* Divides the magnitude of the vector by a scalar.
*
* @param scalar The scalar.
* @return The new scaled Vector2d.
*/
public BoundVector2d div(double scalar) {
return new BoundVector2d(m_position, m_components.div(scalar));
}

/**
* Moves the position of the vector by an offset and returns the new vector.
*
* @param offset The offset.
* @return The new moved Vector2d.
*/
public BoundVector2d move(Translation2d offset) {
return new BoundVector2d(m_position.plus(offset), m_components);
}

/**
* Rotates the vector around its position and returns the new vector.
*
* @param rotation The rotation to transform the vector by.
* @return The new rotated vector.
*/
public BoundVector2d rotateBy(Rotation2d rotation) {
return new BoundVector2d(m_position, m_components.rotateBy(rotation));
}

/**
* Constructs a new Pose2d with the same position and direction as the vector.
*
* @return The new Pose2d.
*/
public Pose2d toPose2d() {
return new Pose2d(m_position, getAngle());
}

@Override
public String toString() {
return String.format(
"BoundVector2d(Position: %.2s, Components: %.2s)",
m_position.toString(), m_components.toString());
}

@Override
public int hashCode() {
return Objects.hash(m_position, m_components);
}

// TODO: Add Protobuf serialization

/** vector2d struct for serialization. */
public static final BoundVector2dStruct struct = new BoundVector2dStruct();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package edu.wpi.first.math.geometry.struct;

import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.math.geometry.BoundVector2d;
import edu.wpi.first.util.struct.Struct;
import java.nio.ByteBuffer;

public class BoundVector2dStruct implements Struct<BoundVector2d> {
@Override
public Class<BoundVector2d> getTypeClass() {
return BoundVector2d.class;
}

@Override
public String getTypeName() {
return "Vector2d";
}

@Override
public int getSize() {
return Translation2d.struct.getSize() * 2;
}

@Override
public String getSchema() {
return "Translation2d origin;Translation2d components";
}

@Override
public BoundVector2d unpack(ByteBuffer bb) {
var origin = Translation2d.struct.unpack(bb);
var components = Translation2d.struct.unpack(bb);
return new BoundVector2d(origin, components);
}

@Override
public void pack(ByteBuffer bb, BoundVector2d value) {
Translation2d.struct.pack(bb, value.getPosition());
Translation2d.struct.pack(bb, value.getComponents());
}

@Override
public Struct<?>[] getNested() {
return new Struct<?>[] {Translation2d.struct};
}
}
Loading