AxisValue action channels now have a 'valid' flag, like Poses do

This commit is contained in:
Seth Alves 2019-09-07 18:05:38 -07:00
parent 73e6be9c37
commit 954aeb5e25
21 changed files with 57 additions and 26 deletions

View file

@ -12,10 +12,13 @@
namespace controller { namespace controller {
AxisValue::AxisValue(const float value, const quint64 timestamp) : AxisValue::AxisValue(const float value, const quint64 timestamp, bool valid) :
value(value), timestamp(timestamp) { } value(value), timestamp(timestamp), valid(valid) {
}
bool AxisValue::operator==(const AxisValue& right) const { bool AxisValue::operator==(const AxisValue& right) const {
return value == right.value && timestamp == right.timestamp; return value == right.value &&
timestamp == right.timestamp &&
valid == right.valid;
} }
} }

View file

@ -21,14 +21,14 @@ namespace controller {
float value { 0.0f }; float value { 0.0f };
// The value can be timestamped to determine if consecutive identical values should be output (e.g., mouse movement). // The value can be timestamped to determine if consecutive identical values should be output (e.g., mouse movement).
quint64 timestamp { 0 }; quint64 timestamp { 0 };
bool valid { false };
AxisValue() {} AxisValue() {}
AxisValue(const float value, const quint64 timestamp); AxisValue(const float value, const quint64 timestamp, bool valid = true);
bool operator ==(const AxisValue& right) const; bool operator ==(const AxisValue& right) const;
bool operator !=(const AxisValue& right) const { return !(*this == right); } bool operator !=(const AxisValue& right) const { return !(*this == right); }
}; };
} }
#endif // hifi_controllers_AxisValue_h #endif // hifi_controllers_AxisValue_h

View file

@ -77,13 +77,13 @@ namespace controller {
return { getButton(channel), 0 }; return { getButton(channel), 0 };
case ChannelType::POSE: case ChannelType::POSE:
return { getPose(channel).valid ? 1.0f : 0.0f, 0 }; return { getPose(channel).valid ? 1.0f : 0.0f, 0, getPose(channel).valid };
default: default:
break; break;
} }
return { 0.0f, 0 }; return { 0.0f, 0, false };
} }
AxisValue InputDevice::getValue(const Input& input) const { AxisValue InputDevice::getValue(const Input& input) const {

View file

@ -354,6 +354,10 @@ Input::NamedVector StandardController::getAvailableInputs() const {
makePair(HIPS, "Hips"), makePair(HIPS, "Hips"),
makePair(SPINE2, "Spine2"), makePair(SPINE2, "Spine2"),
makePair(HEAD, "Head"), makePair(HEAD, "Head"),
makePair(LEFT_EYE, "LeftEye"),
makePair(RIGHT_EYE, "RightEye"),
makePair(LEFT_EYE_BLINK, "LeftEyeBlink"),
makePair(RIGHT_EYE_BLINK, "RightEyeBlink"),
// Aliases, PlayStation style names // Aliases, PlayStation style names
makePair(LB, "L1"), makePair(LB, "L1"),

View file

@ -90,6 +90,8 @@ namespace controller {
// Grips // Grips
LEFT_GRIP, LEFT_GRIP,
RIGHT_GRIP, RIGHT_GRIP,
LEFT_EYE_BLINK,
RIGHT_EYE_BLINK,
NUM_STANDARD_AXES, NUM_STANDARD_AXES,
LZ = LT, LZ = LT,
RZ = RT RZ = RT
@ -174,6 +176,8 @@ namespace controller {
TRACKED_OBJECT_13, TRACKED_OBJECT_13,
TRACKED_OBJECT_14, TRACKED_OBJECT_14,
TRACKED_OBJECT_15, TRACKED_OBJECT_15,
LEFT_EYE,
RIGHT_EYE,
NUM_STANDARD_POSES NUM_STANDARD_POSES
}; };

View file

@ -256,6 +256,9 @@ void UserInputMapper::update(float deltaTime) {
for (auto& channel : _actionStates) { for (auto& channel : _actionStates) {
channel = 0.0f; channel = 0.0f;
} }
for (unsigned int i = 0; i < _actionStatesValid.size(); i++) {
_actionStatesValid[i] = true;
}
for (auto& channel : _poseStates) { for (auto& channel : _poseStates) {
channel = Pose(); channel = Pose();
@ -1233,5 +1236,17 @@ void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
} }
} }
void UserInputMapper::setActionState(Action action, float value, bool valid) {
_actionStates[toInt(action)] = value;
_actionStatesValid[toInt(action)] = valid;
}
void UserInputMapper::deltaActionState(Action action, float delta, bool valid) {
_actionStates[toInt(action)] += delta;
bool wasValid = _actionStatesValid[toInt(action)];
_actionStatesValid[toInt(action)] = wasValid & valid;
}
} }

View file

@ -82,13 +82,14 @@ namespace controller {
QString getActionName(Action action) const; QString getActionName(Action action) const;
QString getStandardPoseName(uint16_t pose); QString getStandardPoseName(uint16_t pose);
float getActionState(Action action) const { return _actionStates[toInt(action)]; } float getActionState(Action action) const { return _actionStates[toInt(action)]; }
bool getActionStateValid(Action action) const { return _actionStatesValid[toInt(action)]; }
Pose getPoseState(Action action) const; Pose getPoseState(Action action) const;
int findAction(const QString& actionName) const; int findAction(const QString& actionName) const;
QVector<QString> getActionNames() const; QVector<QString> getActionNames() const;
Input inputFromAction(Action action) const { return getActionInputs()[toInt(action)].first; } Input inputFromAction(Action action) const { return getActionInputs()[toInt(action)].first; }
void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; } void setActionState(Action action, float value, bool valid = true);
void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; } void deltaActionState(Action action, float delta, bool valid = true);
void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; } void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; }
bool triggerHapticPulse(float strength, float duration, controller::Hand hand); bool triggerHapticPulse(float strength, float duration, controller::Hand hand);
bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand); bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand);
@ -146,6 +147,7 @@ namespace controller {
std::vector<float> _actionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f); std::vector<float> _actionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
std::vector<float> _actionScales = std::vector<float>(toInt(Action::NUM_ACTIONS), 1.0f); std::vector<float> _actionScales = std::vector<float>(toInt(Action::NUM_ACTIONS), 1.0f);
std::vector<float> _lastActionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f); std::vector<float> _lastActionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
std::vector<bool> _actionStatesValid = std::vector<bool>(toInt(Action::NUM_ACTIONS), false);
std::vector<Pose> _poseStates = std::vector<Pose>(toInt(Action::NUM_ACTIONS)); std::vector<Pose> _poseStates = std::vector<Pose>(toInt(Action::NUM_ACTIONS));
std::vector<AxisValue> _lastStandardStates = std::vector<AxisValue>(); std::vector<AxisValue> _lastStandardStates = std::vector<AxisValue>();
@ -167,7 +169,7 @@ namespace controller {
ConditionalPointer conditionalFor(const QJSValue& endpoint); ConditionalPointer conditionalFor(const QJSValue& endpoint);
ConditionalPointer conditionalFor(const QScriptValue& endpoint); ConditionalPointer conditionalFor(const QScriptValue& endpoint);
ConditionalPointer conditionalFor(const Input& endpoint) const; ConditionalPointer conditionalFor(const Input& endpoint) const;
MappingPointer parseMapping(const QJsonValue& json); MappingPointer parseMapping(const QJsonValue& json);
RoutePointer parseRoute(const QJsonValue& value); RoutePointer parseRoute(const QJsonValue& value);
EndpointPointer parseDestination(const QJsonValue& value); EndpointPointer parseDestination(const QJsonValue& value);

View file

@ -100,7 +100,7 @@ namespace controller {
_currentPose = value; _currentPose = value;
} }
protected: protected:
AxisValue _currentValue { 0.0f, 0 }; AxisValue _currentValue { 0.0f, 0, false };
Pose _currentPose {}; Pose _currentPose {};
}; };

View file

@ -26,7 +26,7 @@ void ActionEndpoint::apply(AxisValue newValue, const Pointer& source) {
_currentValue.value += newValue.value; _currentValue.value += newValue.value;
if (_input != Input::INVALID_INPUT) { if (_input != Input::INVALID_INPUT) {
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value); userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value, newValue.valid);
} }
} }

View file

@ -32,7 +32,7 @@ public:
virtual void reset() override; virtual void reset() override;
private: private:
AxisValue _currentValue { 0.0f, 0 }; AxisValue _currentValue { 0.0f, 0, false };
Pose _currentPose{}; Pose _currentPose{};
}; };

View file

