Difference between revisions of "Architecture Tutorial: Retrieve laser scans"
|  (→Calling getObservations) |  (→Calling getObservations) | ||
| (7 intermediate revisions by 2 users not shown) | |||
| Line 4: | Line 4: | ||
| The interface of this module is described in [[Architecture:Specification_of_BABEL_Interfaces#Common_Sensory_Interface| this section]] and this tutorial explains how to write a client module to query the latest laser scans from ''BS_RangeSensors''. | The interface of this module is described in [[Architecture:Specification_of_BABEL_Interfaces#Common_Sensory_Interface| this section]] and this tutorial explains how to write a client module to query the latest laser scans from ''BS_RangeSensors''. | ||
| + | |||
| + | |||
| + | '''Notice that this tutorial only covers the specific case of writing the codification of the client module in the C/C++ language.''' | ||
| + | |||
| + | |||
| + | <br> | ||
| == Steps == | == Steps == | ||
| Line 9: | Line 15: | ||
| === Calling ''getObservations'' === | === Calling ''getObservations'' === | ||
| − | At the point in your module where you need to request the laser scans,  | + | At the point in your module where you need to request the laser scans, the service "getObservations" from "BS_RangeSensors" must be invoked. This is the definition of that service, just to know how it looks like: | 
| + | |||
| + | <center> | ||
| + | [[Image:tut-scans_service.jpg]] | ||
| + | </center> | ||
| + | |||
| + | |||
| + | To call that service, '''you must use the aracne-atom "request-synchronous&blocking"'''. It can be inserted in your code from the BABEL_MD menu. | ||
| + | A dialog will appear asking you which module and service you want to call. Write this information by hand or by using the button "From ICE..." as in the image: | ||
| + | |||
| + | <center> | ||
| + | [[Image:tut-scans_wizard1.jpg]] | ||
| + | </center> | ||
| + | |||
| + | Accept and a wizard will appear asking you for the arguments of the service. Fill it out as in the figure: | ||
| + | |||
| + | <center> | ||
| + | [[Image:tut-scans_wizard2.jpg]] | ||
| + | </center> | ||
| + | |||
| + | |||
| + | Now, this aracne atom must have some preparatory C++ code '''before''' it, and some C++ code '''after''' it to process the results.  | ||
| + | |||
| + | You can use the following fragments of code, self-explained in its comments.  | ||
| + | '''Pay attention to''': | ||
| + | * The label "YOUR CODE HERE" for the place where to process the laser scan. | ||
| + | * The point "ARACNE_ATOM_HERE" at which the aracne atom "request-synchronous&blocking" must be inserted.  | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| Line 35: | Line 58: | ||
| bool err_var;                              // BABEL communication error? | bool err_var;                              // BABEL communication error? | ||
| − | + | /**** ARACNE_ATOM_HERE  ****/ | |
| − | //  | + | // Communications error? Propagate it: | 
| if (err_var) | if (err_var) | ||
| { | { | ||
| − | + | 	// communication error | |
| } | } | ||
| + | else | ||
| + | { | ||
| + | 	// service requested ok | ||
| + | 	CObservation2DRangeScanPtr laserScan; // A smart-pointer to the laser scan (read below) | ||
| − | + | 	if (!sensorError) | |
| − | |||
| − | if ( | ||
| − | |||
| − | |||
| 	{ | 	{ | ||
| − | 		// De-serialize the object: | + | 		try | 
| − | + | 		{ | |
| + | 			// De-serialize the object: | ||
| + | 			mrpt::utils::CSerializablePtr obj = SeqOfBytes2MRPTObject(SF); | ||
| − | + | 			// Assure it's a valid observation (if not, the "catch" block will take control): | |
| − | + | 			ASSERT_(obj) | |
| − | + | 			ASSERT_( IS_CLASS(obj,CSensoryFrame) ) | |
| − | + | 			CSensoryFramePtr theSF = CSensoryFramePtr(obj); | |
| − | + | 			laserScan = theSF->getObservationByClass<CObservation2DRangeScan>(); // Get the first scan, if any. | |
| + | 		} | ||
| + | 		catch(std::exception &e) | ||
| + | 		{ | ||
| + | 			// Process ERROR, message in e.what() | ||
| + | 		} | ||
| 	} | 	} | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | // Free memory of the Sequence | + | 	// Free memory of the Sequence | 
| − | |||
| − | |||
| 	delete SF; | 	delete SF; | ||
| 	SF = NULL; | 	SF = NULL; | ||
| − | |||
| − | // Now, we have the latest scan laser in the variable "laserScan", which   | + | 	// Now, we have the latest scan laser in the variable "laserScan", which   | 
| − | //  is a smart pointer to a mrpt::slam::CObservation2DRangeScan | + | 	//  is a smart pointer to a mrpt::slam::CObservation2DRangeScan | 
| − | // ------------------------------------------------------------------------- | + | 	// ------------------------------------------------------------------------- | 
| − | if (laserScan) | + | 	if (laserScan) | 
| − | { | + | 	{ | 
| − | + | 		// ******* YOUR CODE HERE ************** | |
| − | + | 		// Access to the object data members to get the scan data. | |
| − | + | 		// Refer to: http://babel.isa.uma.es/mrpt/reference/svn/classmrpt_1_1slam_1_1_c_observation2_d_range_scan.html | |
| − | + | 		// Examples: | |
| − | + | 		//   Scan size: laserScan->scan.size() | |
| − | + | 		//   Scan point[0]: laserScan->scan[0] | |
| − | + | 		//   Scan point[0] is valid: laserScan->validRange[0]!=0 | |
| − | } | + | 	} | 
| − | else | + | 	else | 
| − | { | + | 	{ | 
| − | + | 		// For some reason (comms error, hardware error, etc...) there is no laser scan. | |
| + | 	} | ||
| } | } | ||
| − | |||
| </cpp> | </cpp> | ||
| === Auxiliary code === | === Auxiliary code === | ||
| − | Add the following auxiliary function to your module " | + | Add the following auxiliary function to your module "Auxiliary logic" section, since this function is used in the code above: | 
| <cpp> | <cpp> | ||
| Line 112: | Line 134: | ||
| } | } | ||
| </cpp> | </cpp> | ||
| − | |||
| === Non-deportabilities of the module  === | === Non-deportabilities of the module  === | ||
Latest revision as of 17:58, 23 July 2009
Contents
Overview
Following the Robotic Architecture proposed here, laser scans from either a simulated or a real robot should be accessible from a single module, named BS_RangeSensors.
The interface of this module is described in this section and this tutorial explains how to write a client module to query the latest laser scans from BS_RangeSensors.
Notice that this tutorial only covers the specific case of writing the codification of the client module in the C/C++ language.
Steps
Calling getObservations
At the point in your module where you need to request the laser scans, the service "getObservations" from "BS_RangeSensors" must be invoked. This is the definition of that service, just to know how it looks like:
To call that service, you must use the aracne-atom "request-synchronous&blocking". It can be inserted in your code from the BABEL_MD menu.
A dialog will appear asking you which module and service you want to call. Write this information by hand or by using the button "From ICE..." as in the image:
Accept and a wizard will appear asking you for the arguments of the service. Fill it out as in the figure:
Now, this aracne atom must have some preparatory C++ code before it, and some C++ code after it to process the results. 
You can use the following fragments of code, self-explained in its comments. Pay attention to:
- The label "YOUR CODE HERE" for the place where to process the laser scan.
- The point "ARACNE_ATOM_HERE" at which the aracne atom "request-synchronous&blocking" must be inserted.
<cpp> using namespace mrpt; using namespace mrpt::utils; using namespace mrpt::slam;
// Retrieve the latest laser scan // ----------------------------------------------------- BABEL::BS_RangeSensors::SeqOfBytes *SF; // The sequence of bytes sent by the server module BABEL::Boolean sensorError; // Sensor error? bool err_var; // BABEL communication error?
/**** ARACNE_ATOM_HERE ****/
// Communications error? Propagate it: if (err_var) { // communication error } else { // service requested ok
CObservation2DRangeScanPtr laserScan; // A smart-pointer to the laser scan (read below)
if (!sensorError) { try { // De-serialize the object: mrpt::utils::CSerializablePtr obj = SeqOfBytes2MRPTObject(SF);
// Assure it's a valid observation (if not, the "catch" block will take control): ASSERT_(obj) ASSERT_( IS_CLASS(obj,CSensoryFrame) )
CSensoryFramePtr theSF = CSensoryFramePtr(obj);
laserScan = theSF->getObservationByClass<CObservation2DRangeScan>(); // Get the first scan, if any. } catch(std::exception &e) { // Process ERROR, message in e.what() } }
// Free memory of the Sequence delete SF; SF = NULL;
	// Now, we have the latest scan laser in the variable "laserScan", which 
	//  is a smart pointer to a mrpt::slam::CObservation2DRangeScan
	// -------------------------------------------------------------------------
	if (laserScan)
	{
		// ******* YOUR CODE HERE **************
		// Access to the object data members to get the scan data.
		// Refer to: http://babel.isa.uma.es/mrpt/reference/svn/classmrpt_1_1slam_1_1_c_observation2_d_range_scan.html
		// Examples:
		//   Scan size: laserScan->scan.size()
		//   Scan point[0]: laserScan->scan[0]
		//   Scan point[0] is valid: laserScan->validRange[0]!=0
	}
	else
	{
		// For some reason (comms error, hardware error, etc...) there is no laser scan.
	}
}
</cpp>
Auxiliary code
Add the following auxiliary function to your module "Auxiliary logic" section, since this function is used in the code above:
<cpp> // SeqOfBytes2MRPTObject: Convert a BABEL sequence of bytes into a MRPT object. // IMPORTANT: "T of seqofbytes" must be a POINTER to a BABEL sequence, not a reference to it. template <typename T> mrpt::utils::CSerializablePtr SeqOfBytes2MRPTObject(const T &seqofbytes) { if (seqofbytes->length()==0) return mrpt::utils::CSerializablePtr(); mrpt::utils::CMemoryStream memBlock;
memBlock.assignMemoryNotOwn(&(*seqofbytes)[0], seqofbytes->length() );
return memBlock.ReadObject(); } </cpp>
Non-deportabilities of the module
If your module didn't use MRPT before adding these code fragments, it must be inserted by:
- Selecting the tab "Non-deportabilities" in BABEL_MD.
- Select "Execution".
- Add "mrpt-core" from the list below.
- Save the module.
You'll need MRPT installed as explained here.




