-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/master'
- Loading branch information
Showing
4 changed files
with
167 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Reach - Leap Motion OSC Sender | ||
|
||
Reach is a free and open source application, written using [JUCE](https://juce.com), to map [Leap Motion](https://leapmotion.com) data to OSC messages. Using the latest Leap Motion SDK [Orion](https://developer.leapmotion.com/orion/) this app | ||
enables easy mapping of leap motion parameters in any other environment without having to code a single line. | ||
|
||
### [**Web Page**](http://niccologranieri.com/reach/) - [**DOWNLOAD**](https://github.com/NiccoloGranieri/Reach/releases) | ||
|
||
## Key Features | ||
- Tracking and OSC parsing of hand nodes' spatial position (x, y, z), and grab hand gesture. | ||
- Detection and OSC parsing of grab gesture | ||
|
||
## Acknowledgements | ||
|
||
Reach is a software supported by [Integra Lab](http://integra.io). | ||
|
||
### Team: | ||
- [Niccolò Granieri](http://niccologranieri.com), creator | ||
- [Jefferson Bledsoe](https://twitter.com/Jeff_Bledsoe), developer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,107 @@ | ||
#include "JuceHeader.h" | ||
#include "LeapLogger.h" | ||
|
||
//============================================================================== | ||
LeapLogger::LeapLogger () | ||
{ | ||
createNewLogFile (); | ||
|
||
startTimer (5); | ||
} | ||
|
||
LeapLogger::~LeapLogger() | ||
{ | ||
stopTimer(); | ||
} | ||
|
||
//============================================================================== | ||
void LeapLogger::createNewLogFile() | ||
{ | ||
DBG("CREATING FILE"); | ||
const auto logFilename = String(String(ProjectInfo::projectName) | ||
+ "_Session" + String (currentSessionNumber) + "_Log_" | ||
+ Time::getCurrentTime().formatted("%d-%m-%Y_%H-%M-%S")); | ||
|
||
const auto logExtension = String(".csv"); | ||
|
||
auto logFile = File::getSpecialLocation(File::SpecialLocationType::userDesktopDirectory) | ||
.getChildFile(logFilename + logExtension); | ||
|
||
Logger::setCurrentLogger(nullptr); | ||
logger.reset(new FileLogger(logFile, {})); | ||
Logger::setCurrentLogger(logger.get()); | ||
|
||
logger->logMessage(ProjectInfo::projectName + String(" Data Log")); | ||
logger->logMessage({}); | ||
logger->logMessage(dataNames); | ||
logger->logMessage({}); | ||
|
||
logFrameData.ensureStorageAllocated(200); | ||
|
||
++currentSessionNumber; | ||
DBG(currentSessionNumber); | ||
DBG(logFilename); | ||
} | ||
|
||
//============================================================================== | ||
void LeapLogger::hiResTimerCallback() | ||
{ | ||
if (! controller.isConnected()) | ||
{ | ||
DBG("DISCONNECT"); | ||
shouldStartNewSession = true; | ||
return; | ||
} | ||
|
||
if (shouldStartNewSession && controller.isConnected()) | ||
{ | ||
DBG("NEW FILE INSIDE CALLBACK"); | ||
createNewLogFile(); | ||
shouldStartNewSession = false; | ||
return; | ||
} | ||
|
||
const auto& frame = controller.frame(); | ||
|
||
if (frame.id() == lastFrameId) | ||
return; | ||
|
||
const auto& hands = frame.hands(); | ||
|
||
if (hands.isEmpty()) | ||
return; | ||
|
||
logFrameData.clearQuick(); | ||
|
||
for (auto& hand : hands) | ||
{ | ||
if (hand.isLeft()) | ||
logFrameData.add("Left"); | ||
else | ||
logFrameData.add("Right"); | ||
|
||
logFrameData.add(static_cast<String> (hand.stabilizedPalmPosition().x)); | ||
logFrameData.add(static_cast<String> (hand.stabilizedPalmPosition().y)); | ||
logFrameData.add(static_cast<String> (hand.stabilizedPalmPosition().z)); | ||
|
||
logFrameData.add(static_cast<String> (hand.wristPosition().x)); | ||
logFrameData.add(static_cast<String> (hand.wristPosition().y)); | ||
logFrameData.add(static_cast<String> (hand.wristPosition().z)); | ||
|
||
for (auto& finger : hand.fingers()) | ||
{ | ||
for (auto i = 0; ++i < 4;) | ||
{ | ||
const auto& boneType = static_cast<Leap::Bone::Type> (i); | ||
const auto& bone = finger.bone (boneType); | ||
logFrameData.add(static_cast<String> (bone.nextJoint().x)); | ||
logFrameData.add(static_cast<String> (bone.nextJoint().y)); | ||
logFrameData.add(static_cast<String> (bone.nextJoint().z)); | ||
} | ||
} | ||
} | ||
|
||
logger->logMessage (logFrameData.joinIntoString (",")); | ||
|
||
lastFrameId = frame.id(); | ||
} | ||
#include "JuceHeader.h" | ||
#include "LeapLogger.h" | ||
|
||
//============================================================================== | ||
LeapLogger::LeapLogger () | ||
{ | ||
createNewLogFile (); | ||
|
||
startTimer (5); | ||
} | ||
|
||
LeapLogger::~LeapLogger() | ||
{ | ||
stopTimer(); | ||
} | ||
|
||
//============================================================================== | ||
void LeapLogger::createNewLogFile() | ||
{ | ||
DBG("CREATING FILE"); | ||
const auto logFilename = String(String(ProjectInfo::projectName) | ||
+ "_Session" + String (currentSessionNumber) + "_Log_" | ||
+ Time::getCurrentTime().formatted("%d-%m-%Y_%H-%M-%S")); | ||
|
||
const auto logExtension = String(".csv"); | ||
|
||
auto logFile = File::getSpecialLocation(File::SpecialLocationType::userDesktopDirectory) | ||
.getChildFile(logFilename + logExtension); | ||
|
||
Logger::setCurrentLogger(nullptr); | ||
logger.reset(new FileLogger(logFile, {})); | ||
Logger::setCurrentLogger(logger.get()); | ||
|
||
logger->logMessage(ProjectInfo::projectName + String(" Data Log")); | ||
logger->logMessage({}); | ||
logger->logMessage(dataNames); | ||
logger->logMessage({}); | ||
|
||
logFrameData.ensureStorageAllocated(200); | ||
|
||
++currentSessionNumber; | ||
DBG(currentSessionNumber); | ||
DBG(logFilename); | ||
} | ||
|
||
//============================================================================== | ||
void LeapLogger::hiResTimerCallback() | ||
{ | ||
if (! controller.isConnected()) | ||
{ | ||
DBG("DISCONNECT"); | ||
shouldStartNewSession = true; | ||
return; | ||
} | ||
|
||
if (shouldStartNewSession && controller.isConnected()) | ||
{ | ||
DBG("NEW FILE INSIDE CALLBACK"); | ||
createNewLogFile(); | ||
shouldStartNewSession = false; | ||
return; | ||
} | ||
|
||
const auto& frame = controller.frame(); | ||
|
||
if (frame.id() == lastFrameId) | ||
return; | ||
|
||
const auto& hands = frame.hands(); | ||
|
||
if (hands.isEmpty()) | ||
return; | ||
|
||
logFrameData.clearQuick(); | ||
|
||
for (auto& hand : hands) | ||
{ | ||
if (hand.isLeft()) | ||
logFrameData.add("Left"); | ||
else | ||
logFrameData.add("Right"); | ||
|
||
logFrameData.add(static_cast<String> (hand.stabilizedPalmPosition().x)); | ||
logFrameData.add(static_cast<String> (hand.stabilizedPalmPosition().y)); | ||
logFrameData.add(static_cast<String> (hand.stabilizedPalmPosition().z)); | ||
|
||
logFrameData.add(static_cast<String> (hand.wristPosition().x)); | ||
logFrameData.add(static_cast<String> (hand.wristPosition().y)); | ||
logFrameData.add(static_cast<String> (hand.wristPosition().z)); | ||
|
||
for (auto& finger : hand.fingers()) | ||
{ | ||
for (auto i = 0; ++i < 4;) | ||
{ | ||
const auto& boneType = static_cast<Leap::Bone::Type> (i); | ||
const auto& bone = finger.bone (boneType); | ||
logFrameData.add(static_cast<String> (bone.nextJoint().x)); | ||
logFrameData.add(static_cast<String> (bone.nextJoint().y)); | ||
logFrameData.add(static_cast<String> (bone.nextJoint().z)); | ||
} | ||
} | ||
} | ||
|
||
logger->logMessage (logFrameData.joinIntoString (",")); | ||
|
||
lastFrameId = frame.id(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,41 @@ | ||
#pragma once | ||
|
||
#include "JuceHeader.h" | ||
#include "Leap.h" | ||
|
||
//============================================================================== | ||
class LeapLogger : public HighResolutionTimer | ||
{ | ||
public: | ||
//========================================================================== | ||
LeapLogger (); | ||
~LeapLogger(); | ||
|
||
//========================================================================== | ||
void setLogFile (File logFolder); | ||
|
||
private: | ||
//========================================================================== | ||
std::unique_ptr<FileLogger> logger; | ||
StringArray logFrameData; | ||
bool shouldStartNewSession = false; | ||
|
||
int currentSessionNumber = 0; | ||
|
||
//========================================================================== | ||
Leap::Controller controller; | ||
int lastFrameId = -1; | ||
|
||
//========================================================================== | ||
const StringArray jointTypes = { "/TYPE_THUMB", "/TYPE_INDEX", "/TYPE_MIDDLE", "/TYPE_RING", "/TYPE_PINKY" }; | ||
const StringArray joints = { "/knuckle", "/joint1", "/joint2", "/joint3" }; | ||
String dataNames{ "Hand,PalmX,PalmY,PalmZ,WristX,WristY,WristZ,Finger1Bone1X,Finger1Bone1Y,Finger1Bone1Z,Finger1Bone2X,Finger1Bone2Y,Finger1Bone2Z,Finger1Bone3X,Finger1Bone3Y,Finger1Bone3Z,Finger1Bone4X,Finger1Bone4Y,Finger1Bone4Z,Finger2Bone1X,Finger2Bone1Y,Finger2Bone1Z,Finger2Bone2X,Finger2Bone2Y,Finger2Bone2Z,Finger2Bone3X,Finger2Bone3Y,Finger2Bone3Z,Finger2Bone4X,Finger2Bone4Y,Finger2Bone4Z,Finger3Bone1X,Finger3Bone1Y,Finger3Bone1Z,Finger3Bone2X,Finger3Bone2Y,Finger3Bone2Z,Finger3Bone3X,Finger3Bone3Y,Finger3Bone3Z,Finger3Bone4X,Finger3Bone4Y,Finger3Bone4Z,Finger4Bone1X,Finger4Bone1Y,Finger4Bone1Z,Finger4Bone2X,Finger4Bone2Y,Finger4Bone2Z,Finger4Bone3X,Finger4Bone3Y,Finger4Bone3Z,Finger4Bone4X,Finger4Bone4Y,Finger4Bone4Z" }; | ||
|
||
//========================================================================== | ||
void createNewLogFile(); | ||
|
||
//========================================================================== | ||
void hiResTimerCallback() override; | ||
|
||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LeapLogger) | ||
}; | ||
#pragma once | ||
|
||
#include "JuceHeader.h" | ||
#include "Leap.h" | ||
|
||
//============================================================================== | ||
class LeapLogger : public HighResolutionTimer | ||
{ | ||
public: | ||
//========================================================================== | ||
LeapLogger (); | ||
~LeapLogger(); | ||
|
||
//========================================================================== | ||
void setLogFile (File logFolder); | ||
|
||
private: | ||
//========================================================================== | ||
std::unique_ptr<FileLogger> logger; | ||
StringArray logFrameData; | ||
bool shouldStartNewSession = false; | ||
|
||
int currentSessionNumber = 0; | ||
|
||
//========================================================================== | ||
Leap::Controller controller; | ||
int lastFrameId = -1; | ||
|
||
//========================================================================== | ||
const StringArray jointTypes = { "/TYPE_THUMB", "/TYPE_INDEX", "/TYPE_MIDDLE", "/TYPE_RING", "/TYPE_PINKY" }; | ||
const StringArray joints = { "/knuckle", "/joint1", "/joint2", "/joint3" }; | ||
String dataNames{ "Hand,PalmX,PalmY,PalmZ,WristX,WristY,WristZ,Finger1Bone1X,Finger1Bone1Y,Finger1Bone1Z,Finger1Bone2X,Finger1Bone2Y,Finger1Bone2Z,Finger1Bone3X,Finger1Bone3Y,Finger1Bone3Z,Finger1Bone4X,Finger1Bone4Y,Finger1Bone4Z,Finger2Bone1X,Finger2Bone1Y,Finger2Bone1Z,Finger2Bone2X,Finger2Bone2Y,Finger2Bone2Z,Finger2Bone3X,Finger2Bone3Y,Finger2Bone3Z,Finger2Bone4X,Finger2Bone4Y,Finger2Bone4Z,Finger3Bone1X,Finger3Bone1Y,Finger3Bone1Z,Finger3Bone2X,Finger3Bone2Y,Finger3Bone2Z,Finger3Bone3X,Finger3Bone3Y,Finger3Bone3Z,Finger3Bone4X,Finger3Bone4Y,Finger3Bone4Z,Finger4Bone1X,Finger4Bone1Y,Finger4Bone1Z,Finger4Bone2X,Finger4Bone2Y,Finger4Bone2Z,Finger4Bone3X,Finger4Bone3Y,Finger4Bone3Z,Finger4Bone4X,Finger4Bone4Y,Finger4Bone4Z" }; | ||
|
||
//========================================================================== | ||
void createNewLogFile(); | ||
|
||
//========================================================================== | ||
void hiResTimerCallback() override; | ||
|
||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LeapLogger) | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters