Commit 250bffc6 authored by Thomas BOUTROUE's avatar Thomas BOUTROUE

Add a PhysicalState and LinkPhysicalStateToDigitalSensor

This allows watching a physical value and changing a state

It uses low/high threshold to do hysterisis

Fix #42
parent beb25bf4
......@@ -37,6 +37,7 @@ QML_ENUM_CLASS (ObjectFamily,
ANGLE,
BLOCK,
MARKER,
STATE,
WORLD,
CANOPEN,
CANBUS,
......
......@@ -398,3 +398,40 @@ void LinkDigitalOutputToDigitalInput::syncNormal (void) {
void LinkDigitalOutputToDigitalInput::syncReverse (void) {
m_output->set_value (m_input->get_value ());
}
LinkPhysicalStateToDigitalSensor::LinkPhysicalStateToDigitalSensor (QObject * parent)
: AbstractLink (parent)
, m_state (Q_NULLPTR)
, m_sensor (Q_NULLPTR)
{
Manager::instance ().registerObject (this);
}
LinkPhysicalStateToDigitalSensor::~LinkPhysicalStateToDigitalSensor (void) {
Manager::instance ().unregisterObject (this);
}
void LinkPhysicalStateToDigitalSensor::onComponentCompleted (void) {
AbstractLink::onComponentCompleted ();
if (get_title ().isEmpty ()) {
set_title ("Watch");
}
Manager::instance ().intializeObject (this);
}
void LinkPhysicalStateToDigitalSensor::initHandler (void) {
update_state (get_source () ? get_source ()->as<PhysicalState> () : Q_NULLPTR);
update_sensor (get_target () ? get_target ()->as<DigitalSensor> () : Q_NULLPTR);
}
void LinkPhysicalStateToDigitalSensor::ensureValid (void) {
update_valid (m_state && m_sensor);
}
void LinkPhysicalStateToDigitalSensor::syncNormal (void) {
m_sensor->set_value (m_state->get_state ());
}
void LinkPhysicalStateToDigitalSensor::syncReverse (void) {
m_state->update_state (m_sensor->get_value ());
}
......@@ -17,6 +17,7 @@ class DigitalOutput;
class DigitalSensor;
class DigitalActuator;
class PhysicalValue;
class PhysicalState;
class AbstractLink : public BasicObject {
Q_OBJECT
......@@ -197,4 +198,21 @@ public:
void syncReverse (void) Q_DECL_FINAL;
};
class LinkPhysicalStateToDigitalSensor : public AbstractLink {
Q_OBJECT
QML_READONLY_PTR_PROPERTY (PhysicalState, state)
QML_READONLY_PTR_PROPERTY (DigitalSensor, sensor)
public:
explicit LinkPhysicalStateToDigitalSensor (QObject * parent = Q_NULLPTR);
virtual ~LinkPhysicalStateToDigitalSensor (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
#endif // LINK_H
......@@ -81,6 +81,7 @@ Manager::Manager (void)
, m_linksPhysicalValueToAnalogSensor (50)
, m_linksAnalogOutputToAnalogInput (50)
, m_linksDigitalOutputToDigitalInput (50)
, m_linksPhysicalStateToDigitalSensor (50)
, m_transformers (100)
, m_affineTransformers (50)
, m_customTransformers (20)
......@@ -102,6 +103,7 @@ Manager::Manager (void)
, m_physicalValues (500)
, m_physicalBlocks (10)
, m_physicalMarkers (20)
, m_physicalStates (20)
, m_canOpens (20)
, m_canBuses (5)
, m_serialBuses (5)
......@@ -289,6 +291,7 @@ void Manager::deinit (void) {
m_physicalValues.clear ();
m_physicalBlocks.clear ();
m_physicalMarkers.clear ();
m_physicalStates.clear ();
m_routines.clear ();
m_routinesOnTimer.clear ();
m_routinesOnEvent.clear ();
......@@ -307,6 +310,7 @@ void Manager::deinit (void) {
m_linksPhysicalValueToAnalogSensor.clear ();
m_linksAnalogOutputToAnalogInput.clear ();
m_linksDigitalOutputToDigitalInput.clear ();
m_linksPhysicalStateToDigitalSensor.clear ();
m_transformers.clear ();
m_affineTransformers.clear ();
m_customTransformers.clear ();
......@@ -661,7 +665,7 @@ void Manager::onTick (void) {
const int time = int (m_chrono.elapsed ());
m_chrono.restart ();
for (LinkPhysicalValueToAnalogSensor * link : arrayRange (m_linksPhysicalValueToAnalogSensor)) {
link->sync (); // PHYSICAL -> SENSOR
link->sync (); // PHYSICAL VALUE -> SENSOR
}
for (LinkAnalogSensorToAnalogInput * link : arrayRange (m_linksAnalogSensorToAnalogInput)) {
link->sync (); // SENSOR -> AIN
......@@ -690,6 +694,12 @@ void Manager::onTick (void) {
for (PhysicalValue * value : arrayRange (m_physicalValues)) {
value->move (time); // move value after running actuators
}
for (PhysicalState * state : arrayRange (m_physicalStates)) {
state->refreshState (); // recompute states after updating physical values
}
for (LinkPhysicalStateToDigitalSensor * link : arrayRange (m_linksPhysicalStateToDigitalSensor)) {
link->sync (); // PHYSICAL STATE -> SENSOR
}
if (m_physicalWorld) {
m_physicalWorld->processPhysics ();
}
......@@ -855,6 +865,9 @@ void Manager::doInitObjects (void) {
else if (LinkDigitalOutputToDigitalInput * sublink = link->as<LinkDigitalOutputToDigitalInput> ()) {
m_linksDigitalOutputToDigitalInput.add (sublink);
}
else if (LinkPhysicalStateToDigitalSensor * sublink = link->as<LinkPhysicalStateToDigitalSensor> ()) {
m_linksPhysicalStateToDigitalSensor.add (sublink);
}
else { }
}
else if (AbstractTransformer * transformer = basicObject->as<AbstractTransformer> ()) {
......@@ -896,6 +909,11 @@ void Manager::doInitObjects (void) {
block->refreshVertexList ();
usePath = true;
}
else if (PhysicalState * state = basicObject->as<PhysicalState> ()) {
dump ("STATE", state);
m_physicalStates.add (state);
usePath = true;
}
else if (PhysicalMarker * marker = basicObject->as<PhysicalMarker> ()) {
dump ("MARKER", marker);
m_physicalMarkers.add (marker);
......@@ -1216,6 +1234,9 @@ void Manager::doBuildChains (void) {
link->update_enabled (enabled);
link->update_reversed (reversed);
}
for (LinkPhysicalStateToDigitalSensor * link : arrayRange (m_linksPhysicalStateToDigitalSensor)) {
link->update_enabled (true);
}
/// clear old chains
qDeleteAll (analogSensorChains);
qDeleteAll (digitalSensorChains);
......
......@@ -66,11 +66,13 @@ class LinkDigitalSensorToDigitalInput;
class LinkPhysicalValueToAnalogSensor;
class LinkAnalogOutputToAnalogInput;
class LinkDigitalOutputToDigitalInput;
class LinkPhysicalStateToDigitalSensor;
class PhysicalWorld;
class PhysicalValue;
class PhysicalBlock;
class PhysicalMarker;
class PhysicalState;
class AbstractTransformer;
class AffineTransformer;
......@@ -196,6 +198,7 @@ protected:
Collection<LinkPhysicalValueToAnalogSensor> m_linksPhysicalValueToAnalogSensor;
Collection<LinkAnalogOutputToAnalogInput> m_linksAnalogOutputToAnalogInput;
Collection<LinkDigitalOutputToDigitalInput> m_linksDigitalOutputToDigitalInput;
Collection<LinkPhysicalStateToDigitalSensor> m_linksPhysicalStateToDigitalSensor;
Collection<AbstractTransformer> m_transformers;
Collection<AffineTransformer> m_affineTransformers;
......@@ -222,6 +225,7 @@ protected:
Collection<PhysicalValue> m_physicalValues;
Collection<PhysicalBlock> m_physicalBlocks;
Collection<PhysicalMarker> m_physicalMarkers;
Collection<PhysicalState> m_physicalStates;
Collection<CanOpen> m_canOpens;
Collection<CanBus> m_canBuses;
......
......@@ -466,6 +466,37 @@ QJsonObject PhysicalBlock::exportState (void) const {
};
}
PhysicalState::PhysicalState (QObject * parent)
: BasicObject (ObjectFamily::STATE, parent)
, m_lowThreshold (0.0f)
, m_highThreshold (1.0f)
, m_inverted (false)
, m_state (false)
{
Manager::instance ().registerObject (this);
}
PhysicalState::~PhysicalState (void) {
Manager::instance ().unregisterObject (this);
}
void PhysicalState::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
Manager::instance ().intializeObject (this);
}
void PhysicalState::refreshState (void) {
if (m_referenceValue) {
if (m_referenceValue->get_val () >= m_highThreshold) {
update_state (m_inverted ? false : true);
}
else if (m_referenceValue->get_val () <= m_lowThreshold) {
update_state (m_inverted ? true : false);
}
else { }
}
}
PhysicalWorld::PhysicalWorld (QObject * parent)
: BasicObject (ObjectFamily::WORLD, parent)
, m_subObjects (this)
......@@ -480,7 +511,9 @@ PhysicalWorld::PhysicalWorld (QObject * parent)
Manager::instance ().registerObject (this);
}
PhysicalWorld::~PhysicalWorld (void) { }
PhysicalWorld::~PhysicalWorld (void) {
Manager::instance ().unregisterObject (this);
}
void PhysicalWorld::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
......
......@@ -230,6 +230,23 @@ public:
void refreshAncestors (void);
};
class PhysicalState : public BasicObject {
Q_OBJECT
QML_WRITABLE_PTR_PROPERTY (PhysicalValue, referenceValue)
QML_WRITABLE_VAR_PROPERTY (float, lowThreshold)
QML_WRITABLE_VAR_PROPERTY (float, highThreshold)
QML_WRITABLE_VAR_PROPERTY (bool, inverted)
QML_READONLY_VAR_PROPERTY (bool, state)
public:
explicit PhysicalState (QObject * parent = Q_NULLPTR);
virtual ~PhysicalState (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void refreshState (void);
};
class PhysicalWorld : public BasicObject {
Q_OBJECT
Q_INTERFACES (QQmlParserStatus)
......
......@@ -115,6 +115,7 @@ DigitalSensor::DigitalSensor (QObject * parent)
, m_value (false)
, m_trueLabel ("ON")
, m_falseLabel ("OFF")
, m_sourceLink (Q_NULLPTR)
, m_targetLinks (this)
{
Manager::instance ().registerObject (this);
......@@ -132,6 +133,9 @@ QJsonObject DigitalSensor::exportState (void) const {
void DigitalSensor::onComponentCompleted (void) {
AbstractSensor::onComponentCompleted ();
if (m_sourceLink) {
m_sourceLink->set_target (this);
}
for (LinkDigitalSensorToDigitalInput * link : m_targetLinks) {
link->set_source (this);
}
......
......@@ -11,6 +11,7 @@ class PhysicalValue;
class LinkAnalogSensorToAnalogInput;
class LinkDigitalSensorToDigitalInput;
class LinkPhysicalValueToAnalogSensor;
class LinkPhysicalStateToDigitalSensor;
class AbstractSensor : public BasicObject {
Q_OBJECT
......@@ -72,6 +73,8 @@ class DigitalSensor : public AbstractSensor {
QML_WRITABLE_VAR_PROPERTY (bool, value)
QML_WRITABLE_CSTREF_PROPERTY (QString, trueLabel)
QML_WRITABLE_CSTREF_PROPERTY (QString, falseLabel)
// source link
QML_WRITABLE_PTR_PROPERTY (LinkPhysicalStateToDigitalSensor, sourceLink)
// target links
QML_LIST_PROPERTY (LinkDigitalSensorToDigitalInput, targetLinks)
......
......@@ -169,6 +169,7 @@ void SharedObject::registerQmlTypes (QQmlEngine * qmlEngine) {
qmlRegisterType<LinkPhysicalValueToAnalogSensor> (uri, maj, min, "LinkPhysicalValueToAnalogSensor");
qmlRegisterType<LinkAnalogOutputToAnalogInput> (uri, maj, min, "LinkAnalogOutputToAnalogInput");
qmlRegisterType<LinkDigitalOutputToDigitalInput> (uri, maj, min, "LinkDigitalOutputToDigitalInput");
qmlRegisterType<LinkPhysicalStateToDigitalSensor> (uri, maj, min, "LinkPhysicalStateToDigitalSensor");
qmlRegisterType<CanBus> (uri, maj, min, "CanBus");
qmlRegisterType<CanOpen> (uri, maj, min, "CanOpen");
qmlRegisterType<NetworkDefinition> (uri, maj, min, "NetworkDefinition");
......@@ -180,6 +181,7 @@ void SharedObject::registerQmlTypes (QQmlEngine * qmlEngine) {
qmlRegisterType<PhysicalBlock> (uri, maj, min, "PhysicalBlock");
qmlRegisterType<PhysicalValue> (uri, maj, min, "PhysicalValue");
qmlRegisterType<PhysicalMarker> (uri, maj, min, "PhysicalMarker");
qmlRegisterType<PhysicalState> (uri, maj, min, "PhysicalState");
qmlRegisterType<PhysicalWorld> (uri, maj, min, "PhysicalWorld");
qmlRegisterType<RoutineOnCanFrame> (uri, maj, min, "RoutineOnCanFrame");
qmlRegisterType<RoutineOnSerialFrame> (uri, maj, min, "RoutineOnSerialFrame");
......
......@@ -19,6 +19,11 @@ AbstractDelegateSensor {
}
CheckableBox {
size: Style.fontSizeBig;
enabled: (digitalSensor
&& ((digitalSensor.sourceLink
&& (digitalSensor.sourceLink.detached
|| digitalSensor.sourceLink.reversed))
|| !digitalSensor.sourceLink));
anchors.verticalCenter: parent.verticalCenter;
onEdited: { digitalSensor.value = value; }
......@@ -35,6 +40,12 @@ AbstractDelegateSensor {
}
Stretcher { }
}
Repeater {
model: (digitalSensor ? digitalSensor.sourceLink : 0);
delegate: DelegateLinkSource {
link: modelData;
}
}
Repeater {
model: (digitalSensor ? digitalSensor.targetLinks : 0);
delegate: DelegateLinkTarget {
......
......@@ -438,6 +438,24 @@ NetworkDefinition {
}
]
}
DigitalSensor {
id: sensorArmFullIn;
uid: "SENSOR_ARM_FULL_IN";
title: "Arm full-in sensor";
description: "Sensor checking if arm is fully retracted in";
sourceLink: LinkPhysicalStateToDigitalSensor {
source: stateFullIn;
}
}
DigitalSensor {
id: sensorArmFullOut;
uid: "SENSOR_ARM_FULL_OUT";
title: "Arm full-out sensor";
description: "Sensor checking if arm is fully telescoped out";
sourceLink: LinkPhysicalStateToDigitalSensor {
source: stateFullOut;
}
}
AnalogSensor {
id: sensorSlewAng;
uid: "SENSOR_SLEW";
......@@ -902,6 +920,22 @@ NetworkDefinition {
}
}
}
PhysicalState {
id: stateFullIn;
uid: "ARM_FULL_IN";
referenceValue: blockArm.size.toFront;
lowThreshold: (blockArm.size.toFront.min + 0.10);
highThreshold: (lowThreshold + 0.50);
inverted: true;
}
PhysicalState {
id: stateFullOut;
uid: "ARM_FULL_OUT";
referenceValue: blockArm.size.toFront;
lowThreshold: (highThreshold - 0.50);
highThreshold: (blockArm.size.toFront.max - 0.10);
inverted: false;
}
PhysicalBlock {
id: blockExtraArm;
uid: "EXTRA_ARM";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment