[PD] [flext] Inheriting access to variables declared once in a library

Thomas Grill gr at grrrr.org
Tue Aug 1 13:53:51 CEST 2006


Hi Christian,
the basic question is if you really need signals for input/output of  
force/position.
Obviously you aren't using the individual samples of a block, hence  
it's a waste of cpu. You are proably better off with messages, where  
you can also use 3-element lists for input/output of data.
Concerning your "static" variables, they are obviously not initialized  
which will result in undefined behaviour. For the "link problems" it's  
relevant how and where you move the variables, which is impossible to  
anticipate without the actual code.
As far as i can see you cannot really separate the position and force  
into two objects as they share the same resource. Having more than one  
instance of an object will yield aliased results.
best greetings,
Thomas

Am 01.08.2006 um 07:59 schrieb Christian Frisson:

> Re-,
>
> More about the project: I'm trying to wrap a GPL C++ haptik API called  
> the
> Haptik Library (http://www.haptiklibrary.org) in a library of flext  
> externals
> in order to sense/actuate haptic devices directly under Pd/MSP. First  
> attemps
> have been made with Pd under Windows XP (Linux will follow), compiling  
> with
> nmake from VC++7 and debugging with a SensAble PHANToM Omni haptic  
> device.
> Basically a morph between the library example from the flext tutorial  
> and the
> "HelloHaptikConsole" example from the Haptik Library.
>
> I hope you won't mind my pasting the code deliberately on the body of  
> the
> message (see below for the "ugly static" version), as I want to wait  
> for a
> proper first release before setting up a webpage.
>
> I've tried to move the "static" variables as private members of the  
> base flext
> class and create protected accessors, but the compilation ended as a  
> link error
> (I'll paste the number ID on the next message).
>
> On the list of yet unhandled important issues:
> * the "m_signal" functions are not in sync with the frequency rate of  
> the haptic
> device;
> * both "m_signal" instances seems to crosstalk, as they behave  
> normally alone,
> but not together, the following quotation of the Pd C external howto  
> initiating
> the answer:
>
> "Optimization of the DSP-tree tries to avoid unnecessary  
> copy-operations.
> Therefore it is possible, that in- and out-signal are located at the  
> same
> address in the memory. In this case, the programmer has to be careful  
> not to
> write into the out-signal before having read the in-signal to avoid  
> overwriting
> data that is not yet saved."
>
> Thanks for your previous realtime answer and beforehand for the one to  
> come!
> Christian
>
> /*
> ----------------------------------------------------------------------- 
> --
> haptik~ - the Haptik Library wrapped as a library of flext externals
> Copyright (c) 2006 Christian Frisson
> To be released under a GPL license
> ----------------------------------------------------------------------- 
> --
> */
>
> // include flext header
>
> #include <flext.h>
>
>
>
> // check for appropriate flext version
>
> #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 400)
>
> #error You need at least flext version 0.4.0
>
> #endif
>
>
>
> // include Haptik headers
>
> #include <windows.h>
>
> #include <conio.h>
>
> #include <stdio.h>
>
> #include <RSLib\Haptik.hpp>
>
> using namespace RSLib;
>
> using namespace RSLib::Math;
>
>
>
> Haptik haptikWrapper;
>
> IHaptikDeviceInterface hapticDevice;
>
> bool haptikDeviceStatus;
>
> UINT32 haptikID, haptikRate, uRes;
>
> HaptikData fdata, pdata;
>
>
>
> / 
> /---------------------------------------------------------------------- 
> -
>
> class haptik:
>
> 	// inherit from basic flext class
>
> 	public flext_dsp
>
> {
>
> 	// obligatory flext header (class name,base class name)
>
> 	FLEXT_HEADER(haptik,flext_dsp)
>
>
>
> 	public:
>
> 		// constructor
>
> 		haptik();
>
> 		~haptik();
>
>
>
> 	protected:
>
> 		void m_off(); // method to set the device on
>
> 		void m_on(); // method to set the device on
>
> 		void m_dev(int d); // method to set the device ID
>
> 		void m_rate(int r); // method to set the device ID
>
> 		void m_callback(HaptikData& data);// device callback
>
>
>
> 	private:
>
> 		FLEXT_CALLBACK(m_on);
>
> 		FLEXT_CALLBACK(m_off);
>
> 		FLEXT_CALLBACK_I(m_dev);
>
> 		FLEXT_CALLBACK_I(m_rate);
>
> };
>
>
>
> haptik::haptik()
>
> {
>
> 	// define inlets:
>
> 	// first inlet must always be of type anything (or signal for dsp  
> objects)
>
> 	AddInSignal("dev, on, off, rate, position x or force x"); // signal  
> inlet for
> force
>
>
>
> 	// register methods
>
> 	// set up tagged methods for the default inlet (0)
>
> 	// the underscore _ after CADDMETHOD indicates that a message tag is  
> used
>
>
>
> 	FLEXT_ADDMETHOD_(0,"on",m_on); // register method for tag "on"
>
> 	FLEXT_ADDMETHOD_(0,"off",m_off); // register method for tag "off"
>
> 	FLEXT_ADDMETHOD_I(0,"dev",m_dev); // register method for tag "dev"  
> and int
> argument
>
> 	FLEXT_ADDMETHOD_I(0,"rate",m_rate); // register method for tag "rate"  
> and int
> argument
>
> }
>
>
>
> haptik::~haptik()
>
> {
>
> 	if (haptikDeviceStatus)
>
> 		hapticDevice->Stop();
>
>
>
> 	// release interface
>
> 	RELEASE_HAPTIK_INTERFACE(hapticDevice);
>
> }
>
>
>
> void haptik::m_on()
>
> {
>
> 	if (!haptikDeviceStatus)
>
> 	{
>
>
>
> 		// warn user if no device has been found
>
> 		if (haptikWrapper.numberOfDevices == 0)
>
> 		{
>
> 			post("%s - No Haptik Devices Found! Checkout configuration
> file!",thisName());
>
> 			return;
>
> 		}
>
> 		// list installed devices
>
> 		if (haptikID == -1)
>
> 		{
>
> 			post("%s - Installed devices:",thisName());
>
> 			for(UINT32 i = 0 ; i<haptikWrapper.numberOfDevices ; i++)
>
> 				post("%s - \t[%d] %s (%s) by
> %s",thisName(),i,haptikWrapper.device[i].name,haptikWrapper.device[i].m 
> odel,haptikWrapper.device[i].manufacturer);
>
> 			post("%s - Please choose your device using a message  
> box",thisName());
>
> 			return;
>
> 		}
>
>
>
> 		// ask for an interface to that device
>
> 		hapticDevice = (IHaptikDeviceInterface)  
> haptikWrapper.GetDeviceInterface(
> haptikID == -1 ? HAPTIK_DEFAULT_DEVICE : haptikID );
>
> 		if (hapticDevice == NULL)
>
> 		{
>
> 		post("%s - Invalid Interface. Is device connected?",thisName());
>
> 		return;
>
> 		}
>
>
>
> 		// set an object-based callback
>
> 		uRes =
> hapticDevice- 
> >Init(METHOD_ADDRESS(haptik,m_callback),OBJECT_ADDRESS(haptik,*this));
>
> 		if FAILED(uRes)
>
> 		{
>
> 			RELEASE_HAPTIK_INTERFACE(hapticDevice);
>
> 			post("%s - Failed to Initialize device",thisName());
>
> 			return;
>
> 		}
>
>
>
> 		// set rate
>
> 		uRes = hapticDevice->SetRate(haptikRate);
>
> 		if FAILED(uRes)
>
> 		{
>
> 			RELEASE_HAPTIK_INTERFACE(hapticDevice);
>
> 			post("%s - Failed to Start device",thisName());
>
> 			return;
>
> 		}
>
>
>
> 		// start device
>
> 		uRes = hapticDevice->Start();
>
> 		if FAILED(uRes)
>
> 		{
>
> 			RELEASE_HAPTIK_INTERFACE(hapticDevice);
>
> 			post("%s - Failed to Start device",thisName());
>
> 			return;
>
> 		}
>
>
>
> 		// user interaction...
>
> 		post("%s - Device is on",thisName());
>
> 		haptikDeviceStatus = true ;
>
> 	}
>
> 	else
>
> 		post("%s - Device is already on!",thisName());
>
> }
>
>
>
> void haptik::m_off()
>
> {
>
> 	if (haptikDeviceStatus)
>
> 	{
>
> 		post("%s - Device is off",thisName());
>
> 		hapticDevice->Stop();
>
>
>
> 		// release interface
>
> 		RELEASE_HAPTIK_INTERFACE(hapticDevice);
>
>
>
> 		haptikDeviceStatus = false;
>
> 	}
>
> 	else
>
> 		post("%s - Device is already off!",thisName());
>
> }
>
>
>
> void haptik::m_dev(int d)
>
> {
>
> 	if ((d<haptikWrapper.numberOfDevices) && (d>-1))
>
> 	{
>
> 		if (!haptikDeviceStatus)
>
> 		{
>
> 			haptikID = (UINT32)d;
>
> 			post("%s - Device [%d] chosen",thisName(),d);
>
> 		}
>
> 		else
>
> 			post("%s - Please disable the current device first",thisName());
>
> 	}
>
> 	else
>
> 		post("%s - No such device!",thisName());
>
> }
>
>
>
> void haptik::m_rate(int r)
>
> {
>
> 	if ((r>=1) && (r<=1000))
>
> 	{
>
> 		if (haptikDeviceStatus)
>
> 		{
>
> 			uRes = hapticDevice->SetRate((UINT32)r);
>
> 			if FAILED(uRes)
>
> 			{
>
> 				RELEASE_HAPTIK_INTERFACE(hapticDevice);
>
> 				post("%s - Failed to set device rate",thisName());
>
> 				return;
>
> 			}
>
> 		}
>
> 		haptikRate=(UINT32)r;
>
> 		post("%s - Rate set at: %i",thisName(),haptikRate);
>
> 	}
>
> 	else
>
> 		post("%s - Please choose a rate between 1 and 1000 Hz",thisName());
>
> }
>
>
>
> void haptik::m_callback(HaptikData& data)
>
> {
>
> 	pdata.position = data.position;
>
> 	data.forceFeedback = fdata.forceFeedback;
>
> 	//data.torqueFeedback = Vector3(0,0,0);
>
> }
>
>
>
> / 
> /---------------------------------------------------------------------- 
> -
>
> class haptikposition:
>
> 	// inherit from basic flext class
>
> 	public haptik
>
> {
>
> 	// obligatory flext header (class name,base class name)
>
> 	FLEXT_HEADER(haptikposition,haptik)
>
>
>
> 	public:
>
> 		haptikposition();
>
>
>
> 	protected:
>
> 		virtual void m_signal(int n, float *const *in, float *const *out);
>
> };
>
>
>
> FLEXT_LIB("haptik~.position",haptikposition);
>
>
>
> haptikposition::haptikposition()
>
> {
>
> 	// define outlets:
>
> 	AddOutSignal("position (3 element list)"); //signal outlet for  
> position x
>
> 	AddOutSignal("position (3 element list)"); //signal outlet for  
> position y
>
> 	AddOutSignal("position (3 element list)"); //signal outlet for  
> position z
>
> }
>
>
>
> void haptikposition::m_signal(int n, float *const *in, float *const  
> *out)
>
> {
>
> 	float *outx = out[0];
>
> 	float *outy = out[1];
>
> 	float *outz = out[2];
>
>
>
> 	while (n--)
>
> 	{
>
> 		if (haptikDeviceStatus)
>
> 		{
>
> 			// output position
>
> 			*outz++ = pdata.position.z;
>
> 			*outy++ = pdata.position.y;
>
> 			*outx++ = pdata.position.x;
>
> 		}
>
> 	}
>
> } // end m_signal
>
>
>
> / 
> /---------------------------------------------------------------------- 
> -
>
> class haptikforce:
>
> 	// inherit from basic flext class
>
> 	public haptik
>
> {
>
> 	// obligatory flext header (class name,base class name)
>
> 	FLEXT_HEADER(haptikforce,haptik)
>
>
>
> 	public:
>
> 		haptikforce();
>
>
>
> 	protected:
>
> 		virtual void m_signal(int n, float *const *in, float *const *out);
>
> };
>
>
>
> FLEXT_LIB("haptik~.force",haptikforce);
>
>
>
> haptikforce::haptikforce()
>
> {
>
> 	// define inlets:
>
> 	// first inlet must always be of type anything (or signal for dsp  
> objects)
>
> 	AddInSignal("force (3 element list)"); // signal inlet for force y
>
> 	AddInSignal("force (3 element list)"); // signal inlet for force z
>
> }
>
>
>
> void haptikforce::m_signal(int n, float *const *in, float *const *out)
>
> {
>
> 	const float *insx = in[0];
>
> 	const float *insy = in[1];
>
> 	const float *insz = in[2];
>
>
>
> 	while (n--)
>
> 	{
>
> 		if (haptikDeviceStatus)
>
> 		{
>
> 			// input force
>
> 			fdata.forceFeedback.x = *insx++;
>
> 			fdata.forceFeedback.y = *insy++;
>
> 			fdata.forceFeedback.z = *insz++;
>
> 			fdata.torqueFeedback = Vector3(0,0,0);
>
> 		}
>
> 	}
>
> } // end m_signal
>
>
>
> / 
> /---------------------------------------------------------------------- 
> -
>
> static void lib_setup()
>
> {
>
> 	post("Haptik~ Library v0.01");
>
> 	post("Christian Frisson - 06/07/31");
>
> 	post("");
>
> 	// call the objects' setup routines
>
> 	FLEXT_SETUP(haptikposition);
>
> 	FLEXT_SETUP(haptikforce);
>
>
>
> 	haptikDeviceStatus = false;
>
> 	haptikID = -1;
>
> 	haptikRate = 1000;
>
> }
>
> // setup the library
>
> FLEXT_LIB_SETUP(haptik,lib_setup)
>
>





More information about the Pd-list mailing list