From fad5e28347393ee8ed9ee0ce14b2f1daaf8df7c0 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 28 Nov 2012 14:47:09 -0800 Subject: [PATCH] Moving I/O code into head class, playing with blocks --- SerialInterface.cpp | 4 +- SerialInterface.h | 9 ++ head.cpp | 133 +++--------------- head.h | 5 + interface.xcodeproj/project.pbxproj | 2 +- .../UserInterfaceState.xcuserstate | Bin 104780 -> 104831 bytes main.cpp | 72 ++++++---- network.cpp | 8 +- network.h | 3 + util.cpp | 16 ++- world.h | 4 +- 11 files changed, 102 insertions(+), 154 deletions(-) diff --git a/SerialInterface.cpp b/SerialInterface.cpp index e3b63fcdae..1ac8225951 100644 --- a/SerialInterface.cpp +++ b/SerialInterface.cpp @@ -60,10 +60,10 @@ int read_sensors(int first_measurement, float * avg_adc_channels, int * adc_chan { // Channels: // 0, 1 = Head Pitch and Yaw - // 2,3,4 = Head XYZ Acceleration + // 2,3,4 = Head X,Y,Z Acceleration // int samples_read = 0; - const float AVG_RATE[] = {0.001, 0.001, 0.01, 0.01, 0.01}; + const float AVG_RATE[] = {0.001, 0.001, 0.001, 0.001, 0.001}; char bufchar[1]; while (read(serial_fd, bufchar, 1) > 0) { diff --git a/SerialInterface.h b/SerialInterface.h index 3fd7a2146e..cc2d76600e 100644 --- a/SerialInterface.h +++ b/SerialInterface.h @@ -12,4 +12,13 @@ int read_sensors(int first_measurement, float * avg_adc_channels, int * adc_chan #define NUM_CHANNELS 5 #define SERIAL_PORT_NAME "/dev/tty.usbmodem641" +// Acceleration sensors, in screen/world coord system (X = left/right, Y = Up/Down, Z = fwd/back) +#define ACCEL_X 3 +#define ACCEL_Y 4 +#define ACCEL_Z 2 + +// Gyro sensors, in coodinate system of head/airplane +#define PITCH_RATE 0 +#define YAW_RATE 1 + #endif diff --git a/head.cpp b/head.cpp index 98cbf0d0d3..d2b2a0ed02 100644 --- a/head.cpp +++ b/head.cpp @@ -9,6 +9,7 @@ #include #include "head.h" #include "util.h" +#include "glm/gtx/vector_angle.hpp" float skinColor[] = {1.0, 0.84, 0.66}; float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; @@ -56,14 +57,7 @@ void Head::reset() leanForward = leanSideways = 0; } -// Read the sensors -void readSensors() -{ - -} - -/* -void update_pos(float frametime) +void Head::UpdatePos(float frametime, int * adc_channels, float * avg_adc_channels, int head_mirror, glm::vec3 * gravity) // Using serial data, update avatar/render position and angles { float measured_pitch_rate = adc_channels[0] - avg_adc_channels[0]; @@ -75,111 +69,28 @@ void update_pos(float frametime) const float HEAD_ROTATION_SCALE = 0.20; const float HEAD_LEAN_SCALE = 0.02; if (head_mirror) { - myHead.addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); - myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - myHead.addLean(measured_lateral_accel * frametime * HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); + addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); + addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); + addLean(measured_lateral_accel * frametime * HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { - myHead.addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); - myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - myHead.addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); + addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); + addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); + addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); + } + + // Try to measure absolute roll from sensors + const float MIN_ROLL = 3.0; + glm::vec3 v1(gravity->x, gravity->y, 0); + glm::vec3 v2(adc_channels[ACCEL_X], adc_channels[ACCEL_Y], 0); + float newRoll = acos(glm::dot(glm::normalize(v1), glm::normalize(v2))) ; + if (newRoll != NAN) { + newRoll *= 1000.0; + if (newRoll > MIN_ROLL) { + if (adc_channels[ACCEL_X] > gravity->x) newRoll *= -1.0; + //SetRoll(newRoll); + } } - // Decay avatar head back toward zero - //pitch *= (1.f - 5.0*frametime); - //yaw *= (1.f - 7.0*frametime); - - // Update head_mouse model - const float MIN_MOUSE_RATE = 30.0; - const float MOUSE_SENSITIVITY = 0.1; - if (powf(measured_yaw_rate*measured_yaw_rate + - measured_pitch_rate*measured_pitch_rate, 0.5) > MIN_MOUSE_RATE) - { - head_mouse_x -= measured_yaw_rate*MOUSE_SENSITIVITY; - head_mouse_y += measured_pitch_rate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH; - } - head_mouse_x = max(head_mouse_x, 0); - head_mouse_x = min(head_mouse_x, WIDTH); - head_mouse_y = max(head_mouse_y, 0); - head_mouse_y = min(head_mouse_y, HEIGHT); - - // Update render direction (pitch/yaw) based on measured gyro rates - const int MIN_YAW_RATE = 300; - const float YAW_SENSITIVITY = 0.03; - const int MIN_PITCH_RATE = 300; - const float PITCH_SENSITIVITY = 0.04; - - if (fabs(measured_yaw_rate) > MIN_YAW_RATE) - { - if (measured_yaw_rate > 0) - render_yaw_rate -= (measured_yaw_rate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; - else - render_yaw_rate -= (measured_yaw_rate + MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; - } - if (fabs(measured_pitch_rate) > MIN_PITCH_RATE) - { - if (measured_pitch_rate > 0) - render_pitch_rate += (measured_pitch_rate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; - else - render_pitch_rate += (measured_pitch_rate + MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; - } - render_yaw += render_yaw_rate; - render_pitch += render_pitch_rate; - - // Decay render_pitch toward zero because we never look constantly up/down - render_pitch *= (1.f - 2.0*frametime); - - // Decay angular rates toward zero - render_pitch_rate *= (1.f - 5.0*frametime); - render_yaw_rate *= (1.f - 7.0*frametime); - - // Update slide left/right based on accelerometer reading - const int MIN_LATERAL_ACCEL = 20; - const float LATERAL_SENSITIVITY = 0.001; - if (fabs(measured_lateral_accel) > MIN_LATERAL_ACCEL) - { - if (measured_lateral_accel > 0) - lateral_vel += (measured_lateral_accel - MIN_LATERAL_ACCEL) * LATERAL_SENSITIVITY * frametime; - else - lateral_vel += (measured_lateral_accel + MIN_LATERAL_ACCEL) * LATERAL_SENSITIVITY * frametime; - } - - //slide += lateral_vel; - lateral_vel *= (1.f - 4.0*frametime); - - // Update fwd/back based on accelerometer reading - const int MIN_FWD_ACCEL = 20; - const float FWD_SENSITIVITY = 0.001; - - if (fabs(measured_fwd_accel) > MIN_FWD_ACCEL) - { - if (measured_fwd_accel > 0) - fwd_vel += (measured_fwd_accel - MIN_FWD_ACCEL) * FWD_SENSITIVITY * frametime; - else - fwd_vel += (measured_fwd_accel + MIN_FWD_ACCEL) * FWD_SENSITIVITY * frametime; - - } - // Decrease forward velocity - fwd_vel *= (1.f - 4.0*frametime); - - // Update forward vector based on pitch and yaw - fwd_vec[0] = -sinf(render_yaw*PI/180); - fwd_vec[1] = sinf(render_pitch*PI/180); - fwd_vec[2] = cosf(render_yaw*PI/180); - - // Advance location forward - location[0] += fwd_vec[0]*fwd_vel; - location[1] += fwd_vec[1]*fwd_vel; - location[2] += fwd_vec[2]*fwd_vel; - - // Slide location sideways - location[0] += fwd_vec[2]*-lateral_vel; - location[2] += fwd_vec[0]*lateral_vel; - - // Update head and manipulator objects with object with current location - myHead.setPos(glm::vec3(location[0], location[1], location[2])); - balls.updateHand(myHead.getPos() + myHand.getPos(), glm::vec3(0,0,0), myHand.getRadius()); } -*/ - void Head::addLean(float x, float z) { // Add Body lean as impulse @@ -201,7 +112,7 @@ void Head::simulate(float deltaTime) // Move toward new target Pitch += (PitchTarget - Pitch)*22*deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; Yaw += (YawTarget - Yaw)*22*deltaTime; // (1.f - DECAY*deltaTime); - Roll *= (1.f - DECAY*deltaTime); + //Roll *= (1.f - DECAY*deltaTime); } leanForward *= (1.f - DECAY*30.f*deltaTime); diff --git a/head.h b/head.h index be228137ec..5875114e77 100644 --- a/head.h +++ b/head.h @@ -13,6 +13,7 @@ #include "field.h" #include "world.h" #include +#include "SerialInterface.h" class Head { float noise; @@ -51,11 +52,15 @@ class Head { public: Head(void); void reset(); + void UpdatePos(float frametime, int * adc_channels, float * avg_adc_channels, + 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 addPitch(float p) {Pitch -= p; } void addYaw(float y){Yaw -= y; } + void addRoll(float r){Roll += r; } void addLean(float x, float z); void getPitch(float); void render(); diff --git a/interface.xcodeproj/project.pbxproj b/interface.xcodeproj/project.pbxproj index 8930389ea0..613476cb65 100644 --- a/interface.xcodeproj/project.pbxproj +++ b/interface.xcodeproj/project.pbxproj @@ -140,11 +140,11 @@ isa = PBXGroup; children = ( 08FB7796FE84155DC02AAC07 /* main.cpp */, + D4EE3BC015E746E900EE4C89 /* world.h */, D409B9A6165CA7A50099B0B3 /* agent.h */, D409B9A7165CA7BB0099B0B3 /* agent.cpp */, D409B988165849030099B0B3 /* cloud.h */, D409B989165849180099B0B3 /* cloud.cpp */, - D4EE3BC015E746E900EE4C89 /* world.h */, B6BDAE4315F6BE53002A07DF /* particle.cpp */, B6BDAE4115F6BE4D002A07DF /* particle.h */, D4EE3BBD15E7465700EE4C89 /* field.cpp */, diff --git a/interface.xcodeproj/project.xcworkspace/xcuserdata/philip.xcuserdatad/UserInterfaceState.xcuserstate b/interface.xcodeproj/project.xcworkspace/xcuserdata/philip.xcuserdatad/UserInterfaceState.xcuserstate index 1aded4aa69d1438242e9e35135534eb0091d71d7..9c6cf6345d1121e26ceb918d0ca0ead6635f79f7 100644 GIT binary patch delta 30392 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 delta 30408 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 1000) done = 1; } + gravity.x = avg_adc_channels[ACCEL_X]; + gravity.y = avg_adc_channels[ACCEL_Y]; + gravity.z = avg_adc_channels[ACCEL_Z]; + + std::cout << "Gravity: " << gravity.x << "," << gravity.y << "," << gravity.z << "\n"; printf( "Done.\n" ); } @@ -347,27 +369,13 @@ void reset_sensors() void update_pos(float frametime) // Using serial data, update avatar/render position and angles { - float measured_pitch_rate = adc_channels[0] - avg_adc_channels[0]; - float measured_yaw_rate = adc_channels[1] - avg_adc_channels[1]; - float measured_lateral_accel = adc_channels[3] - avg_adc_channels[3]; - float measured_fwd_accel = avg_adc_channels[2] - adc_channels[2]; + float measured_pitch_rate = adc_channels[PITCH_RATE] - avg_adc_channels[PITCH_RATE]; + float measured_yaw_rate = adc_channels[YAW_RATE] - avg_adc_channels[YAW_RATE]; + float measured_lateral_accel = adc_channels[ACCEL_X] - avg_adc_channels[ACCEL_X]; + float measured_fwd_accel = avg_adc_channels[ACCEL_Z] - adc_channels[ACCEL_Z]; + + myHead.UpdatePos(frametime, &adc_channels[0], &avg_adc_channels[0], head_mirror, &gravity); - // Update avatar head position based on measured gyro rates - const float HEAD_ROTATION_SCALE = 0.20; - const float HEAD_LEAN_SCALE = 0.02; - if (head_mirror) { - myHead.addYaw(measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); - myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - myHead.addLean(measured_lateral_accel * frametime * HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); - } else { - myHead.addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); - myHead.addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); - myHead.addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); - } - // Decay avatar head back toward zero - //pitch *= (1.f - 5.0*frametime); - //yaw *= (1.f - 7.0*frametime); - // Update head_mouse model const float MIN_MOUSE_RATE = 30.0; const float MOUSE_SENSITIVITY = 0.1; @@ -510,7 +518,7 @@ void display(void) glTranslatef(location[0], location[1], location[2]); glPushMatrix(); - glTranslatef(WORLD_SIZE/2, WORLD_SIZE/2, WORLD_SIZE/2); + //glTranslatef(-WORLD_SIZE/2, -WORLD_SIZE/2, -WORLD_SIZE/2); int i = 0; while (i < cube_count) { glPushMatrix(); @@ -592,18 +600,25 @@ void display(void) for(i = 0; i < NUM_CHANNELS; i++) { // Actual value + glLineWidth(2.0); glColor4f(1, 1, 1, 1); glBegin(GL_LINES); glVertex2f(disp_x, HEIGHT*0.95); glVertex2f(disp_x, HEIGHT*(0.25 + 0.75f*adc_channels[i]/4096)); glEnd(); // Trailing Average value - glColor4f(0, 0, 0.8, 1); + glColor4f(1, 1, 0, 1); glBegin(GL_LINES); glVertex2f(disp_x + 2, HEIGHT*0.95); glVertex2f(disp_x + 2, HEIGHT*(0.25 + 0.75f*avg_adc_channels[i]/4096)); glEnd(); + glColor3f(1,0,0); + glBegin(GL_LINES); + glLineWidth(2.0); + glVertex2f(disp_x - 10, HEIGHT*0.5 - (adc_channels[i] - avg_adc_channels[i])); + glVertex2f(disp_x + 10, HEIGHT*0.5 - (adc_channels[i] - avg_adc_channels[i])); + glEnd(); sprintf(val, "%d", adc_channels[i]); drawtext(disp_x-GAP/2, (HEIGHT*0.95)+2, 0.08, 90, 1.0, 0, val, 0, 1, 0); @@ -653,10 +668,13 @@ void key(unsigned char k, int x, int y) } if (k == 'h') display_head = !display_head; - if (k == 'm') display_hand = !display_hand; + if (k == 'b') display_hand = !display_hand; + if (k == 'm') head_mirror = !head_mirror; + if (k == 'f') display_field = !display_field; if (k == 'l') display_levels = !display_levels; + if (k == 'e') location[1] -= WORLD_SIZE/100.0; if (k == 'c') location[1] += WORLD_SIZE/100.0; if (k == 'w') fwd_vel += 0.05; diff --git a/network.cpp b/network.cpp index e386ac913d..7cc72a53a4 100644 --- a/network.cpp +++ b/network.cpp @@ -73,7 +73,6 @@ int network_init() //from.sin_addr.s_addr = htonl(ip_address); from.sin_port = htons( (unsigned short) UDP_PORT ); - return handle; } @@ -94,7 +93,6 @@ int notify_spaceserver(int handle, float x, float y, float z) { int packet_size = strlen(data); int sent_bytes = sendto( handle, (const char*)data, packet_size, 0, (sockaddr*)&spaceserver_address, sizeof(sockaddr_in) ); - if ( sent_bytes != packet_size ) { printf( "failed to send to spaceserver: return value = %d\n", sent_bytes ); @@ -103,9 +101,11 @@ int notify_spaceserver(int handle, float x, float y, float z) { return sent_bytes; } + int network_send(int handle, char * packet_data, int packet_size) -{ - int sent_bytes = sendto( handle, (const char*)packet_data, packet_size, +{ + int sent_bytes = 0; + sent_bytes = sendto( handle, (const char*)packet_data, packet_size, 0, (sockaddr*)&dest_address, sizeof(sockaddr_in) ); if ( sent_bytes != packet_size ) diff --git a/network.h b/network.h index e06f416b9e..ea3f98cd72 100644 --- a/network.h +++ b/network.h @@ -25,6 +25,9 @@ const char DESTINATION_IP[] = "127.0.0.1"; const char SPACESERVER_IP[] = "127.0.0.1"; const int SPACESERVER_PORT = 40000; +// Randomly send a ping packet every N packets sent +const int PING_PACKET_COUNT = 20; + int network_init(); int network_send(int handle, char * packet_data, int packet_size); int network_receive(int handle, char * packet_data, int delay /*msecs*/); diff --git a/util.cpp b/util.cpp index 89fdcc8900..90dcf451ee 100644 --- a/util.cpp +++ b/util.cpp @@ -26,21 +26,23 @@ void makeCubes(float location[3], float scale, int * index, //std::cout << "loc: " << location[0] << "," //<< location[1] << "," << location[2] << "\n"; if ((*index >= MAX_CUBES) || (scale < SMALLEST_CUBE)) return; - if (randFloat() < 0.5) { + if (scale < 3 && (randFloat() < .1)) { // Make a cube - for (i = 0; i < 3; i++) cubes_position[*index*3 + i] = location[i]; + for (i = 0; i < 3; i++) cubes_position[*index*3 + i] = location[i]+scale/2.0; + float color = randFloat(); cubes_scale[*index] = scale; - cubes_color[*index*3] = randFloat(); - cubes_color[*index*3 + 1] = randFloat(); - cubes_color[*index*3 + 2] = randFloat(); + cubes_color[*index*3] = color; + cubes_color[*index*3 + 1] = color; + cubes_color[*index*3 + 2] = color; *index += 1; - //std::cout << "Quad made at scale " << scale << "\n"; + //std::cout << "Loc: " << location[0] << "," << location[1] + //<< "," << location[2] << " scale " << scale << "\n"; } else { for (i = 0; i < 8; i++) { spot[0] = location[0] + (i%2)*scale/2.0; spot[1] = location[1] + ((i/2)%2)*scale/2.0; spot[2] = location[2] + ((i/4)%2)*scale/2.0; - //std::cout << spot[0] << "," << spot[1] << "," << spot[2] << "\n"; + //std::cout << "called with " << spot[0] << "," << spot[1] << "," << spot[2] << "\n"; makeCubes(spot, scale/2.0, index, cubes_position, cubes_scale, cubes_color); } } diff --git a/world.h b/world.h index 106f47ff69..b59b19cb88 100644 --- a/world.h +++ b/world.h @@ -14,7 +14,7 @@ const float WORLD_SIZE = 10.0; #define PI 3.14159265 -#define MAX_CUBES 2000 -#define SMALLEST_CUBE 0.01 +#define MAX_CUBES 0 +#define SMALLEST_CUBE 0.1 #endif