use AgentData class to abstract implemenation of linked data

This commit is contained in:
Stephen Birarda 2013-02-21 12:56:57 -08:00
parent c57380012e
commit 060f4dceca
12 changed files with 181 additions and 226 deletions

View file

@ -36,18 +36,24 @@ unsigned char packetData[MAX_PACKET_SIZE];
const int LOGOFF_CHECK_INTERVAL = 5000;
#define DEBUG_TO_SELF 0
int lastActiveCount = 0;
AgentList agentList(DOMAIN_LISTEN_PORT);
int listForBroadcast(unsigned char *listBuffer) {
int listForBroadcast(unsigned char *listBuffer, sockaddr *agentPublicAddress, sockaddr *agentLocalAddress, char agentType) {
unsigned char *currentBufferPos = listBuffer + 1;
unsigned char *startPointer = currentBufferPos;
for(std::vector<Agent>::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) {
*currentBufferPos++ = agent->type;
currentBufferPos += packSocket(currentBufferPos, agent->publicSocket);
currentBufferPos += packSocket(currentBufferPos, agent->localSocket);
if (DEBUG_TO_SELF || !agent->matches(agentPublicAddress, agentLocalAddress, agentType)) {
*currentBufferPos++ = agent->type;
currentBufferPos += packSocket(currentBufferPos, agent->publicSocket);
currentBufferPos += packSocket(currentBufferPos, agent->localSocket);
}
}
return 1 + (currentBufferPos - startPointer); // 1 is added for the leading 'D'
@ -71,7 +77,7 @@ int main(int argc, const char * argv[])
agentList.addOrUpdateAgent((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType);
int listBytes = listForBroadcast(broadcastPacket);
int listBytes = listForBroadcast(broadcastPacket, (sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType);
if (listBytes > 0) {
agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, listBytes);

View file

@ -9,12 +9,12 @@ set(PORTAUDIO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio)
project(interface)
if (APPLE)
# link in required OS X frameworks and include the right GL headers
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon")
set(GL_HEADERS "#include <GLUT/glut.h>\n#include <OpenGL/glext.h>")
# link in required OS X frameworks and include the right GL headers
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon")
set(GL_HEADERS "#include <GLUT/glut.h>\n#include <OpenGL/glext.h>")
else (APPLE)
# include the right GL headers for UNIX
set(GL_HEADERS "#include <GL/gl.h>\n#include <GL/glut.h>\n#include <GL/glext.h>")
# include the right GL headers for UNIX
set(GL_HEADERS "#include <GL/gl.h>\n#include <GL/glut.h>\n#include <GL/glext.h>")
endif (APPLE)
# create the InterfaceConfig.h file based on GL_HEADERS above

View file

@ -272,7 +272,7 @@ void *receiveAudioViaUDP(void *args) {
* @return Returns true if successful or false if an error occurred.
Use Audio::getError() to retrieve the error code.
*/
Audio::Audio(Head *mainHead, Oscilloscope * s)
Audio::Audio(Oscilloscope * s)
{
paError = Pa_Initialize();
if (paError != paNoError) goto error;
@ -292,8 +292,6 @@ Audio::Audio(Head *mainHead, Oscilloscope * s)
pthread_create(&audioReceiveThread, NULL, receiveAudioViaUDP, (void *) &threadArgs);
audioData->linkedHead = mainHead;
paError = Pa_OpenDefaultStream(&stream,
2, // input channels
2, // output channels

View file

@ -11,14 +11,13 @@
#include <iostream>
#include <portaudio.h>
#include "Head.h"
#include "AudioData.h"
#include "Oscilloscope.h"
class Audio {
public:
// initializes audio I/O
Audio(Head* mainHead, Oscilloscope * s);
Audio(Oscilloscope * s);
void render();
void render(int screenWidth, int screenHeight);

View file

@ -12,13 +12,10 @@
#include <iostream>
#include <stdint.h>
#include "AudioRingBuffer.h"
#include "Head.h"
#include "UDPSocket.h"
class AudioData {
public:
Head *linkedHead;
public:
AudioRingBuffer *ringBuffer;
UDPSocket *audioSocket;

View file

@ -12,7 +12,6 @@
#include "Head.h"
#include "Util.h"
#include "SerialInterface.h"
#include "Audio.h"
float skinColor[] = {1.0, 0.84, 0.66};
float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
@ -60,6 +59,10 @@ Head::Head()
setNoise(0);
}
Head::~Head() {
// all data is primitive, do nothing
}
void Head::reset()
{
Pitch = Yaw = Roll = 0;
@ -328,7 +331,6 @@ void Head::render(int faceToFace, float * myLocation)
}
// Transmit data to agents requesting it
int Head::getBroadcastData(char* data)
@ -341,12 +343,12 @@ int Head::getBroadcastData(char* data)
return strlen(data);
}
void Head::recvBroadcastData(char * data, int size)
{
sscanf(data, "%f,%f,%f,%f,%f,%f,%f,%f", &Pitch, &Yaw, &Roll,
void Head::parseData(void *data, int size) {
// parse head data for this agent
sscanf((char *)data, "%f,%f,%f,%f,%f,%f,%f,%f",
&Pitch, &Yaw, &Roll,
&position.x, &position.y, &position.z,
&loudness, &averageLoudness);
//printf("%f,%f,%f,%f,%f,%f\n", Pitch, Yaw, Roll, position.x, position.y, position.z);
}
void Head::SetNewHeadTarget(float pitch, float yaw)

View file

@ -10,6 +10,7 @@
#define __interface__head__
#include <iostream>
#include "AgentData.h"
#include "Field.h"
#include "world.h"
#include "InterfaceConfig.h"
@ -17,83 +18,84 @@
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
class Head {
float noise;
float Pitch;
float Yaw;
float Roll;
float PitchRate;
float YawRate;
float RollRate;
float EyeballPitch[2];
float EyeballYaw[2];
float EyebrowPitch[2];
float EyebrowRoll[2];
float EyeballScaleX, EyeballScaleY, EyeballScaleZ;
float interPupilDistance;
float interBrowDistance;
float NominalPupilSize;
float PupilSize;
float MouthPitch;
float MouthYaw;
float MouthWidth;
float MouthHeight;
float leanForward;
float leanSideways;
float PitchTarget;
float YawTarget;
float NoiseEnvelope;
float PupilConverge;
float scale;
// Sound loudness information
float loudness;
float averageLoudness;
glm::vec3 position;
int eyeContact;
eyeContactTargets eyeContactTarget;
void readSensors();
float renderYaw, renderPitch; // Pitch from view frustum when this is own head.
public:
Head(void);
void reset();
void UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
void setNoise (float mag) { noise = mag; }
void setPitch(float p) {Pitch = p; }
void setYaw(float y) {Yaw = y; }
void setRoll(float r) {Roll = r; };
void setScale(float s) {scale = s; };
void setRenderYaw(float y) {renderYaw = y;}
void setRenderPitch(float p) {renderPitch = p;}
float getRenderYaw() {return renderYaw;}
float getRenderPitch() {return renderPitch;}
void setLeanForward(float dist);
void setLeanSideways(float dist);
void addPitch(float p) {Pitch -= p; }
void addYaw(float y){Yaw -= y; }
void addRoll(float r){Roll += r; }
void addLean(float x, float z);
float getPitch() {return Pitch;}
float getRoll() {return Roll;}
float getYaw() {return Yaw;}
void render(int faceToFace, float * myLocation);
void simulate(float);
// Send and receive network data
int getBroadcastData(char* data);
void recvBroadcastData(char * data, int size);
float getLoudness() {return loudness;};
float getAverageLoudness() {return averageLoudness;};
void setAverageLoudness(float al) {averageLoudness = al;};
void setLoudness(float l) {loudness = l;};
void SetNewHeadTarget(float, float);
glm::vec3 getPos() { return position; };
void setPos(glm::vec3 newpos) { position = newpos; };
class Head : public AgentData {
public:
Head();
~Head();
void reset();
void UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
void setNoise (float mag) { noise = mag; }
void setPitch(float p) {Pitch = p; }
void setYaw(float y) {Yaw = y; }
void setRoll(float r) {Roll = r; };
void setScale(float s) {scale = s; };
void setRenderYaw(float y) {renderYaw = y;}
void setRenderPitch(float p) {renderPitch = p;}
float getRenderYaw() {return renderYaw;}
float getRenderPitch() {return renderPitch;}
void setLeanForward(float dist);
void setLeanSideways(float dist);
void addPitch(float p) {Pitch -= p; }
void addYaw(float y){Yaw -= y; }
void addRoll(float r){Roll += r; }
void addLean(float x, float z);
float getPitch() {return Pitch;}
float getRoll() {return Roll;}
float getYaw() {return Yaw;}
void render(int faceToFace, float * myLocation);
void simulate(float);
// Send and receive network data
int getBroadcastData(char * data);
void parseData(void *data, int size);
float getLoudness() {return loudness;};
float getAverageLoudness() {return averageLoudness;};
void setAverageLoudness(float al) {averageLoudness = al;};
void setLoudness(float l) {loudness = l;};
void SetNewHeadTarget(float, float);
glm::vec3 getPos() { return position; };
void setPos(glm::vec3 newpos) { position = newpos; };
private:
float noise;
float Pitch;
float Yaw;
float Roll;
float PitchRate;
float YawRate;
float RollRate;
float EyeballPitch[2];
float EyeballYaw[2];
float EyebrowPitch[2];
float EyebrowRoll[2];
float EyeballScaleX, EyeballScaleY, EyeballScaleZ;
float interPupilDistance;
float interBrowDistance;
float NominalPupilSize;
float PupilSize;
float MouthPitch;
float MouthYaw;
float MouthWidth;
float MouthHeight;
float leanForward;
float leanSideways;
float PitchTarget;
float YawTarget;
float NoiseEnvelope;
float PupilConverge;
float scale;
// Sound loudness information
float loudness;
float averageLoudness;
glm::vec3 position;
int eyeContact;
eyeContactTargets eyeContactTarget;
void readSensors();
float renderYaw, renderPitch; // Pitch from view frustum when this is own head.
};
#endif

View file

@ -107,7 +107,7 @@ Lattice lattice(160,100);
Finger myFinger(WIDTH, HEIGHT);
Field field;
Audio audio(&myHead, &audioScope);
Audio audio(&audioScope);
#define RENDER_FRAME_MSECS 8
int steps_per_frame = 0;
@ -512,7 +512,7 @@ void update_pos(float frametime)
const int MAX_BROADCAST_STRING = 200;
char broadcast_string[MAX_BROADCAST_STRING];
int broadcast_bytes = myHead.getBroadcastData(broadcast_string);
// broadcastToAgents(&agentSocket, broadcast_string, broadcast_bytes, sendToSelf);
agentList.broadcastToAgents(broadcast_string, broadcast_bytes);
}
int render_test_spot = WIDTH/2;
@ -560,8 +560,12 @@ void display(void)
// Draw field vectors
if (display_field) field.render();
// Render heads of other agents
// render_agents(sendToSelf, &location[0]);
// Render heads of other agents
for(std::vector<Agent>::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) {
if (agent->linkedData != NULL) {
((Head *)agent->linkedData)->render(0, &location[0]);
}
}
if (display_hand) myHand.render();
@ -647,22 +651,6 @@ void display(void)
char agents[100];
sprintf(agents, "Agents nearby: %d\n", nearbyAgents);
drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0);
#ifdef MARKER_CAPTURE
/* Render marker acquisition stuff */
pthread_mutex_lock(&frame_lock);
if(marker_capture_frame){
marker_acq_view.render(marker_capture_frame); // render the acquisition view, if it's visible.
}
// Draw marker images, if requested.
if (marker_capture_enabled && marker_capture_display && marker_capture_frame){
marker_capturer.glDrawIplImage(marker_capture_frame, WIDTH - 140, 10, 0.1, -0.1);
marker_capturer.glDrawIplImage(marker_capture_blob_frame, WIDTH - 280, 10, 0.1, -0.1);
}
pthread_mutex_unlock(&frame_lock);
/* Done rendering marker acquisition stuff */
#endif
glPopMatrix();
@ -694,22 +682,6 @@ void key(unsigned char k, int x, int y)
// Process keypresses
if (k == 'q') ::terminate();
// marker capture
#ifdef MARKER_CAPTURE
if(k == 'x'){
printf("Toggling marker capture display.\n");
marker_capture_display = !marker_capture_display;
marker_capture_display ? marker_acq_view.show() : marker_acq_view.hide();
}
// delegate keypresses to the marker acquisition view when it's visible;
// override other key mappings by returning...
if(marker_acq_view.visible){
marker_acq_view.handle_key(k);
return;
}
#endif
if (k == '/') stats_on = !stats_on; // toggle stats
if (k == 'n')
{
@ -762,7 +734,7 @@ void *networkReceive(void *args)
{
sockaddr senderAddress;
ssize_t bytesReceived;
unsigned char *incomingPacket = new unsigned char[MAX_PACKET_SIZE];
char *incomingPacket = new char[MAX_PACKET_SIZE];
while (true) {
if (agentList.getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) {
@ -770,49 +742,6 @@ void *networkReceive(void *args)
bytescount += bytesReceived;
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
// // If packet is a Mouse data packet, copy it over
// if (incomingPacket[0] == 'P') {
// //
// // Got Ping, reply immediately!
// //
// //printf("Replying to ping!\n");
// char reply[] = "R";
// agentList.getAgentSocket()->send(&senderAddress, reply, 1);
// } else if (incomingPacket[0] == 'R') {
// //
// // Got Reply, record as appropriate
// //
//// setAgentPing(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port));
//
// } else if (incomingPacket[0] == 'M') {
// //
// // mouse location packet
// //
// sscanf(incomingPacket, "M %d %d", &target_x, &target_y);
// target_display = 1;
// //printf("X = %d Y = %d\n", target_x, target_y);
// } else if (incomingPacket[0] == 'D') {
// //
// // Message from domainserver
// //
// //printf("agent list received!\n");
// nearbyAgents = agentList.updateList(&incomingPacket[1]);
// std::cout << "Received " << nearbyAgents << " from DS!\n";
//// kludgyMixerUpdate(audio);
// } else if (incomingPacket[0] == 'H') {
// //
// // Broadcast packet from another agent
// //
// //printf("broadcast received");
//// update_agent(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), &incomingPacket[1], bytesReceived - 1);
// } else if (incomingPacket[0] == 'T') {
// // Received a self-test packet (to get one's own IP), copy it to local variable!
//// printf("My Address: %s:%u\n",
//// inet_ntoa(senderAddress.sin_addr),
//// senderAddress.sin_port);
// }
}
}
@ -915,14 +844,9 @@ void mouseoverFunc( int x, int y)
}
}
#ifdef MARKER_CAPTURE
void *poll_marker_capture(void *threadarg){
while(1){
marker_capturer.tick();
}
void attachNewHeadToAgent(Agent *newAgent) {
newAgent->linkedData = new Head();
}
#endif
int main(int argc, char** argv)
{
@ -952,13 +876,6 @@ int main(int argc, char** argv)
}
} else printf("Using static domainserver IP: %s\n", DOMAIN_IP);
//std::cout << "Test address: " << inet_ntoa(testAddress.sin_addr) << "\n";
//gethostbyname(hostname);
// Send one test packet to detect own IP, port:
//char selfTest[] = "T";
//agentSocket.send((char *)"127.0.0.1", AGENT_UDP_PORT, selfTest, 1);
printf("Testing stats math... ");
StDev stdevtest;
stdevtest.reset();
@ -983,6 +900,8 @@ int main(int argc, char** argv)
printf("Stdev=FAIL ");
printf("\n");
// the callback for our instance of AgentList is attachNewHeadToAgent
agentList.newAgentCallback = &attachNewHeadToAgent;
// create thread for receipt of data via UDP
pthread_t networkReceiveThread;
@ -1014,28 +933,8 @@ int main(int argc, char** argv)
glutTimerFunc(1000, Timer, 0);
#ifdef MARKER_CAPTURE
if (marker_capture_enabled) {
// start capture thread
if (pthread_mutex_init(&frame_lock, NULL) != 0){
printf("Frame lock mutext init failed. Exiting.\n");
return 1;
}
pthread_t capture_thread;
pthread_create(&capture_thread, NULL, poll_marker_capture, NULL);
}
#endif
glutMainLoop();
#ifdef MARKER_CAPTURE
if (marker_capture_enabled) {
pthread_mutex_destroy(&frame_lock);
pthread_exit(NULL);
}
#endif
pthread_join(networkReceiveThread, NULL);
::terminate();
return EXIT_SUCCESS;

View file

@ -44,8 +44,10 @@ Agent::Agent(const Agent &otherAgent) {
type = otherAgent.type;
linkedData = (AgentData *) malloc(sizeof(otherAgent.linkedData));
// copy over linkedData
linkedData = NULL;
memcpy((void*)linkedData, (void *)otherAgent.linkedData, sizeof(otherAgent.linkedData));
}
Agent& Agent::operator=(Agent otherAgent) {

View file

@ -11,7 +11,8 @@
class AgentData {
public:
virtual ~AgentData();
virtual ~AgentData() = 0;
virtual void parseData(void * data, int size) = 0;
};
#endif

View file

@ -21,14 +21,19 @@ UDPSocket * AgentList::getAgentSocket() {
return &agentSocket;
}
void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
switch (packetData[0]) {
void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
switch (((char *)packetData)[0]) {
case 'D':
{
// list of agents from domain server
updateList(packetData, dataBytes);
updateList((unsigned char *)packetData, dataBytes);
break;
}
case 'H':
{
// head data from another agent
updateAgentWithData(senderAddress, packetData, dataBytes);
}
case 'P':
{
// ping from another agent
@ -45,6 +50,30 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD
}
}
void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
// find the agent by the sockaddr
int agentIndex = indexOfMatchingAgent(senderAddress);
if (agentIndex != -1) {
Agent matchingAgent = agents[agentIndex];
if (matchingAgent.linkedData != NULL) {
matchingAgent.linkedData->parseData(packetData, dataBytes);
}
}
}
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
if (socketMatch(agent->activeSocket, senderAddress)) {
return agent - agents.begin();
}
}
return -1;
}
int AgentList::updateList(unsigned char *packetData, size_t dataBytes) {
int readAgents = 0;
@ -84,9 +113,16 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
// we didn't have this agent, so add them
Agent newAgent = Agent(publicSocket, localSocket, agentType);
if (socketMatch(publicSocket, localSocket)) {
// likely debugging scenario with DS + agent on local network
// set the agent active right away
newAgent.activeSocket = newAgent.localSocket;
}
std::cout << "Added agent - " << &newAgent << "\n";
agents.push_back(newAgent);
newAgentCallback(&newAgent);
agents.push_back(newAgent);
return true;
} else {
@ -95,6 +131,16 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
}
}
void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
if (agent->activeSocket != NULL) {
// we know which socket is good for this agent, send there
agentSocket.send((sockaddr *)agent->activeSocket, broadcastData, sizeof(&broadcastData));
}
}
}
void AgentList::pingAgents() {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
char payload[] = "P";
@ -126,6 +172,7 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
if (matchedSocket != NULL) {
// matched agent, stop checking
// update the agent's ping
agent->activeSocket = matchedSocket;
break;
}
}

View file

@ -21,17 +21,19 @@ class AgentList {
AgentList();
AgentList(int socketListenPort);
std::vector<Agent> agents;
void(*newAgentCallback)(Agent *);
UDPSocket* getAgentSocket();
int updateList(unsigned char *packetData, size_t dataBytes);
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType);
void processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes);
void broadcastToAgents(char *broadcastData, size_t dataBytes, bool sendToSelf);
void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
void broadcastToAgents(char *broadcastData, size_t dataBytes);
void pingAgents();
private:
UDPSocket agentSocket;
int indexOfMatchingAgent(sockaddr *senderAddress);
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
void handlePingReply(sockaddr *agentAddress);
};