Files
BQP/srcs/RobotNet10/RobotApp/Communication/CartographerSharp/Common/Time/TimeUtils.cs
2026-07-13 09:25:40 +07:00

127 lines
4.2 KiB
C#

/*
* Copyright 2016 The Cartographer Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.InteropServices;
namespace CartographerSharp.Common.Time;
/// <summary>
/// Universal Time Scale clock for Cartographer.
/// Represents durations and timestamps as 64-bit integers representing
/// 100 nanosecond ticks since the Epoch (January 1, 1 at the start of day in UTC).
/// </summary>
public static partial class TimeUtils
{
/// <summary>
/// UTS Epoch offset from Unix Epoch in seconds.
/// </summary>
public const long UtsEpochOffsetFromUnixEpochInSeconds = 719162L * 24L * 60L * 60L;
/// <summary>
/// Ticks per second in Universal Time Scale (100 nanoseconds = 10,000,000 ticks per second).
/// </summary>
public const long TicksPerSecond = 10_000_000L;
/// <summary>
/// Creates a Duration from seconds.
/// </summary>
public static TimeSpan FromSeconds(double seconds)
{
return TimeSpan.FromTicks((long)(seconds * TicksPerSecond));
}
/// <summary>
/// Creates a Duration from milliseconds.
/// </summary>
public static TimeSpan FromMilliseconds(long milliseconds)
{
// Convert milliseconds to 100-nanosecond ticks (1 ms = 10,000 ticks)
// This matches the C++ implementation: std::chrono::duration_cast<Duration>(std::chrono::milliseconds(milliseconds))
return TimeSpan.FromTicks(milliseconds * 10_000L);
}
/// <summary>
/// Returns the given duration in seconds.
/// </summary>
public static double ToSeconds(TimeSpan duration)
{
return duration.TotalSeconds;
}
/// <summary>
/// Creates a Time from Universal Time Scale ticks.
/// </summary>
public static DateTime FromUniversal(long ticks)
{
// Universal Time Scale epoch is January 1, 1 at the start of day in UTC
// We need to convert from UTS epoch to .NET DateTime epoch (January 1, 0001)
// UTS epoch offset: 719162 days = January 1, 1
// .NET DateTime epoch: January 1, 0001
// So we can use DateTime directly since both use the same epoch
return new DateTime(ticks, DateTimeKind.Utc);
}
/// <summary>
/// Outputs the Universal Time Scale timestamp for a given Time.
/// </summary>
public static long ToUniversal(DateTime time)
{
return time.ToUniversalTime().Ticks;
}
/// <summary>
/// CPU time consumed by the thread so far, in seconds.
/// </summary>
public static double GetThreadCpuTimeSeconds()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// Windows implementation would use GetThreadTimes
// For now, return 0 on Windows
return 0.0;
}
else
{
// Linux implementation using clock_gettime with CLOCK_THREAD_CPUTIME_ID
var timespec = new Timespec();
if (clock_gettime(ClockId.CLOCK_THREAD_CPUTIME_ID, ref timespec) == 0)
{
return timespec.tv_sec + 1e-9 * timespec.tv_nsec;
}
return 0.0;
}
}
[StructLayout(LayoutKind.Sequential)]
private struct Timespec
{
public long tv_sec; // seconds
public long tv_nsec; // nanoseconds
}
private enum ClockId
{
CLOCK_REALTIME = 0,
CLOCK_MONOTONIC = 1,
CLOCK_PROCESS_CPUTIME_ID = 2,
CLOCK_THREAD_CPUTIME_ID = 3,
CLOCK_MONOTONIC_RAW = 4,
}
[LibraryImport("libc", SetLastError = true)]
private static partial int clock_gettime(ClockId clockid, ref Timespec tp);
}