@ -27,7 +27,9 @@ bool CompositeEndpoint::readable() const {
AxisValue CompositeEndpoint::peek() const { AxisValue CompositeEndpoint::peek() const {
auto negative = first->peek(); auto negative = first->peek();
auto positive = second->peek(); auto positive = second->peek();
auto result = AxisValue(positive.value - negative.value, std::max(positive.timestamp, negative.timestamp)); auto result = AxisValue(positive.value - negative.value,
std::max(positive.timestamp, negative.timestamp),
negative.valid && positive.valid);
return result; return result;
} }
@ -35,7 +37,9 @@ AxisValue CompositeEndpoint::peek() const {
AxisValue CompositeEndpoint::value() { AxisValue CompositeEndpoint::value() {
auto negative = first->value(); auto negative = first->value();
auto positive = second->value(); auto positive = second->value();
auto result = AxisValue(positive.value - negative.value, std::max(positive.timestamp, negative.timestamp)); auto result = AxisValue(positive.value - negative.value,
std::max(positive.timestamp, negative.timestamp),
negative.valid && positive.valid);
return result; return result;
} }

View file

@ -16,7 +16,7 @@ using namespace controller;
AxisValue InputEndpoint::peek() const { AxisValue InputEndpoint::peek() const {
if (isPose()) { if (isPose()) {
return peekPose().valid ? AxisValue(1.0f, 0) : AxisValue(0.0f, 0); return peekPose().valid ? AxisValue(1.0f, 0) : AxisValue(0.0f, 0, false);
} }
auto userInputMapper = DependencyManager::get<UserInputMapper>(); auto userInputMapper = DependencyManager::get<UserInputMapper>();
auto deviceProxy = userInputMapper->getDevice(_input); auto deviceProxy = userInputMapper->getDevice(_input);

View file

@ -41,7 +41,7 @@ protected:
private: private:
QScriptValue _callable; QScriptValue _callable;
float _lastValueRead { 0.0f }; float _lastValueRead { 0.0f };
AxisValue _lastValueWritten { 0.0f, 0 }; AxisValue _lastValueWritten { 0.0f, 0, false };
bool _returnPose { false }; bool _returnPose { false };
Pose _lastPoseRead; Pose _lastPoseRead;

View file

@ -19,7 +19,7 @@ class ClampFilter : public Filter {
public: public:
ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {}; ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {};
virtual AxisValue apply(AxisValue value) const override { virtual AxisValue apply(AxisValue value) const override {
return { glm::clamp(value.value, _min, _max), value.timestamp }; return { glm::clamp(value.value, _min, _max), value.timestamp, value.valid };
} }
virtual Pose apply(Pose value) const override { return value; } virtual Pose apply(Pose value) const override { return value; }

View file

@ -20,7 +20,7 @@ public:
ConstrainToIntegerFilter() = default; ConstrainToIntegerFilter() = default;
virtual AxisValue apply(AxisValue value) const override { virtual AxisValue apply(AxisValue value) const override {
return { glm::sign(value.value), value.timestamp }; return { glm::sign(value.value), value.timestamp, value.valid };
} }
virtual Pose apply(Pose value) const override { return value; } virtual Pose apply(Pose value) const override { return value; }

View file

@ -20,7 +20,7 @@ public:
ConstrainToPositiveIntegerFilter() = default; ConstrainToPositiveIntegerFilter() = default;
virtual AxisValue apply(AxisValue value) const override { virtual AxisValue apply(AxisValue value) const override {
return { (value.value <= 0.0f) ? 0.0f : 1.0f, value.timestamp }; return { (value.value <= 0.0f) ? 0.0f : 1.0f, value.timestamp, value.valid };
} }
virtual Pose apply(Pose value) const override { return value; } virtual Pose apply(Pose value) const override { return value; }

View file

@ -18,7 +18,7 @@ AxisValue DeadZoneFilter::apply(AxisValue value) const {
if (magnitude < _min) { if (magnitude < _min) {
return { 0.0f, value.timestamp }; return { 0.0f, value.timestamp };
} }
return { (magnitude - _min) * scale, value.timestamp }; return { (magnitude - _min) * scale, value.timestamp, value.valid };
} }
bool DeadZoneFilter::parseParameters(const QJsonValue& parameters) { bool DeadZoneFilter::parseParameters(const QJsonValue& parameters) {

View file

@ -19,7 +19,6 @@ HysteresisFilter::HysteresisFilter(float min, float max) : _min(min), _max(max)
} }
}; };
AxisValue HysteresisFilter::apply(AxisValue value) const { AxisValue HysteresisFilter::apply(AxisValue value) const {
if (_signaled) { if (_signaled) {
if (value.value <= _min) { if (value.value <= _min) {
@ -30,7 +29,7 @@ AxisValue HysteresisFilter::apply(AxisValue value) const {
_signaled = true; _signaled = true;
} }
} }
return { _signaled ? 1.0f : 0.0f, value.timestamp }; return { _signaled ? 1.0f : 0.0f, value.timestamp, value.valid };
} }
bool HysteresisFilter::parseParameters(const QJsonValue& parameters) { bool HysteresisFilter::parseParameters(const QJsonValue& parameters) {

View file

@ -6,5 +6,5 @@ NotFilter::NotFilter() {
} }
AxisValue NotFilter::apply(AxisValue value) const { AxisValue NotFilter::apply(AxisValue value) const {
return { (value.value == 0.0f) ? 1.0f : 0.0f, value.timestamp }; return { (value.value == 0.0f) ? 1.0f : 0.0f, value.timestamp, value.valid };
} }

View file

@ -29,7 +29,7 @@ AxisValue PulseFilter::apply(AxisValue value) const {
_lastEmitTime = DEFAULT_LAST_EMIT_TIME; _lastEmitTime = DEFAULT_LAST_EMIT_TIME;
} }
return { result, value.timestamp }; return { result, value.timestamp, value.valid };
} }
bool PulseFilter::parseParameters(const QJsonValue& parameters) { bool PulseFilter::parseParameters(const QJsonValue& parameters) {

View file

@ -23,7 +23,7 @@ public:
ScaleFilter(float scale) : _scale(scale) {} ScaleFilter(float scale) : _scale(scale) {}
virtual AxisValue apply(AxisValue value) const override { virtual AxisValue apply(AxisValue value) const override {
return { value.value * _scale, value.timestamp }; return { value.value * _scale, value.timestamp, value.valid };
} }
virtual Pose apply(Pose value) const override { virtual Pose apply(Pose value) const override {