Deallocate and reallocate memory. Resetting Polygon in FLTK - memory

#include "Simple_window.h"
#include "Graph.h"
#include <math.h>
#include <iostream>
#include <limits>
using namespace std;
int main(){
Simple_window win(Point(100,100),600,400,"Marks");
Graph_lib::Polygon poly;
bool over = true;
int n = 0;
while(over){
Marks pp("x");
pp.add(Point(300,200));
cout<<"Enter number of sides (3 or more): ";
while(!(cin>>n)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"Enter number of sides (3 or more): ";
}
if(n<3){
break;
}
//Finding the angle and number of sides...
if(n%2 != 0){
//logic for polygon...
}
}else{
//logic for polygon...
}
}
poly.set_color(Color::magenta); // adjust properties of poly
win.attach (poly); // connect poly to the window
win.attach(pp);
win.wait_for_button(); // Display!
}
}
What does this program does it make n-sided polygons. After I set my polygon. I wish to reset it. After i enter the amount of sides in a polygon. I click on "next" it will ask me how many polygons again and repeat the process. Someone told me to call delete. However I'm not sure how I would type that in. As in delete poly.points? or delete polygon ? I tried a few but I kept getting errors.
My second question is on line 38. Originally I had it so If i entered a number less than 3 the program will end. But the program won't end. So i had to use break;
if(n<3){
over=false;
cout<<"why wont this end ?"<<endl;
}
boolean over is set to true. While true loop. If n < 3 over is false. thus end the program? it Wont end.

There is no need to reset the poly if you stick the declaration inside the first while loop.
while(over){
Graph_lib::Polygon poly;
...
win.wait_for_button();
}
Re: why your program won't end. Break is good enough but if you don't like using break
use continue
put the rest of the loop body in an else clause
Edit: Re: changing the title: I don't know the Simpe_Window interface: it is not part of FLTK - it is a Stroustrup creation. If it is derived from FL_Window, use label(new title).

Related

STM32 - Reading I2S to record a .WAV file. Audio choppy, what is causing it?

I'm using an STM32 (STM32F446RE) to receive audio from two INMP441 mems microphone in an stereo setup via I2S protocol and record it into a .WAV on a micro SD card, using the HAL library.
I wrote the firmware that records audio into a .WAV with FreeRTOS. But the audio files that I record sound like Darth Vader. Here is a screenshot of the audio in audacity:
if you zoom in you can see a constant noise being inserted in between the real audio data:
I don't know what is causing this.
I have tried increasing the MessageQueue, but that doesnt seem to be the problem, the queue is kept at 0 most of the time. I've tried different frame sizes and sampling rates, changing the number of channels, using only one inmp441. All this without any success.
I proceed explaining the firmware.
Here is a block diagram of the architecture for the RTOS that I have implemented:
It consists of three tasks. The first one receives a command via UART (with interrupts) that signals to start or stop recording. the second one is simply an state machine that walks through the steps to write a .WAV.
Here the code for the WriteWavFileTask:
switch(audio_state)
{
case STATE_START_RECORDING:
sprintf(filename, "%saud_%03d.wav", SDPath, count++);
do
{
res = f_open(&file_ptr, filename, FA_CREATE_ALWAYS|FA_WRITE);
}
while(res != FR_OK);
res = fwrite_wav_header(&file_ptr, I2S_SAMPLE_FREQUENCY, I2S_FRAME, 2);
HAL_I2S_Receive_DMA(&hi2s2, aud_buf, READ_SIZE);
audio_state = STATE_RECORDING;
break;
case STATE_RECORDING:
osDelay(50);
break;
case STATE_STOP:
HAL_I2S_DMAStop(&hi2s2);
while(osMessageQueueGetCount(AudioQueueHandle)) osDelay(1000);
filesize = f_size(&file_ptr);
data_len = filesize - 44;
total_len = filesize - 8;
f_lseek(&file_ptr, 4);
f_write(&file_ptr, (uint8_t*)&total_len, 4, bw);
f_lseek(&file_ptr, 40);
f_write(&file_ptr, (uint8_t*)&data_len, 4, bw);
f_close(&file_ptr);
audio_state = STATE_IDLE;
break;
case STATE_IDLE:
osThreadSuspend(WAVHandle);
audio_state = STATE_START_RECORDING;
break;
default:
osDelay(50);
break;
Here are the macros used in the code for readability:
#define I2S_DATA_WORD_LENGTH (24) // industry-standard 24-bit I2S
#define I2S_FRAME (32) // bits per sample
#define READ_SIZE (128) // samples to read from I2S
#define WRITE_SIZE (READ_SIZE*I2S_FRAME/16) // half words to write
#define WRITE_SIZE_BYTES (WRITE_SIZE*2) // bytes to write
#define I2S_SAMPLE_FREQUENCY (16000) // sample frequency
The last task is the responsible for processing the buffer received via I2S. Here is the code:
void convert_endianness(uint32_t *array, uint16_t Size) {
for (int i = 0; i < Size; i++) {
array[i] = __REV(array[i]);
}
}
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
convert_endianness((uint32_t *)aud_buf, READ_SIZE);
osMessageQueuePut(AudioQueueHandle, aud_buf, 0L, 0);
HAL_I2S_Receive_DMA(hi2s, aud_buf, READ_SIZE);
}
void pvrWriteAudioTask(void *argument)
{
/* USER CODE BEGIN pvrWriteAudioTask */
static UINT *bw;
static uint16_t aud_ptr[WRITE_SIZE];
/* Infinite loop */
for(;;)
{
osMessageQueueGet(AudioQueueHandle, aud_ptr, 0L, osWaitForever);
res = f_write(&file_ptr, aud_ptr, WRITE_SIZE_BYTES, bw);
}
/* USER CODE END pvrWriteAudioTask */
}
This tasks reads from a queue an array of 256 uint16_t elements containing the raw audio data in PCM. f_write takes the Size parameter in number of bytes to write to the SD card, so 512 bytes. The I2S Receives 128 frames (for a 32 bit frame, 128 words).
The following is the configuration for the I2S and clocks:
Any help would be much appreciated!
Solution
As pmacfarlane pointed out, the problem was with the method used for buffering the audio data. The solution consisted of easing the overhead on the ISR and implementing a circular DMA for double buffering. Here is the code:
#define I2S_DATA_WORD_LENGTH (24) // industry-standard 24-bit I2S
#define I2S_FRAME (32) // bits per sample
#define READ_SIZE (128) // samples to read from I2S
#define BUFFER_SIZE (READ_SIZE*I2S_FRAME/16) // number of uint16_t elements expected
#define WRITE_SIZE_BYTES (BUFFER_SIZE*2) // bytes to write
#define I2S_SAMPLE_FREQUENCY (16000) // sample frequency
uint16_t aud_buf[2*BUFFER_SIZE]; // Double buffering
static volatile int16_t *BufPtr;
void convert_endianness(uint32_t *array, uint16_t Size) {
for (int i = 0; i < Size; i++) {
array[i] = __REV(array[i]);
}
}
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
BufPtr = aud_buf;
osSemaphoreRelease(RxAudioSemHandle);
}
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
BufPtr = &aud_buf[BUFFER_SIZE];
osSemaphoreRelease(RxAudioSemHandle);
}
void pvrWriteAudioTask(void *argument)
{
/* USER CODE BEGIN pvrWriteAudioTask */
static UINT *bw;
/* Infinite loop */
for(;;)
{
osSemaphoreAcquire(RxAudioSemHandle, osWaitForever);
convert_endianness((uint32_t *)BufPtr, READ_SIZE);
res = f_write(&file_ptr, BufPtr, WRITE_SIZE_BYTES, bw);
}
/* USER CODE END pvrWriteAudioTask */
}
Problems
I think the problem is your method of buffering the audio data - mainly in this function:
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
convert_endianness((uint32_t *)aud_buf, READ_SIZE);
osMessageQueuePut(AudioQueueHandle, aud_buf, 0L, 0);
HAL_I2S_Receive_DMA(hi2s, aud_buf, READ_SIZE);
}
The main problem is that you are re-using the same buffer each time. You have queued a message to save aud_buf to the SD-card, but you've also instructed the I2S to start DMAing data into that same buffer, before it has been saved. You'll end up saving some kind of mish-mash of "old" data and "new" data.
#Flexz pointed out that the message queue takes a copy of the data, so there is no issue about the I2S writing over the data that is being written to the SD-card. However, taking the copy (in an ISR) adds overhead, and delays the start of the new I2S DMA.
Another problem is that you are doing the endian conversion in this function (that is called from an ISR). This will block any other (lower priority) interrupts from being serviced while this happens, which is a bad thing in an embedded system. You should do the endian conversion in the task that reads from the queue. ISRs should be very short and do the minimum possible work (often just setting a flag, giving a semaphore, or adding something to a queue).
Lastly, while you are doing the endian conversion, what is happening to audio samples? The previous DMA has completed, and you haven't started a new one, so they will just be dropped on the floor.
Possible solution
You probably want to allocate a suitably big buffer, and configure your DMA to work in circular buffer mode. This means that once started, the DMA will continue forever (until you stop it), so you'll never drop any samples. There won't be any gap between one DMA finishing and a new one starting, since you never need to start a new one.
The DMA provides a "half-complete" interrupt, to say when it has filled half the buffer. So start the DMA, and when you get the half-complete interrupt, queue up the first half of the buffer to be saved. When you get the fully-complete interrupt, queue up the second half of the buffer to be saved. Rinse and repeat.
You might want to add some logic to detect if the interrupt happens before the previous save has completed, since the data will be overrun and possibly corrupted. Depending on the speed of the SD-card (and the sample rate), this may or may not be a problem.

1 000 000 000 000 000 000 th fibonacci number

The problem is Get Under 1,000,000,000,000,000,000th fibonacci number%1,000,000
#include <iostream>
#define fibo(a,b) {long long c=b;b=a;a=(b+c)%1000000;}
using namespace std;
int main(){
long long a=1,b=0; //two num
long long pa,pb,n,k,arr[2][1000]; //last two num,input,input<=2^k
cin>>n;
arr[0][0]=n/2;arr[1][0]=n%2;
for(unsigned long long i=1;n>3;i++){
arr[0][i]=arr[0][i-1]/2;
arr[1][i]=arr[0][i-1]%2;
if(arr[0][i]==1){
k=i;
break;
}
}
if(n<=3){ //special occasions
switch(n){
case 0:cout<<"0"<<endl;break;
case 3:cout<<"2"<<endl;break;
default:cout<<"1"<<endl;
}
return 0;
}
while(k>=0){ //calc
pa=a;pb=b;
a=((pa+pb*2)*pa)%1000000; //F(2n)=(F(n)+F(n-1)*2)*F(n)
b=(pa*pa+pb*pb)%1000000; //F(2n-1)=F(n)^2+F(n-1)^2
if(arr[1][k--]==1){fibo(a,b);} //F(n+1)=F(n)+F(n-1)
}
cout<<a<<endl;
return 0;
}
when is it wrong?
And why is it wrong?
I can't find different occasion.
An alternative approach you could consider using here is the fact that there are only 1,000,000 possible remainders for Fibonacci numbers, so if you were to compute the first 1,000,001 Fibonacci numbers, at some point you would find that the numbers would start to go in a cycle. So consider the following approach:
Compute the first 1,000,001 Fibonacci numbers.
The numbers will eventually enter a cycle. Determine how many steps k are needed to enter the cycle and how long l the cycle is.
The 1,000,000,000,000,000,000th Fibonacci number, mod 1,000,000, can be found by determining what position the 1,000,000,000,000,000,000th Fibonacci number would end up in the cycle, which is the ((1,000,000,000,000,000,000 - k) % l)th position. So look at that position and output the entry there.

how can i draw lines using mouseclick in opencv in a webcam frame?

I want to draw a line using mouse-event in Opencv in a webcam frame. I also want to erase it just like an eraser in MS-Paint.How can i do it? I dont have much idea about it. But i have this scrambled pseduo code from my head which can be completely wrong but i will write it down anyway. I would like to know how to implement it in c++.
So, i will have two three mouse event-
event 1- Mouse leftbuttonup-- this will be used to start the drawing
event 2- Mouse move -- this will be used to move the mouse to draw
event 3:- Mouse leftbuttondown-this will be used to stop the drawing.
event 4- Mouse double click - this event i can use to erase the drawing.
I will also have a drawfunction for a line such as line(Mat image,Point(startx,starty),Point(endx,endy),(0,0,255),1));
Now, i dont know how to implement this in a code format. I tried a lot but i get wrong results. I have a sincere request that please suggest me the code in Mat format not the Iplimage format. Thanks.
please find working code below with inlined explained comments using Mat ;)
Let me know in case of any problem.
PS: In main function, I have changed defauld cam id to 1 for my code, you should keep it suitable for you PC, probably 0. Good Luck.
#include <iostream>
#include <opencv\cv.h>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
class WebCamPaint
{
public:
int cam_id;
std::string win_name;
cv::VideoCapture webCam;
cv::Size frame_size;
cv::Mat cam_frame, drawing_canvas;
cv::Point current_pointer, last_pointer;
cv::Scalar erase_color, paint_color;
int pointer_size;
//! Contructor to initialize basic members to defaults
WebCamPaint()
{
cam_id = 0;
pointer_size = 5;
win_name = std::string("CamView");
current_pointer = last_pointer = cv::Point(0, 0);
erase_color = cv::Scalar(0, 0, 0);
paint_color = cv::Scalar(250, 10, 10);
}
//! init function is required to set some members in case default members needed to change.
bool init()
{
//! Opening cam with specified cam id
webCam.open(cam_id);
//! Check if problem opening video
if (!webCam.isOpened())
{
return false;
}
//! Reading single frame and extracting properties
webCam >> cam_frame;
//! Check if problem reading video
if (cam_frame.empty())
{
return false;
}
frame_size = cam_frame.size();
drawing_canvas = cv::Mat(frame_size, CV_8UC3);
//! Creating Activity / Interface window
cv::namedWindow(win_name);
cv::imshow(win_name, cam_frame);
//! Resetting drawing canvas
drawing_canvas = erase_color;
//! initialization went successful ;)
return true;
}
//! This function deals wih all processing, drawing and displaying ie main UI to user
void startAcivity()
{
//! Keep doing until user presses "Esc" from Keyboard, wait for 20ms for user input
for (char user_input = cv::waitKey(20); user_input != 27; user_input = cv::waitKey(20))
{
webCam >> cam_frame; //Read a frame from webcam
cam_frame |= drawing_canvas; //Merge with actual drawing canvas or drawing pad, try different operation to merge incase you want different effect or solid effect
cv::imshow(win_name, cam_frame); //Display the image to user
//! Change size of pointer using keyboard + / -, don't they sound fun ;)
if (user_input == '+' && pointer_size < 25)
{
pointer_size++;
}
else if (user_input == '-' && pointer_size > 1)
{
pointer_size--;
}
}
}
//! Our function that should be registered in main to opencv Mouse Event Callback
static void onMouseCallback(int event, int x, int y, int flags, void* userdata)
{
/* NOTE: As it will be registered as mouse callback function, so this function will be called if anything happens with mouse
* event : mouse button event
* x, y : position of mouse-pointer relative to the window
* flags : current status of mouse button ie if left / right / middle button is down
* userdata: pointer o any data that can be supplied at time of setting callback,
* we are using here to tell this static function about the this / object pointer at which it should operate
*/
WebCamPaint *object = (WebCamPaint*)userdata;
object->last_pointer = object->current_pointer;
object->current_pointer = cv::Point(x, y);
//! Drawing a line on drawing canvas if left button is down
if (event == 1 || flags == 1)
{
cv::line(object->drawing_canvas, object->last_pointer, object->current_pointer, object->paint_color, object->pointer_size);
}
//! Drawing a line on drawing canvas if right button is down
if (event == 2 || flags == 2)
{
cv::line(object->drawing_canvas, object->last_pointer, object->current_pointer, object->erase_color, object->pointer_size);
}
}
};
int main(int argc, char *argv[])
{
WebCamPaint myCam;
myCam.cam_id = 1;
myCam.init();
cv::setMouseCallback(myCam.win_name, WebCamPaint::onMouseCallback, &myCam);
myCam.startAcivity();
return 0;
}

OpenCV VideoCapture reading issue

This will probably be a dumb question, but i really can't figure it out.
First of all: sorry for the vague title, i'm not really sure about how to describe my problem in a couple of words.
I'm using OpenCV 2.4.3 in MS Visual Studio, C++. I'm using the VideoCapture interface for capturing frames from my laptop webcam.
What my program should do is:
Loop on different poses of the user, for each pose:
wait that the user is in position (a getchar() waits for an input that says "i'm in position" by simply hitting enter)
read the current frame
extract a region of intrest from that frame
save the image in the ROI and then label it
Here is the code:
int main() {
Mat img, face_img, img_start;
Rect *face;
VideoCapture cam(0);
ofstream fout("dataset/dataset.txt");
if(!fout) {
cout<<"Cannot open dataset file! Aborting"<<endl;
return 1;
}
int count = 0; // Number of the (last + 1) image in the dataset
// Orientations are: 0°, +/- 30°, +/- 60°, +/-90°
// Distances are just two, for now
// So it is 7x2 images
cam.read(img_start);
IplImage image = img_start;
face = face_detector(image);
if(!face) {
cout<<"No face detected..? Aborting."<<endl;
return 2;
}
// Double ROI dimensions
face->x = face->x-face->width / 2;
face->y = face->y-face->height / 2;
face->width *= 2;
face->height *=2;
for(unsigned i=0;i<14;++i) {
// Wait for the user to get in position
getchar();
// Get the face ROI
cam.read(img);
face_img = Mat(img, *face);
// Save it
stringstream sstm;
string fname;
sstm << "dataset/image" << (count+i) << ".jpeg";
fname = sstm.str();
imwrite(fname,face_img);
//do some other things..
What i expect from it:
i stand in front of the camera when the program starts and it gets the ROI rectangle using the face_detector() function
when i'm ready, say in pose0, i hit enter and a picture is taken
from that picture a subimage is extracted and it is saved as image0.jpeg
loop this 7 times
What it does:
i stand in front of the camera when the program starts, nothing special here
i hit enter
the ROI is extracted not from the picture taken in that moment, but from the first one
At first, i used img in every cam.capture(), then i changed the first one in cam.capture(img_start) but that didn't help.
The second iteration of my code saves the image that should have been saved in the 1st, the 3rd iteration the one that should have been saved in the 2nd and so on.
I'm probably missing someting important from the VideoCapture, but i really can't figure it out, so here i am.
Thanks for any help, i really appreciate it.
The problem with your implementation is that the camera is not running freely and capturing images in real time. When you start up the camera, the videocapture buffer is filled up while waiting for you to read in the frames. Once the buffer is full, it doesn't drop old frames for new ones until you read and free up space in it.
The solution would be to have a separate capture thread, in addition to your "process" thread. The capture thread keeps reading in frames from the buffer whenever a new frame comes in and stores it in a "recent frame" image object. When the process thread needs the most recent frame (i.e. when you hit Enter), it locks a mutex for thread safety, copies the most recent frame into another object and frees the mutex so that the capture thread continues reading in new frames.
#include <iostream>
#include <stdio.h>
#include <thread>
#include <mutex>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void camCapture(VideoCapture cap, Mat* frame, bool* Capture){
while (*Capture==true) {
cap >> *frame;
}
cout << "camCapture finished\n";
return;
}
int main() {
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
Mat *frame, SFI, Input;
frame = new Mat;
bool *Capture = new bool;
*Capture = true;
//your capture thread has started
thread captureThread(camCapture, cap, frame, Capture);
mtx.lock();
imshow(*frame,current_frame);
mtx.unlock();
//Terminate the thread
mtx.lock();
*Capture = false;
mtx.unlock();
captureThread.join();
return 0;
}
This is the code that I wrote from the above advice. I hope someone can get help from this.
When you are capturing the image continuously, no captured frame will be stored in the opencv buffer, such that there will be no lag in streaming.
If you take screenshot/capture image with some time gap inbetween, the captured image will be first stored in the opencv buffer, after that the image is retrieved from the buffer.
When the buffer is full, when you are calling captureObject >> matObject, the last frame from the image is returned, not the current frame in the capturecard/webcam.
So only you are seeing a lag in your code. This issue can be resolved by taking screenshot based on the frames per second (fps) value of the webcam and time taken to capture the screenshot.
The time taken to read frame from buffer is very less, Measure the time taken to take the screenshot. If it is lesser than the fps we can assume that is read from buffer else it means it is captured from webcam.
Sample Code:
For capturing a recent screenshot from webcam.
#include <opencv2/opencv.hpp>
#include <time.h>
#include <thread>
#include <chrono>
using namespace std;
using namespace cv;
int main()
{
struct timespec start, end;
VideoCapture cap(-1); // first available webcam
Mat screenshot;
double diff = 1000;
double fps = ((double)cap.get(CV_CAP_PROP_FPS))/1000;
while (true)
{
clock_gettime(CLOCK_MONOTONIC, &start);
//camera.grab();
cap.grab();// can also use cin >> screenshot;
clock_gettime(CLOCK_MONOTONIC, &end);
diff = (end.tv_sec - start.tv_sec)*1e9;
diff = (diff + (end.tv_nsec - start.tv_nsec))*1e-9;
std::cout << "\n diff time " << diff << '\n';
if(diff > fps)
{
break;
}
}
cap >> screenshot; // gets recent frame, can also use cap.retrieve(screenshot);
// process(screenshot)
cap.release();
screenshot.release();
return 0;
}

Distance between 2 arduino's using rf links

I currently have a setup where I send a char using a Tx of 434MHz and an Uno to a Mega with a Rx. The Mega counts how many times it receives the char and then if it falls below a certain number it triggers an alarm. Is this a viable way to measure the distance between two microcontrollers while indoors or is there a better way.
Transmitter (Mega)
#include <SoftwareSerial.h>
int rxPin=2; //Goes to the Receiver Pin
int txPin=5; //Make sure it is set to pin 5 going to input of receiver
SoftwareSerial txSerial = SoftwareSerial(rxPin, txPin);
SoftwareSerial rxSerial = SoftwareSerial(txPin, rxPin);
char sendChar ='H';
void setup() {
pinMode(rxPin, INPUT);
pinMode(txPin,OUTPUT);
txSerial.begin(2400);
rxSerial.begin(2400);
}
void loop() {
txSerial.println(sendChar);
Serial.print(sendChar);
}
Receiver
#include <SoftwareSerial.h>
//Make sure it is set to pin 5 going to the data input of the transmitter
int rxPin=5;
int txPin=3; //Don't need to make connections
int LED=13;
int BUZZ=9;
int t=0;
char incomingChar = 0;
int counter = 0;
SoftwareSerial rxSerial = SoftwareSerial(rxPin, txPin);
void setup() {
pinMode(rxPin, INPUT); //initilize rxpin as input
pinMode(BUZZ, OUTPUT); //initilize buzz for output
pinMode(LED, OUTPUT); //initilize led for output
rxSerial.begin(2400); //set baud rate for transmission
Serial.begin(2400); //see above
}
void loop() {
for(int i=0; i<200; i++) {
incomingChar = rxSerial.read(); //read incoming msg from tx
if (incomingChar =='H') {
counter++; //if we get bit "h" count it
}
delay(5); //delay of 10 secs
}
Serial.println(incomingChar);
Serial.println(counter); //prints the the bits we recieved
if(counter<55) {
//if we receive less than 100 bits than print out of range triggers alarm
Serial.println("out of range");
tone(BUZZ,5000,500);digitalWrite(LED,HIGH);
}
else {
noTone(BUZZ);digitalWrite(LED, LOW);
//if we get more than 100 bits than we are within range turn off alarm
Serial.println("in range");
}
counter = 0;
incomingChar=0;
}
In theory you could achieve distance measuring by making the uno send a message which the mega would echo back. That would give the uno a round-trip time for message propagation between the arduinos. You would have to approximate the processing delays. After that it is basic physics. That is basically the same as how radar works. The actual delay would be something like
troundtrip = tuno send + 2*tpropagation + tmega receive + tmega send + tuno receive
I am guessing the distance you are trying to achieve is in the order of meters. Required resolution is going to be an issue, because s = vt => t = s/v, where s is the distance between your arduinos and v = c in case of radio waves. As the transmission delays should stay constant, you have to be able to measure differences in the order of 1/c second intervals, basically. I am not very familiar with arduinos, so I do not know if they are capable of this kind of measurements.
I would suggest you use an ultrasonic range finder like the Maxbotix HRLV-EZ4 sold by Sparkfun.
It is within your price range and it should be able to measure distances up to 5m/195 inches with 1mm resolution.
It is actually possible to do it, I have seen it be done with other microcontrollers. Therefore using arduino you would have to solve the equations,fit in arduino language and make a lot of measurements to value discrepancies over communication itself. Do not forget about atmospheric attenuation wich need to be known and fit in the equations. Humidity may deviate electromagnetic waves.

Resources