Add EPM - Ergo Planet Movie format import (#3520)

To be used as workouts and videosync with free Ergo Planet Videos
EPM files contain video sync plus geolocation information in XML format
Library of free rides: http://wiki.ergoplanet.de/myor/roadmovie-galerie

The problem is altitude set to zero in those examples, likely because it is
redundant when you resort to the EPP (Ergo Planet Program) for slope data,
but the EPP is an unpublished binary format we don't support directly.

So the workflow to use the those synchronized videos is:
1) Import the .epm file to GoldenCheetah as an activity
2) Use Fix Elevation and Fix GPS to add and smooth elevation and route data
3) Export the conditioned activity to GoldenCheetah JSON format
4) Import the .json file as Workout and VideoSync files,
   plus the .avi as media in GC Train mode using Scan Workouts and Media
5) Train using a Video Window with overlay widgets and simulated speed for
   better experience.
This commit is contained in:
Alejandro Martinez
2020-06-23 17:11:02 -03:00
committed by GitHub
parent 3bfcfa57aa
commit 0e3766a504
5 changed files with 229 additions and 2 deletions

92
src/FileIO/EpmParser.cpp Normal file
View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2020 Alejandro Martinez (amtriathlon@gmail.com)
* Based on TcxParser.cpp
*
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
* J.T Conklin (jtc@acorntoolworks.com)
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <QString>
#include <QDebug>
#include "EpmParser.h"
#include "TimeUtils.h"
#include <cmath>
EpmParser::EpmParser(RideFile* rideFile) : rideFile(rideFile)
{
lastDist = 0;
lastSecs = 0;
}
bool
EpmParser::startElement(const QString&, const QString&,
const QString& qName,
const QXmlAttributes& attrs)
{
if (qName == "mapping") { // mappings
double secs = attrs.value("frame").toDouble() / framerate;
double dist = attrs.value("distance").toDouble() / 1000.0;
double speed = 3600.0*(dist - lastDist)/(secs - lastSecs);
lastSecs = secs;
lastDist = dist;
rideFile->appendPoint(secs, 0, 0, dist, speed, 0, 0, 0,
0, 0, 0, 0.0, RideFile::NA, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
} else if (qName == "position") { // positions
double dist = attrs.value("distance").toDouble() / 1000.0;
double lat = attrs.value("lat").toDouble();
double lon = attrs.value("lon").toDouble();
double alt = attrs.value("height").toDouble();
double secs = rideFile->distanceToTime(dist);
rideFile->appendOrUpdatePoint(secs, 0, 0, dist, 0, 0, 0, alt,
lon, lat, 0, 0.0, RideFile::NA, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0, false);
}
// and clear anything left in the buffer
buffer.clear();
return true;
}
bool
EpmParser::endElement(const QString&, const QString&, const QString& qName)
{
// METADATA
if(qName == "name") {
rideFile->setTag("Route", buffer.trimmed());
} else if(qName == "framerate") {
framerate = buffer.trimmed().toDouble();
}
return true;
}
bool
EpmParser::characters(const QString& str)
{
buffer += str;
return true;
}

54
src/FileIO/EpmParser.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2020 Alejandro Martinez (amtriathlon@gmail.com)
* Based on TcxParser.h
*
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
* J.T Conklin (jtc@acorntoolworks.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _EpmParser_h
#define _EpmParser_h
#include "GoldenCheetah.h"
#include "RideFile.h"
#include <QString>
#include <QDateTime>
#include <QXmlDefaultHandler>
class EpmParser : public QXmlDefaultHandler
{
public:
EpmParser(RideFile* rideFile);
bool startElement( const QString&, const QString&, const QString&,
const QXmlAttributes& );
bool endElement( const QString&, const QString&, const QString& );
bool characters( const QString& );
private:
RideFile* rideFile;
QString buffer;
double framerate;
double lastSecs;
double lastDist;
};
#endif // _EpmParser_h

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 Alejandro Martinez (amtriathlon@gmail.com)
* Based on TcxRideFile.cpp
*
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
* J.T Conklin (jtc@acorntoolworks.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "EpmRideFile.h"
#include "EpmParser.h"
static int epmFileReaderRegistered =
RideFileFactory::instance().registerReader(
"epm", "Ergo Planet Movie format", new EpmFileReader());
RideFile *EpmFileReader::openRideFile(QFile &file, QStringList &errors, QList<RideFile*>*) const
{
(void) errors;
RideFile *rideFile = new RideFile();
rideFile->setDeviceType("ErgoPlanet");
rideFile->setFileFormat("Ergo Planet Movie Format (epm)");
EpmParser handler(rideFile);
QXmlInputSource source (&file);
QXmlSimpleReader reader;
reader.setContentHandler (&handler);
reader.parse (source);
return rideFile;
}

34
src/FileIO/EpmRideFile.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 Alejandro Martinez (amtriathlon@gmail.com)
* Based on TcxRideFile.h
*
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
* J.T Conklin (jtc@acorntoolworks.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _EpmRideFile_h
#define _EpmRideFile_h
#include "GoldenCheetah.h"
#include "RideFile.h"
struct EpmFileReader : public RideFileReader {
virtual RideFile *openRideFile(QFile &file, QStringList &errors, QList<RideFile*>* = 0) const;
bool hasWrite() const { return false; }
};
#endif // _EpmRideFile_h

View File

@@ -710,7 +710,9 @@ HEADERS += FileIO/ArchiveFile.h FileIO/AthleteBackup.h FileIO/Bin2RideFile.h Fi
FileIO/SlfParser.h FileIO/SlfRideFile.h FileIO/SmfParser.h FileIO/SmfRideFile.h FileIO/SmlParser.h \
FileIO/SmlRideFile.h FileIO/SrdRideFile.h FileIO/SrmRideFile.h FileIO/SyncRideFile.h FileIO/TcxParser.h \
FileIO/TcxRideFile.h FileIO/TxtRideFile.h FileIO/WkoRideFile.h FileIO/XDataDialog.h FileIO/XDataTableModel.h \
FileIO/FilterHRV.h FileIO/HrvMeasuresCsvImport.h FileIO/LocationInterpolation.h FileIO/TTSReader.h
FileIO/FilterHRV.h FileIO/HrvMeasuresCsvImport.h FileIO/LocationInterpolation.h FileIO/TTSReader.h \
FileIO/EpmParser.h FileIO/EpmRideFile.h
# GUI components
HEADERS += Gui/AboutDialog.h Gui/AddIntervalDialog.h Gui/AnalysisSidebar.h Gui/ChooseCyclistDialog.h Gui/ColorButton.h \
@@ -805,7 +807,7 @@ SOURCES += FileIO/ArchiveFile.cpp FileIO/AthleteBackup.cpp FileIO/Bin2RideFile.c
FileIO/SmlRideFile.cpp FileIO/Snippets.cpp FileIO/SrdRideFile.cpp FileIO/SrmRideFile.cpp FileIO/SyncRideFile.cpp \
FileIO/TacxCafRideFile.cpp FileIO/TcxParser.cpp FileIO/TcxRideFile.cpp FileIO/TxtRideFile.cpp FileIO/WkoRideFile.cpp \
FileIO/XDataDialog.cpp FileIO/XDataTableModel.cpp FileIO/FilterHRV.cpp FileIO/HrvMeasuresCsvImport.cpp \
FileIO/LocationInterpolation.cpp FileIO/TTSReader.cpp
FileIO/LocationInterpolation.cpp FileIO/TTSReader.cpp FileIO/EpmRideFile.cpp FileIO/EpmParser.cpp
## GUI Elements and Dialogs
SOURCES += Gui/AboutDialog.cpp Gui/AddIntervalDialog.cpp Gui/AnalysisSidebar.cpp Gui/ChooseCyclistDialog.cpp Gui/ColorButton.cpp \