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

us.ihmc.javafx.JavaFXQuadrupedVisualizer Maven / Gradle / Ivy

package us.ihmc.javafx;

import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.zip.CRC32;

import controller_msgs.msg.dds.RobotConfigurationData;
import javafx.scene.Group;
import javafx.scene.Node;
import us.ihmc.euclid.transform.RigidBodyTransform;
import us.ihmc.graphicsDescription.structure.Graphics3DNode;
import us.ihmc.javaFXToolkit.node.JavaFXGraphics3DNode;
import us.ihmc.mecano.multiBodySystem.interfaces.OneDoFJointBasics;
import us.ihmc.messager.Messager;
import us.ihmc.messager.MessagerAPIFactory.Topic;
import us.ihmc.robotModels.FullQuadrupedRobotModel;
import us.ihmc.robotModels.FullQuadrupedRobotModelFactory;
import us.ihmc.robotics.robotDescription.RobotDescription;
import us.ihmc.robotics.sensors.ForceSensorDefinition;
import us.ihmc.robotics.sensors.IMUDefinition;
import us.ihmc.simulationConstructionSetTools.grahics.GraphicsIDRobot;
import us.ihmc.simulationconstructionset.graphics.GraphicsRobot;

public class JavaFXQuadrupedVisualizer
{
   private GraphicsRobot graphicsRobot;
   private JavaFXGraphics3DNode robotRootNode;
   private final PrivateAnimationTimer animationTimer = new PrivateAnimationTimer(this::handle);

   private final FullQuadrupedRobotModel fullRobotModel;

   private final OneDoFJointBasics[] allJoints;
   private final int jointNameHash;

   private Messager messager = null;
   private Topic robotModelTopic = null;
   private final AtomicReference robotConfigurationDataReference = new AtomicReference<>();

   private boolean isRobotLoaded = false;
   private final Group rootNode = new Group();

   public JavaFXQuadrupedVisualizer(FullQuadrupedRobotModelFactory fullRobotModelFactory)
   {
      this(fullRobotModelFactory, graphics -> {});
   }

   public JavaFXQuadrupedVisualizer(FullQuadrupedRobotModelFactory fullRobotModelFactory, Consumer graphicsMutator)
   {
      fullRobotModel = fullRobotModelFactory.createFullRobotModel();
      allJoints = fullRobotModel.getOneDoFJoints();

      jointNameHash = calculateJointNameHash(allJoints, fullRobotModel.getForceSensorDefinitions(), fullRobotModel.getIMUDefinitions());

      new Thread(() -> loadRobotModelAndGraphics(fullRobotModelFactory, graphicsMutator), "RobotVisualizerLoading").start();
   }

   public void attachMessager(Messager messager, Topic robotModelTopic)
   {
      this.messager = messager;
      this.robotModelTopic = robotModelTopic;
   }

   private static int calculateJointNameHash(OneDoFJointBasics[] joints, ForceSensorDefinition[] forceSensorDefinitions, IMUDefinition[] imuDefinitions)
   {
      CRC32 crc = new CRC32();
      for (OneDoFJointBasics joint : joints)
      {
         crc.update(joint.getName().getBytes());
      }

      for (ForceSensorDefinition forceSensorDefinition : forceSensorDefinitions)
      {
         crc.update(forceSensorDefinition.getSensorName().getBytes());
      }

      for (IMUDefinition imuDefinition : imuDefinitions)
      {
         crc.update(imuDefinition.getName().getBytes());
      }

      return (int) crc.getValue();
   }

   public boolean isRobotLoaded()
   {
      return isRobotLoaded;
   }

   private void loadRobotModelAndGraphics(FullQuadrupedRobotModelFactory fullRobotModelFactory, Consumer graphicsMutator)
   {
      RobotDescription robotDescription = fullRobotModelFactory.getRobotDescription();
      graphicsRobot = new GraphicsIDRobot(robotDescription.getName(), fullRobotModel.getElevator(), robotDescription);
      robotRootNode = new JavaFXGraphics3DNode(graphicsRobot.getRootNode());
      robotRootNode.setMouseTransparent(true);
      addNodesRecursively(graphicsRobot.getRootNode(), robotRootNode, graphicsMutator);
      robotRootNode.update();

      isRobotLoaded = true;
   }

   public void handle(long now)
   {
      if (!isRobotLoaded)
         return;
      else if (rootNode.getChildren().isEmpty())
         rootNode.getChildren().add(robotRootNode);

      RobotConfigurationData robotConfigurationData = robotConfigurationDataReference.getAndSet(null);
      if (robotConfigurationData == null)
         return;

      if (robotConfigurationData.getJointNameHash() != jointNameHash)
         throw new RuntimeException("Joint names do not match for RobotConfigurationData");

      RigidBodyTransform newRootJointPose = new RigidBodyTransform(robotConfigurationData.getRootOrientation(), robotConfigurationData.getRootTranslation());
      fullRobotModel.getRootJoint().setJointConfiguration(newRootJointPose);

      float[] newJointConfiguration = robotConfigurationData.getJointAngles().toArray();
      for (int i = 0; i < allJoints.length; i++)
         allJoints[i].setQ(newJointConfiguration[i]);

      fullRobotModel.getElevator().updateFramesRecursively();
      graphicsRobot.update();
      robotRootNode.update();

      if (messager != null)
      {
         messager.submitMessage(robotModelTopic, fullRobotModel);
      }
   }

   public void start()
   {
      animationTimer.start();
   }

   public void stop()
   {
      animationTimer.stop();
   }

   private void addNodesRecursively(Graphics3DNode graphics3dNode, JavaFXGraphics3DNode parentNode, Consumer graphicsMutator)
   {
      graphicsMutator.accept(graphics3dNode);
      JavaFXGraphics3DNode node = new JavaFXGraphics3DNode(graphics3dNode);
      parentNode.addChild(node);
      graphics3dNode.getChildrenNodes().forEach(child -> addNodesRecursively(child, node, graphicsMutator));
   }

   public void submitNewConfiguration(RobotConfigurationData robotConfigurationData)
   {
      if (robotConfigurationData.getJointNameHash() != jointNameHash)
         throw new RuntimeException("Joint names do not match for RobotConfigurationData");

      robotConfigurationDataReference.set(robotConfigurationData);
   }

   public FullQuadrupedRobotModel getFullRobotModel()
   {
      return fullRobotModel;
   }

   public Node getRootNode()
   {
      return rootNode;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy