Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
229
tools/track_analyzing/track_analyzer/cmd_tracks.cpp
Normal file
229
tools/track_analyzing/track_analyzer/cmd_tracks.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#include "track_analyzing/track.hpp"
|
||||
#include "track_analyzing/utils.hpp"
|
||||
|
||||
#include "traffic/speed_groups.hpp"
|
||||
|
||||
#include "routing_common/car_model.hpp"
|
||||
#include "routing_common/vehicle_model.hpp"
|
||||
|
||||
#include "routing/edge_estimator.hpp"
|
||||
#include "routing/geometry.hpp"
|
||||
|
||||
#include "storage/routing_helpers.hpp"
|
||||
#include "storage/storage.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
#include "base/logging.hpp"
|
||||
#include "base/timer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
using namespace routing;
|
||||
using namespace std;
|
||||
|
||||
class TrackStats final
|
||||
{
|
||||
public:
|
||||
void AddUsers(uint64_t numUsers) { m_numUsers += numUsers; }
|
||||
void AddTracks(uint64_t numTracks) { m_numTracks += numTracks; }
|
||||
void AddPoints(uint64_t numPoints) { m_numPoints += numPoints; }
|
||||
|
||||
void Add(TrackStats const & rhs)
|
||||
{
|
||||
m_numUsers += rhs.m_numUsers;
|
||||
m_numTracks += rhs.m_numTracks;
|
||||
m_numPoints += rhs.m_numPoints;
|
||||
}
|
||||
|
||||
string GetSummary() const
|
||||
{
|
||||
ostringstream out;
|
||||
out << "users: " << m_numUsers << ", tracks: " << m_numTracks << ", points: " << m_numPoints;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
bool IsEmpty() const { return m_numPoints == 0; }
|
||||
|
||||
private:
|
||||
uint64_t m_numUsers = 0;
|
||||
uint64_t m_numTracks = 0;
|
||||
uint64_t m_numPoints = 0;
|
||||
};
|
||||
|
||||
class ErrorStat final
|
||||
{
|
||||
public:
|
||||
void Add(double value)
|
||||
{
|
||||
m_count += 1.0;
|
||||
m_squares += value * value;
|
||||
m_min = min(m_min, value);
|
||||
m_max = max(m_max, value);
|
||||
}
|
||||
|
||||
double GetStdDev() const
|
||||
{
|
||||
CHECK_GREATER(m_count, 1.0, ());
|
||||
return std::sqrt(m_squares / (m_count - 1.0));
|
||||
}
|
||||
|
||||
string GetStdDevString() const
|
||||
{
|
||||
if (m_count <= 1.0)
|
||||
return "N/A";
|
||||
|
||||
return to_string(GetStdDev());
|
||||
}
|
||||
|
||||
double GetMin() const { return m_min; }
|
||||
double GetMax() const { return m_max; }
|
||||
|
||||
private:
|
||||
double m_count = 0.0;
|
||||
double m_squares = 0.0;
|
||||
double m_min = numeric_limits<double>::max();
|
||||
double m_max = numeric_limits<double>::min();
|
||||
};
|
||||
|
||||
bool TrackHasTrafficPoints(MatchedTrack const & track)
|
||||
{
|
||||
for (MatchedTrackPoint const & point : track)
|
||||
{
|
||||
size_t const index = static_cast<size_t>(point.GetDataPoint().m_traffic);
|
||||
CHECK_LESS(index, static_cast<size_t>(traffic::SpeedGroup::Count), ());
|
||||
if (traffic::kSpeedGroupThresholdPercentage[index] != 100)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
double EstimateDuration(MatchedTrack const & track, shared_ptr<EdgeEstimator> estimator, Geometry & geometry)
|
||||
{
|
||||
double result = 0.0;
|
||||
Segment segment;
|
||||
|
||||
for (MatchedTrackPoint const & point : track)
|
||||
{
|
||||
if (point.GetSegment() == segment)
|
||||
continue;
|
||||
|
||||
segment = point.GetSegment();
|
||||
result +=
|
||||
estimator->CalcSegmentWeight(segment, geometry.GetRoad(segment.GetFeatureId()), EdgeEstimator::Purpose::ETA);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CmdTracks(string const & filepath, string const & trackExtension, StringFilter mwmFilter, StringFilter userFilter,
|
||||
TrackFilter const & filter, bool noTrackLogs, bool noMwmLogs, bool noWorldLogs)
|
||||
{
|
||||
storage::Storage storage;
|
||||
auto numMwmIds = CreateNumMwmIds(storage);
|
||||
|
||||
map<string, TrackStats> mwmToStats;
|
||||
ErrorStat absoluteError;
|
||||
ErrorStat relativeError;
|
||||
|
||||
auto processMwm = [&](string const & mwmName, UserToMatchedTracks const & userToMatchedTracks)
|
||||
{
|
||||
if (mwmFilter(mwmName))
|
||||
return;
|
||||
|
||||
TrackStats & mwmStats = mwmToStats[mwmName];
|
||||
|
||||
shared_ptr<VehicleModelInterface> vehicleModel = CarModelFactory({}).GetVehicleModelForCountry(mwmName);
|
||||
|
||||
Geometry geometry(GeometryLoader::CreateFromFile(GetCurrentVersionMwmFile(storage, mwmName), vehicleModel));
|
||||
|
||||
shared_ptr<EdgeEstimator> estimator = EdgeEstimator::Create(
|
||||
VehicleType::Car, *vehicleModel, nullptr /* trafficStash */, nullptr /* dataSource */, nullptr /* numMwmIds */);
|
||||
|
||||
for (auto const & it : userToMatchedTracks)
|
||||
{
|
||||
string const & user = it.first;
|
||||
if (userFilter(user))
|
||||
continue;
|
||||
|
||||
vector<MatchedTrack> const & tracks = it.second;
|
||||
if (!noTrackLogs)
|
||||
cout << mwmName << ", user: " << user << endl;
|
||||
|
||||
bool thereAreUnfilteredTracks = false;
|
||||
for (MatchedTrack const & track : tracks)
|
||||
{
|
||||
DataPoint const & start = track.front().GetDataPoint();
|
||||
DataPoint const & finish = track.back().GetDataPoint();
|
||||
|
||||
double const length = CalcTrackLength(track, geometry);
|
||||
uint64_t const duration = finish.m_timestamp - start.m_timestamp;
|
||||
double const speed = CalcSpeedKMpH(length, duration);
|
||||
bool const hasTrafficPoints = TrackHasTrafficPoints(track);
|
||||
|
||||
if (!filter.Passes(duration, length, speed, hasTrafficPoints))
|
||||
continue;
|
||||
|
||||
double const estimatedDuration = EstimateDuration(track, estimator, geometry);
|
||||
double const timeError = estimatedDuration - static_cast<double>(duration);
|
||||
|
||||
if (!noTrackLogs)
|
||||
{
|
||||
cout << fixed << setprecision(1) << " points: " << track.size() << ", length: " << length
|
||||
<< ", duration: " << duration << ", estimated duration: " << estimatedDuration << ", speed: " << speed
|
||||
<< ", traffic: " << hasTrafficPoints
|
||||
<< ", departure: " << base::SecondsSinceEpochToString(start.m_timestamp)
|
||||
<< ", arrival: " << base::SecondsSinceEpochToString(finish.m_timestamp)
|
||||
<< setprecision(numeric_limits<double>::max_digits10) << ", start: " << start.m_latLon.m_lat << ", "
|
||||
<< start.m_latLon.m_lon << ", finish: " << finish.m_latLon.m_lat << ", " << finish.m_latLon.m_lon
|
||||
<< endl;
|
||||
}
|
||||
|
||||
mwmStats.AddTracks(1);
|
||||
mwmStats.AddPoints(track.size());
|
||||
absoluteError.Add(timeError);
|
||||
relativeError.Add(timeError / static_cast<double>(duration));
|
||||
thereAreUnfilteredTracks = true;
|
||||
}
|
||||
|
||||
if (thereAreUnfilteredTracks)
|
||||
mwmStats.AddUsers(1);
|
||||
}
|
||||
};
|
||||
|
||||
auto processFile = [&](string const & filename, MwmToMatchedTracks const & mwmToMatchedTracks)
|
||||
{
|
||||
LOG(LINFO, ("Processing", filename));
|
||||
ForTracksSortedByMwmName(mwmToMatchedTracks, *numMwmIds, processMwm);
|
||||
};
|
||||
|
||||
ForEachTrackFile(filepath, trackExtension, numMwmIds, processFile);
|
||||
|
||||
if (!noMwmLogs)
|
||||
{
|
||||
cout << endl;
|
||||
for (auto const & it : mwmToStats)
|
||||
if (!it.second.IsEmpty())
|
||||
cout << it.first << ": " << it.second.GetSummary() << endl;
|
||||
}
|
||||
|
||||
if (!noWorldLogs)
|
||||
{
|
||||
TrackStats worldStats;
|
||||
for (auto const & it : mwmToStats)
|
||||
worldStats.Add(it.second);
|
||||
|
||||
cout << endl << "World: " << worldStats.GetSummary() << endl;
|
||||
cout << fixed << setprecision(1) << "Absolute error: deviation: " << absoluteError.GetStdDevString()
|
||||
<< ", min: " << absoluteError.GetMin() << ", max: " << absoluteError.GetMax() << endl;
|
||||
cout << fixed << setprecision(3) << "Relative error: deviation: " << relativeError.GetStdDevString()
|
||||
<< ", min: " << relativeError.GetMin() << ", max: " << relativeError.GetMax() << endl;
|
||||
}
|
||||
}
|
||||
} // namespace track_analyzing
|
||||
Loading…
Add table
Add a link
Reference in a new issue