Implementing qsort in Objective-C - objective-c

I'm trying to use qsort to sort a C array in descending order based on what this website is suggesting.
Here is the relevant code:
int x = 3;
- (IBAction)CaptureButton:(id)sender
{
x++;
if (x % 3 == 1)
{
int areas[detectedBlobs.size()];
for (int i = 0; i < detectedBlobs.size(); i++)
{
areas[i] = detectedBlobs[i].getWidth() * detectedBlobs[i].getHeight();
}
int compareInts(void const *item1, void const *item2)
{ // first error
int const *int1 = item1;
int const *int2 = item2;
return (*int2 - *int1);
}
qsort(areas, detectedBlobs.size(), sizeof(int), compareInts); // second error
}
}
Here are the two errors I'm getting:
First error:
Function definition is not allowed here
Second error:
Use of undeclared identifier 'compareInts'
If I cannot define the comparator (compareInts) function here, where do I have to define it? Also, how can I get the qsort function to recognize the comparator?

Objective-C does not allow function definitions inside methods. Move compareInts outside of the method, and make it static to hide from other translation units:
static int compareInts(const void* item1, const void* item2) {
const int* int1 = (const int*)item1;
const int* int2 = (const int*)item2;
return (*int2 - *int1);
}
- (IBAction)CaptureButton:(id)sender {
x++;
if (x % 3 == 1) {
int areas[detectedBlobs.size()];
for (int i = 0; i < detectedBlobs.size(); i++) {
areas[i] = detectedBlobs[i].getWidth() * detectedBlobs[i].getHeight();
}
qsort(areas, detectedBlobs.size(), sizeof(int), compareInts);
}
}

Related

How is it possible to randomly remove an element from vector< vector<short> >?

Below is a Sudoku initializer, I am attempting to create a function that based on User input, erases a random element from the the board. The random element can be removed from any part of the board.
class cell{
bool m_occu; //occupied is shown '.'
int m_num;
public:
cell() : m_occu(false), m_num(0) {}
void setMark(const int num){m_num = num; m_occu = true;}
bool isMarked() const { return m_occu; }
int getNum(){ return m_num;}
friend ostream& operator << (ostream& o, const cell& c){
if (!c.m_occu) return o << setw(2) << '-';
return o << setw(2) << c.m_num;
}
};
class board {
vector<vector <cell> >m_map;
bool col_row;
public:
board() {
vector<cell> a_row(9);
col_row = false;
for (int i = 0; i < 9; ++i)
{
for(int j = 0; j < 9; j++)
{
a_row[j].setMark(j+1);
}
random_shuffle(a_row.begin(), a_row.end());
m_map.push_back(a_row);
}
}
void erase(){
}
Here is the code for erase function:
void erase(std::vector your_vector){
your_vector.erase(your_vector.begin() + random(1,your_vector.size()));
}
and this the code for random number generation:
int random(int min, int max) //range(min, max)
{
bool first = true;
if ( first )
{
srand(time(NULL)); //seeding only for the first time
first = false;
}
return min + rand() % (max - min);
}

calling Objective C and C from Swift passing callback function

I am trying to call the HappyTime onvif library from Swift.
I have the library linked in to my project and I am able to call some simple functions, but I am having trouble getting the syntax right in my call which passes my callback function.
Here is the Swift code:
func discoverCameras()
{
HappyInterface.sharedInstance().startProb()
//this line gives syntax error
HappyInterface.sharedInstance().setProbeCB(cameraDiscovered)
}
func cameraDiscovered(cameraFound:UnsafeMutablePointer<DEVICE_BINFO>)
{
table.reloadData()
}
my setProbeCB call gives this error:
Cannot convert value of type '(UnsafeMutablePointer) -> ()' to expected argument type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer, UnsafeMutablePointer<()>) -> ()>>')
Here is the Obj C implementation:
- (void) setProbeCB:(onvif_probe_cb *)cb {
set_probe_cb(*cb, 0);
}
This is the Obj C header:
- (void) setProbeCB:(onvif_probe_cb *)cb;
This is the C header:
#ifndef __H_ONVIF_PROBE_H__
#define __H_ONVIF_PROBE_H__
#include "onvif.h"
typedef void (* onvif_probe_cb)(DEVICE_BINFO * p_res, void * pdata);
#ifdef __cplusplus
extern "C" {
#endif
ONVIF_API void set_probe_cb(onvif_probe_cb cb, void * pdata);
ONVIF_API void set_probe_interval(int interval);
ONVIF_API int start_probe(int interval);
ONVIF_API void stop_probe();
ONVIF_API void send_probe_req();
#ifdef __cplusplus
}
#endif
#endif // __H_ONVIF_PROBE_H__
This is the C code:
/***************************************************************************************/
#define MAX_PROBE_FD 8
/***************************************************************************************/
onvif_probe_cb g_probe_cb = 0;
void * g_probe_cb_data = 0;
pthread_t g_probe_thread = 0;
int g_probe_fd[MAX_PROBE_FD];
int g_probe_interval = 30;
BOOL g_probe_running = FALSE;
/***************************************************************************************/
int onvif_probe_init(unsigned int ip)
{
int opt = 1;
SOCKET fd;
struct sockaddr_in addr;
struct ip_mreq mcast;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd < 0)
{
log_print(LOG_ERR, "socket SOCK_DGRAM error!\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3702);
addr.sin_addr.s_addr = ip;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
// if port 3702 already occupied, only receive unicast message
addr.sin_port = 0;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
closesocket(fd);
log_print(LOG_ERR, "bind error! %s\n", sys_os_get_socket_error());
return -1;
}
}
/* reuse socket addr */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)))
{
log_print(LOG_WARN, "setsockopt SO_REUSEADDR error!\n");
}
memset(&mcast, 0, sizeof(mcast));
mcast.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
mcast.imr_interface.s_addr = ip;
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast, sizeof(mcast)) < 0)
{
#if __WIN32_OS__
if(setsockopt(fd, IPPROTO_IP, 5, (char*)&mcast, sizeof(mcast)) < 0)
#endif
{
closesocket(fd);
log_print(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP error! %s\n", sys_os_get_socket_error());
return -1;
}
}
return fd;
}
char probe_req1[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<Envelope xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\" xmlns=\"http://www.w3.org/2003/05/soap-envelope\">"
"<Header>"
"<wsa:MessageID xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">uuid:%s</wsa:MessageID>"
"<wsa:To xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>"
"<wsa:Action xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>"
"</Header>"
"<Body>"
"<Probe xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">"
"<Types>tds:Device</Types>"
"<Scopes />"
"</Probe>"
"</Body>"
"</Envelope>";
char probe_req2[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<Envelope xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\" xmlns=\"http://www.w3.org/2003/05/soap-envelope\">"
"<Header>"
"<wsa:MessageID xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">uuid:%s</wsa:MessageID>"
"<wsa:To xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>"
"<wsa:Action xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>"
"</Header>"
"<Body>"
"<Probe xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">"
"<Types>dn:NetworkVideoTransmitter</Types>"
"<Scopes />"
"</Probe>"
"</Body>"
"</Envelope>";
int onvif_probe_req_tx(int fd)
{
int len;
int rlen;
char * p_bufs = NULL;
struct sockaddr_in addr;
int buflen = 10*1024;
p_bufs = (char *)malloc(buflen);
if (NULL == p_bufs)
{
return -1;
}
memset(p_bufs, 0, buflen);
sprintf(p_bufs, probe_req1, onvif_uuid_create());
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("239.255.255.250");
addr.sin_port = htons(3702);
len = strlen(p_bufs);
rlen = sendto(fd, p_bufs, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if (rlen != len)
{
log_print(LOG_ERR, "onvif_probe_req_tx::rlen = %d,slen = %d\r\n", rlen, len);
}
usleep(1000);
memset(p_bufs, 0, buflen);
sprintf(p_bufs, probe_req2, onvif_uuid_create());
len = strlen(p_bufs);
rlen = sendto(fd, p_bufs, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if (rlen != len)
{
log_print(LOG_ERR, "onvif_probe_req_tx::rlen = %d,slen = %d\r\n", rlen, len);
}
free(p_bufs);
return rlen;
}
BOOL onvif_parse_device_binfo(XMLN * p_node, DEVICE_BINFO * p_res)
{
XMLN * p_EndpointReference;
XMLN * p_Types;
XMLN * p_XAddrs;
p_EndpointReference = xml_node_soap_get(p_node, "EndpointReference");
if (p_EndpointReference)
{
XMLN * p_Address = xml_node_soap_get(p_EndpointReference, "Address");
if (p_Address && p_Address->data)
{
strncpy(p_res->EndpointReference, p_Address->data, sizeof(p_res->EndpointReference)-1);
}
}
p_Types = xml_node_soap_get(p_node, "Types");
if (p_Types && p_Types->data)
{
p_res->type = parse_DeviceType(p_Types->data);
}
p_XAddrs = xml_node_soap_get(p_node, "XAddrs");
if (p_XAddrs && p_XAddrs->data)
{
parse_XAddr(p_XAddrs->data, &p_res->XAddr);
if (p_res->XAddr.host[0] == '\0' || p_res->XAddr.port == 0)
{
return FALSE;
}
}
else
{
return FALSE;
}
return TRUE;
}
BOOL onvif_probe_res(XMLN * p_node, DEVICE_BINFO * p_res)
{
XMLN * p_body = xml_node_soap_get(p_node, "Body");
if (p_body)
{
XMLN * p_ProbeMatches = xml_node_soap_get(p_body, "ProbeMatches");
if (p_ProbeMatches)
{
XMLN * p_ProbeMatch = xml_node_soap_get(p_ProbeMatches, "ProbeMatch");
while (p_ProbeMatch && soap_strcmp(p_ProbeMatch->name, "ProbeMatch") == 0)
{
if (onvif_parse_device_binfo(p_ProbeMatch, p_res))
{
if (g_probe_cb)
{
g_probe_cb(p_res, g_probe_cb_data);
}
}
p_ProbeMatch = p_ProbeMatch->next;
}
}
else
{
XMLN * p_Hello = xml_node_soap_get(p_body, "Hello");
if (p_Hello)
{
if (onvif_parse_device_binfo(p_Hello, p_res))
{
if (g_probe_cb)
{
g_probe_cb(p_res, g_probe_cb_data);
}
}
}
}
}
return TRUE;
}
int onvif_probe_net_rx()
{
int i;
int ret;
int maxfd = 0;
int fd = 0;
char rbuf[10*1024];
fd_set fdread;
struct timeval tv = {1, 0};
FD_ZERO(&fdread);
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
FD_SET(g_probe_fd[i], &fdread);
if (g_probe_fd[i] > maxfd)
{
maxfd = g_probe_fd[i];
}
}
}
ret = select(maxfd+1, &fdread, NULL, NULL, &tv);
if (ret == 0) // Time expired
{
return 0;
}
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0 && FD_ISSET(g_probe_fd[i], &fdread))
{
int rlen;
int addr_len;
struct sockaddr_in addr;
unsigned int src_ip;
unsigned int src_port;
XMLN * p_node;
fd = g_probe_fd[i];
addr_len = sizeof(struct sockaddr_in);
rlen = recvfrom(fd, rbuf, sizeof(rbuf), 0, (struct sockaddr *)&addr, (socklen_t*)&addr_len);
if (rlen <= 0)
{
log_print(LOG_ERR, "onvif_probe_net_rx::rlen = %d, fd = %d\r\n", rlen, fd);
continue;
}
src_ip = addr.sin_addr.s_addr;
src_port = addr.sin_port;
p_node = xxx_hxml_parse(rbuf, rlen);
if (p_node == NULL)
{
log_print(LOG_ERR, "onvif_probe_net_rx::hxml parse err!!!\r\n");
}
else
{
DEVICE_BINFO res;
memset(&res, 0, sizeof(DEVICE_BINFO));
onvif_probe_res(p_node, &res);
}
xml_node_del(p_node);
}
}
return 1;
}
void * onvif_probe_thread(void * argv)
{
int count = 0;
int i = 0;
int j = 0;
for (; i < get_if_nums() && j < MAX_PROBE_FD; i++, j++)
{
unsigned int ip = get_if_ip(i);
if (ip != 0 && ip != inet_addr("127.0.0.1"))
{
g_probe_fd[j] = onvif_probe_init(ip);
}
}
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
onvif_probe_req_tx(g_probe_fd[i]);
}
}
while (g_probe_running)
{
if (onvif_probe_net_rx() == 0)
{
count++;
}
if (count >= g_probe_interval)
{
count = 0;
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
onvif_probe_req_tx(g_probe_fd[i]);
}
}
}
usleep(1000);
}
g_probe_thread = 0;
return NULL;
}
ONVIF_API void set_probe_cb(onvif_probe_cb cb, void * pdata)
{
g_probe_cb = cb;
g_probe_cb_data = pdata;
}
ONVIF_API void send_probe_req()
{
int i;
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
onvif_probe_req_tx(g_probe_fd[i]);
}
}
}
ONVIF_API void set_probe_interval(int interval)
{
g_probe_interval = interval;
if (g_probe_interval < 10)
{
g_probe_interval = 30;
}
}
ONVIF_API int start_probe(int interval)
{
g_probe_running = TRUE;
set_probe_interval(interval);
g_probe_thread = sys_os_create_thread((void *)onvif_probe_thread, NULL);
if (g_probe_thread)
{
return 0;
}
return -1;
}
ONVIF_API void stop_probe()
{
int i;
g_probe_running = FALSE;
while (g_probe_thread)
{
usleep(1000);
}
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
closesocket(g_probe_fd[i]);
g_probe_fd[i] = 0;
}
}
}
Here is what the DEVICE_BINFO struct looks like:
typedef struct
{
int type; // device type
char EndpointReference[100];
onvif_XAddr XAddr; // xaddr, include port host, url
} DEVICE_BINFO;
One thing that should be fixed is a mismatch in the number of arguments to the callback. Swift calls the Objective-C setProbeCB() method, giving it a pointer to the cameraDiscovered() function, which takes a single argument. Then setProbeCB() gives the function pointer to the C set_probe_cb() function, which expects a pointer to a function that takes two arguments.
Another observation is that setProbeCB() could just take onvif_probe_cb instead of onvif_probe_cb* and then call C code simply as set_probe_cb(cb, 0). However, I don't think it makes much difference.
Also, I think the question could have been distilled to a smaller size.
The following is a simplified example based on your original code. It shows how to implement a callback in Swift and have C code call it, but the real fun starts when passing data via callback parameters and return values. It gets very tricky very fast, and that's why the example doesn't show how to deal with DEVICE_BINFO in Swift code. It's a topic in its own right.
The clue to using (Objective-)C functions and types in Swift is figuring out how they are imported into Swift. For example, to find out how onvif_probe_cb is imported, type it on a line in the Swift code, place the cursor in it, and Quick Help will show you this:
Declaration: typealias onvif_probe_cb = (UnsafeMutablePointer<DEVICE_BINFO>, UnsafeMutablePointer<Void>) -> Void
Declared in: clib.h
That tells us the parameter and return types to use in our Swift implementation of the callback.
The example is by no means production quality: there are all kinds of things that can go haywire in terms of memory management etc. Please see the code comments for additional info.
First, here is the C code header (clib.h):
#ifndef clib_h
#define clib_h
#include <stdio.h>
typedef struct {
char hostname[50];
int32_t port;
char url[200];
} onvif_XAddr;
typedef struct
{
int type; // device type
char EndpointReference[100];
onvif_XAddr XAddr; // xaddr, include port host, url
} DEVICE_BINFO;
/**
* This is the typedef of the function pointer to be used for our callback.
* The function takes a pointer to DEVICE_BINFO and a pointer to some arbitrary
* data meaningful to the code that provides the callback implementation. It will
* be NULL in this example.
*/
typedef void (* onvif_probe_cb)(DEVICE_BINFO * p_res, void * pdata);
/**
* A function to set the callback.
*/
void set_probe_cb(onvif_probe_cb cb, void * pdata);
/**
* This is a function that calls the callback.
*/
void find_device();
#endif /* clib_h */
Here is the rest of our C source (clib.c):
#include "clib.h"
#include <string.h>
onvif_probe_cb gCB = 0; // global variable to store the callback pointer
void * gUserData = 0; // global variable to store pointer to user data
DEVICE_BINFO gDeviceInfo; // global variable to store device info struct
void find_device() {
// Set up gDeviceInfo
gDeviceInfo.XAddr.port = 1234;
strcpy( gDeviceInfo.XAddr.hostname, "myhost");
strcpy( gDeviceInfo.XAddr.url, "http://junk.com");
gDeviceInfo.type = 777;
// ... and, if a callback is available, call it with the device info
if (gCB) gCB(&gDeviceInfo, gUserData);
else puts("No callback available");
}
void set_probe_cb(onvif_probe_cb cb, void * pdata) {
gCB = cb;
gUserData = pdata;
}
Here is the Objective-C wrapper header (oclib.h):
#ifndef oclib_h
#define oclib_h
#import "clib.h"
#import <Foundation/Foundation.h>
/**
* Interface of an Objective-C wrapper around C code in clib.*. We could have
* gone straight to C from Swift, but I'm trying to keep the example close to the
* code in the question. Also, this extra Objective C layer could be helpful in
* translating data structures, such as DEVICE_BINFO, between C and Swift, since
* Objective-C plays much nicer with C data types. This is no surprise: any C code
* is valid Objective-C (Objective-C is a strict superset of C).
*/
#interface MyWrapper : NSObject
-(id)init;
// Please note: this one takes a single argument, while the C function it wraps
// takes 2; see the implementation.
-(void) setProbeCB:(onvif_probe_cb) cb;
-(void) findDevice;
#end
#endif /* oclib_h */
And the wrapper implementation (oclib.m):
#import "oclib.h"
/**
* Implementation of our Objective-C wrapper.
*/
#implementation MyWrapper
-(id)init { return self; }
-(void) setProbeCB:(onvif_probe_cb) cb {
// We don't want anything other than device info to be passed back and
// forth via the callback, so this wrapper function takes a single argument
// and passes 0 as the 2nd argument to the wrapped C function.
set_probe_cb(cb, 0);
}
-(void) findDevice {
find_device();
}
#end
Finally, here is the Swift code that implements the callback (main.swift):
var w : MyWrapper = MyWrapper()
/**
* This is the callback implementation in Swift. We don't use the 2nd argument, userData, but it still
* has to be present to satisfy the way the callback function pointer is specified in C code.
*/
func cameraDiscovered( info : UnsafeMutablePointer<DEVICE_BINFO>, userData : UnsafeMutablePointer<Void>) {
print("Called the Swift callback!")
let devInfo : DEVICE_BINFO = info.memory;
print( "The device type is \(devInfo.type)")
print( "The device port is \(devInfo.XAddr.port)")
}
// Provide the callback to C code via Objective-C
w.setProbeCB(cameraDiscovered)
// ... and call a function that will cause the C code to invoke the callback.
w.findDevice()
The bridging header just has #import oclib.h, thus exposing the contents of both C and Objective-C headers to Swift.
The expected output:
Called the Swift callback!
The device type is 777
The device port is 1234

