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

us.ihmc.scs2.session.log.LogSession Maven / Gradle / Ivy

The newest version!
package us.ihmc.scs2.session.log;

import us.ihmc.commons.Conversions;
import us.ihmc.graphicsDescription.conversion.YoGraphicConversionTools;
import us.ihmc.log.LogTools;
import us.ihmc.robotDataLogger.handshake.YoVariableHandshakeParser;
import us.ihmc.robotDataLogger.logger.LogPropertiesReader;
import us.ihmc.scs2.definition.robot.RobotDefinition;
import us.ihmc.scs2.definition.robot.RobotStateDefinition;
import us.ihmc.scs2.definition.terrain.TerrainObjectDefinition;
import us.ihmc.scs2.definition.yoGraphic.YoGraphicDefinition;
import us.ihmc.scs2.definition.yoGraphic.YoGraphicGroupDefinition;
import us.ihmc.scs2.session.Session;
import us.ihmc.scs2.session.SessionMode;
import us.ihmc.scs2.session.tools.RobotDataLogTools;
import us.ihmc.scs2.session.tools.RobotModelLoader;
import us.ihmc.scs2.sharedMemory.interfaces.YoBufferPropertiesReadOnly;
import us.ihmc.scs2.simulation.TimeConsumer;
import us.ihmc.scs2.simulation.robot.Robot;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class LogSession extends Session
{
   private final String sessionName;
   private final List robots = new ArrayList<>();
   private final List robotDefinitions = new ArrayList<>();
   private final List yoGraphicDefinitions = new ArrayList<>();
   private final Runnable robotStateUpdater;

   private final File logDirectory;
   private final LogDataReader logDataReader;
   private final LogPropertiesReader logProperties;

   /**
    * This is used to jump to a specific position in the log when the user drags the slider.
    * 

* It is thread-safe. *

*/ private final AtomicInteger logPositionRequest = new AtomicInteger(-1); private final List afterReadCallbacks = new ArrayList<>(); public LogSession(File logDirectory, ProgressConsumer progressConsumer) throws IOException { this.logDirectory = logDirectory; try { logDataReader = new LogDataReader(logDirectory, progressConsumer); LogTools.info("Created data reader."); } catch (IOException e) { throw new RuntimeException(e); } logProperties = logDataReader.getLogProperties(); YoVariableHandshakeParser parser = logDataReader.getParser(); rootRegistry.addChild(logDataReader.getYoRegistry()); rootRegistry.addChild(parser.getRootRegistry()); yoGraphicDefinitions.add(new YoGraphicGroupDefinition("SCS1 YoGraphics", YoGraphicConversionTools.toYoGraphicDefinitions(parser.getSCS1YoGraphics()))); if (parser.getSCS2YoGraphics() != null) yoGraphicDefinitions.addAll(parser.getSCS2YoGraphics()); sessionName = logProperties.getNameAsString(); RobotDefinition robotDefinition = RobotDataLogTools.loadRobotDefinition(logDirectory, logProperties); if (robotDefinition != null) { robotDefinitions.add(robotDefinition); Robot robot = new Robot(robotDefinition, getInertialFrame()); robots.add(robot); robotStateUpdater = RobotModelLoader.setupRobotUpdater(robot, parser, rootRegistry); } else { robotStateUpdater = null; } setDesiredBufferPublishPeriod(Conversions.secondsToNanoseconds(1.0 / 30.0)); setSessionDTSeconds(parser.getDt()); setSessionMode(SessionMode.PAUSE); } public void submitLogPositionRequest(int logPosition) { logPositionRequest.set(logPosition); } @Override protected void initializeSession() { // We read the very first frame of the log. logDataReader.read(); if (robotStateUpdater != null) robotStateUpdater.run(); } @Override protected void initializeRunTick() { if (firstRunTick) { // TODO Can probably be a little smarter here, sometimes we don't need to reset the equation manager. equationManager.reset(); YoBufferPropertiesReadOnly properties = sharedBuffer.getProperties(); if (properties.getCurrentIndex() != properties.getOutPoint()) sharedBuffer.setInPoint(properties.getCurrentIndex()); else if (!firstLogPositionRequest) // That means the user has scrubbed through the data. sharedBuffer.setInPoint(properties.getCurrentIndex()); sharedBuffer.incrementBufferIndex(true); // Sync the log position index (logDataReader.index) the current YoVariable (logDataReader.currentRecordTick()) value. // Without that, scrubbing through a chart and then resuming log reading will start from an arbitrary position in the log file (corresponding to where we last stop reading the log file). logDataReader.seek(logDataReader.getCurrentLogPosition()); nextRunBufferRecordTickCounter = 0; firstRunTick = false; } else if (nextRunBufferRecordTickCounter <= 0) { sharedBuffer.incrementBufferIndex(true); sharedBuffer.processLinkedPushRequests(false); } // Push from the linked registries are unnecessary when reading a log file. } @Override protected double doSpecificRunTick() { boolean endOfLog = logDataReader.read(); if (endOfLog) setSessionMode(SessionMode.PAUSE); if (robotStateUpdater != null) robotStateUpdater.run(); double currentTime = logDataReader.getCurrentRobotTime(); for (int i = 0; i < afterReadCallbacks.size(); i++) afterReadCallbacks.get(i).accept(currentTime); return currentTime; } private boolean firstLogPositionRequest = true; @Override public void pauseTick() { if (firstPauseTick) firstLogPositionRequest = true; int logPosition = logPositionRequest.getAndSet(-1); if (logPosition == -1) { super.pauseTick(); } else {// Handles when the user is scrubbing through the log using the log slider. processBufferRequests(false); logDataReader.seek(logPosition); logDataReader.read(); if (robotStateUpdater != null) robotStateUpdater.run(); if (firstLogPositionRequest) { // We increment only once when starting to scrub through the data to not write on the last data point. sharedBuffer.incrementBufferIndex(true); firstLogPositionRequest = false; } sharedBuffer.writeBuffer(); sharedBuffer.prepareLinkedBuffersForPull(); publishBufferProperties(sharedBuffer.getProperties()); } } /** * Adds a callback to be executed after reading each line of the log file. *

* This can be used to register some post-processing on the log data. *

* * @param callback the callback to add. */ public void addAfterReadCallback(TimeConsumer callback) { afterReadCallbacks.add(Objects.requireNonNull(callback, "The callback cannot be null.")); } /** * Removes a callback that was previously added. * * @param callback the callback to remove. * @return {@code true} if the callback was removed, {@code false} if it was not found. */ public boolean removeAfterReadCallback(TimeConsumer callback) { return afterReadCallbacks.remove(callback); } @Override public String getSessionName() { return sessionName; } @Override public List getRobotDefinitions() { return robotDefinitions; } @Override public List getTerrainObjectDefinitions() { return Collections.emptyList(); } @Override public List getYoGraphicDefinitions() { return yoGraphicDefinitions; } public List getRobots() { return robots; } @Override public List getCurrentRobotStateDefinitions(boolean initialState) { return robots.stream().map(Robot::getCurrentRobotStateDefinition).collect(Collectors.toList()); } public File getLogDirectory() { return logDirectory; } public LogDataReader getLogDataReader() { return logDataReader; } public LogPropertiesReader getLogProperties() { return logProperties; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy