I am experimenting with cv::dft: a 1HZ sinus signal is generated, and displayed in the frequency domain. But for some reason it hasn't got the maximum component at 1Hz. My code is the following:
const int FRAME_RATE = 20; //!< sampling rate in [Hz]
const int WINDOW_SIZE = 256;
double len = double(WINDOW_SIZE)/double(FRAME_RATE); // signal length in seconds
double Fb = 1./len; // frequency bin in Hz
// Constructing frequency vector
std::vector<double> f;
double freq_step = 0;
for (int i = 0; i < WINDOW_SIZE; ++i)
{
f.push_back(freq_step);
freq_step += Fb;
}
// Create time vector
std::vector<double> t;
double time_step = 0;
for(int i = 0; i<WINDOW_SIZE; ++i)
{
t.push_back(time_step);
time_step += 1./double(FRAME_RATE);
}
// Creating sin signal with 1Hz period
std::vector<double> y;
for(auto val : t)
{
y.push_back(sin(1*FRAME_RATE*val));
}
// Compute DFT
cv::Mat fd;
cv::dft(y, fd, cv::DFT_REAL_OUTPUT);
fd = cv::abs(fd);
If I plot the signal in time and frequency domain: plot(t, y); plot(f, fd) the result is the following:
The time signal is good, but the frequency signal has maximum around 6HZ instead of 1HZ.
Where did I take the mistake?
Related
I'm trying to setup a pipeline allowing me to detect musical notes from audio samples, but the input layer where I identify the frequency content of the samples does not land on the expected values. In the example below I...
build what I expect to be a 440Hz (A4) sine wave in the FFTW input buffer
apply the Hamming window function
lookup the first half the output bins to find the 4 top values and their frequency
void GenerateSinWave(fftw_complex* outputArray, int N, double frequency, double samplingRate)
{
double sampleDurationSeconds = 1.0 / samplingRate;
for (int i = 0; i < N; ++i)
{
double sampleTime = i * sampleDurationSeconds;
outputArray[i][0] = sin(M_2_PI * frequency * sampleTime);
}
}
void HammingWindow(fftw_complex* array, int N)
{
static const double a0 = 25.0 / 46.0;
static const double a1 = 1 - a0;
for (int i = 0; i < N; ++i)
array[i][0] *= a0 - a1 * cos((M_2_PI * i) / N);
}
int main()
{
const int N = 4096;
double samplingRate = 44100;
double A4Frequency = 440;
fftw_complex in[N] = { 0 };
fftw_complex out[N] = { 0 };
fftw_plan plan = fftw_plan_dft_1d(N, 0, 0, FFTW_FORWARD, FFTW_ESTIMATE);
GenerateSinWave(in, N, A4Frequency, samplingRate);
HammingWindow(in, N);
fftw_execute_dft(plan, in, out);
// Find the 4 top values
double binHzRange = samplingRate / N;
for (int i = 0; i < 4; ++i)
{
double maxValue = 0;
int maxBin = 0;
for (int bin = 0; bin < (N/2); ++bin)
{
if (out[bin][0] > maxValue)
{
maxValue = out[bin][0];
maxBin = bin;
}
}
out[maxBin][0] = 0; // remove value for next pass
double binMidFreq = (maxBin * binHzRange) + (binHzRange / 2);
std::cout << (i + 1) << " -> Freq: " << binMidFreq << " Hz - Value: " << maxValue << "\n";
}
fftw_destroy_plan(plan);
}
I was expecting something close to 440 or lower/higher harmonics, however the results are far from that:
1 -> Freq: 48.4497Hz - Value: 110.263
2 -> Freq: 59.2163Hz - Value: 19.2777
3 -> Freq: 69.9829Hz - Value: 5.68717
4 -> Freq: 80.7495Hz - Value: 2.97571
This flow is mostly inspired by this other SO answer. I feel that my lack of knowledge about signal processing might be in cause! My sin wave generation and window function seem to be ok, but audio analysis and FFTW are full of mysteries...
Any insight about how to improve my usage of FFTW, approach signal processing or simply write better code is appreciated!
EDIT: fixed integer division leading to Hamming a0 parameter always being 0. Results changed a little, but still far of the expected 440 Hz
I think you've misunderstood the M_2_PI constant in your GenerateSinWave function. M_2_PI is defined as 2.0 / PI.
You should be using 2 * M_PI instead.
This mistake will mean that your generated signal has a frequency of only around 45 Hz. This should be close to the output frequencies you are seeing.
The same constant needs correcting in your HammingWindow function too.
I'm trying to provide a sinusoidal wave using PWM modulation.
my circuit is comprised of the following:
Arduino Uno
H bridge - controls the direction (pins 4,5) and the PWM voltage (PWM pin 6)
Solenoid motor - the sine output should be fed to the motor
I saw some guides online, but most of them use Sinewave tables and low-level code that I couldn't quite comprehend, so I have decided to give it a try with some more trivial code as followed:
const int DIR1_PIN = 4;
const int DIR2_PIN = 5;
const int PWM_PIN = 6;
const int LED_PIN = 9;
const int numSamples = 20;
const int sampleFreq = 2000;
const float pi = 3.1415;
float f = 1; // signal frequency
float T = 1/f;
float dt = T/numSamples;
int sineSignal[numSamples]; // sine values would be added here
int dir1Array[numSamples]; // 11....100....0 indicates direction
int dir2Array[numSamples]; // 00....011....1 indicates other direction
void setup()
{
pinMode(LED_PIN, OUTPUT); // the led is just an indicator to what the output is
pinMode(DIR1_PIN, OUTPUT);
pinMode(DIR2_PIN, OUTPUT);
pinMode(PWM_PIN, OUTPUT);
for (int n = 0; n < numSamples; n++)
{
sineSignal[n] = abs((int) (255 * (sin(2 * pi * f * n * dt))));
if (n < numSamples / 2)
{
dir1Array[n] = HIGH;
dir2Array[n] = LOW;
}
else
{
dir1Array[n] = LOW;
dir2Array[n] = HIGH;
}
}
}
void loop()
{
for (int n = 0; n < numSamples; n++)
{
analogWrite(LED_PIN, sineSignal[n]);
analogWrite(PWM_PIN, sineSignal[n]);
digitalWrite(DIR1_PIN, dir1Array[n]);
digitalWrite(DIR2_PIN, dir2Array[n]);
delay(sampleFreq); // not quite sure how the delay affects the frequency f
}
}
long story short, this code does not allow me to control the frequency f (getting the same output for different values of f)
any Idea on how to generate such output for varying f? how should one set up a delay call, if even?
Thank you!
I am reading my hand pose from a Leap Motion sensor and I want to calculate how fast the hand moves (by calculating derivativex = dx / dt) in X direction. My solution is to put 100 hand pose values in an array and keep updating this array with new values when new messages (msg->palmpos.x) arrive in the callback function through topic leapmotion/data.
My question is when I print the derivativex = dx / dt with ROS_ERROR("Hello %f", "derivativex") the output is always: 0
what I've been doing wrong? link for the topic that my callback is listening.
my call back function:
#include "geometry_msgs/TwistStamped.h"
#include "jog_msgs/JogJoint.h"
#include "jog_msgs/leapros.h"
#include "ros/ros.h"
#include <ros/console.h>
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;
namespace to_twist
{
class spaceNavToTwist
{
public:
spaceNavToTwist() : spinner_(1)
{
joy_sub_ = n_.subscribe("leapmotion/data", 1, &spaceNavToTwist::joyCallback, this);
// Changed "spacenav/joy" to topic "/leapmotion/data"
twist_pub_ = n_.advertise<geometry_msgs::TwistStamped>("jog_arm_server/delta_jog_cmds", 1);
joint_delta_pub_ = n_.advertise<jog_msgs::JogJoint>("jog_arm_server/joint_delta_jog_cmds", 1);
spinner_.start();
ros::waitForShutdown();
};
const int arraySize = 100;// constant variable can be used to specify array size
double vectorx[ arraySize ] = {};// initialize elements of array n to 0
int resolution = 10;
double derivativex = 0;
double dx = 0;
int dt = 0;
private:
ros::NodeHandle n_;
ros::Subscriber joy_sub_;
ros::Publisher twist_pub_, joint_delta_pub_;
ros::AsyncSpinner spinner_;
// Convert incoming joy commands to TwistStamped commands for jogging.
void joyCallback(const jog_msgs::leapros::ConstPtr& msg)
{
for ( int count = 0; count < arraySize; ++count ) {// store the values of poses
vectorx[ count ] = msg->palmpos.x;
if (count>resolution) {
dx = vectorx[ count-1 ] - vectorx[ count-(resolution-1) ];
dt = resolution;
derivativex = dx / dt;
ROS_ERROR("Hello %f", derivativex);
}
if (count == arraySize) {
count=0;
}
}
Issue 1: The log function ROS_ERROR is misused. You should pass a float instead of a string, otherwise, you will get an undefined behavior :
ROS_ERROR("Hello %f", derivativex); // <-- there is no double quotes.
Issue 2: derivative of X is always 0 because of the assignment at the beginning of the for loop:
for ( int count = 0; count < arraySize; ++count ) {// store the values of poses
//Could you please explain why the program needs this ???
vectorx[ count ] = msg->palmpos.x; // <-- every element in vectorx is set to this values (const in each function call).
if (count>resolution) {
dx = vectorx[ count-1 ] - vectorx[ count-(resolution-1) ]; // is the same as (msg->palmpos.x - msg->palmpos.x) --> 0
dt = resolution;
derivativex = dx / dt;
ROS_ERROR("Hello %f", derivativex);
}
if (count == arraySize) {
count = 0; //<-- never get here because of count is always lesser than arraySize
}
}
I guess that you want to append msg->palmpos.x to the vectorx ? You should use std::vector for vectorx, it will be much easier.
Here is the modified version of your program, using std::vector :
//add this to your file
#include <vector>
//Your program body ...
//...
//As we are using C++, try to use C++ facilities if possible.
//const int arraySize = 100;// constant variable can be used to specify array size
//double vectorx[ arraySize ] = {};// initialize elements of array n to 0
std::vector<double> vectorx;
int resolution = 10;
int max_vector_size = 100; //keep 100 elements in the vectorx.
//...
// Convert incoming joy commands to TwistStamped commands for jogging.
void joyCallback(const jog_msgs::leapros::ConstPtr& msg)
{
//store the x coordinate in the vectorx
vectorx.push_back( msg->palmpos.x );
if( vectorx.size() > resolution ){
int id_back = vectorx.size() - 1;
double dx = vectorx[id_back] - vectorx[ id_back - resolution ];
double dt = resolution;
derivativex = dx / dt;
ROS_ERROR("Hello %f", derivativex);
}
while(vectorx.size() > max_vector_size ) {
vectorx.erase( vectorx.begin() ); //remove the first element
}
}//eof joyCallback
I needed to make a meters counter for a work thing, so I decided to just Arduino for it. I found an old encoder, found/wrote a simple code and hacked it all together and encountered a unexpected problem.
For some reason my counter won't count past around 8 meters or 31991 encoder pulses. Once it reaches this 8m limit, the number turns negative and starts counting backwards like -7.9 > -7.8 (i.e. continues counting upward towards 0).
Then it reaches zero and again counts to 8...
This is very strange to me and my limited coding knowledge can't fix it.
Does anyone know how to fix this or what I could do to make it work?
#include <LiquidCrystal.h>
#define inputA_in 6
#define inputB_in 7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int inputA_V = 0;
int inputB_V = 0;
int inputA = 0;
int inputB = 0;
int counter = 0;
// smeni vrednost tuka pred run
int console_frequency_milliseconds = 200; /// edna sekunda
int aLastState = 0;
int bLastState = 0;
float meters = 0.0;
unsigned long lasttime = 0;
int move_positive = 0;
int move_negative = 0;
int maximum_input_digital_v = 300; //treba da citash od konzola i da gi setirash max i min
int minimum_input_digital_v = 0;
int logical_threshold_v = 150; //brojkive se random staveni
void setup() {
pinMode (inputA_in, INPUT);
pinMode (inputB_in, INPUT);
Serial.begin (9600);
lcd.begin(16, 2);
// Print a message to the LCD
lcd.print("Metraza [m]");
aLastState = inputA;
bLastState = inputB;
lasttime = 0;
}
void loop () {
inputA = digitalRead(inputA_in);
if (inputA != aLastState) {
if (digitalRead(inputB_in) != inputA) {
counter ++;
aLastState = inputA;
} else {
counter --;
aLastState = inputA;
}
}
if (millis() - console_frequency_milliseconds > lasttime)//Detect once every 150ms
{
meters = 0.50014 * counter / 2000;
Serial.print("Position: ");
Serial.println(meters);
lasttime = millis();
lcd.setCursor(0, 1);
//Print a message to second line of LCD
lcd.print(meters);
}
}
Your counter is a simple int,
int counter = 0;
It seems that on your system they are only 16bit wide (with a maximum value of 32767), not surprising.
Use
long int counter = 0;
to get wider variables.
You might also want to change the calculation from
meters = 0.50014 * counter / 2000;
to
meters = 0.50014 * counter / 2000.0;
to avoid losing precision and range. Even with an int that would extend your range from 31991 encoder pulses to 32757 encoder pulses; and analog for the wider range.
You might also like to try changing the counter to an unsigned int or unsigned long int. I did not analyse your whole code, but I think you do not have anything which relies on representation of negative numbers. So you probably could double the range again. But no guarantees, subject to testing.
I have a program that solves generally for 1D brownian motion using an Euler's Method.
Being a stochastic process, I want to average it over many particles. But I find that as I ramp up the number of particles, it overloads and i get the std::badalloc error, which I understand is a memory error.
Here is my full code
#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <ctime>
using namespace std;
// Box-Muller Method to generate gaussian numbers
double generateGaussianNoise(double mu, double sigma) {
const double epsilon = std::numeric_limits<double>::min();
const double tau = 2.0 * 3.14159265358979323846;
static double z0, z1;
static bool generate;
generate = !generate;
if (!generate) return z1 * sigma + mu;
double u1, u2;
do {
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
} while (u1 <= epsilon);
z0 = sqrt(-2.0 * log(u1)) * cos(tau * u2);
z1 = sqrt(-2.0 * log(u1)) * sin(tau * u2);
return z0 * sigma + mu;
}
int main() {
// Initialize Variables
double gg; // Gaussian Number Picked from distribution
// Integrator
double t0 = 0; // Setting the Time Window
double tf = 10;
double n = 5000; // Number of Steps
double h = (tf - t0) / n; // Time Step Size
// Set Constants
const double pii = atan(1) * 4; // pi
const double eta = 1; // viscous constant
const double m = 1; // mass
const double aa = 1; // radius
const double Temp = 30; // Temperature in Kelvins
const double KB = 1; // Boltzmann Constant
const double alpha = (6 * pii * eta * aa);
// More Constants
const double mu = 0; // Gaussian Mean
const double sigma = 1; // Gaussian Std Deviation
const double ng = n; // No. of pts to generate for Gauss distribution
const double npart = 1000; // No. of Particles
// Initial Conditions
double x0 = 0;
double y0 = 0;
double t = t0;
// Vectors
vector<double> storX; // Vector that keeps displacement values
vector<double> storY; // Vector that keeps velocity values
vector<double> storT; // Vector to store time
vector<double> storeGaussian; // Vector to store Gaussian numbers generated
vector<double> holder; // Placeholder Vector for calculation operations
vector<double> mainstore; // Vector that holds the final value desired
storT.push_back(t0);
// Prepares mainstore
for (int z = 0; z < (n+1); z++) {
mainstore.push_back(0);
}
for (int NN = 0; NN < npart; NN++) {
holder.clear();
storX.clear();
storY.clear();
storT.clear();
storT.push_back(0);
// Prepares holder
for (int z = 0; z < (n+1); z++) {
holder.push_back(0);
storX.push_back(0);
storY.push_back(0);
}
// Gaussian Generator
srand(time(NULL));
for (double iiii = 0; iiii < ng; iiii++) {
gg = generateGaussianNoise(0, 1); // generateGaussianNoise(mu,sigma)
storeGaussian.push_back(gg);
}
// Solver
for (int ii = 0; ii < n; ii++) {
storY[ii + 1] =
storY[ii] - (alpha / m) * storY[ii] * h +
(sqrt(2 * alpha * KB * Temp) / m) * sqrt(h) * storeGaussian[ii];
storX[ii + 1] = storX[ii] + storY[ii] * h;
holder[ii + 1] =
pow(storX[ii + 1], 2); // Finds the displacement squared
t = t + h;
storT.push_back(t);
}
// Updates the Main Storage
for (int z = 0; z < storX.size(); z++) {
mainstore[z] = mainstore[z] + holder[z];
}
}
// Average over the number of particles
for (int z = 0; z < storX.size(); z++) {
mainstore[z] = mainstore[z] / (npart);
}
// Outputs the data
ofstream fout("LangevinEulerTest.txt");
for (int jj = 0; jj < storX.size(); jj++) {
fout << storT[jj] << '\t' << mainstore[jj] << '\t' << storX[jj] << endl;
}
return 0;
}
As you can see, npart is the variable that I change to vary the number of particles. But after each iteration, I do clear my storage vectors like storX,storY... So on paper, the number of particles should not affect memory? I am only just calling the compiler to repeat many more times, and add onto the main storage vector mainstore. I am running my code on a computer with 4GB ram.
Would greatly appreciate it if anyone could point out my errors in logic or suggest improvements.
Edit: Currently the number of particles is set to npart = 1000.
So when I try to ramp it up to like npart = 20000 or npart = 50000, it gives me memory errors.
Edit2 I've edited the code to allocate an extra index to each of the storage vectors. But it does not seem to fix the memory overflow
There is an out of bounds exception in the solver part. storY has size n and you access ii+1 where i goes up to n-1. So for your code provided. storY has size 5000. It is allowed to access with indices between 0 and 4999 (including) but you try to access with index 5000. The same for storX, holder and mainstore.
Also, storeGaussian does not get cleared before adding new variables. It grows by n for each npart loop. You access only the first n values of it in the solver part anyway.
Please note, that vector::clear removes all elements from the vector, but does not necessarily change the vector's capacity (i.e. it's storage array), see the documentation.
This won't cause the problem here, because you'll reuse the same array in the next runs, but it's something to be aware when using vectors.