"Binary/Unary operator '++/<' cannot be applied to an operand of type" AND "Use of unresolved identifier '=-'"

I am translating an Obj-C app to Swift and having trouble dealing with some syntax. I believe I have declared the variable types correctly so I don't know why I'm be getting these errors. Maybe some blocks are located incorrectly inside classes/functions when they should be outside or something. I would love it if you could review my code. I'm new to programming so what may be a clear and explicit explanation to you probably will still be vague for me so please show with examples using existing names.
Thanks
"Unary operator '++' cannot be applied to an operand of type 'Int?'"
and
"Binary operator '<' cannot be applied to an operand of type 'Int? and Float'"
and
"Use of unresolved identifier '=-'"
import UIKit
import Foundation
import AVFoundation
let minFramesForFilterToSettle = 10
enum CurrentState {
case statePaused
case stateSampling
}
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
let session = AVCaptureSession()
var camera : AVCaptureDevice?
var validFrameCounter: Int = 0
var pulseDetector: PulseDetector!
var filter: Filter!
var currentState = CurrentState.stateSampling // Is this initialized correctly?
override func viewDidLoad() {
super.viewDidLoad()
self.pulseDetector = PulseDetector()
self.filter = Filter()
// TO DO startCameraCapture() // call to un-used function.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
let NZEROS = 10
let NPOLES = 10
class Filter {
var xv = [Float](count: NZEROS + 1, repeatedValue: 0)
var yv = [Float](count: NPOLES + 1, repeatedValue: 0)
func processValue(value: Float) -> Float {
let gain: Float = 1.894427025e+01
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; xv[6] = xv[7]; xv[7] = xv[8]; xv[8] = xv[9]; xv[9] = xv[10]; xv[10] = value / gain;
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; yv[6] = yv[7]; yv[7] = yv[8]; yv[8] = yv[9]; yv[9] = yv[10];
yv[10] = (xv[10] - xv[0]) + 5 * (xv[2] - xv[8]) + 10 * (xv[6] - xv[4])
+ ( -0.0000000000 * yv[0]) + ( 0.0357796363 * yv[1])
+ ( -0.1476158522 * yv[2]) + ( 0.3992561394 * yv[3])
+ ( -1.1743136181 * yv[4]) + ( 2.4692165842 * yv[5])
+ ( -3.3820859632 * yv[6]) + ( 3.9628972812 * yv[7])
+ ( -4.3832594900 * yv[8]) + ( 3.2101976096 * yv[9]);
return yv[10];
}
}
let maxPeriod = 1.5 // float?
let minPeriod = 0.1 // float?
let invalidEntry:Double = -11
let maxPeriodsToStore:Int = 20
let averageSize:Float = 20
class PulseDetector {
var upVals: [Float] = [averageSize]
var downVals: [Float] = [averageSize]
var upValIndex: Int?
var downValIndex: Int?
var lastVal: Float?
var periodStart: Float?
var periods: [Double] = []
var periodTimes: [Double] = []
var periodIndex: Int?
var started: Bool?
var freq: Float?
var average: Float?
var wasDown: Bool?
func reset() {
for var i=0; i < maxPeriodsToStore; i++ {
periods[i] = invalidEntry
}
for var i=0; i < averageSize; i++ { // why error when PulseDetector.h said averageSize was an Int?
upVals[i] = invalidEntry
downVals[i] = invalidEntry
}
freq = 0.5
periodIndex = 0
downValIndex = 0
upValIndex = 0
}
func addNewValue(newVal:Float, atTime:Double) -> Float {
// we keep track of the number of values above and below zero
if newVal > 0 {
upVals[upValIndex!] = newVal
upValIndex++
if upValIndex >= averageSize {
upValIndex = 0
}
}
if newVal < 0 {
downVals[downValIndex] =- newVal
downValIndex++
if downValIndex >= averageSize {
downValIndex = 0
}
}
// work out the average value above zero
var count: Float
var total: Float
for var i=0; i < averageSize; i++ {
if upVals[i] != invalidEntry {
count++
total+=upVals[i]
}
}
var averageUp = total/count
// and the average value below zero
count=0;
total=0;
for var i=0; i < averageSize; i++ {
if downVals[i] != invalidEntry {
count++
total+=downVals[i]
}
}
var averageDown = total/count
// is the new value a down value?
if newVal < (-0.5*averageDown) {
wasDown = true
}
// original Objective-C code
PulseDetector.h
#import <Foundation/Foundation.h>
#define MAX_PERIODS_TO_STORE 20 // is this an Int?
#define AVERAGE_SIZE 20 // is this a Float?
#define INVALID_PULSE_PERIOD -1 // done
#interface PulseDetector : NSObject {
float upVals[AVERAGE_SIZE];
float downVals[AVERAGE_SIZE];
int upValIndex;
int downValIndex;
float lastVal;
float periodStart;
double periods[MAX_PERIODS_TO_STORE]; // this is an array!
double periodTimes[MAX_PERIODS_TO_STORE]; // this is an rray !!
int periodIndex;
bool started;
float freq;
float average;
bool wasDown;
}
#property (nonatomic, assign) float periodStart; // var periodStart = float?
-(float) addNewValue:(float) newVal atTime:(double) time; // declaring a method called addNewValue with 2 arguments called atTime and time that returns a float
-(float) getAverage; // declaring a method called getAverage that returns a float
-(void) reset; // declaring a method that returns nothing
#end
PulseDetector.m
#import <QuartzCore/QuartzCore.h>
#import "PulseDetector.h"
#import <vector>
#import <algorithm>
#define MAX_PERIOD 1.5
#define MIN_PERIOD 0.1
#define INVALID_ENTRY -100 // is this a double?
#implementation PulseDetector
#synthesize periodStart;
- (id) init
{
self = [super init];
if (self != nil) {
// set everything to invalid
[self reset];
}
return self;
}
-(void) reset {
for(int i=0; i<MAX_PERIODS_TO_STORE; i++) {
periods[i]=INVALID_ENTRY;
}
for(int i=0; i<AVERAGE_SIZE; i++) {
upVals[i]=INVALID_ENTRY;
downVals[i]=INVALID_ENTRY;
}
freq=0.5;
periodIndex=0;
downValIndex=0;
upValIndex=0;
}
-(float) addNewValue:(float) newVal atTime:(double) time {
// we keep track of the number of values above and below zero
if(newVal>0) {
upVals[upValIndex]=newVal;
upValIndex++;
if(upValIndex>=AVERAGE_SIZE) {
upValIndex=0;
}
}
if(newVal<0) {
downVals[downValIndex]=-newVal;
downValIndex++;
if(downValIndex>=AVERAGE_SIZE) {
downValIndex=0;
}
}
// work out the average value above zero
float count=0;
float total=0;
for(int i=0; i<AVERAGE_SIZE; i++) {
if(upVals[i]!=INVALID_ENTRY) {
count++;
total+=upVals[i];
}
}
float averageUp=total/count;
// and the average value below zero
count=0;
total=0;
for(int i=0; i<AVERAGE_SIZE; i++) {
if(downVals[i]!=INVALID_ENTRY) {
count++;
total+=downVals[i];
}
}
float averageDown=total/count;
// is the new value a down value?
if(newVal<-0.5*averageDown) {
wasDown=true;
}
// is the new value an up value and were we previously in the down state?
if(newVal>=0.5*averageUp && wasDown) {
wasDown=false;
// work out the difference between now and the last time this happenned
if(time-periodStart<MAX_PERIOD && time-periodStart>MIN_PERIOD) {
periods[periodIndex]=time-periodStart;
periodTimes[periodIndex]=time;
periodIndex++;
if(periodIndex>=MAX_PERIODS_TO_STORE) {
periodIndex=0;
}
}
// track when the transition happened
periodStart=time;
}
// return up or down
if(newVal<-0.5*averageDown) {
return -1;
} else if(newVal>0.5*averageUp) {
return 1;
}
return 0;
}
-(float) getAverage {
double time=CACurrentMediaTime();
double total=0;
double count=0;
for(int i=0; i<MAX_PERIODS_TO_STORE; i++) {
// only use upto 10 seconds worth of data
if(periods[i]!=INVALID_ENTRY && time-periodTimes[i]<10) {
count++;
total+=periods[i];
}
}
// do we have enough values?
if(count>2) {
return total/count;
}
return INVALID_PULSE_PERIOD;
}
#end
Your problem is that you didn't copied the defines:
#define MAX_PERIODS_TO_STORE 20 // is this an Int?
#define AVERAGE_SIZE 20 // is this a Float?
#define INVALID_PULSE_PERIOD -1 // done
You have to change your defines so they work in your Swift code.
Check this answer how to replace the Objective-C #define to make Swift-Workable.
Also you could just change the defines to variables and initialize your variables with them.
First, a bit on optionals. Variables that end with a '?' are Optional, meaning that they are allowed to be nil (basically not exist). The compiler will not know at compile time whether this variable exists or not, because you are allowed to set it to nil.
"Unary operator '++' cannot be applied to an operand of type 'Int?'"
You seem to have read that last word as Int, but it is Int? which is significant. Basically, since it is an optional (as indicated by the question mark), the compiler knows it can be nil. You cannot use ++ on nil, and since optionals can be nil, you cannot use ++ on optionals. You must forcibly unwrap it first:
downValIndex!++ //note the exclamation point for unwrapping
"Use of unresolved identifier '=-'"
=- isnt a thing. -= is a thing. So
downVals[downValIndex] -= newVal
downVals[downValIndex] = downVals[downValIndex]-newVal //equivalent to above
"Binary operator '>=' cannot be applied to an operand of type 'Int? and Float'"
The compiler thinks you have an optional int on the left of the < and a Float on the right. Assuming you want two Ints, you must unwrap the left and make sure the right is cast to be an int (something like this). If you want two floats instead, cast or define as floats instead of ints.
if downValIndex! >= averageSize as! Int { //casting to Int
You should just be defining averageSize as an int though
var averageSize:Int = 10 //or whatever number
Also, you have lots of optionals. If any of them can be defined to something at compile time, it will make your life easier as you won't need to unwrap them everywhere. Alternately you could implicitly unwrap them (only do this if you are absolutely sure they will never be nil).
var implicitlyUnwrappedOptional:Int!

How to acquire skeletal joint data to text file from two kinect cameras in SkeletalViewer? (C++)

I am currently working on a project to use multiple kinect cameras to acquire x,y,z coordinates of skeletal data in SkeletalViewer. I have an idea to use the KinectID or index of different kinect cameras to extract the sets of skeletal joints data into 2 different text files. But I am not sure if I am doing right. Please help to take a look at the modification below, or I will appreciate all your kind advice on other method to solve this problem.
In SkeletalViewer.h, I modified as following:
public:
FILE* mp3DFile0;
FILE* mp3DFile1;
char mText[1024];
INuiSensor * m_pNuiSensor;
BSTR m_instanceId;
array SensorIndex;
In NuiImpl.cpp, I modified as following:
1) define array
ref class MyClass {
public:
int m_i;
};
array<MyClass^>^ arrSensor() {
int i;
array< MyClass^ >^ local = gcnew array< MyClass^ >(2);
for (i = 0; i < 2; i++) {
local[i] = gcnew MyClass;
local[i]->m_i = i;
}
return local;
}
2) create array to store sensor index to do for loop later
HRESULT CSkeletalViewerApp::Nui_Init( )
{
HRESULT hr;
bool result;
//create an array to store two file pointers
FILE* mp3DFile[] = { mp3DFile0, mp3DFile1 };
fopen_s(mp3DFile0, "D:/Kinect/KinectCam0.txt", "w+");
fopen_s(mp3DFile1, "D:/Kinect/KinectCam1.txt", "w+");
.
.
if ( !m_pNuiSensor )
{
hr = NuiCreateSensorByIndex(0, &m_pNuiSensor);
//I am not sure about how to utilize this index in this case
.
.
}
if (NuiGetSensorCount(&m_pNuiSensor) > 1)
{
array< MyClass^ >^ SensorIndex;
SensorIndex = arrSensor();
}
}
3) use for loop to store data to different text file using index
void CSkeletalViewerApp::Nui_DrawSkeleton( const NUI_SKELETON_DATA & skel, int windowWidth, int windowHeight )
{
int i;
int h;
for (h = 0; h < 2; h++)
{
//when index point to the current kinect
if (SensorIndex[h] == &m_pNuiSensor)
{
for (i = 0; i < NUI_SKELETON_POSITION_COUNT; i++)
{
m_Points[i] = SkeletonToScreen(skel.SkeletonPositions[i], windowWidth, windowHeight);
memset(mText, 0, 1024);
sprintf(mText, "(%0.3f,%0.3f,%0.3f)", skel.SkeletonPositions[i].x, skel.SkeletonPositions[i].y, skel.SkeletonPositions[i].z);
if (mp3DFile[h]) {
fputs((const char*)mText, mp3DFile[h]);
}
}
if (mp3DFile[h]) {
fputs("\n", mp3DFile[h]);
}
}
}
.
.
}
I am a newbie in this Kinect programming. Thank you very much for your help! :)

