Skip to content

Commit df12980

Browse files
committed
Node invalidation on world state update
1 parent 44c64ec commit df12980

File tree

3 files changed

+51
-36
lines changed

3 files changed

+51
-36
lines changed

common/src/main/kotlin/com/lambda/command/commands/PathCommand.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ object PathCommand : LambdaCommand(
5858
execute {
5959
val v = fastVectorOf(x().value(), y().value(), z().value())
6060
Pathfinder.dStar.invalidate(v)
61+
Pathfinder.needsUpdate = true
6162
this@PathCommand.info("Invalidated ${v.string}")
6263
}
6364
}
@@ -71,7 +72,7 @@ object PathCommand : LambdaCommand(
7172
required(integer("Z", -30000000, 30000000)) { z ->
7273
execute {
7374
val v = fastVectorOf(x().value(), y().value(), z().value())
74-
Pathfinder.graph.remove(v)
75+
Pathfinder.graph.removeNode(v)
7576
this@PathCommand.info("Removed ${v.string}")
7677
}
7778
}

common/src/main/kotlin/com/lambda/pathing/dstar/DStarLite.kt

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import com.lambda.util.math.minus
3030
import com.lambda.util.math.plus
3131
import com.lambda.util.math.times
3232
import com.lambda.util.world.FastVector
33+
import com.lambda.util.world.add
34+
import com.lambda.util.world.fastVectorOf
3335
import com.lambda.util.world.string
3436
import com.lambda.util.world.toCenterVec3d
3537
import kotlin.math.min
@@ -146,33 +148,33 @@ class DStarLite(
146148

147149
/**
148150
* Invalidates a node (e.g., it became an obstacle) and updates affected neighbors.
149-
* Call `computeShortestPath()` afterwards.
150151
*/
151152
fun invalidate(u: FastVector) {
152-
// 1. Invalidate node in graph and get its direct valid neighbors
153-
// This also clears the neighbors' cached successors, forcing re-initialization.
154-
val neighborsToUpdate = graph.invalidate(u)
155-
156-
// 2. Update the rhs value for all affected neighbors.
157-
// Since their edge information might change upon re-initialization,
158-
// the safest approach is to recompute their rhs from scratch.
159-
neighborsToUpdate.forEach { neighbor ->
160-
if (neighbor != goal) {
161-
// Recompute rhs based on its *potentially new* set of successors
162-
// Note: minSuccessorCost will trigger re-initialization
163-
setRHS(neighbor, minSuccessorCost(neighbor))
164-
}
165-
// Check consistency and update queue status for the neighbor
166-
updateVertex(neighbor)
153+
graph.neighbors(u).forEach { v ->
154+
graph.invalidated.add(v)
155+
updateEdge(u, v, INF)
156+
updateEdge(v, u, INF)
167157
}
168-
169-
// 3. Update the invalidated node itself (likely sets g=INF, rhs=INF)
170-
if (u != goal) {
171-
setRHS(u, minSuccessorCost(u)) // Should return INF
158+
graph.invalidated.forEach { v ->
159+
val currentConnections = graph.successors(v)
160+
val actualConnections = graph.initialize(v)
161+
val changedConnections = currentConnections.filter { (succ, cost) -> cost != actualConnections[succ] }
162+
val newConnections = actualConnections.filter { (succ, _) -> succ !in currentConnections }
163+
val removedConnections = currentConnections.filter { (succ, _) -> succ !in actualConnections }
164+
changedConnections.forEach { (succ, cost) ->
165+
updateEdge(v, succ, cost)
166+
updateEdge(succ, v, cost)
167+
}
168+
newConnections.forEach { (succ, cost) ->
169+
updateEdge(v, succ, cost)
170+
updateEdge(succ, v, cost)
171+
}
172+
removedConnections.forEach { (succ, _) ->
173+
updateEdge(v, succ, INF)
174+
updateEdge(succ, v, INF)
175+
}
172176
}
173-
// Ensure g is INF and update queue status
174-
setG(u, INF)
175-
updateVertex(u)
177+
graph.invalidated.clear()
176178
}
177179

178180
/**
@@ -184,13 +186,18 @@ class DStarLite(
184186
*/
185187
fun updateEdge(u: FastVector, v: FastVector, c: Double) {
186188
val cOld = graph.cost(u, v)
189+
if (cOld == c) return
187190
graph.setCost(u, v, c)
188191
if (cOld > c) {
189192
if (u != goal) setRHS(u, min(rhs(u), c + g(v)))
190193
} else if (rhs(u) == cOld + g(v)) {
191194
if (u != goal) setRHS(u, minSuccessorCost(u))
192195
}
193196
updateVertex(u)
197+
// if (c == INF) {
198+
// graph.removeEdge(u, v)
199+
// graph.removeEdge(v, u)
200+
// }
194201
}
195202

196203
/**

common/src/main/kotlin/com/lambda/pathing/dstar/LazyGraph.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,42 +52,49 @@ class LazyGraph(
5252

5353
/** Initializes a node if not already initialized, then returns successors. */
5454
fun successors(u: FastVector): MutableMap<FastVector, Double> =
55-
successors.getOrPut(u) {
56-
nodeInitializer(u).onEach { (neighbor, cost) ->
57-
predecessors.getOrPut(neighbor) { hashMapOf() }[u] = cost
58-
}.toMutableMap()
59-
}
55+
successors.getOrPut(u) { initialize(u).toMutableMap() }
6056

6157
/** Initializes predecessors by ensuring successors of neighboring nodes. */
6258
fun predecessors(u: FastVector): Map<FastVector, Double> {
6359
successors(u)
6460
return predecessors[u] ?: emptyMap()
6561
}
6662

67-
fun remove(u: FastVector) {
63+
fun removeNode(u: FastVector) {
6864
successors.remove(u)
6965
successors.values.forEach { it.remove(u) }
7066
predecessors.remove(u)
7167
predecessors.values.forEach { it.remove(u) }
7268
}
7369

70+
fun removeEdge(u: FastVector, v: FastVector) {
71+
successors[u]?.remove(v)
72+
predecessors[v]?.remove(u)
73+
if (successors[u]?.isEmpty() == true) {
74+
successors.remove(u)
75+
}
76+
if (predecessors[v]?.isEmpty() == true) {
77+
predecessors.remove(v)
78+
}
79+
}
80+
81+
fun initialize(u: FastVector) =
82+
nodeInitializer(u).onEach { (neighbor, cost) ->
83+
predecessors.getOrPut(neighbor) { hashMapOf() }[u] = cost
84+
}
85+
7486
fun setCost(u: FastVector, v: FastVector, c: Double) {
7587
successors[u]?.put(v, c)
7688
predecessors[v]?.put(u, c)
7789
}
7890

79-
fun invalidate(u: FastVector) =
80-
neighbors(u).apply {
81-
forEach { remove(it) }
82-
invalidated.addAll(this)
83-
}
84-
8591
fun clear() {
8692
successors.clear()
8793
predecessors.clear()
8894
invalidated.clear()
8995
}
9096

97+
fun edges(u: FastVector) = successors(u).entries + predecessors(u).entries
9198
fun neighbors(u: FastVector): Set<FastVector> = successors(u).keys + predecessors(u).keys
9299

93100
/** Returns the cost of the edge from u to v (or ∞ if none exists) */

0 commit comments

Comments
 (0)