mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-21 05:43:37 +00:00
committed by
Konstantin Pastbin
parent
c9cbb64f12
commit
76ffc99abd
237
tools/track_analyzing/track_analyzer/cmd_tracks.cpp
Normal file
237
tools/track_analyzing/track_analyzer/cmd_tracks.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user