CUDA Thrust sort_by_key when the key is a tuple dealt with by zip_iterator's with custom comparison predicate

I've looked through a lot of questions here for something similar and there are quite a few, albeit with one minor change. I'm trying to sort values with a zip_iterator as a compound key.
Specifically, I have the following function:
void thrustSort(
unsigned int * primaryKey,
float * secondaryKey,
unsigned int * values,
unsigned int numberOfPoints)
{
thrust::device_ptr dev_ptr_pkey = thrust::device_pointer_cast(primaryKey);
thrust::device_ptr dev_ptr_skey = thrust::device_pointer_cast(secondaryKey);
thrust::device_ptr dev_ptr_values = thrust::device_pointer_cast(values);
thrust::tuple,thrust::device_ptr> keytup_begin =
thrust::make_tuple,thrust::device_ptr>(dev_ptr_pkey, dev_ptr_skey);
thrust::zip_iterator, thrust::device_ptr > > first =
thrust::make_zip_iterator, thrust::device_ptr > >(keytup_begin);
thrust::sort_by_key(first, first + numberOfPoints, dev_ptr_values, ZipComparator());
}
and this custom predicate:
typedef thrust::device_ptr<unsigned int> tdp_uint ;
typedef thrust::device_ptr<float> tdp_float ;
typedef thrust::tuple<tdp_uint, tdp_float> tdp_uif_tuple ;
struct ZipComparator
{
__host__ __device__
inline bool operator() (const tdp_uif_tuple &a, const tdp_uif_tuple &b)
{
if(a.head < b.head) return true;
if(a.head == b.head) return a.tail < b.tail;
return false;
}
};
The errors I'm getting are:
Error 1 error : no instance of constructor "thrust::device_ptr::device_ptr [with T=unsigned int]" matches the argument list C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.0\include\thrust\detail\tuple.inl 309 1 ---
Error 2 error : no instance of constructor "thrust::device_ptr::device_ptr [with T=float]" matches the argument list C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.0\include\thrust\detail\tuple.inl 401 1 ---
Any ideas what might cause this / how do I write a predicate that indeed works?
Thanks in Advance,
Nathan
The comparator takes arguments of type const thrust::tuple<unsigned int, float>&. The const tdp_uif_tuple& type you defined expands to const thrust::tuple<thrust::device_ptr<unsigned int>, thrust:device_ptr<float> >&
The code below compiles for me:
struct ZipComparator
{
__host__ __device__
inline bool operator() (const thrust::tuple<unsigned int, float> &a, const thrust::tuple<unsigned int, float> &b)
{
if(a.head < b.head) return true;
if(a.head == b.head) return a.tail < b.tail;
return false;
}
};
Hope it does for you as well :)
http://code.google.com/p/thrust/wiki/QuickStartGuide#zip_iterator has more details on the zip iterator.
Not required, but if you're looking to clean up the length of those templates, you can do this:
void thrustSort(
unsigned int * primaryKey,
float * secondaryKey,
unsigned int * values,
unsigned int numberOfPoints)
{
tdp_uint dev_ptr_pkey(primaryKey);
tdp_float dev_ptr_skey(secondaryKey);
tdp_uint dev_ptr_values(values);
thrust::tuple<tdp_uint, tdp_float> keytup_begin = thrust::make_tuple(dev_ptr_pkey, dev_ptr_skey);
thrust::zip_iterator<thrust::tuple<tdp_uint, tdp_float> > first =
thrust::make_zip_iterator(keytup_begin);
thrust::sort_by_key(first, first + numberOfPoints, dev_ptr_values, ZipComparator());
}
A lot of the template arguments can be inferred from the arguments.
This is a fully worked example on how using sort_by_key when the key is a tuple dealt with by zip_iterator's and a customized comparison operator.
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include "Utilities.cuh"
// --- Defining tuple type
typedef thrust::tuple<int, int> Tuple;
/**************************/
/* TUPLE ORDERING FUNCTOR */
/**************************/
struct TupleComp
{
__host__ __device__ bool operator()(const Tuple& t1, const Tuple& t2)
{
if (t1.get<0>() < t2.get<0>())
return true;
if (t1.get<0>() > t2.get<0>())
return false;
return t1.get<1>() < t2.get<1>();
}
};
/********/
/* MAIN */
/********/
int main()
{
const int N = 8;
// --- Keys and values on the host: allocation and definition
int h_keys1[N] = { 1, 3, 3, 3, 2, 3, 2, 1 };
int h_keys2[N] = { 1, 5, 3, 8, 2, 8, 1, 1 };
float h_values[N] = { 0.3, 5.1, 3.2, -0.08, 2.1, 5.2, 1.1, 0.01};
printf("\n\n");
printf("Original\n");
for (int i = 0; i < N; i++) {
printf("%i %i %f\n", h_keys1[i], h_keys2[i], h_values[i]);
}
// --- Keys and values on the device: allocation
int *d_keys1; gpuErrchk(cudaMalloc(&d_keys1, N * sizeof(int)));
int *d_keys2; gpuErrchk(cudaMalloc(&d_keys2, N * sizeof(int)));
float *d_values; gpuErrchk(cudaMalloc(&d_values, N * sizeof(float)));
// --- Keys and values: host -> device
gpuErrchk(cudaMemcpy(d_keys1, h_keys1, N * sizeof(int), cudaMemcpyHostToDevice));
gpuErrchk(cudaMemcpy(d_keys2, h_keys2, N * sizeof(int), cudaMemcpyHostToDevice));
gpuErrchk(cudaMemcpy(d_values, h_values, N * sizeof(float), cudaMemcpyHostToDevice));
// --- From raw pointers to device_ptr
thrust::device_ptr<int> dev_ptr_keys1 = thrust::device_pointer_cast(d_keys1);
thrust::device_ptr<int> dev_ptr_keys2 = thrust::device_pointer_cast(d_keys2);
thrust::device_ptr<float> dev_ptr_values = thrust::device_pointer_cast(d_values);
// --- Declare outputs
thrust::device_vector<float> d_values_output(N);
thrust::device_vector<Tuple> d_keys_output(N);
auto begin_keys = thrust::make_zip_iterator(thrust::make_tuple(dev_ptr_keys1, dev_ptr_keys2));
auto end_keys = thrust::make_zip_iterator(thrust::make_tuple(dev_ptr_keys1 + N, dev_ptr_keys2 + N));
thrust::sort_by_key(begin_keys, end_keys, dev_ptr_values, TupleComp());
int *h_keys1_output = (int *)malloc(N * sizeof(int));
int *h_keys2_output = (int *)malloc(N * sizeof(int));
float *h_values_output = (float *)malloc(N * sizeof(float));
gpuErrchk(cudaMemcpy(h_keys1_output, d_keys1, N * sizeof(int), cudaMemcpyDeviceToHost));
gpuErrchk(cudaMemcpy(h_keys2_output, d_keys2, N * sizeof(int), cudaMemcpyDeviceToHost));
gpuErrchk(cudaMemcpy(h_values_output, d_values, N * sizeof(float), cudaMemcpyDeviceToHost));
printf("\n\n");
printf("Ordered\n");
for (int i = 0; i < N; i++) {
printf("%i %i %f\n", h_keys1_output[i], h_keys2_output[i], h_values_output[i]);
}
}