Internal/newTraceGenExtension: TrackObject_Test.cs

File TrackObject_Test.cs, 12.7 KB (added by jkol, 3 years ago)
Line 
1using System.Linq;
2using System.Xml.Linq;
3using System;
4using System.IO;
5using System.Collections.Generic;
6using UnityEngine;
7
8//Holds the connections, the number of objects in them and the default
9//attenuation values to output in the absence of an object pair.
10public class Connection
11{
12 public int name { get; set; }
13 public int defattn { get; set; }
14 public int maxobj { get; set; }
15}
16
17//Holds the object details which include the name, the type, the id and
18//the other objects it is linked to for each connection.
19public class Objects
20{
21 public string name { get; set; }
22 public string type { get; set; }
23 public int id { get; set; }
24 public Dictionary<int, string[]> links = new Dictionary<int, string[]>();
25}
26
27public class TrackObject_Test : MonoBehaviour
28{
29 List<Connection> connectionList = new List<Connection>();//List of connections of class type connection
30 List<Objects> objectlist = new List<Objects>();//List of objects of class type object
31
32 Dictionary<string, float>[] attnupdate;//Contains an array of dictionary values of each connection type with the key being the link i.e., 1-2, 1-3, ... and the value being the final attenuation to write to file.
33 Dictionary<string, int> attnfactor = new Dictionary<string, int>(); // Holds a dictionary with the key as object type and the value being the attenuation factor.
34 Dictionary<string, string[]> objmap = new Dictionary<string, string[]>(); // Contains a map of the object name with its type. For example, 1 is a key for Car-121
35
36 string path = @"Attenuation.csv";
37
38 float interval, duration, frequency;
39 float nextTime = 0;
40
41 bool exec = false;//bool value to start the trackers after all objects have been loaded
42 bool config = false;//bool value to run the trackers iff the config file exists. In its absence, the simulator exhibits normal behavior
43 public void GetDefValues()
44 {
45 using (var xmlReader = new StreamReader("config.xml"))
46 {
47 var doc = XDocument.Load(xmlReader);
48 XNamespace nonamespace = XNamespace.None;
49
50 var xmlProducts = doc.Descendants(nonamespace + "link");//Obtains all descendants of tag 'link'
51 foreach (var item in xmlProducts)
52 {
53 if (item != null && item.Attribute("default_attn") != null)
54 {
55 var connection = new Connection//Populates the connectionList
56 {
57 name = int.Parse(item.Attribute("name").Value),
58 defattn = int.Parse(item.Attribute("default_attn").Value),
59 maxobj = int.Parse(item.Attribute("max_obj").Value)
60 };
61 connectionList.Add(connection);
62 }
63 }
64 }
65 }
66 //Populates the objectlist from the xml file
67 public void GetConnections()
68 {
69 using (var xmlReader = new StreamReader("config.xml"))
70 {
71 var doc = XDocument.Load(xmlReader);
72 XNamespace nonamespace = XNamespace.None;
73
74 var xmlProducts = doc.Descendants(nonamespace + "object");
75 foreach (var item in xmlProducts)
76 {
77 if (item != null && item.Attribute("id") != null)
78 {
79 var objlist = new Objects
80 {
81 name = item.Attribute("name").Value,
82 type = item.Attribute("type").Value,
83 id = int.Parse(item.Attribute("id").Value),
84 };
85
86 string[] conList;
87 foreach (var size in item.Descendants("link"))
88 {
89 int i = int.Parse(size.Attribute("name").Value);
90 conList = (size.Value).Split(',');
91 objlist.links.Add(i, conList);
92 }
93 objectlist.Add(objlist);
94 }
95 }
96 }
97 }
98
99 //Populates the attnfactor from the config file
100 public void GetAttnFactor()
101 {
102 using (var xmlReader = new StreamReader("config.xml"))
103 {
104 var doc = XDocument.Load(xmlReader);
105 XNamespace nonamespace = XNamespace.None;
106
107 var xmlProducts = doc.Descendants(nonamespace + "attn");
108 foreach (var item in xmlProducts)
109 {
110 if (item != null)
111 {
112 int fac = int.Parse(item.Attribute("factor").Value);
113 string type = item.Attribute("type").Value;
114 attnfactor.Add(type, fac);
115 }
116 }
117 }
118 }
119
120 //Reads the simulation parameters like the time interval, run time and the frequency to be used with attenuation calculations
121 public void GetParameters()
122 {
123 using (var xmlReader = new StreamReader("config.xml"))
124 {
125 var doc = XDocument.Load(xmlReader);
126 XNamespace nonamespace = XNamespace.None;
127 var xmlProducts = doc.Descendants(nonamespace + "sim_parameters");
128 foreach (var item in xmlProducts)
129 {
130 interval = int.Parse(item.Attribute("time_int").Value);
131 duration = int.Parse(item.Attribute("max_time").Value);
132 frequency = int.Parse(item.Attribute("frequency").Value);
133 }
134 }
135 }
136
137 //Populates the attenuation update dictionary with default values at time t=0.
138 //Also allocates space to each element of Dictionary array based on the
139 //number of elements of each connection type.
140 public void PopulateDefaultValues()
141 {
142 attnupdate = new Dictionary< string, float>[connectionList.Count];
143 for (int i=0; i< connectionList.Count; i++)
144 {
145 attnupdate[i] = new Dictionary<string, float>();
146 for (int j = 1; j <= (connectionList[i].maxobj); j++)
147 {
148 for (int k = j+1; k <= (connectionList[i].maxobj); k++)//n(n-1) links for max n objects
149 {
150 attnupdate[i].Add((j.ToString() + "-" + k.ToString()), connectionList[i].defattn);
151 }
152 }
153 }
154 }
155
156 //Maps object name to "objecttype-id"
157 void Compobjmap()
158 {
159 string temp = "";
160 for (int i = 0; i < objectlist.Count; i++)
161 {
162 temp = objectlist[i].type + "-" + objectlist[i].id;
163 objmap.Add(objectlist[i].name, temp.Split('-'));
164 }
165 }
166
167 //Computes the attenuation values for the object pairs specified in the config file.
168 void ComputeDistance()
169 {
170 Vector3 coord1 = new Vector3();//Holds coordinates for the first object
171 Vector3 coord2 = new Vector3();//Holds coordinates for the second object
172
173 for (int i = 0; i < objectlist.Count; i++)//Iterate through every object
174 {
175 for(int j=0;j<connectionList.Count;j++)//Iterate through all the objects that the 'i'th object is paired with for each connection type.
176 {
177 string[] a;
178 if (objectlist[i].links.ContainsKey(connectionList[j].name) )
179 {
180 a = objectlist[i].links[connectionList[j].name];//Holds the objects that object i is connected to of connection type j
181
182 coord1 = GetCoordinates(objectlist[i].name);
183 for (int k = 0; k < a.Length; k++)
184 {
185 string temp = "";
186 coord2 = GetCoordinates(a[k]);
187
188 if (int.Parse(a[k]) < int.Parse(objectlist[i].name))//Checks to ensure that in the link i-j, i<j and the key i-j always has i<j
189 temp = a[k] + "-" + objectlist[i].name;
190 else if (int.Parse(a[k]) > int.Parse(objectlist[i].name))
191 temp = objectlist[i].name + "-" + a[k];
192
193 if (temp != "" && int.Parse(a[k]) <= connectionList[j].maxobj && int.Parse(objectlist[i].name) <= connectionList[j].maxobj)
194 attnupdate[j][temp] = DistanceFunction(Vector3.Distance(coord1, coord2)) + GetRayHit(coord1, coord2);//Update the jth index of dictionary array attn update for object i. Sums up the distance function and the attenuation caused by objects present between the source and destination.
195 }
196 }
197 }
198 }
199 }
200
201 //Writes to Attenuation.csv. Creates new file if file doesn't already exist
202 void WriteToFile(float timestamp)
203 {
204 string fileText = "";
205 string[] output = new string[connectionList.Count];
206
207 for (int i = 0; i < connectionList.Count; i++)
208 {
209 output[i] = "";
210 for (int j = 1; j <= (connectionList[i].maxobj); j++)
211 {
212 for (int k = j + 1; k <= (connectionList[i].maxobj); k++)
213 {
214 output[i] += ((attnupdate[i][j.ToString() + "-" + k.ToString()]).ToString()) + ",";//Returns the attenuation value for the key "object 1 - object 2"
215 }
216 }
217
218 if (i != connectionList.Count - 1)
219 {
220 output[i] += ",";
221 }
222 }
223 fileText = timestamp.ToString() + ",";
224
225 for (int i = 0; i < connectionList.Count; i++)
226 {
227 fileText += output[i];
228 }
229
230 if (!File.Exists(path))
231 File.WriteAllText(path, fileText);
232 else
233 File.AppendAllText(path, fileText);
234
235 File.AppendAllText(path, "\n");
236 }
237
238 //Returns the coordinates for object type passed.
239 //The objmap dictionary gives the name and id of the object
240 Vector3 GetCoordinates(string item)
241 {
242 GameObject[] ob = null;
243 string[] dob;
244 objmap.TryGetValue(item, out dob);
245 ob = GameObject.FindGameObjectsWithTag(dob[0]);//0th index is the name of the object
246 return ob[int.Parse(dob[1])].transform.position;//1st index holds the id
247 }
248 //Returns the sum of the attenuation factor of all objects between 2 objects
249 float GetRayHit(Vector3 source, Vector3 dest)
250 {
251 RaycastHit[] hits;
252 string obj = "";
253 int fac = 0, attn = 0;
254 hits = Physics.RaycastAll(source, dest, Vector3.Distance(source, dest));//Array of objects between source and destination
255
256 for (int i = 0; i < hits.Length; i++)
257 {
258 obj = hits[i].collider.tag;
259 attnfactor.TryGetValue(obj, out fac);//Fetch attnfactor for the object
260 attn += fac;
261 }
262 return attn;
263 }
264
265 float DistanceFunction(float distance)
266 {
267 return 20f * (float)Math.Log10(distance) + 20f * (float)Math.Log10(frequency) - 27.55f ;
268 }
269
270 void Start()//Called once before start of simulation for initialization
271 {
272 if (File.Exists("config.xml"))//Checks if config file exists
273 config = true;
274 if (Time.time <= duration && config)//If config file exists and the time is less than the duration
275 {
276 GetDefValues();//Read XML for connections
277 GetConnections();//Read XML for objects
278 PopulateDefaultValues();//Populate the attnupdate dictionary with default values
279 GetParameters();//Read XML for simulation parameters
280 GetAttnFactor();//Read XML for attenuation factors
281
282 objectlist = objectlist.OrderBy(o => o.name).ToList();//Sort objectlist by name
283 connectionList = connectionList.OrderBy(o => o.name).ToList();//Sort connectionlist by name
284
285 Compobjmap();//Maps name to object type and id
286 }
287 }
288
289 void FixedUpdate()//Called every 0.03 secs
290 {
291 if (Time.time >= nextTime && Time.time <= duration && config)//Checks if its time for the next update and time is less than duration
292 {
293 if (exec)//Set to true if objects have been loaded.
294 {
295 ComputeDistance();//Compute attenuation values
296 WriteToFile(nextTime);//Write the values to the file
297 nextTime += (interval / 1000);//Update the clock for the next time the values have to be updated
298 }
299 else//See if objects have been loaded
300 {
301 GameObject[] sample = GameObject.FindGameObjectsWithTag("Car");
302 if (sample.Length > 1)
303 {
304 exec = true;
305 }
306 }
307 }
308 else if(Time.time > duration)//Quit if duration has exceeded
309 {
310 Application.Quit();
311 }
312 }
313}
314