Skip to content

Commit

Permalink
Substantial refactor.
Browse files Browse the repository at this point in the history
- replace some hard-coded variables by a maxNumBlobs variable
- Directly return a movement vector from the blob detector, so client code doesn't have to store previous blob positions
- everything needs to be thoroughly tested
  • Loading branch information
vberthiaume committed Dec 16, 2024
1 parent 77ab3e4 commit 2d13db4
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 65 deletions.
64 changes: 31 additions & 33 deletions include/puara/descriptors/touch.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,29 @@ namespace puara_gestures
class Touch
{
public:
static const int maxNumBlobs = BlobDetection::maxNumBlobs;
float touchAll = 0.0f; // f, 0--1
float touchTop = 0.0f; // f, 0--1
float touchMiddle = 0.0f; // f, 0--1
float touchBottom = 0.0f; // f, 0--1
float brush = 0.0f; // f, 0--? (~cm/s)
double multiBrush[4]{}; // ffff, 0--? (~cm/s)
double multiBrush[maxNumBlobs]{}; // ffff, 0--? (~cm/s)
float rub{}; // f, 0--? (~cm/s)
double multiRub[4]{}; // ffff, 0--? (~cm/s)
double multiRub[maxNumBlobs]{}; // ffff, 0--? (~cm/s)

// touch array
int touchSizeEdge
= 4; // amount of touch stripes for top and bottom portions (arbitrary)
int lastState_blobPos[4]{};
int touchSizeEdge = 4; // amount of touch stripes for top and bottom portions (arbitrary)

BlobDetection blob;
int blobPos[4]{}; // starting position (index) of each blob
int brushCounter[4]{};
int brushCounter[maxNumBlobs]{};

// Arrays of LeakyIntegrator instances
utils::LeakyIntegrator multiBrushIntegrator[4];
utils::LeakyIntegrator multiRubIntegrator[4];
utils::LeakyIntegrator multiBrushIntegrator[maxNumBlobs];
utils::LeakyIntegrator multiRubIntegrator[maxNumBlobs];

Touch()
{
for(int i = 0; i < 4; ++i)
for(int i = 0; i < maxNumBlobs; ++i)
{
multiBrushIntegrator[i] = utils::LeakyIntegrator(0.0f, 0.0f, 0.7f, 100, 0);
multiRubIntegrator[i] = utils::LeakyIntegrator(0.0f, 0.0f, 0.7f, 100, 0);
Expand Down Expand Up @@ -65,28 +64,27 @@ class Touch
// normalized between 0 and 1
touchBottom = touchAverage(discrete_touch, (touchSize - touchSizeEdge), touchSize);

// Save last blob detection state before reading new data
for(int i = 0; i < (sizeof(blobPos) / sizeof(blobPos[0])); ++i)
{
lastState_blobPos[i] = blobPos[i];
}
//NOW HERE -- not too sure what the heck that loop is, but that i is probably just == 4 lol
//I need to continue moving the blobPos logic to the blobDetector
//I should add a getBlobPos to it so this client doesn't have to store it itself

// 1D blob detection: used for brush
blob.blobDetection1D(discrete_touch, touchSize, blobPos);
// 1D blob detection: used for brush
const auto movement = blob.blobDetection1D(discrete_touch, touchSize);

// brush: direction and intensity of capsense brush motion
// rub: intensity of rub motion
// in ~cm/s (distance between stripes = ~1.5cm)
for(int i = 0; i < (sizeof(blobPos) / sizeof(blobPos[0])); ++i)
for(int i = 0; i < maxNumBlobs; ++i)
{
float movement = blobPos[i] - lastState_blobPos[i];
if(blobPos[i] == -1)
{
multiBrush[i] = 0;
multiRub[i] = 0;
brushCounter[i] = 0;
}
else if(movement == 0)
//TODO: unclear how we ever could get here?
// if(blobPos[i] == -1)
// {
// multiBrush[i] = 0;
// multiRub[i] = 0;
// brushCounter[i] = 0;
// }
// else
if(movement[i] == 0)
{
if(brushCounter[i] < 10)
{
Expand All @@ -107,11 +105,11 @@ class Touch
// (std::abs(movement * 0.15)), multiRub[i], 0.7, leakyRubFreq,
// leakyRubTimer);
//
multiBrush[i] = multiBrushIntegrator[i].integrate(movement * 0.15);
multiRub[i] = multiRubIntegrator[i].integrate(std::abs(movement * 0.15));
multiBrush[i] = multiBrushIntegrator[i].integrate(movement[i] * 0.15);
multiRub[i] = multiRubIntegrator[i].integrate(std::abs(movement[i] * 0.15));
}
}
else if(std::abs(movement) > 1)
else if(std::abs(movement[i]) > 1)
{
// multiBrush[i] = multiBrushIntegrator[i].integrate(
// 0, multiBrush[i], 0.6, leakyBrushFreq, leakyBrushTimer);
Expand All @@ -126,14 +124,14 @@ class Touch
// (std::abs(movement * 0.15)) * 0.15, multiRub[i], 0.99, leakyRubFreq,
// leakyRubTimer);

multiBrush[i] = multiBrushIntegrator[i].integrate(movement * 0.15);
multiRub[i] = multiRubIntegrator[i].integrate((std::abs(movement * 0.15)));
multiBrush[i] = multiBrushIntegrator[i].integrate(movement[i] * 0.15);
multiRub[i] = multiRubIntegrator[i].integrate((std::abs(movement[i] * 0.15)));

brushCounter[i] = 0;
}
}
brush = utils::arrayAverageZero(multiBrush, 4);
rub = utils::arrayAverageZero(multiRub, 4);
brush = utils::arrayAverageZero(multiBrush, maxNumBlobs);
rub = utils::arrayAverageZero(multiRub, maxNumBlobs);
}

float touchAverage(float* touchArrayStrips, int firstStrip, int lastStrip)
Expand Down
70 changes: 41 additions & 29 deletions include/puara/utils/blobDetection.h
Original file line number Diff line number Diff line change
@@ -1,45 +1,57 @@

#pragma once
namespace puara_gestures
{

struct BlobDetection
class BlobDetection
{
int maxBlobs = 4; // max amount of blobs to be detected
int blobAmount{}; // amount of detected blobs
int blobCenter[4]{}; // shows the "center" (index) of each blob (former blobArray)
float blobSize[4]{}; // "size" (amount of stripes) of each blob
public:
static const int maxNumBlobs = 4; // max amount of blobs to be detected

#include <vector>

void blobDetection1D(int* discrete_touch, int touchSize, int* blobPos)
std::vector<int> blobDetection1D(const int* const touchArray, const int size)
{
blobAmount = 0;
int sizeCounter = 0;
int stripe = 0;
for(int i = 0; i < 4; i++)
int blobCenter[maxNumBlobs]{}; // shows the "center" (index) of each blob
float blobSize[maxNumBlobs]{}; // "size" (amount of stripes) of each blob
int blobAmount{}; // amount of detected blobs
int sizeCounter{};

for(int i = 0; i < maxNumBlobs; i++)
{
blobCenter[i] = 0;
//cache the last blobPos before clearing it
lastState_blobPos[i] = blobPos[i];
blobPos[i] = 0;
blobSize[i] = 0;
}

for(; stripe < touchSize; stripe++)
for(int stripe = 0; stripe < size; ++stripe)
{
if(blobAmount < maxBlobs)
if(touchArray[stripe] == 1)
{
if(discrete_touch[stripe] == 1)
{ // check for beggining of blob...
sizeCounter = 1;
blobPos[blobAmount] = stripe;
while(discrete_touch[stripe + sizeCounter] == 1)
{ // then keep checking for end
sizeCounter++;
}
blobSize[blobAmount] = sizeCounter;
blobCenter[blobAmount] = stripe + (sizeCounter / 2);
stripe += sizeCounter + 1; // skip stripes already read
blobAmount++;
}
sizeCounter = 1;
blobPos[blobAmount] = stripe;

while(touchArray[stripe + sizeCounter] == 1)
sizeCounter++;

blobSize[blobAmount] = sizeCounter;
blobCenter[blobAmount] = stripe + (sizeCounter / 2);
stripe += sizeCounter + 1;

if(++blobAmount >= maxNumBlobs)
break;
}
}

//return the movement since the last time blobDetection1D was called
std::vector<int> movement(blobAmount, 0);
for(int i = 0; i < blobAmount; ++i)
movement[i] = blobPos[i] - lastState_blobPos[i];

return movement;
}

private:
int blobPos[maxNumBlobs]{};
int lastState_blobPos[maxNumBlobs]{};
};
}
}
7 changes: 4 additions & 3 deletions tests/testing_touch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ int main()
{
Touch touch;

int touchSize = 16;
int discrete_touch[16] = {0};
const int touchSize = 16;
int discrete_touch[touchSize] = {0};

// simulate a touch (1) at a position 5
// simulate a blob of size 2 starting at position 5
discrete_touch[5] = 1;
discrete_touch[6] = 1;

// Update the touch data
touch.updateTouchArray(discrete_touch, touchSize);
Expand Down

0 comments on commit 2d13db4

Please sign in to comment.