I''m working on GNURadio. Included math.h in my program but still get an error saying that abs was not declared in this scope.
Here is my header file.
#ifndef INCLUDED_SLM_H
#define INCLUDED_SLM_H
#include "candidate_t.h"
namespace gr {
namespace uwspr {
class SLM {
public:
// returns frequency drift according to the straight line model
float slmFrequencyDrift(mode_nonlinear m_nl, float cf, float t);
// generator of trajectory parameters for the straight line model
bool slmGenerator(mode_nonlinear *m_nl);
// initialize the generator
void slmGeneratorInit();
// index of current instances
int current;
SLM(){};
~SLM(){};
};
} // namespace uwspr
} // namespace gr
#endif /* INCLUDED_SLM_H */
Here is my code snippet for main function.
#include "slm.h"
#include <math.h>
#ifndef DEBUG
#define DEBUG 1 // set debug mode
#endif
#include "debugmacro.h"
namespace gr {
namespace uwspr {
// Returns frequency drift (in Hz) due to the Doppler effect according to
// the straight line model, described in paper:
float SLM::slmFrequencyDrift(mode_nonlinear m_nl, float cf, float t)
// m_nl = trajectory parameters
// t = time, in seconds
{
const float c = 1500.0; // sound speed (m/s)
// sign of velocity vector
float Sign = (((m_nl.V1 * t + m_nl.p1) * m_nl.V1 +
(m_nl.V2 * t + m_nl.p2) * m_nl.V2) > 0) *
2 -
1;
//
double numerator = abs(m_nl.V1 * (m_nl.V1 * t + m_nl.p1) +
m_nl.V2 * (m_nl.V2 * t + m_nl.p2));
// norm of connectiong vector (Eq. 16)
double denominator =
sqrt(pow(m_nl.V1 * t + m_nl.p1, 2) + pow(m_nl.V2 * t + m_nl.p2, 2));
if (denominator == 0) {
return 0.0;
} else {
// return -Sign;
return -Sign * numerator / denominator * cf / c;
}
}
// Generators of trajectory parameters for the straight line model
bool SLM::slmGenerator(mode_nonlinear *m_nl) {
// control variables for init velocity
const double V1_min = -2, V1_max = 2, V1_step = 1;
const int nV1 = (V1_max - V1_min) / V1_step + 1;
const double V2_min = -2, V2_max = 2, V2_step = 1;
const int nV2 = (V2_max - V2_min) / V2_step + 1;
// control variables for init position on y-axis
const int p2_min = 50, p2_max = 850, p2_step = 200;
const int np2 = (p2_max - p2_min) / p2_step + 1;
// number of generated instances
const int last = nV1 * nV2 * np2;
// indices into the instances
static int ip2, iV1, iV2;
if (current == 0) {
ip2 = 0;
iV1 = 0;
iV2 = 0;
}
if (current < last) { // not generated all instances?
if (ip2 >= np2) {
ip2 = 0; // reset index into the list positions
iV1++; // next horizontal velocity
if (iV1 >= nV1) {
iV1 = 0; // reset index into the list horiz. velocities
iV2++; // next vertical velocity
}
}
// map horizontal velocity index to horizontal velocity (m/s)
m_nl->V1 = iV1 * V1_step + V1_min;
// map vertical velocity index to vertical velocity (m/s)
m_nl->V2 = iV2 * V2_step + V2_min;
// init coordinate on x-axis is always null
m_nl->p1 = 0;
// map y-axis coordinate index to y-axis coordinate (m)
m_nl->p2 = ip2 * p2_step + p2_min;
ip2++; // next position on y-axis
current++; // index of next instance
return true;
} else {
return false; // reach the end
}
}
void SLM::slmGeneratorInit() { current = 0; }
} /* namespace uwspr */
} /* namespace gr */
abs is not defined in <math.h>. It can be found in <stdlib.h> and it is also defined as std::abs in <cmath>.
Surprisingly, the abs function is defined in <stdlib.h> rather than <math.h>. (At least, that's the case since C++17). Try including <stdlib.h> or <cstdlib> and see if that fixes things.
Hope this helps!
The problem is that you were using the C header file, math.h. The C standard already defined (the global scope) int ::abs(int) to take an int and return an int, and this is defined in stdlib.h. The float version, double ::fabs(double) is defined in math.h, which is the one you need to use.
C++ has overloads, so std::abs has double std::abs(double) and int std::abs(int) overloads. So you could just use the C++ header, cmath, and use std::abs (or std::fabs to prevent conversions) instead.
Related
I wanted to calculate p-values of a t-statistic for a two tailed test with 5% level of significance. And I wanted to do this with the standard library. I was wondering if this was possible using the student_t_distribution from the < random > module.
My code currently is as following
#include <iostream>
int main(){
double t_stat = 0.0267; // t-statistic
double alpha_los = 0.05; // level of significance
double dof = 30; // degrees of freedom
// calculate P > |t| and compare with alpha_los
return 0;
}
Thank you
The <random> header just provides you with the ability to get random numbers from different distributions.
If you are able to use boost you can do the following:
#include <boost/math/distributions/students_t.hpp>
int main() {
double t_stat = 0.0267; // t-statistic
double alpha_los = 0.05; // level of significance
double dof = 30; // degrees of freedom
boost::math::students_t dist(dof);
double P_x_greater_t = 1.0 - boost::math::cdf(dist, t_stat);
double P_x_smaller_negative_t = boost::math::cdf(dist, -t_stat);
if(P_x_greater_t + P_x_smaller_negative_t < alpha_los) {
} else {
}
}
I have programmed a simple dragon curve fractal. It seems to work for the most part, but there is an odd logical error that shifts the rotation of certain lines by one pixel. This wouldn't normally be an issue, but after a few generations, at the right size, the fractal begins to look wonky.
I am using open cv in c++ to generate it, but I'm pretty sure it's a logical error rather than a display error. I have printed the values to the console multiple times and seen for myself that there is a one-digit difference between values that are intended to be the exact same - meaning a line may have a y of 200 at one end and 201 at another.
Here is the full code:
#include<iostream>
#include<cmath>
#include<opencv2/opencv.hpp>
const int width=500;
const int height=500;
const double PI=std::atan(1)*4.0;
struct point{
double x;
double y;
point(double x_,double y_){
x=x_;
y=y_;
}};
cv::Mat img(width,height,CV_8UC3,cv::Scalar(255,255,255));
double deg_to_rad(double degrees){return degrees*PI/180;}
point rotate(int degree, int centx, int centy, int ll) {
double radians = deg_to_rad(degree);
return point(centx + (ll * std::cos(radians)), centy + (ll * std::sin(radians)));
}
void generate(point & r, std::vector < point > & verticies, int rotation = 90) {
int curRotation = 90;
bool start = true;
point center = r;
point rot(0, 0);
std::vector<point> verticiesc(verticies);
for (point i: verticiesc) {
double dx = center.x - i.x;
double dy = center.y - i.y;
//distance from centre
int ll = std::sqrt(dx * dx + dy * dy);
//angle from centre
curRotation = std::atan2(dy, dx) * 180 / PI;
//add 90 degrees of rotation
rot = rotate(curRotation + rotation, center.x, center.y, ll);
verticies.push_back(rot);
//endpoint, where the next centre will be
if (start) {
r = rot;
start = false;
}
}
}
void gen(int gens, int bwidth = 1) {
int ll = 7;
std::vector < point > verticies = {
point(width / 2, height / 2 - ll),
point(width / 2, height / 2)
};
point rot(width / 2, height / 2);
for (int i = 0; i < gens; i++) {
generate(rot, verticies);
}
//draw lines
for (int i = 0; i < verticies.size(); i += 2) {
cv::line(img, cv::Point(verticies[i].x, verticies[i].y), cv::Point(verticies[i + 1].x, verticies[i + 1].y), cv::Scalar(0, 0, 0), 1, 8);
}
}
int main() {
gen(10);
cv::imshow("", img);
cv::waitKey(0);
return 0;
}
First, you use int to store point coordinates - that's a bad idea - you lose all accuracy of point position. Use double or float.
Second, your method for drawing fractals is not too stable numericly. You'd better store original shape and all rotation/translation/scale that indicate where and how to draw scaled copies of the original shape.
Also, I believe this is a bug:
for(point i: verices)
{
...
vertices.push_back(rot);
...
}
Changing size of vertices while inside such a for-loop might cause a crash or UB.
Turns out it was to do with floating-point precision. I changed
x=x_;
y=y_;
to
x=std::round(x_);
y=std::round(y_);
and it works.
I have been trying to compile a code for a accelerometer which is avaiable from two sources but referring to the same code on github:
https://github.com/ayildirim/OpenVR
https://github.com/ptrbrtz/razor-9dof-ahrs/
Both of this sources contain the following arduino code(c++):
#define HW__VERSION_CODE 10736 // SparkFun "9DOF Razor IMU" version "SEN-10736" (HMC5883L magnetometer)
// OUTPUT OPTIONS
/*****************************************************************/
// Set your serial port baud rate used to send out data here!
#define OUTPUT__BAUD_RATE 57600
// Sensor data output interval in milliseconds
// This may not work, if faster than 20ms (=50Hz)
// Code is tuned for 20ms, so better leave it like that
#define OUTPUT__DATA_INTERVAL 20 // in milliseconds
// Output mode definitions (do not change)
#define OUTPUT__MODE_CALIBRATE_SENSORS 0 // Outputs sensor min/max values as text for manual calibration
#define OUTPUT__MODE_ANGLES 1 // Outputs yaw/pitch/roll in degrees
#define OUTPUT__MODE_SENSORS_CALIB 2 // Outputs calibrated sensor values for all 9 axes
#define OUTPUT__MODE_SENSORS_RAW 3 // Outputs raw (uncalibrated) sensor values for all 9 axes
#define OUTPUT__MODE_SENSORS_BOTH 4 // Outputs calibrated AND raw sensor values for all 9 axes
// Output format definitions (do not change)
#define OUTPUT__FORMAT_TEXT 0 // Outputs data as text
#define OUTPUT__FORMAT_BINARY 1 // Outputs data as binary float
// Select your startup output mode and format here!
int output_mode = OUTPUT__MODE_ANGLES;
int output_format = OUTPUT__FORMAT_TEXT;
// Select if serial continuous streaming output is enabled per default on startup.
#define OUTPUT__STARTUP_STREAM_ON true // true or false
// If set true, an error message will be output if we fail to read sensor data.
// Message format: "!ERR: reading <sensor>", followed by "\r\n".
boolean output_errors = false; // true or false
// Bluetooth
// You can set this to true, if you have a Rovering Networks Bluetooth Module attached.
// The connect/disconnect message prefix of the module has to be set to "#".
// (Refer to manual, it can be set like this: SO,#)
// When using this, streaming output will only be enabled as long as we're connected. That way
// receiver and sender are synchronzed easily just by connecting/disconnecting.
// It is not necessary to set this! It just makes life easier when writing code for
// the receiving side. The Processing test sketch also works without setting this.
// NOTE: When using this, OUTPUT__STARTUP_STREAM_ON has no effect!
#define OUTPUT__HAS_RN_BLUETOOTH false // true or false
// SENSOR CALIBRATION
/*****************************************************************/
// How to calibrate? Read the tutorial at http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
// Put MIN/MAX and OFFSET readings for your board here!
// Accelerometer
// "accel x,y,z (min/max) = X_MIN/X_MAX Y_MIN/Y_MAX Z_MIN/Z_MAX"
#define ACCEL_X_MIN ((float) -289)
#define ACCEL_X_MAX ((float) 294)
#define ACCEL_Y_MIN ((float) -268)
#define ACCEL_Y_MAX ((float) 288)
#define ACCEL_Z_MIN ((float) -294)
#define ACCEL_Z_MAX ((float) 269)
// Magnetometer (standard calibration)
// "magn x,y,z (min/max) = X_MIN/X_MAX Y_MIN/Y_MAX Z_MIN/Z_MAX"
//#define MAGN_X_MIN ((float) -600)
//#define MAGN_X_MAX ((float) 600)
//#define MAGN_Y_MIN ((float) -600)
//#define MAGN_Y_MAX ((float) 600)
//#define MAGN_Z_MIN ((float) -600)
//#define MAGN_Z_MAX ((float) 600)
// Magnetometer (extended calibration)
// Uncommend to use extended magnetometer calibration (compensates hard & soft iron errors)
#define CALIBRATION__MAGN_USE_EXTENDED true
const float magn_ellipsoid_center[3] = {
3.80526, -16.4455, 87.4052};
const float magn_ellipsoid_transform[3][3] = {
{
0.970991, 0.00583310, -0.00265756 }
, {
0.00583310, 0.952958, 2.76726e-05 }
, {
-0.00265756, 2.76726e-05, 0.999751 }
};
// Gyroscope
// "gyro x,y,z (current/average) = .../OFFSET_X .../OFFSET_Y .../OFFSET_Z
#define GYRO_AVERAGE_OFFSET_X ((float) 23.85)
#define GYRO_AVERAGE_OFFSET_Y ((float) -53.41)
#define GYRO_AVERAGE_OFFSET_Z ((float) -15.32)
/*
// Calibration example:
// "accel x,y,z (min/max) = -278.00/270.00 -254.00/284.00 -294.00/235.00"
#define ACCEL_X_MIN ((float) -278)
#define ACCEL_X_MAX ((float) 270)
#define ACCEL_Y_MIN ((float) -254)
#define ACCEL_Y_MAX ((float) 284)
#define ACCEL_Z_MIN ((float) -294)
#define ACCEL_Z_MAX ((float) 235)
// "magn x,y,z (min/max) = -511.00/581.00 -516.00/568.00 -489.00/486.00"
//#define MAGN_X_MIN ((float) -511)
//#define MAGN_X_MAX ((float) 581)
//#define MAGN_Y_MIN ((float) -516)
//#define MAGN_Y_MAX ((float) 568)
//#define MAGN_Z_MIN ((float) -489)
//#define MAGN_Z_MAX ((float) 486)
// Extended magn
#define CALIBRATION__MAGN_USE_EXTENDED true
const float magn_ellipsoid_center[3] = {91.5, -13.5, -48.1};
const float magn_ellipsoid_transform[3][3] = {{0.902, -0.00354, 0.000636}, {-0.00354, 0.9, -0.00599}, {0.000636, -0.00599, 1}};
// Extended magn (with Sennheiser HD 485 headphones)
//#define CALIBRATION__MAGN_USE_EXTENDED true
//const float magn_ellipsoid_center[3] = {72.3360, 23.0954, 53.6261};
//const float magn_ellipsoid_transform[3][3] = {{0.879685, 0.000540833, -0.0106054}, {0.000540833, 0.891086, -0.0130338}, {-0.0106054, -0.0130338, 0.997494}};
//"gyro x,y,z (current/average) = -32.00/-34.82 102.00/100.41 -16.00/-16.38"
#define GYRO_AVERAGE_OFFSET_X ((float) -34.82)
#define GYRO_AVERAGE_OFFSET_Y ((float) 100.41)
#define GYRO_AVERAGE_OFFSET_Z ((float) -16.38)
*/
// DEBUG OPTIONS
/*****************************************************************/
// When set to true, gyro drift correction will not be applied
#define DEBUG__NO_DRIFT_CORRECTION false
// Print elapsed time after each I/O loop
#define DEBUG__PRINT_LOOP_TIME false
/*****************************************************************/
/****************** END OF USER SETUP AREA! *********************/
/*****************************************************************/
// Check if hardware version code is defined
#ifndef HW__VERSION_CODE
// Generate compile error
#error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.pde (or .ino)!
#endif
#include <Wire.h>
#include <Compass.h>
#include <DCM.h>
#include <Math.h>
#include <Output.h>
#include <Sensors.h>
// Sensor calibration scale and offset values
#define ACCEL_X_OFFSET ((ACCEL_X_MIN + ACCEL_X_MAX) / 2.0f)
#define ACCEL_Y_OFFSET ((ACCEL_Y_MIN + ACCEL_Y_MAX) / 2.0f)
#define ACCEL_Z_OFFSET ((ACCEL_Z_MIN + ACCEL_Z_MAX) / 2.0f)
#define ACCEL_X_SCALE (GRAVITY / (ACCEL_X_MAX - ACCEL_X_OFFSET))
#define ACCEL_Y_SCALE (GRAVITY / (ACCEL_Y_MAX - ACCEL_Y_OFFSET))
#define ACCEL_Z_SCALE (GRAVITY / (ACCEL_Z_MAX - ACCEL_Z_OFFSET))
#define MAGN_X_OFFSET ((MAGN_X_MIN + MAGN_X_MAX) / 2.0f)
#define MAGN_Y_OFFSET ((MAGN_Y_MIN + MAGN_Y_MAX) / 2.0f)
#define MAGN_Z_OFFSET ((MAGN_Z_MIN + MAGN_Z_MAX) / 2.0f)
#define MAGN_X_SCALE (100.0f / (MAGN_X_MAX - MAGN_X_OFFSET))
#define MAGN_Y_SCALE (100.0f / (MAGN_Y_MAX - MAGN_Y_OFFSET))
#define MAGN_Z_SCALE (100.0f / (MAGN_Z_MAX - MAGN_Z_OFFSET))
// Gain for gyroscope (ITG-3200)
#define GYRO_GAIN 0.06957 // Same gain on all axes
#define GYRO_SCALED_RAD(x) (x * TO_RAD(GYRO_GAIN)) // Calculate the scaled gyro readings in radians per second
// DCM parameters
#define Kp_ROLLPITCH 0.02f
#define Ki_ROLLPITCH 0.00002f
#define Kp_YAW 1.2f
#define Ki_YAW 0.00002f
// Stuff
#define STATUS_LED_PIN 13 // Pin number of status LED
#define GRAVITY 256.0f // "1G reference" used for DCM filter and accelerometer calibration
#define TO_RAD(x) (x * 0.01745329252) // *pi/180
#define TO_DEG(x) (x * 57.2957795131) // *180/pi
// Sensor variables
float accel[3]; // Actually stores the NEGATED acceleration (equals gravity, if board not moving).
float accel_min[3];
float accel_max[3];
float magnetom[3];
float magnetom_min[3];
float magnetom_max[3];
float magnetom_tmp[3];
float gyro[3];
float gyro_average[3];
int gyro_num_samples = 0;
// DCM variables
float MAG_Heading;
float Accel_Vector[3]= {
0, 0, 0}; // Store the acceleration in a vector
float Gyro_Vector[3]= {
0, 0, 0}; // Store the gyros turn rate in a vector
float Omega_Vector[3]= {
0, 0, 0}; // Corrected Gyro_Vector data
float Omega_P[3]= {
0, 0, 0}; // Omega Proportional correction
float Omega_I[3]= {
0, 0, 0}; // Omega Integrator
float Omega[3]= {
0, 0, 0};
float errorRollPitch[3] = {
0, 0, 0};
float errorYaw[3] = {
0, 0, 0};
float DCM_Matrix[3][3] = {
{
1, 0, 0 }
, {
0, 1, 0 }
, {
0, 0, 1 }
};
float Update_Matrix[3][3] = {
{
0, 1, 2 }
, {
3, 4, 5 }
, {
6, 7, 8 }
};
float Temporary_Matrix[3][3] = {
{
0, 0, 0 }
, {
0, 0, 0 }
, {
0, 0, 0 }
};
// Euler angles
float yaw;
float pitch;
float roll;
// DCM timing in the main loop
unsigned long timestamp;
unsigned long timestamp_old;
float G_Dt; // Integration time for DCM algorithm
// More output-state variables
boolean output_stream_on;
boolean output_single_on;
int curr_calibration_sensor = 0;
boolean reset_calibration_session_flag = true;
int num_accel_errors = 0;
int num_magn_errors = 0;
int num_gyro_errors = 0;
void read_sensors() {
Read_Gyro(); // Read gyroscope
Read_Accel(); // Read accelerometer
Read_Magn(); // Read magnetometer
}
// Read every sensor and record a time stamp
// Init DCM with unfiltered orientation
// TODO re-init global vars?
void reset_sensor_fusion() {
float temp1[3];
float temp2[3];
float xAxis[] = {
1.0f, 0.0f, 0.0f };
read_sensors();
timestamp = millis();
// GET PITCH
// Using y-z-plane-component/x-component of gravity vector
pitch = -atan2(accel[0], sqrt(accel[1] * accel[1] + accel[2] * accel[2]));
// GET ROLL
// Compensate pitch of gravity vector
Vector_Cross_Product(temp1, accel, xAxis);
Vector_Cross_Product(temp2, xAxis, temp1);
// Normally using x-z-plane-component/y-component of compensated gravity vector
// roll = atan2(temp2[1], sqrt(temp2[0] * temp2[0] + temp2[2] * temp2[2]));
// Since we compensated for pitch, x-z-plane-component equals z-component:
roll = atan2(temp2[1], temp2[2]);
// GET YAW
Compass_Heading();
yaw = MAG_Heading;
// Init rotation matrix
init_rotation_matrix(DCM_Matrix, yaw, pitch, roll);
}
// Apply calibration to raw sensor readings
void compensate_sensor_errors() {
// Compensate accelerometer error
accel[0] = (accel[0] - ACCEL_X_OFFSET) * ACCEL_X_SCALE;
accel[1] = (accel[1] - ACCEL_Y_OFFSET) * ACCEL_Y_SCALE;
accel[2] = (accel[2] - ACCEL_Z_OFFSET) * ACCEL_Z_SCALE;
// Compensate magnetometer error
#if CALIBRATION__MAGN_USE_EXTENDED == true
for (int i = 0; i < 3; i++)
magnetom_tmp[i] = magnetom[i] - magn_ellipsoid_center[i];
Matrix_Vector_Multiply(magn_ellipsoid_transform, magnetom_tmp, magnetom);
#else
magnetom[0] = (magnetom[0] - MAGN_X_OFFSET) * MAGN_X_SCALE;
magnetom[1] = (magnetom[1] - MAGN_Y_OFFSET) * MAGN_Y_SCALE;
magnetom[2] = (magnetom[2] - MAGN_Z_OFFSET) * MAGN_Z_SCALE;
#endif
// Compensate gyroscope error
gyro[0] -= GYRO_AVERAGE_OFFSET_X;
gyro[1] -= GYRO_AVERAGE_OFFSET_Y;
gyro[2] -= GYRO_AVERAGE_OFFSET_Z;
}
// Reset calibration session if reset_calibration_session_flag is set
void check_reset_calibration_session()
{
// Raw sensor values have to be read already, but no error compensation applied
// Reset this calibration session?
if (!reset_calibration_session_flag) return;
// Reset acc and mag calibration variables
for (int i = 0; i < 3; i++) {
accel_min[i] = accel_max[i] = accel[i];
magnetom_min[i] = magnetom_max[i] = magnetom[i];
}
// Reset gyro calibration variables
gyro_num_samples = 0; // Reset gyro calibration averaging
gyro_average[0] = gyro_average[1] = gyro_average[2] = 0.0f;
reset_calibration_session_flag = false;
}
void turn_output_stream_on()
{
output_stream_on = true;
digitalWrite(STATUS_LED_PIN, HIGH);
}
void turn_output_stream_off()
{
output_stream_on = false;
digitalWrite(STATUS_LED_PIN, LOW);
}
// Blocks until another byte is available on serial port
char readChar()
{
while (Serial.available() < 1) {
} // Block
return Serial.read();
}
void setup()
{
// Init serial output
Serial.begin(OUTPUT__BAUD_RATE);
// Init status LED
pinMode (STATUS_LED_PIN, OUTPUT);
digitalWrite(STATUS_LED_PIN, LOW);
// Init sensors
delay(50); // Give sensors enough time to start
I2C_Init();
Accel_Init();
Magn_Init();
Gyro_Init();
// Read sensors, init DCM algorithm
delay(20); // Give sensors enough time to collect data
reset_sensor_fusion();
// Init output
#if (OUTPUT__HAS_RN_BLUETOOTH == true) || (OUTPUT__STARTUP_STREAM_ON == false)
turn_output_stream_off();
#else
turn_output_stream_on();
#endif
}
// Main loop
void loop()
{
// Read incoming control messages
if (Serial.available() >= 2)
{
if (Serial.read() == '#') // Start of new control message
{
int command = Serial.read(); // Commands
if (command == 'f') // request one output _f_rame
output_single_on = true;
else if (command == 's') // _s_ynch request
{
// Read ID
byte id[2];
id[0] = readChar();
id[1] = readChar();
// Reply with synch message
Serial.print("#SYNCH");
Serial.write(id, 2);
Serial.println();
}
else if (command == 'o') // Set _o_utput mode
{
char output_param = readChar();
if (output_param == 'n') // Calibrate _n_ext sensor
{
curr_calibration_sensor = (curr_calibration_sensor + 1) % 3;
reset_calibration_session_flag = true;
}
else if (output_param == 't') // Output angles as _t_ext
{
output_mode = OUTPUT__MODE_ANGLES;
output_format = OUTPUT__FORMAT_TEXT;
}
else if (output_param == 'b') // Output angles in _b_inary format
{
output_mode = OUTPUT__MODE_ANGLES;
output_format = OUTPUT__FORMAT_BINARY;
}
else if (output_param == 'c') // Go to _c_alibration mode
{
output_mode = OUTPUT__MODE_CALIBRATE_SENSORS;
reset_calibration_session_flag = true;
}
else if (output_param == 's') // Output _s_ensor values
{
char values_param = readChar();
char format_param = readChar();
if (values_param == 'r') // Output _r_aw sensor values
output_mode = OUTPUT__MODE_SENSORS_RAW;
else if (values_param == 'c') // Output _c_alibrated sensor values
output_mode = OUTPUT__MODE_SENSORS_CALIB;
else if (values_param == 'b') // Output _b_oth sensor values (raw and calibrated)
output_mode = OUTPUT__MODE_SENSORS_BOTH;
if (format_param == 't') // Output values as _t_text
output_format = OUTPUT__FORMAT_TEXT;
else if (format_param == 'b') // Output values in _b_inary format
output_format = OUTPUT__FORMAT_BINARY;
}
else if (output_param == '0') // Disable continuous streaming output
{
turn_output_stream_off();
reset_calibration_session_flag = true;
}
else if (output_param == '1') // Enable continuous streaming output
{
reset_calibration_session_flag = true;
turn_output_stream_on();
}
else if (output_param == 'e') // _e_rror output settings
{
char error_param = readChar();
if (error_param == '0') output_errors = false;
else if (error_param == '1') output_errors = true;
else if (error_param == 'c') // get error count
{
Serial.print("#AMG-ERR:");
Serial.print(num_accel_errors);
Serial.print(",");
Serial.print(num_magn_errors);
Serial.print(",");
Serial.println(num_gyro_errors);
}
}
}
#if OUTPUT__HAS_RN_BLUETOOTH == true
// Read messages from bluetooth module
// For this to work, the connect/disconnect message prefix of the module has to be set to "#".
else if (command == 'C') // Bluetooth "#CONNECT" message (does the same as "#o1")
turn_output_stream_on();
else if (command == 'D') // Bluetooth "#DISCONNECT" message (does the same as "#o0")
turn_output_stream_off();
#endif // OUTPUT__HAS_RN_BLUETOOTH == true
}
else
{
} // Skip character
}
// Time to read the sensors again?
if((millis() - timestamp) >= OUTPUT__DATA_INTERVAL)
{
timestamp_old = timestamp;
timestamp = millis();
if (timestamp > timestamp_old)
G_Dt = (float) (timestamp - timestamp_old) / 1000.0f; // Real time of loop run. We use this on the DCM algorithm (gyro integration time)
else G_Dt = 0;
// Update sensor readings
read_sensors();
if (output_mode == OUTPUT__MODE_CALIBRATE_SENSORS) // We're in calibration mode
{
check_reset_calibration_session(); // Check if this session needs a reset
if (output_stream_on || output_single_on) output_calibration(curr_calibration_sensor);
}
else if (output_mode == OUTPUT__MODE_ANGLES) // Output angles
{
// Apply sensor calibration
compensate_sensor_errors();
// Run DCM algorithm
Compass_Heading(); // Calculate magnetic heading
Matrix_update();
Normalize();
Drift_correction();
Euler_angles();
if (output_stream_on || output_single_on) output_angles();
}
else // Output sensor values
{
if (output_stream_on || output_single_on) output_sensors();
}
output_single_on = false;
#if DEBUG__PRINT_LOOP_TIME == true
Serial.print("loop time (ms) = ");
Serial.println(millis() - timestamp);
#endif
}
#if DEBUG__PRINT_LOOP_TIME == true
else
{
Serial.println("waiting...");
}
#endif
}
And well, the code only includes the library which is for I2C communication, but there are 5 more files (.ino which is simply an .cpp) that have few functions being declared.
By just simply trying to compile the code, the following error is given:
Final_arduino_code.ino: In function ‘void read_sensors()’:
Final_arduino_code:427: error: ‘Read_Gyro’ was not declared in this scope
Final_arduino_code:428: error: ‘Read_Accel’ was not declared in this scope
Final_arduino_code:429: error: ‘Read_Magn’ was not declared in this scope
Final_arduino_code.ino: In function ‘void reset_sensor_fusion()’:
Final_arduino_code:450: error: ‘Vector_Cross_Product’ was not declared in this scope
Final_arduino_code:458: error: ‘Compass_Heading’ was not declared in this scope
Final_arduino_code:462: error: ‘init_rotation_matrix’ was not declared in this scope
Final_arduino_code.ino: In function ‘void compensate_sensor_errors()’:
Final_arduino_code:476: error: ‘Matrix_Vector_Multiply’ was not declared in this scope
Final_arduino_code.ino: In function ‘void setup()’:
Final_arduino_code:541: error: ‘I2C_Init’ was not declared in this scope
Final_arduino_code:542: error: ‘Accel_Init’ was not declared in this scope
Final_arduino_code:543: error: ‘Magn_Init’ was not declared in this scope
Final_arduino_code:544: error: ‘Gyro_Init’ was not declared in this scope
Final_arduino_code.ino: In function ‘void loop()’:
Final_arduino_code:675: error: ‘output_calibration’ was not declared in this scope
Final_arduino_code:683: error: ‘Compass_Heading’ was not declared in this scope
Final_arduino_code:684: error: ‘Matrix_update’ was not declared in this scope
Final_arduino_code:685: error: ‘Normalize’ was not declared in this scope
Final_arduino_code:686: error: ‘Drift_correction’ was not declared in this scope
Final_arduino_code:687: error: ‘Euler_angles’ was not declared in this scope
Final_arduino_code:689: error: ‘output_angles’ was not declared in this scope
Final_arduino_code:693: error: ‘output_sensors’ was not declared in this scope
Well, most of those functions have being declared in the other files in the same folder of the this main code, BUT, I have tried making a header (.h) to each of the files, just declaring the functions, it didn't work, I have tried including the files as they are, didn't work, tried to change them to .cpp and including, didn't work.
I posted as an issue to both of the github pages but still got no answer.
Please help me to fix these errors, thanks in advance.
but there are 5 more files (.ino which is simply an .cpp)
It is not that simple, they are not .cpp files. They are supposed to be built with the Ino toolkit, the project's home page is here. Judging from the compiler errors you get, you are not using this toolkit.
The core part that's missing are the .h files that the compiler normally needs to understand what functions like Read_Gyro() look like. Currently the projects you listed have no .h file and no corresponding #include directives. Not actually sure how Ino works but I'd guess it acts like a preprocessor that merges the .ino files into one big ball of source code before letting the compiler lose on it.
Using the toolkit is strongly recommended to get ahead and avoid substantial changes.
As I do not have enough reputation, I'll tell how the Guilherme Garcia da Rosa's answer put me on the right direction.
Unfortunately his contribution appears to be no longer valid with Arduino IDE 1.6.5
I managed to open the project this way :
1- Close Arduino IDE first
2- Create a directory named Final_arduino_code (maybe case sensitive)
3- Open Arduino IDE, and the sketch Final_arduino_code.ino
The IDE will automatically load all files.
The program uploaded successfully for me this way.
The original project owner "Ahmet YILDIRIM" replied to my problem and helped me to compile the project, this was his answer:
You know when you try opening an INO file, Arduino IDE asks you if you
would like to create a new folder for that specific file.
If you click yes, it seperates that file into a new folder.
If I remember correctly you should either press “No” then add other
files as new tabs. If you click “Yes”, then add other files into new
created folder and then open them all in new tabs.
I hope it helps
I 'm researching about Video Stabilization field. I implement a application using OpenCV.
My progress such as:
Surf points extraction
Matching
estimateRigidTransform
warpAffine
But the result video is not be stable. Can anyone help me this problem or provide me some source code link to improve?
Sample video: Hippo video
Here is my code [EDIT]
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/opencv.hpp>
const double smooth_level = 0.7;
using namespace cv;
using namespace std;
struct TransformParam
{
TransformParam() {}
TransformParam(double _dx, double _dy, double _da) {
dx = _dx;
dy = _dy;
da = _da;
}
double dx; // translation x
double dy; // translation y
double da; // angle
};
int main( int argc, char** argv )
{
VideoCapture cap ("test12.avi");
Mat cur, cur_grey;
Mat prev, prev_grey;
cap >> prev;
cvtColor(prev, prev_grey, COLOR_BGR2GRAY);
// Step 1 - Get previous to current frame transformation (dx, dy, da) for all frames
vector <TransformParam> prev_to_cur_transform; // previous to current
int k=1;
int max_frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
VideoWriter writeVideo ("stable.avi",0,30,cvSize(prev.cols,prev.rows),true);
Mat last_T;
double avg_dx = 0, avg_dy = 0, avg_da = 0;
Mat smooth_T(2,3,CV_64F);
while(true) {
cap >> cur;
if(cur.data == NULL) {
break;
}
cvtColor(cur, cur_grey, COLOR_BGR2GRAY);
// vector from prev to cur
vector <Point2f> prev_corner, cur_corner;
vector <Point2f> prev_corner2, cur_corner2;
vector <uchar> status;
vector <float> err;
goodFeaturesToTrack(prev_grey, prev_corner, 200, 0.01, 30);
calcOpticalFlowPyrLK(prev_grey, cur_grey, prev_corner, cur_corner, status, err);
// weed out bad matches
for(size_t i=0; i < status.size(); i++) {
if(status[i]) {
prev_corner2.push_back(prev_corner[i]);
cur_corner2.push_back(cur_corner[i]);
}
}
// translation + rotation only
Mat T = estimateRigidTransform(prev_corner2, cur_corner2, false);
// in rare cases no transform is found. We'll just use the last known good transform.
if(T.data == NULL) {
last_T.copyTo(T);
}
T.copyTo(last_T);
// decompose T
double dx = T.at<double>(0,2);
double dy = T.at<double>(1,2);
double da = atan2(T.at<double>(1,0), T.at<double>(0,0));
prev_to_cur_transform.push_back(TransformParam(dx, dy, da));
avg_dx = (avg_dx * smooth_level) + (dx * (1- smooth_level));
avg_dy = (avg_dy * smooth_level) + (dy * (1- smooth_level));
avg_da = (avg_da * smooth_level) + (da * (1- smooth_level));
smooth_T.at<double>(0,0) = cos(avg_da);
smooth_T.at<double>(0,1) = -sin(avg_da);
smooth_T.at<double>(1,0) = sin(avg_da);
smooth_T.at<double>(1,1) = cos(avg_da);
smooth_T.at<double>(0,2) = avg_dx;
smooth_T.at<double>(1,2) = avg_dy;
Mat stable;
warpAffine(prev,stable,smooth_T,prev.size());
Mat canvas = Mat::zeros(cur.rows, cur.cols*2+10, cur.type());
prev.copyTo(canvas(Range::all(), Range(0, prev.cols)));
stable.copyTo(canvas(Range::all(), Range(prev.cols+10, prev.cols*2+10)));
imshow("before and after", canvas);
waitKey(20);
writeVideo.write(stable);
cur.copyTo(prev);
cur_grey.copyTo(prev_grey);
k++;
}
}
First, you can just blur you image. It will helps a bit. Second, you can easily smooth your matrix by simplest implementation of exponential smooth A(t+1) = a*A(t)+(1-a)*A(t+1) and play with a-value in [0;1] range. Third, you can turn off some type of transformations like rotation, shift etc.
Here is code example:
t = estimateRigidTransform(new, old, 0); // 0 means not all transformations (5 of 6)
if(!t.empty()){
// t(Range(0,2), Range(0,2)) = Mat::eye(2, 2, CV_64FC1); // turning off rotation
// t.at<double>(0,2) = 0; t.at<double>(1,2) = 0; // turning off shift dx and dy
tAvrg = tAvrg*a + t*(1-a); // a - smooth level in [0;1] range, play with it
warpAffine(new, stable, tAvrg, Size(new.cols, new.rows));
}
I have line that is defined as two points.
start = (xs,ys)
end = (xe, ye)
Drawing function that I'm using Only accepts lines that are fully in screen coordinates.
Screen size is (xSize, ySize).
Top left corner is (0,0). Bottom right corner is (xSize, ySize).
Some other funcions gives me line that that is defined for example as start(-50, -15) end(5000, 200). So it's ends are outside of screen size.
In C++
struct Vec2
{
int x, y
};
Vec2 start, end //This is all little bit pseudo code
Vec2 screenSize;//You can access coordinates like start.x end.y
How can I calculate new start and endt that is at the screen edge, not outside screen.
I know how to do it on paper. But I can't transfer it to c++.
On paper I'm sershing for point that belongs to edge and line. But it is to much calculations for c++.
Can you help?
There are many line clipping algorithms like:
Cohen–Sutherland wikipedia page with implementation
Liang–Barsky wikipedia page
Nicholl–Lee–Nicholl (NLN)
and many more. see Line Clipping on wikipedia
[EDIT1]
See below figure:
there are 3 kinds of start point:
sx > 0 and sy < 0 (red line)
sx < 0 and sy > 0 (yellow line)
sx < 0 and sy < 0 (green and violet lines)
In situations 1 and 2 simply find Xintersect and Yintersect respectively and choose them as new start point.
As you can see, there are 2 kinds of lines in situation 3. In this situation find Xintersect and Yintersect and choose the intersect point near the end point which is the point that has minimum distance to endPoint.
min(distance(Xintersect, endPoint), distance(Yintersect, endPoint))
[EDIT2]
// Liang-Barsky function by Daniel White # http://www.skytopia.com/project/articles/compsci/clipping.html
// This function inputs 8 numbers, and outputs 4 new numbers (plus a boolean value to say whether the clipped line is drawn at all).
//
bool LiangBarsky (double edgeLeft, double edgeRight, double edgeBottom, double edgeTop, // Define the x/y clipping values for the border.
double x0src, double y0src, double x1src, double y1src, // Define the start and end points of the line.
double &x0clip, double &y0clip, double &x1clip, double &y1clip) // The output values, so declare these outside.
{
double t0 = 0.0; double t1 = 1.0;
double xdelta = x1src-x0src;
double ydelta = y1src-y0src;
double p,q,r;
for(int edge=0; edge<4; edge++) { // Traverse through left, right, bottom, top edges.
if (edge==0) { p = -xdelta; q = -(edgeLeft-x0src); }
if (edge==1) { p = xdelta; q = (edgeRight-x0src); }
if (edge==2) { p = -ydelta; q = -(edgeBottom-y0src);}
if (edge==3) { p = ydelta; q = (edgeTop-y0src); }
r = q/p;
if(p==0 && q<0) return false; // Don't draw line at all. (parallel line outside)
if(p<0) {
if(r>t1) return false; // Don't draw line at all.
else if(r>t0) t0=r; // Line is clipped!
} else if(p>0) {
if(r<t0) return false; // Don't draw line at all.
else if(r<t1) t1=r; // Line is clipped!
}
}
x0clip = x0src + t0*xdelta;
y0clip = y0src + t0*ydelta;
x1clip = x0src + t1*xdelta;
y1clip = y0src + t1*ydelta;
return true; // (clipped) line is drawn
}
Here is a function I wrote. It cycles through all 4 planes (left, top, right, bottom) and clips each point by the plane.
// Clips a line segment to an axis-aligned rectangle
// Returns true if clipping is successful
// Returns false if line segment lies outside the rectangle
bool clipLineToRect(int a[2], int b[2],
int xmin, int ymin, int xmax, int ymax)
{
int mins[2] = {xmin, ymin};
int maxs[2] = {xmax, ymax};
int normals[2] = {1, -1};
for (int axis=0; axis<2; axis++) {
for (int plane=0; plane<2; plane++) {
// Check both points
for (int pt=1; pt<=2; pt++) {
int* pt1 = pt==1 ? a : b;
int* pt2 = pt==1 ? b : a;
// If both points are outside the same plane, the line is
// outside the rectangle
if ( (a[0]<xmin && b[0]<xmin) || (a[0]>xmax && b[0]>xmax) ||
(a[1]<ymin && b[1]<ymin) || (a[1]>ymax && b[1]>ymax)) {
return false;
}
const int n = normals[plane];
if ( (n==1 && pt1[axis]<mins[axis]) || // check left/top plane
(n==-1 && pt1[axis]>maxs[axis]) ) { // check right/bottom plane
// Calculate interpolation factor t using ratio of signed distance
// of each point from the plane
const float p = (n==1) ? mins[axis] : maxs[axis];
const float q1 = pt1[axis];
const float q2 = pt2[axis];
const float d1 = n * (q1-p);
const float d2 = n * (q2-p);
const float t = d1 / (d1-d2);
// t should always be between 0 and 1
if (t<0 || t >1) {
return false;
}
// Interpolate to find the new point
pt1[0] = (int)(pt1[0] + (pt2[0] - pt1[0]) * t );
pt1[1] = (int)(pt1[1] + (pt2[1] - pt1[1]) * t );
}
}
}
}
return true;
}
Example Usage:
void testClipLineToRect()
{
int screenWidth = 320;
int screenHeight = 240;
int xmin=0;
int ymin=0;
int xmax=screenWidth-1;
int ymax=screenHeight-1;
int a[2] = {-10, 10};
int b[2] = {300, 250};
printf("Before clipping:\n\ta={%d, %d}\n\tb=[%d, %d]\n",
a[0], a[1], b[0], b[1]);
if (clipLineToRect(a, b, xmin, ymin, xmax, ymax)) {
printf("After clipping:\n\ta={%d, %d}\n\tb=[%d, %d]\n",
a[0], a[1], b[0], b[1]);
}
else {
printf("clipLineToRect returned false\n");
}
}
Output:
Before clipping:
a={-10, 10}
b=[300, 250]
After clipping:
a={0, 17}
b=[285, 239]