All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.ihmc.scs2.definition.robot.JointDefinition Maven / Gradle / Ivy

package us.ihmc.scs2.definition.robot;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;

import us.ihmc.euclid.interfaces.Transformable;
import us.ihmc.euclid.tools.EuclidHashCodeTools;
import us.ihmc.euclid.transform.interfaces.RigidBodyTransformReadOnly;
import us.ihmc.euclid.transform.interfaces.Transform;
import us.ihmc.euclid.tuple3D.interfaces.Tuple3DReadOnly;
import us.ihmc.mecano.multiBodySystem.interfaces.JointBasics;
import us.ihmc.mecano.multiBodySystem.interfaces.RigidBodyBasics;
import us.ihmc.scs2.definition.YawPitchRollTransformDefinition;
import us.ihmc.scs2.definition.state.interfaces.JointStateBasics;
import us.ihmc.scs2.definition.state.interfaces.JointStateReadOnly;

public abstract class JointDefinition implements Transformable
{
   private String name;
   private YawPitchRollTransformDefinition transformToParent = new YawPitchRollTransformDefinition();

   private RigidBodyDefinition predecessor;
   private RigidBodyDefinition successor;

   private List sensorDefinitions = new ArrayList<>();
   private List kinematicPointDefinitions = new ArrayList<>();
   private List externalWrenchPointDefinitions = new ArrayList<>();
   private List groundContactPointDefinitions = new ArrayList<>();

   private LoopClosureDefinition loopClosureDefinition = null;

   public JointDefinition()
   {
   }

   public JointDefinition(String name)
   {
      setName(name);
   }

   public JointDefinition(String name, Tuple3DReadOnly offsetFromParent)
   {
      this(name);
      transformToParent.getTranslation().set(offsetFromParent);
   }

   public JointDefinition(JointDefinition other)
   {
      name = other.name;
      transformToParent.set(other.transformToParent);
      for (SensorDefinition sensorDefinition : other.sensorDefinitions)
         sensorDefinitions.add(sensorDefinition.copy());
      for (KinematicPointDefinition kinematicPointDefinition : other.kinematicPointDefinitions)
         kinematicPointDefinitions.add(kinematicPointDefinition.copy());
      for (ExternalWrenchPointDefinition externalWrenchPointDefinition : other.externalWrenchPointDefinitions)
         externalWrenchPointDefinitions.add(externalWrenchPointDefinition.copy());
      for (GroundContactPointDefinition groundContactPointDefinition : other.groundContactPointDefinitions)
         groundContactPointDefinitions.add(groundContactPointDefinition.copy());
      loopClosureDefinition = other.loopClosureDefinition == null ? null : other.loopClosureDefinition.copy();
   }

   @XmlAttribute
   public void setName(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return name;
   }

   @XmlElement
   public void setTransformToParent(YawPitchRollTransformDefinition transformToParent)
   {
      this.transformToParent = transformToParent;
   }

   public void setTransformToParent(RigidBodyTransformReadOnly transformToParent)
   {
      this.transformToParent.set(transformToParent);
   }

   public YawPitchRollTransformDefinition getTransformToParent()
   {
      return transformToParent;
   }

   @XmlTransient
   public void setPredecessor(RigidBodyDefinition predecessor)
   {
      this.predecessor = predecessor;
   }

   public RigidBodyDefinition getPredecessor()
   {
      return predecessor;
   }

   @XmlTransient
   public void setLoopClosureSuccessor(RigidBodyDefinition successor)
   {
      if (loopClosureDefinition == null)
         loopClosureDefinition = new LoopClosureDefinition();
      this.successor = successor;
   }

   @XmlElement
   public void setSuccessor(RigidBodyDefinition successor)
   {
      if (this.successor != null)
         this.successor.setParentJoint(null);

      this.successor = successor;

      if (this.successor != null)
         this.successor.setParentJoint(this);
   }

   public RigidBodyDefinition getSuccessor()
   {
      return successor;
   }

   public JointDefinition getParentJoint()
   {
      if (predecessor == null)
         return null;
      else
         return predecessor.getParentJoint();
   }

   public abstract void setInitialJointState(JointStateReadOnly initialJointState);

   public abstract JointStateBasics getInitialJointState();

   @XmlElement(name = "sensor")
   public void setSensorDefinitions(List sensorDefinitions)
   {
      this.sensorDefinitions = sensorDefinitions;
   }

   public void addSensorDefinition(SensorDefinition sensorDefinition)
   {
      sensorDefinitions.add(sensorDefinition);
   }

   public List getSensorDefinitions()
   {
      return sensorDefinitions;
   }

   public  List getSensorDefinitions(Class sensorType)
   {
      return sensorDefinitions.stream().filter(sensorType::isInstance).map(sensorType::cast).collect(Collectors.toList());
   }

   @XmlElement(name = "kinematicPoint")
   public void setKinematicPointDefinitions(List kinematicPointDefinitions)
   {
      this.kinematicPointDefinitions = kinematicPointDefinitions;
   }

   public void addKinematicPointDefinition(KinematicPointDefinition kinematicPointDefinition)
   {
      kinematicPointDefinitions.add(kinematicPointDefinition);
   }

   public List getKinematicPointDefinitions()
   {
      return kinematicPointDefinitions;
   }

   @XmlElement(name = "externalWrenchPoint")
   public void setExternalWrenchPointDefinitions(List externalWrenchPointDefinitions)
   {
      this.externalWrenchPointDefinitions = externalWrenchPointDefinitions;
   }

   public void addExternalWrenchPointDefinition(ExternalWrenchPointDefinition externalWrenchPointDefinition)
   {
      externalWrenchPointDefinitions.add(externalWrenchPointDefinition);
   }

   public List getExternalWrenchPointDefinitions()
   {
      return externalWrenchPointDefinitions;
   }

   @XmlElement(name = "groundContactPoint")
   public void setGroundContactPointDefinitions(List groundContactPointDefinitions)
   {
      this.groundContactPointDefinitions = groundContactPointDefinitions;
   }

   public void addGroundContactPointDefinition(GroundContactPointDefinition groundContactPointDefinition)
   {
      groundContactPointDefinitions.add(groundContactPointDefinition);
   }

   public List getGroundContactPointDefinitions()
   {
      return groundContactPointDefinitions;
   }

   public void setLoopClosureDefinition(LoopClosureDefinition loopClosureDefinition)
   {
      this.loopClosureDefinition = loopClosureDefinition;
   }

   public boolean isLoopClosure()
   {
      return loopClosureDefinition != null;
   }

   public LoopClosureDefinition getLoopClosureDefinition()
   {
      return loopClosureDefinition;
   }

   public abstract JointBasics toJoint(RigidBodyBasics predecessor);

   @Override
   public void applyTransform(Transform transform)
   {
      transform.transform(transformToParent);
      kinematicPointDefinitions.forEach(kp -> kp.applyTransform(transform));
      externalWrenchPointDefinitions.forEach(efp -> efp.applyTransform(transform));
      groundContactPointDefinitions.forEach(gcp -> gcp.applyTransform(transform));
      sensorDefinitions.forEach(sensor -> sensor.applyTransform(transform));
   }

   @Override
   public void applyInverseTransform(Transform transform)
   {
      transform.inverseTransform(transformToParent);
      kinematicPointDefinitions.forEach(kp -> kp.applyInverseTransform(transform));
      externalWrenchPointDefinitions.forEach(efp -> efp.applyInverseTransform(transform));
      groundContactPointDefinitions.forEach(gcp -> gcp.applyInverseTransform(transform));
      sensorDefinitions.forEach(sensor -> sensor.applyInverseTransform(transform));
   }

   public abstract JointDefinition copy();

   public JointDefinition copyRecursive()
   {
      JointDefinition copy = copy();
      if (!isLoopClosure()) // Prevent infinite copying loop, but needs to be addressed manually
         copy.setSuccessor(successor.copyRecursive());
      return copy;
   }

   @Override
   public String toString()
   {
      String successorString = successor == null ? "null" : successor.getName();
      return name + ": origin: " + transformToParent + ", successor: " + successorString;
   }

   @Override
   public int hashCode()
   {
      long bits = 1L;
      bits = EuclidHashCodeTools.addToHashCode(bits, name);
      bits = EuclidHashCodeTools.addToHashCode(bits, transformToParent);
      // The predecessor is not used. This joint's hash code depends on the subtree it is the root of.
      bits = EuclidHashCodeTools.addToHashCode(bits, successor);
      bits = EuclidHashCodeTools.addToHashCode(bits, sensorDefinitions);
      bits = EuclidHashCodeTools.addToHashCode(bits, kinematicPointDefinitions);
      bits = EuclidHashCodeTools.addToHashCode(bits, externalWrenchPointDefinitions);
      bits = EuclidHashCodeTools.addToHashCode(bits, groundContactPointDefinitions);
      bits = EuclidHashCodeTools.addToHashCode(bits, loopClosureDefinition);
      return EuclidHashCodeTools.toIntHashCode(bits);
   }

   @Override
   public boolean equals(Object object)
   {
      if (object == this)
         return true;
      if (object == null)
         return false;
      if (getClass() != object.getClass())
         return false;

      JointDefinition other = (JointDefinition) object;

      if (!Objects.equals(name, other.name))
         return false;
      if (!Objects.equals(transformToParent, other.transformToParent))
         return false;
      // The predecessors are not compared. We only compared from this joint to downstream towards the end-effectors.
      if (!Objects.equals(successor, other.successor))
         return false;

      if (!Objects.equals(sensorDefinitions, other.sensorDefinitions))
         return false;
      if (!Objects.equals(kinematicPointDefinitions, other.kinematicPointDefinitions))
         return false;
      if (!Objects.equals(externalWrenchPointDefinitions, other.externalWrenchPointDefinitions))
         return false;
      if (!Objects.equals(groundContactPointDefinitions, other.groundContactPointDefinitions))
         return false;

      if (!Objects.equals(loopClosureDefinition, other.loopClosureDefinition))
         return false;

      return true;
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy