Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/timesource options #266

Merged
merged 13 commits into from
Feb 27, 2024
2 changes: 1 addition & 1 deletion Assets/AWSIM/Scenes/Main/AutowareSimulation.unity
Original file line number Diff line number Diff line change
Expand Up @@ -4046,7 +4046,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 3077555317673241940, guid: 27181f17b3e1bb607a4b8fcb8a827e0f, type: 3}
propertyPath: Type
value: 2
value: 3
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 27181f17b3e1bb607a4b8fcb8a827e0f, type: 3}
Expand Down
16 changes: 16 additions & 0 deletions Assets/AWSIM/Scenes/Main/AutowareSimulation/AutowareSimulation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class AutowareSimulation : MonoBehaviour
{
[SerializeField] TrafficManager trafficManager;
[SerializeField] Transform egoTransform;
private TimeSourceSelector timeSourceSelector;

[Header("Player Config")]
[SerializeField] string commandLineConfigParam = "--json_path";
Expand All @@ -33,13 +34,15 @@ public class EgoConfiguration
public class Configuration
{
public float TimeScale; // Reflected in Time.timeScale
public string TimeSource; // Reflected in TimeSourceSelector
public int RandomTrafficSeed; // Reflected in TrafficManager.seed
public int MaxVehicleCount; // Reflected in TrafficManager.maxVehicleCount
public EgoConfiguration Ego = new EgoConfiguration();
}

void Awake()
{
CollectComponents();

#if !UNITY_EDITOR
// initialize
Expand All @@ -62,6 +65,19 @@ void Awake()

var rotation = Quaternion.Euler(config.Ego.EulerAngles);
egoTransform.rotation = ROS2Utility.RosToUnityRotation(rotation);

// set time source
timeSourceSelector?.SetType(config.TimeSource);
}
}

void CollectComponents()
{
// get time source selector
timeSourceSelector = FindObjectOfType<TimeSourceSelector>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using FindObjectOfType, could you please add a [SerializeField] TimeSourceSelector to AutowareSimulation.cs?
I would like to avoid type find at runtime as much as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've just made the change. Thanks

if(timeSourceSelector == null)
{
Debug.LogWarning("TimeSource: There is no TimeSourceSelector object in the active scene. The default time source will be used.");
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Assets/AWSIM/Scenes/Main/AutowareSimulation/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"TimeScale": 0.2,
"TimeSource": "simulation",
"RandomTrafficSeed": 33,
"MaxVehicleCount": 2,
"Ego": {
Expand All @@ -14,4 +15,4 @@
"z": 35.0
}
}
}
}
48 changes: 48 additions & 0 deletions Assets/AWSIM/Scripts/Clock/Scripts/DotNetSimulationTimeSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Threading;
using ROS2;

namespace AWSIM
{
/// <summary>
/// A thread-safe timesource class that provides simulation time based on the dot net system utc time.
/// This time source takes into account the value of the simulation timescale and
/// starts at zero value when the simulation is started.
/// </summary>
public class DotNetSimulationTimeSource : ITimeSource
{
private DateTime prevDateTime;
private double time;
private bool hasStarted = false;

private readonly object lockObject = new object();

public DotNetSimulationTimeSource()
{
hasStarted = false;
}

public void GetTime(out int seconds, out uint nanoseconds)
{
lock (lockObject)
{
DateTime currDateTime = DateTime.UtcNow;

if(!hasStarted)
{
hasStarted = true;
time = 0.0;

prevDateTime = currDateTime;
}

TimeSpan timeSpan = currDateTime - prevDateTime;
prevDateTime = currDateTime;

time += timeSpan.TotalMilliseconds * 0.001f * TimeScaleProvider.TimeScale;
TimeUtils.TimeFromTotalSeconds(time, out seconds, out nanoseconds);
}
}
}

}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 17 additions & 4 deletions Assets/AWSIM/Scripts/Clock/Scripts/DotNetSystemTimeSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,43 @@
namespace AWSIM
{
/// <summary>
/// A thread-safe timesource class that provides the dot net system utc time.
/// A thread-safe timesource class that provides the dot net system utc time since epoch.
/// This timesource takes into account the value of the simulation timescale.
/// </summary>
public class DotNetSystemTimeSource : ITimeSource
{
private DateTime prevDateTime;
private double time;
private bool hasStarted = false;

private readonly object lockObject = new object();

public DotNetSystemTimeSource()
{
prevDateTime = DateTime.UtcNow;
time = 0.0;
hasStarted = false;
}

public void GetTime(out int seconds, out uint nanoseconds)
{
lock (lockObject)
{
DateTime currDateTime = DateTime.UtcNow;

if(!hasStarted)
{
hasStarted = true;

// get the time in millisecond since epoch
long timeOffset = ((DateTimeOffset)currDateTime).ToUnixTimeMilliseconds();
time = (double)timeOffset * 0.001;

prevDateTime = currDateTime;
}

TimeSpan timeSpan = currDateTime - prevDateTime;
prevDateTime = currDateTime;

time += timeSpan.TotalMilliseconds * 0.001f * TimeScaleProvider.TimeScale;
time += timeSpan.TotalMilliseconds * 0.001 * TimeScaleProvider.TimeScale;
TimeUtils.TimeFromTotalSeconds(time, out seconds, out nanoseconds);
}
}
Expand Down
41 changes: 41 additions & 0 deletions Assets/AWSIM/Scripts/Clock/Scripts/TimeAsDoubleProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using UnityEngine;

namespace AWSIM
{
/// <summary>
/// A thread-safe static class to provide the value of the Unity time as double.
/// </summary>
public static class TimeAsDoubleProvider
{
private static readonly object lockObject = new object();

private static double timeAsDouble = 0.0;
public static double TimeAsDouble
{
get
{
lock(lockObject)
{
return timeAsDouble;
}
}
}


#region [Public Methods]

/// <summary>
/// Synchronise the value of the timeAsDouble variable with the Time.timeAsDouble from the Unity thread.
/// </summary>
public static void DoUpdate()
{
lock(lockObject)
{
timeAsDouble = Time.timeAsDouble;
}
}

#endregion
}
}

11 changes: 11 additions & 0 deletions Assets/AWSIM/Scripts/Clock/Scripts/TimeAsDoubleProvider.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions Assets/AWSIM/Scripts/Clock/Scripts/TimeScaleProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ public static void DoUpdate()
{
lock(lockObject)
{
if (Mathf.Abs(Time.timeScale - timeScale) > 0.01f)
{
timeScale = Time.timeScale;
}
timeScale = Time.timeScale;
}
}

Expand Down
31 changes: 29 additions & 2 deletions Assets/AWSIM/Scripts/Clock/Scripts/TimeSourceProvider.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using AWSIM.Samples;
using ROS2;
using System;

Expand All @@ -12,7 +13,9 @@ public enum TimeSourceType
{
UNITY,
SS2,
DOTNET
DOTNET_SYSTEM,
DOTNET_SIMULATION,
ROS2,
}

#region [Event]
Expand Down Expand Up @@ -96,7 +99,7 @@ public static void SetTimeSource(TimeSourceType type)
}

// dot net system time source
if(type == TimeSourceType.DOTNET)
if(type == TimeSourceType.DOTNET_SYSTEM)
{
if(currentTimeSource == null || !(currentTimeSource is DotNetSystemTimeSource))
{
Expand All @@ -107,6 +110,30 @@ public static void SetTimeSource(TimeSourceType type)
return;
}

// dot net simulation time source
if(type == TimeSourceType.DOTNET_SIMULATION)
{
if(currentTimeSource == null || !(currentTimeSource is DotNetSimulationTimeSource))
{
currentTimeSource = new DotNetSimulationTimeSource();
onTimeSourceChanged?.Invoke();
}

return;
}

// ros2 time source
if(type == TimeSourceType.ROS2)
{
if(currentTimeSource == null || !(currentTimeSource is ROS2TimeSource))
{
currentTimeSource = new ROS2TimeSource();
onTimeSourceChanged?.Invoke();
}

return;
}

// default time source
if(currentTimeSource == null || !(currentTimeSource is UnityTimeSource))
{
Expand Down
54 changes: 54 additions & 0 deletions Assets/AWSIM/Scripts/Clock/Scripts/TimeSourceSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,60 @@ private void Awake()
TimeSourceProvider.SetTimeSource(Type);
}

#region [Public Methods]

/// <summary>
/// Set the time source of the desired type.
/// </summary>
/// <param name="type">Type of requested time source.</param>
public void SetType(string type)
{
if(type == null || type == "")
{
return;
}

if(string.CompareOrdinal(type.ToLower(), "unity") == 0)
{
SetType(TimeSourceProvider.TimeSourceType.UNITY);
}
else if(string.CompareOrdinal(type.ToLower(), "simulation") == 0)
{
SetType(TimeSourceProvider.TimeSourceType.DOTNET_SIMULATION);
}
else if(string.CompareOrdinal(type.ToLower(), "system") == 0)
{
SetType(TimeSourceProvider.TimeSourceType.DOTNET_SYSTEM);
}
else if(string.CompareOrdinal(type.ToLower(), "ss2") == 0)
{
SetType(TimeSourceProvider.TimeSourceType.SS2);
}
else if(string.CompareOrdinal(type.ToLower(), "ros2") == 0)
{
SetType(TimeSourceProvider.TimeSourceType.ROS2);
}
else
{
Debug.LogWarning("TimeSourceSelector: " + type + " is not recognized as a valid time source.");
}
}

#endregion

#region [Private Methods]

/// <summary>
/// Set the time source of the desired type.
/// </summary>
/// <param name="type">Type of requested time source.</param>
private void SetType(TimeSourceProvider.TimeSourceType type)
{
Type = type;
TimeSourceProvider.SetTimeSource(Type);
}

#endregion
}

}
10 changes: 10 additions & 0 deletions Assets/AWSIM/Scripts/ROS/ClockPublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void Awake()
void Start()
{
TimeScaleProvider.DoUpdate();
TimeAsDoubleProvider.DoUpdate();
StartClockThread();
}

Expand All @@ -43,6 +44,15 @@ void OnDestroy()

#endregion

#region [Main Thread]

void Update()
{
TimeAsDoubleProvider.DoUpdate();
}

#endregion

#region [Clock Thread]

void StartClockThread()
Expand Down
1 change: 1 addition & 0 deletions Assets/Ros2ForUnity/Scripts/Time/DotnetTimeSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace ROS2
/// DateTime based clock that has resolution increased using Stopwatch.
/// DateTime is used to synchronize since Stopwatch tends to drift.
/// </summary>
[System.Obsolete("This TimeSource is deprecated and will be removed in the future versions. Please use DotNetSystemTimeSource instead.")]
public class DotnetTimeSource : ITimeSource
{
private readonly double maxUnsyncedSeconds = 10;
Expand Down
1 change: 1 addition & 0 deletions Assets/Ros2ForUnity/Scripts/Time/ROS2ScalableTimeSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace ROS2
/// <summary>
/// ros2 time source (system time by default).
/// </summary>
[System.Obsolete("This TimeSource is deprecated and will be removed in the future versions. Please use DotNetSystemTimeSource instead.")]
public class ROS2ScalableTimeSource : ITimeSource
{
private Thread mainThread;
Expand Down
Loading
Loading