Prepare for spherical average
This commit is contained in:
parent
1e1e5b1344
commit
d026996ce2
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
using Vector3 = UnityEngine.Vector3;
|
||||
#endif
|
||||
@ -137,6 +139,19 @@ namespace LinearAlgebra {
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Spherical operator *(Spherical v, float d) {
|
||||
Spherical r = new(v.distance * d, v.direction);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static bool operator ==(Spherical v1, Spherical v2) {
|
||||
return (v1.distance == v2.distance && v1.direction == v2.direction);
|
||||
}
|
||||
|
||||
public static bool operator !=(Spherical v1, Spherical v2) {
|
||||
return (v1.distance != v2.distance || v1.direction != v2.direction);
|
||||
}
|
||||
|
||||
public static float Distance(Spherical v1, Spherical v2) {
|
||||
// Convert degrees to radians
|
||||
float thetaARadians = v1.direction.horizontal.inRadians;
|
||||
@ -162,5 +177,37 @@ namespace LinearAlgebra {
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
public static Spherical Average(List<Spherical> vectors) {
|
||||
float sumSinPhiCosTheta = 0.0f;
|
||||
float sumSinPhiSinTheta = 0.0f;
|
||||
float sumCosPhi = 0.0f;
|
||||
|
||||
int n = vectors.Count;
|
||||
|
||||
// Step 1: Accumulate sine and cosine components
|
||||
foreach(Spherical v in vectors) {
|
||||
float sinHorizontal = AngleFloat.Sin(v.direction.horizontal);
|
||||
sumSinPhiCosTheta += v.distance * sinHorizontal * AngleFloat.Cos(v.direction.vertical);
|
||||
sumSinPhiSinTheta += v.distance * sinHorizontal * AngleFloat.Sin(v.direction.vertical);
|
||||
sumCosPhi += v.distance * AngleFloat.Cos(v.direction.horizontal);
|
||||
}
|
||||
|
||||
// Step 2: Calculate average components
|
||||
float avgSinPhiCosTheta = sumSinPhiCosTheta / n;
|
||||
float avgSinPhiSinTheta = sumSinPhiSinTheta / n;
|
||||
float avgCosPhi = sumCosPhi / n;
|
||||
|
||||
// Step 3: Calculate the magnitude of the average vector
|
||||
float rAvg = MathF.Sqrt(avgSinPhiCosTheta * avgSinPhiCosTheta +
|
||||
avgSinPhiSinTheta * avgSinPhiSinTheta +
|
||||
avgCosPhi * avgCosPhi);
|
||||
|
||||
// Step 4: Calculate average angles
|
||||
AngleFloat horizontalAvg = AngleFloat.Acos(avgCosPhi / rAvg); // Handle rAvg != 0 case
|
||||
AngleFloat verticalAvg = AngleFloat.Atan2(avgSinPhiSinTheta, avgSinPhiCosTheta);
|
||||
|
||||
return new Spherical(rAvg, new Direction(horizontalAvg, verticalAvg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using LinearAlgebra;
|
||||
|
||||
@ -73,7 +74,7 @@ public class Neuroid : Nucleus {
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
public virtual void UpdateState() {
|
||||
public override void UpdateState() {
|
||||
Vector3 resultVector = Vector3.zero;
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
Nucleus synapseNucleus = synapse.nucleus;
|
||||
@ -93,18 +94,23 @@ public class Neuroid : Nucleus {
|
||||
resultVector /= this.synapses.Count;
|
||||
|
||||
Spherical result = Spherical.FromVector3(resultVector);
|
||||
float d = Spherical.Distance(result, this.outputValue);
|
||||
if (d < 0.1f) {
|
||||
//Debug.Log($"insignificant update: {d}");
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputValue = result;
|
||||
// List<Spherical> vectors = new();
|
||||
// foreach (Synapse synapse in this.synapses) {
|
||||
// if (synapse.nucleus.isSleeping)
|
||||
// continue;
|
||||
|
||||
// vectors.Add(synapse.nucleus.outputValue);
|
||||
// }
|
||||
// Spherical result2 = Spherical.Average(vectors);
|
||||
// if (average == false)
|
||||
// result2 *= vectors.Count;
|
||||
|
||||
foreach (Receiver receiver in this.receivers) {
|
||||
if (receiver.nucleus is Neuroid neuroid)
|
||||
neuroid.SetInput(this);
|
||||
}
|
||||
// if (result2 != result)
|
||||
// Debug.Log($"update error {result2} != {result}");
|
||||
|
||||
UpdateResult(result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -151,6 +151,20 @@ public class Nucleus {
|
||||
synapses.Add(newSynapse);
|
||||
}
|
||||
|
||||
public virtual void UpdateState() { }
|
||||
|
||||
public void UpdateResult(Spherical result) {
|
||||
float d = Spherical.Distance(result, this.outputValue);
|
||||
if (d < 0.1f) {
|
||||
//Debug.Log($"insignificant update: {d}");
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputValue = result;
|
||||
foreach (Receiver receiver in this.receivers)
|
||||
receiver.nucleus.UpdateState();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
|
||||
@ -74,19 +74,9 @@ public class Perceptoid : Neuroid {
|
||||
this.receivers = new();
|
||||
}
|
||||
|
||||
public void UpdateState(int thingId, Spherical receptorValue) {
|
||||
this.thingId = thingId;
|
||||
Spherical result = receptorValue;
|
||||
|
||||
float d = Spherical.Distance(result, this.outputValue);
|
||||
if (d < 0.1f) {
|
||||
//Debug.Log($"insignificant update: {d}");
|
||||
return;
|
||||
}
|
||||
this.outputValue = result;
|
||||
foreach (Receiver receiver in this.receivers)
|
||||
if (receiver.nucleus is Neuroid neuroid)
|
||||
neuroid.SetInput(this);
|
||||
public override void UpdateState() {
|
||||
Spherical result = this.receptor.localPosition;
|
||||
UpdateResult(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -87,6 +87,7 @@ public class Receptor {
|
||||
return;
|
||||
}
|
||||
// Debug.Log($"Stimulus {thingType} {thingId} {selectedPerceptoid.name}");
|
||||
selectedPerceptoid.UpdateState(thingId, this.localPosition);
|
||||
selectedPerceptoid.thingId = thingId;
|
||||
selectedPerceptoid.UpdateState();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user