Curvature regulators #80
1 changed files with 22 additions and 11 deletions
|
@ -148,7 +148,15 @@ pub trait Regulator: ProblemPoser + OutlineItem {
|
||||||
fn measurement(&self) -> ReadSignal<f64>;
|
fn measurement(&self) -> ReadSignal<f64>;
|
||||||
fn set_point(&self) -> Signal<SpecifiedValue>;
|
fn set_point(&self) -> Signal<SpecifiedValue>;
|
||||||
|
|
||||||
fn activate(&self, _assembly: &Assembly) {}
|
// this method is used to responsively precondition the assembly for
|
||||||
|
// realization when the regulator becomes a constraint, or is edited while
|
||||||
|
// acting as a constraint. it should track the set point, do any desired
|
||||||
|
// preconditioning when the set point is present, and use its return value
|
||||||
|
// to report whether the set is present. the default implementation does no
|
||||||
|
// preconditioning
|
||||||
|
fn try_activate(&self, _assembly: &Assembly) -> bool {
|
||||||
|
self.set_point().with(|set_pt| set_pt.is_present())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InversiveDistanceRegulator {
|
pub struct InversiveDistanceRegulator {
|
||||||
|
@ -240,14 +248,18 @@ impl Regulator for HalfCurvatureRegulator {
|
||||||
self.set_point
|
self.set_point
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&self, assembly: &Assembly) {
|
fn try_activate(&self, assembly: &Assembly) -> bool {
|
||||||
if let Some(half_curv) = self.set_point.with_untracked(|set_pt| set_pt.value) {
|
match self.set_point.with(|set_pt| set_pt.value) {
|
||||||
|
Some(half_curv) => {
|
||||||
let representation = assembly.elements.with_untracked(
|
let representation = assembly.elements.with_untracked(
|
||||||
|elts| elts[self.subject].representation
|
|elts| elts[self.subject].representation
|
||||||
);
|
);
|
||||||
representation.update(
|
representation.update(
|
||||||
|rep| change_half_curvature(rep, half_curv)
|
|rep| change_half_curvature(rep, half_curv)
|
||||||
);
|
);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,8 +394,7 @@ impl Assembly {
|
||||||
console::log_1(&JsValue::from(
|
console::log_1(&JsValue::from(
|
||||||
format!("Updated regulator with subjects {:?}", regulator_rc.subjects())
|
format!("Updated regulator with subjects {:?}", regulator_rc.subjects())
|
||||||
));
|
));
|
||||||
glen marked this conversation as resolved
Outdated
|
|||||||
if regulator_rc.set_point().with(|set_pt| set_pt.is_present()) {
|
if regulator_rc.try_activate(&self_for_effect) {
|
||||||
regulator_rc.activate(&self_for_effect);
|
|
||||||
self_for_effect.realize();
|
self_for_effect.realize();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue
This function evokes a few questions:
A) Seems like there is some duplication at least of structure/behavior here with the insert_new_product_regulator; is there anything that can be profitable factored out (some common insert_regulator common functionality that both of these can use)?
B) Why do you have to do so much work updating the guess (I think that's what's going on) when you start regulating curvature, but it seems like you don't do much of anything when you start regulating an inversive distance?
C) This very much has the look of engine code that has leaked into the assembly: nitty gritty dealing with the internal coordinates of an element. Any chance it could be implemented in the engine and just called here, or perhaps even just deferred until a pre-processing step when the realization is called? Either way, it also might make the code between insert curvature regulator and insert product regulator more similar and easier to share between the two.
I agree that the code is organized similarly, but I haven't found anything we can usefully factor out. For example, I don't see a way to put the shared organization in a shared constructor, because
ProductRegulator
andHalfCurvatureRegulator
are different structures. The only thing that seems really straightforwardly shared is initializing the set point tocreate_signal(SpecifiedValue::from_empty_spec())
,which seems like too little code to factor out profitably.
We don't have to be so careful about updating the guess. My first prototype of the curvature regulator didn't do anything special when it started regulating; the curvature component of the representation vector would just get overwritten with the desired value at the beginning of the engine's realization routine. That seemed to work fine in the examples I played with.
I felt compelled to be careful about updating the guess for three related reasons:
I'd be open to also choosing the initial guess more carefully when we start regulating an inversive distance. That seems tricker to me, though, and I haven't felt a need for it.
Yes, I think this code is on the border between the assembly module's responsibilities and the engine's responsibilities. I decided to put it in the assembly module because its core purpose is to decide how an otherwise unconstrained sphere should behave when you change its curvature. That seems more like user interaction than like constraint solving to me.
On the other hand, the engine does provide representation-specific implementations of other user-facing, mostly-representation-agnostic tasks, like creating a sphere from a center and a radius (
sphere
) or a direction, an offset, and a curvature (sphere_with_offset
). If we can find a mostly-representation-agnostic way to describe how we update the curvature, maybe it would feel similar in spirit to those tasks.I've adopted this approach in commit
4654bf0
by moving the half-curvature change routine into the engine module. I haven't come up with a representation-agnostic description of how the sphere is supposed to change, so I'm just calling the routinechange_half_curvature
for now.