diff --git a/dfall_ws/src/dfall_pkg/crazyradio/CrazyRadio.py b/dfall_ws/src/dfall_pkg/crazyradio/CrazyRadio.py
index 2a9ae6dcd1ab0743fe1712cdd0a80553281e064f..ee4569312a33fc00851554fc595a34dc8cbf0ecf 100755
--- a/dfall_ws/src/dfall_pkg/crazyradio/CrazyRadio.py
+++ b/dfall_ws/src/dfall_pkg/crazyradio/CrazyRadio.py
@@ -55,8 +55,10 @@ import struct
 import logging
 
 # Import the ROS bag package for logging
-import rosbag
-from rospkg import RosPack
+#import rosbag
+#from rospkg import RosPack
+
+# Import the ROS standard message types
 from std_msgs.msg import Float32
 from std_msgs.msg import String
 
@@ -133,11 +135,11 @@ FLYING_VEHICLE_STATE_TYPE_CRAZYFLIE_STATE_ESTIMATE    = 2
 
 
 # Open the ROS bag for logging
-rp = RosPack()
-record_file = rp.get_path('dfall_pkg') + '/LoggingOnboard.bag'
-rospy.loginfo('afdsasdfasdfsadfasdfasdfasdfasdfasdfasdf')
-rospy.loginfo(record_file)
-bag = rosbag.Bag(record_file, 'w')
+#rp = RosPack()
+#record_file = rp.get_path('dfall_pkg') + '/LoggingOnboard.bag'
+#rospy.loginfo('afdsasdfasdfsadfasdfasdfasdfasdfasdfasdf')
+#rospy.loginfo(record_file)
+#bag = rosbag.Bag(record_file, 'w')
 
 class CrazyRadioClient:
     """
@@ -769,8 +771,8 @@ if __name__ == '__main__':
 
 
     # Close the ROS loggin bag
-    bag.close()
-    rospy.loginfo("[CRAZY RADIO] Logging bag closed")
+    #bag.close()
+    #rospy.loginfo("[CRAZY RADIO] Logging bag closed")
 
     # Close the CrazyRadio link
     cf_client._cf.close_link()
diff --git a/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h b/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h
index de922337cfda598797d36915256aa311662bb180..5e09499b58d66bf629711c54b55a296f47f249b9 100644
--- a/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h
+++ b/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h
@@ -124,30 +124,46 @@ std::string m_namespace_to_coordinator_parameter_service;
 
 
 
+// VARIABLES FOR SOTRING THE PARAMETERS OF WHICH
+// MEASUREMENT STREAMS TO USE
+bool yaml_shouldUse_mocapMeasurements = false;
+bool yaml_shouldUse_onboardEstimate   = false;
+
+// SUBSCRIBERS FOR THE MEASUREMENT STREAMS
+ros::Subscriber viconSubscriber;
+ros::Subscriber onboardEstimateSubscriber;
+
+
+
+// VARIABLES FOR AVAILABILITY AND VALIDITY OF MEASUREMENTS
+// > Boolen indicating if the Mocap data is availble
+bool m_isAvailable_measurement_data = false;
+// > Boolen indicating if the object is "long term" invalid
+bool m_isValid_measurement_data = false;
+// > Number of consecutive invalid measurements that triggers
+//   the "m_isValid_measurement_data" variable to be "false"
+int yaml_consecutive_invalid_threshold = 30;
+// > Timer that when triggered determines that the
+//   "m_isAvailable_measurement_data" variable becomes false
+ros::Timer m_timer_measurement_data_timeout_check;
+// > Time out duration after which measurement data is
+//   considered unavailable
+float yaml_measurement_timeout_duration = 1.0;
+
+
+
 // VARIABLES FOR THE MOTION CAPTURE DATA
 // > The index for which element in the "motion capture
 //   data" array is expected to match the name in
 //   "m_context", (negative numbers indicate unknown)
 int m_poseDataIndex = -1;
-// > Boolen indicating if the Mocap data is availble
-bool m_isAvailable_mocap_data = false;
-// > Boolen indicating if the object is "long term" occuled
-bool m_isOcculded_mocap_data = false;
-// > Number of consecutive occulsions that trigger the
-//   "m_isOcculded_mocap_data" variable to be "true"
-int yaml_consecutive_occulsions_threshold = 30;
-// > Timer that when triggered determines that the
-//   "m_isAvailable_mocap_data" variable becomes true
-ros::Timer m_timer_mocap_timeout_check;
-// > Time out duration after which Mocap is considered unavailable
-float yaml_mocap_timeout_duration = 1.0;
-
-// VARIABLES FOR GETTING MOTION CAPTURE DATA OF OTHER OBJECTS
+//  > The index for getting motion capture data of other
+//    objects
 int m_otherObjectPoseDataIndex = -1;
 
 
 
-// VARIABLES FOR STORING THE PARAMTER OF THE POSITION
+// VARIABLES FOR STORING THE PARAMETERS FOR THE POSITION
 // AND TILT ANGLE SAFTY CHECKS
 // > Boolean indicating whether the tilt angle check
 //   should be performed
@@ -280,12 +296,27 @@ int getPoseDataForObjectNameWithExpectedIndex(const ViconData& viconData, std::s
 // > For converting the global frame motion capture
 //   data to the local frame of this agent
 void coordinatesToLocal(FlyingVehicleState& cf);
-// > Callback run when motion capture data has not
-//   been receive for a specified time
-void timerCallback_mocap_timeout_check(const ros::TimerEvent&);
+
+
+
+// FUNCTIONS FOR HANDLING THE ONBOARD STATE ESTIMATE
+// > Callback run every time new state estimate
+//   data is available from onboard the flying vehicle
+void onboardEstimateCallback(const FlyingVehicleState& flyingVehicleState);
+
+
+
+// FUNCTIONS FOR CALLING THE CONTROLLER SERVICE
+// > For calling the controller service for the currently
+//   selected controller, and then sending the control
+//   command to the CrazyRadio node
+void callControllerServiceWithGivenData(FlyingVehicleState& dataForThisAgent, FlyingVehicleState& dataForOtherAgent);
 // > For sending a command, via the CrazyRadio, that
 //   the motors should be set to zero
 void sendZeroOutputCommandForMotors();
+// > Callback run when measurement data has not
+//   been received for a specified time
+void timerCallback_measurement_data_timeout_check(const ros::TimerEvent&);
 
 
 
diff --git a/dfall_ws/src/dfall_pkg/param/FlyingAgentClientConfig.yaml b/dfall_ws/src/dfall_pkg/param/FlyingAgentClientConfig.yaml
index 6edb428394692da236ffb24a4c522657fb19c334..94b423c16324d79819f98455a74817a37970fa08 100755
--- a/dfall_ws/src/dfall_pkg/param/FlyingAgentClientConfig.yaml
+++ b/dfall_ws/src/dfall_pkg/param/FlyingAgentClientConfig.yaml
@@ -14,17 +14,22 @@ testMotorsController: "TestMotorsControllerService/TestMotorsController"
 # Controller for requests manoeuvres to be performed
 defaultController_requestManoeuvre: "DefaultControllerService/RequestManoeuvre"
 
+# Flags for which measurement streams to use
+shouldUse_mocapMeasurements: false
+shouldUse_onboardEstimate: true
+
 # Flag for whether to use angle for switching
 # to the Default Controller
 isEnabled_strictSafety: true
 maxTiltAngle_for_strictSafety_degrees: 70
 
-# Number of consecutive occulsions that will deem the
-# object as "long-term" occuled
-consecutive_occulsions_threshold: 30
+# Number of consecutive invalid measurements that
+# will deem the object as "long-term" unavailable
+consecutive_invalid_threshold: 30
 
-# Time out duration after which Mocap is considered unavailable
-mocap_timeout_duration: 2.0
+# Time out duration after which measurements are
+# considered unavailable
+measurement_timeout_duration: 2.0
 
 # Flag for whether the take-off should be performed
 # with the default controller
diff --git a/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp b/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp
index 9e249f432eb2cea2e2c6c29ada9ef3dc3ee0e64a..ba64d0847db933703ec9d5f1b766c1d2d567287e 100755
--- a/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp
+++ b/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp
@@ -59,7 +59,6 @@
 
 
 
-
 //    ----------------------------------------------------------------------------------
 //    M   M   OOO   TTTTT  III   OOO   N   N
 //    MM MM  O   O    T     I   O   O  NN  N
@@ -81,12 +80,9 @@ void viconCallback(const ViconData& viconData)
 	//       CAPTURE SYSTEM. HENCE ANY OPTERATIONS PERFORMED IN
 	//       THIS FUNCTION MUST BE NON-BLOCKING.
 
-	// Initialise a counter of consecutive frames of motion
-	// capture data where the agent is occuled
-	static int number_of_consecutive_occulsions = 0;
-
 	// Initilise a variable for the pose data of this agent
 	FlyingVehicleState poseDataForThisAgent;
+	poseDataForThisAgent.isValid = false;
 
 	// Extract the pose data for the allocated object from the
 	// full motion capture array
@@ -94,6 +90,8 @@ void viconCallback(const ViconData& viconData)
 	//       indicates that the pose data was not found.
 	m_poseDataIndex = getPoseDataForObjectNameWithExpectedIndex( viconData, m_context.crazyflieName , m_poseDataIndex , poseDataForThisAgent );
 
+
+
 	// Initilise a variable for the pose data of another agent
 	FlyingVehicleState poseDataForOtherAgent;
 	poseDataForOtherAgent.isValid = false;
@@ -104,73 +102,231 @@ void viconCallback(const ViconData& viconData)
 	//       indicates that the pose data was not found.
 	//m_otherObjectPoseDataIndex = getPoseDataForObjectNameWithExpectedIndex( viconData, "NameOfOtherObject" , m_otherObjectPoseDataIndex , poseDataForOtherAgent );
 
-	// Detecting time-out of the motion capture data
-	// > Update the flag
-	m_isAvailable_mocap_data = true;
-	// > Stop any previous instance that might still be running
-	m_timer_mocap_timeout_check.stop();
-	// > Set the period again (second argument is reset)
-	m_timer_mocap_timeout_check.setPeriod( ros::Duration(yaml_mocap_timeout_duration), true);
-	// > Start the timer again
-	m_timer_mocap_timeout_check.start();
 
 
 	// Only continue if:
-	// (1) the pose for this agent was found, and
-	// (2) the controllers are actually available
-	// (2) the flying state is something other than MOTORS-OFF
+	// (1) the pose for this agent was found
+	if (m_poseDataIndex >= 0)
+	{
+		callControllerServiceWithGivenData(poseDataForThisAgent, poseDataForOtherAgent);
+	}
+	else
+	{
+		// Send the command to turn the motors off
+		sendZeroOutputCommandForMotors();
+	}
+}
+
+
+
+
+
+int getPoseDataForObjectNameWithExpectedIndex(const ViconData& viconData, std::string name , int expected_index , FlyingVehicleState& pose_to_fill_in)
+{
+	// Initialise an integer for the index where the object
+	// "name" is found
+	// > Initialise an negative to indicate not found
+	int object_index = -1;
+
+	// Get the length of the "pose data array"
+	int length_poseData = viconData.crazyflies.size();
+
+	// If the "expected index" is non-negative and less than
+	// the length of the data array, then attempt to check
+	// for a name match
 	if (
-		(m_poseDataIndex >= 0)
+		(0 <= expected_index)
 		and
-		(m_controllers_avialble)
+		(expected_index < length_poseData)
 	)
 	{
+		// Check if the names match
+		if (viconData.crazyflies[expected_index].vehicleName == name)
+		{
+			object_index = expected_index;
+		}
+	}
 
-        // If motors-off and testing motors
-        if (
-            m_flying_state == STATE_MOTORS_OFF
-            &&
-            m_controller_nominally_selected == TESTMOTORS_CONTROLLER
-            &&
-            m_testMotorsController.exists()
-            )
-        {
-            // Initliase the "Contrller" service call variable
-            Controller testMotorsCall;
+	// If not found, then iterate the data array looking
+	// for a name match
+	if (object_index < 0)
+	{
+		for( int i=0 ; i<length_poseData ; i++ )
+		{    
+			// Check if the names match
+			if(viconData.crazyflies[i].vehicleName == name)
+			{
+				object_index = i;
+			}
+		}
+	}
 
-            // Initialise a local boolean success variable
-            bool isSuccessful_testMotorsCall = false;
+	// If not found, then retrun, else fill in the pose data
+	if (object_index < 0)
+	{
+		return object_index;
+	}
+	else
+	{
+		pose_to_fill_in = viconData.crazyflies[object_index];
+		coordinatesToLocal(pose_to_fill_in);
+		return object_index;
+	}
+}
 
-            // Call the controller service client
-            isSuccessful_testMotorsCall = m_testMotorsController.call(testMotorsCall);
 
-            // Ensure success and enforce safety
-            if(isSuccessful_testMotorsCall)
-            {
-                m_commandForSendingToCrazyfliePublisher.publish(testMotorsCall.response.controlOutput);
-            }
-            else
-            {
-                // Let the user know that the controller call failed
-                ROS_ERROR_STREAM("[FLYING AGENT CLIENT] Failed to call test motors controller, valid: " << m_testMotorsController.isValid() << ", exists: " << m_testMotorsController.exists());
-                // Change back to the default controller
-                setControllerNominallySelected(DEFAULT_CONTROLLER);
-                // Send the command to turn the motors off
-                sendZeroOutputCommandForMotors();
-            }
-            return;
-        }
+void coordinatesToLocal(FlyingVehicleState& cf)
+{
+	// Get the area into a local variable
+	AreaBounds area = m_context.localArea;
+
+	// Shift the X-Y coordinates
+	float originX = (area.xmin + area.xmax) / 2.0;
+	float originY = (area.ymin + area.ymax) / 2.0;
+	cf.x -= originX;
+	cf.y -= originY;
+
+	// Shift the Z coordinate
+	// change Z origin to zero, i.e., to the table height, zero of global coordinates, instead of middle of the box
+	//float originZ = 0.0;
+	// float originZ = (area.zmin + area.zmax) / 2.0;
+	//cf.z -= originZ;
+}
+
+
+
+
+
+//    ---------------------------------------------------------------------------- %
+//     OOO   N   N  BBBB    OOO     A    RRRR   DDDD 
+//    O   O  NN  N  B   B  O   O   A A   R   R  D   D
+//    O   O  N N N  BBBB   O   O  A   A  RRRR   D   D
+//    O   O  N  NN  B   B  O   O  AAAAA  R   R  D   D
+//     OOO   N   N  BBBB    OOO   A   A  R   R  DDDD 
+//
+//    EEEEE   SSSS  TTTTT  III  M   M    A    TTTTT  EEEEE
+//    E      S        T     I   MM MM   A A     T    E    
+//    EEE     SSS     T     I   M M M  A   A    T    EEE  
+//    E          S    T     I   M   M  AAAAA    T    E    
+//    EEEEE  SSSS     T    III  M   M  A   A    T    EEEEE
+//    ---------------------------------------------------------------------------- %
+
+// FUNCTIONS FOR HANDLING THE ONBOARD STATE ESTIMATE
+// > Callback run every time new state estimate
+//   data is available from onboard the flying vehicle
+void onboardEstimateCallback(const FlyingVehicleState& flyingVehicleState)
+{
+	// Pass the receive data directly through
+	// > Copy into a local vairable first
+	FlyingVehicleState dataForThisAgent;
+	dataForThisAgent = flyingVehicleState;
+	
+	// Initialise an empty variable for the "other
+	// agent data" argument
+	FlyingVehicleState dataForOtherAgent;
+	dataForOtherAgent.isValid = false;
+
+	// Call the "call controller service" function
+	callControllerServiceWithGivenData( dataForThisAgent , dataForOtherAgent );
+}
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//     CCCC    A    L      L    
+//    C       A A   L      L    
+//    C      A   A  L      L    
+//    C      AAAAA  L      L    
+//     CCCC  A   A  LLLLL  LLLLL
+//
+//     CCCC   OOO   N   N  TTTTT  RRRR    OOO   L      L      EEEEE  RRRR 
+//    C      O   O  NN  N    T    R   R  O   O  L      L      E      R   R
+//    C      O   O  N N N    T    RRRR   O   O  L      L      EEE    RRRR 
+//    C      O   O  N  NN    T    R   R  O   O  L      L      E      R   R
+//     CCCC   OOO   N   N    T    R   R   OOO   LLLLL  LLLLL  EEEEE  R   R
+//
+//     SSSS  EEEEE  RRRR   V   V  III   CCCC  EEEEE
+//    S      E      R   R  V   V   I   C      E    
+//     SSS   EEE    RRRR   V   V   I   C      EEE  
+//        S  E      R   R   V V    I   C      E    
+//    SSSS   EEEEE  R   R    V    III   CCCC  EEEEE
+//    ----------------------------------------------------------------------------------
+
+// FUNCTION FOR CALLING THE CONTROLLER SERVICE FOR THE
+// CURRENTLY SELECTED CONTROLLER, AND THEN SENDING THE
+// CONTROL COMMAND TO THE CRAZYRADIO NODE
+void callControllerServiceWithGivenData(FlyingVehicleState& dataForThisAgent, FlyingVehicleState& dataForOtherAgent)
+{
+
+	// Initialise a counter of consecutive frames of motion
+	// capture data where the agent is occuled
+	static int number_of_consecutive_invalid_measurements = 0;
+
+	// Detecting time-out of the measurement data
+	// > Update the flag
+	m_isAvailable_measurement_data = true;
+	// > Stop any previous instance that might still be running
+	m_timer_measurement_data_timeout_check.stop();
+	// > Set the period again (second argument is reset)
+	m_timer_measurement_data_timeout_check.setPeriod( ros::Duration(yaml_measurement_timeout_duration), true);
+	// > Start the timer again
+	m_timer_measurement_data_timeout_check.start();
+
+	// Only continue if:
+	// (1) the controllers are actually available
+	if (m_controllers_avialble)
+	{
+
+		// Call the "test motors" controller only if:
+		// (1) in the motors-off state, and
+		// (2) "test motors" controller is selected, and
+		// (3) "test motors" controller exists
+		if (
+			m_flying_state == STATE_MOTORS_OFF
+			&&
+			m_controller_nominally_selected == TESTMOTORS_CONTROLLER
+			&&
+			m_testMotorsController.exists()
+			)
+		{
+			// Initliase the "Contrller" service call variable
+			Controller testMotorsCall;
+
+			// Initialise a local boolean success variable
+			bool isSuccessful_testMotorsCall = false;
+
+			// Call the controller service client
+			isSuccessful_testMotorsCall = m_testMotorsController.call(testMotorsCall);
+
+			// Ensure success and enforce safety
+			if(isSuccessful_testMotorsCall)
+			{
+				m_commandForSendingToCrazyfliePublisher.publish(testMotorsCall.response.controlOutput);
+			}
+			else
+			{
+				// Let the user know that the controller call failed
+				ROS_ERROR_STREAM("[FLYING AGENT CLIENT] Failed to call test motors controller, valid: " << m_testMotorsController.isValid() << ", exists: " << m_testMotorsController.exists());
+				// Change back to the default controller
+				setControllerNominallySelected(DEFAULT_CONTROLLER);
+				// Send the command to turn the motors off
+				sendZeroOutputCommandForMotors();
+			}
+			return;
+		}
 
 
 
 		// Only continue if:
 		// (1) the agent's pose data is valid
-		if(poseDataForThisAgent.isValid)
+		if(dataForThisAgent.isValid)
 		{
 			// Update the flag
-			m_isOcculded_mocap_data = false;
+			m_isValid_measurement_data = true;
 			// Reset the "consecutive occulsions" flag
-			number_of_consecutive_occulsions = 0;
+			number_of_consecutive_invalid_measurements = 0;
 
 
 			// Only continue if:
@@ -182,13 +338,13 @@ void viconCallback(const ViconData& viconData)
 				Controller controllerCall;
 
 				// Fill in the pose data for this agent
-				controllerCall.request.ownCrazyflie = poseDataForThisAgent;
+				controllerCall.request.ownCrazyflie = dataForThisAgent;
 
 				// Fill in the pose data of another agaent, if the data
 				// is avaialable
-				if (m_otherObjectPoseDataIndex >= 0)
+				if (dataForOtherAgent.isValid)
 				{
-					controllerCall.request.otherCrazyflies.push_back(poseDataForOtherAgent);
+					controllerCall.request.otherCrazyflies.push_back(dataForOtherAgent);
 				}
 
 				// Fill in the "isFirstControllerCall" field
@@ -206,7 +362,7 @@ void viconCallback(const ViconData& viconData)
 				// PERFORM THE SAFTY CHECK (IF NOT THE DEFAULT CONTROLLER)
 				if ( getInstantController() != DEFAULT_CONTROLLER )
 				{
-					if ( !safetyCheck_on_positionAndTilt(poseDataForThisAgent) )
+					if ( !safetyCheck_on_positionAndTilt(dataForThisAgent) )
 					{
 						setInstantController(DEFAULT_CONTROLLER);
 						ROS_INFO_STREAM("[FLYING AGENT CLIENT] safety check failed, switching to DEFAULT CONTROLLER");
@@ -268,24 +424,24 @@ void viconCallback(const ViconData& viconData)
 		else
 		{
 			// Increment the number of consective occulations
-			number_of_consecutive_occulsions++;
+			number_of_consecutive_invalid_measurements++;
 			// Update the flag if this exceeds the threshold
 			if (
-				(!m_isOcculded_mocap_data)
+				(m_isValid_measurement_data)
 				and
-				(number_of_consecutive_occulsions > yaml_consecutive_occulsions_threshold)
+				(number_of_consecutive_invalid_measurements > yaml_consecutive_invalid_threshold)
 			)
 			{
 				// Update the flag
-				m_isOcculded_mocap_data = true;
+				m_isValid_measurement_data = false;
 				// Inform the user
-				ROS_ERROR_STREAM("[FLYING AGENT CLIENT] Agent was occluded for more than " << yaml_consecutive_occulsions_threshold << " consecutive frames." );
+				ROS_ERROR_STREAM("[FLYING AGENT CLIENT] Measurement data was invalid for more than " << yaml_consecutive_invalid_threshold << " consecutive measurements." );
 				// Send the command to turn the motors off
 				sendZeroOutputCommandForMotors();
 				// Update the flying state
 				requestChangeFlyingStateTo( STATE_MOTORS_OFF );
 			}
-		} // END OF: "if(poseDataForThisAgent.isValid)"
+		} // END OF: "if(dataForThisAgent.isValid)"
 
 	}
 	else
@@ -293,104 +449,15 @@ void viconCallback(const ViconData& viconData)
 		// Send the command to turn the motors off
 		sendZeroOutputCommandForMotors();
 
-	} // END OF: "if ( (m_poseDataIndex >= 0) and (m_controllers_avialble) )"
-
-}
+	} // END OF: "if (m_controllers_avialble)"
 
 
-
-
-
-int getPoseDataForObjectNameWithExpectedIndex(const ViconData& viconData, std::string name , int expected_index , FlyingVehicleState& pose_to_fill_in)
-{
-    // Initialise an integer for the index where the object
-    // "name" is found
-    // > Initialise an negative to indicate not found
-    int object_index = -1;
-
-    // Get the length of the "pose data array"
-    int length_poseData = viconData.crazyflies.size();
-
-    // If the "expected index" is non-negative and less than
-    // the length of the data array, then attempt to check
-    // for a name match
-    if (
-        (0 <= expected_index)
-        and
-        (expected_index < length_poseData)
-    )
-    {
-        // Check if the names match
-        if (viconData.crazyflies[expected_index].vehicleName == name)
-        {
-            object_index = expected_index;
-        }
-    }
-
-    // If not found, then iterate the data array looking
-    // for a name match
-    if (object_index < 0)
-    {
-        for( int i=0 ; i<length_poseData ; i++ )
-        {    
-            // Check if the names match
-            if(viconData.crazyflies[i].vehicleName == name)
-            {
-                object_index = i;
-            }
-        }
-    }
-
-    // If not found, then retrun, else fill in the pose data
-    if (object_index < 0)
-    {
-        return object_index;
-    }
-    else
-    {
-        pose_to_fill_in = viconData.crazyflies[object_index];
-        coordinatesToLocal(pose_to_fill_in);
-        return object_index;
-    }
-}
-
-
-void coordinatesToLocal(FlyingVehicleState& cf)
-{
-	// Get the area into a local variable
-    AreaBounds area = m_context.localArea;
-
-    // Shift the X-Y coordinates
-    float originX = (area.xmin + area.xmax) / 2.0;
-    float originY = (area.ymin + area.ymax) / 2.0;
-    cf.x -= originX;
-    cf.y -= originY;
-
-    // Shift the Z coordinate
-    // change Z origin to zero, i.e., to the table height, zero of global coordinates, instead of middle of the box
-    //float originZ = 0.0;
-    // float originZ = (area.zmin + area.zmax) / 2.0;
-    //cf.z -= originZ;
 }
 
 
-void timerCallback_mocap_timeout_check(const ros::TimerEvent&)
-{
-	// Update the flag
-	m_isAvailable_mocap_data = false;
-	// Inform the user
-	ROS_ERROR_STREAM("[FLYING AGENT CLIENT] Motion Capture Data has been unavailable for " << yaml_mocap_timeout_duration << " seconds." );
-	// Ensure that the motors are turned off
-	if ( !(m_flying_state==STATE_MOTORS_OFF) )
-	{
-		// Send the command to turn the motors off
-        sendZeroOutputCommandForMotors();
-        // Update the flying state
-        requestChangeFlyingStateTo( STATE_MOTORS_OFF );
-	}
-}
-
 
+// FUNCTION FOR SENDING A COMMAND, VIA THE CRAZYRADIO, THAT
+// THE MOTORS SHOULD BE SET TO ZERO
 void sendZeroOutputCommandForMotors()
 {
 	// Initialise a "control command" struct
@@ -407,8 +474,28 @@ void sendZeroOutputCommandForMotors()
 	zeroOutput.motorCmd2 = 0.0;
 	zeroOutput.motorCmd3 = 0.0;
 	zeroOutput.motorCmd4 = 0.0;
-    // Publish the command
-    m_commandForSendingToCrazyfliePublisher.publish(zeroOutput);
+	// Publish the command
+	m_commandForSendingToCrazyfliePublisher.publish(zeroOutput);
+}
+
+
+
+// CALLBACK FUNCTION RUN WHEN MEASUREMENT DATA HAS
+// NOT BEEN RECEIVED FOR A SPECIFIED TIME
+void timerCallback_measurement_data_timeout_check(const ros::TimerEvent&)
+{
+	// Update the flag
+	m_isAvailable_measurement_data = false;
+	// Inform the user
+	ROS_ERROR_STREAM("[FLYING AGENT CLIENT] Measurement data has been unavailable for " << yaml_measurement_timeout_duration << " seconds." );
+	// Ensure that the motors are turned off
+	if ( !(m_flying_state==STATE_MOTORS_OFF) )
+	{
+		// Send the command to turn the motors off
+		sendZeroOutputCommandForMotors();
+		// Update the flying state
+		requestChangeFlyingStateTo( STATE_MOTORS_OFF );
+	}
 }
 
 
@@ -432,60 +519,60 @@ void sendZeroOutputCommandForMotors()
 // Checks if crazyflie is within allowed area
 bool safetyCheck_on_positionAndTilt(FlyingVehicleState data)
 {
-    // Check on the X position
-    float symmetric_bound_x = 0.5 * (m_context.localArea.xmax-m_context.localArea.xmin);
-    if((data.x < -symmetric_bound_x) or (data.x > symmetric_bound_x))
-    {
-        ROS_INFO_STREAM("[FLYING AGENT CLIENT] x safety failed");
-        return false;
-    }
-    // Check on the Y position
-    float symmetric_bound_y = 0.5 * (m_context.localArea.ymax-m_context.localArea.ymin);
-    if((data.y < -symmetric_bound_y) or (data.y > symmetric_bound_y))
-    {
-        ROS_INFO_STREAM("[FLYING AGENT CLIENT] y safety failed");
-        return false;
-    }
-    // Check on the Z position
-    if((data.z < m_context.localArea.zmin) or (data.z > m_context.localArea.zmax))
-    {
-        ROS_INFO_STREAM("[FLYING AGENT CLIENT] z safety failed");
-        return false;
-    }
+	// Check on the X position
+	float symmetric_bound_x = 0.5 * (m_context.localArea.xmax-m_context.localArea.xmin);
+	if((data.x < -symmetric_bound_x) or (data.x > symmetric_bound_x))
+	{
+		ROS_INFO_STREAM("[FLYING AGENT CLIENT] x safety failed");
+		return false;
+	}
+	// Check on the Y position
+	float symmetric_bound_y = 0.5 * (m_context.localArea.ymax-m_context.localArea.ymin);
+	if((data.y < -symmetric_bound_y) or (data.y > symmetric_bound_y))
+	{
+		ROS_INFO_STREAM("[FLYING AGENT CLIENT] y safety failed");
+		return false;
+	}
+	// Check on the Z position
+	if((data.z < m_context.localArea.zmin) or (data.z > m_context.localArea.zmax))
+	{
+		ROS_INFO_STREAM("[FLYING AGENT CLIENT] z safety failed");
+		return false;
+	}
 
-    // Check the title angle (if required)
-    // > The tilt anlge between the body frame and inertial frame z-axis is
-    //   give by:
-    //   tilt angle  =  1 / ( cos(roll)*cos(pitch) )
-    // > But this would be too sensitve to a divide by zero error, so instead
-    //   we just check if each angle separately exceeds the limit
-    if(yaml_isEnabled_strictSafety)
-    {
-        // Check on the ROLL angle
-        if(
-            (data.roll > yaml_maxTiltAngle_for_strictSafety_radians)
-            or
-            (data.roll < -yaml_maxTiltAngle_for_strictSafety_radians)
-        )
-        {
-            ROS_INFO_STREAM("[FLYING AGENT CLIENT] roll too big.");
-            return false;
-        }
-        // Check on the PITCH angle
-        if(
-            (data.pitch > yaml_maxTiltAngle_for_strictSafety_radians)
-            or
-            (data.pitch < -yaml_maxTiltAngle_for_strictSafety_radians)
-        )
-        {
-            ROS_INFO_STREAM("[FLYING AGENT CLIENT] pitch too big.");
-            return false;
-        }
-    }
+	// Check the title angle (if required)
+	// > The tilt anlge between the body frame and inertial frame z-axis is
+	//   give by:
+	//   tilt angle  =  1 / ( cos(roll)*cos(pitch) )
+	// > But this would be too sensitve to a divide by zero error, so instead
+	//   we just check if each angle separately exceeds the limit
+	if(yaml_isEnabled_strictSafety)
+	{
+		// Check on the ROLL angle
+		if(
+			(data.roll > yaml_maxTiltAngle_for_strictSafety_radians)
+			or
+			(data.roll < -yaml_maxTiltAngle_for_strictSafety_radians)
+		)
+		{
+			ROS_INFO_STREAM("[FLYING AGENT CLIENT] roll too big.");
+			return false;
+		}
+		// Check on the PITCH angle
+		if(
+			(data.pitch > yaml_maxTiltAngle_for_strictSafety_radians)
+			or
+			(data.pitch < -yaml_maxTiltAngle_for_strictSafety_radians)
+		)
+		{
+			ROS_INFO_STREAM("[FLYING AGENT CLIENT] pitch too big.");
+			return false;
+		}
+	}
 
-    // If the code makes it to here then all the safety checks passed,
-    // Hence return "true"
-    return true;
+	// If the code makes it to here then all the safety checks passed,
+	// Hence return "true"
+	return true;
 }
 
 
@@ -573,7 +660,7 @@ void requestChangeFlyingStateToTakeOff()
 	else
 	{
 		// Check that the Motion Capture data is available
-		if ( m_isAvailable_mocap_data and !m_isOcculded_mocap_data )
+		if ( m_isAvailable_measurement_data and m_isValid_measurement_data )
 		{
 			// Check whether a "controller" take-off should
 			// be performed, and that not already in the
@@ -627,13 +714,13 @@ void requestChangeFlyingStateToTakeOff()
 		else
 		{
 			// Inform the user of the problem
-			if (!m_isAvailable_mocap_data)
+			if (!m_isAvailable_measurement_data)
 			{
-				ROS_ERROR("[FLYING AGENT CLIENT] Take-off not possible because the motion capture data is unavailable.");
+				ROS_ERROR("[FLYING AGENT CLIENT] Take-off not possible because the measurement data is unavailable.");
 			}
-			if (m_isOcculded_mocap_data)
+			if (!m_isValid_measurement_data)
 			{
-				ROS_ERROR("[FLYING AGENT CLIENT] Take-off not possible because the object is \"long-term\" occuled.");
+				ROS_ERROR("[FLYING AGENT CLIENT] Take-off not possible because the object measurements are \"long-term\" invalid.");
 			}
 		}
 	}
@@ -1414,16 +1501,20 @@ void fetchFlyingAgentClientConfigYamlParameters(ros::NodeHandle& nodeHandle)
     // Add the "FlyingAgentClientConfig" namespace to the "nodeHandle"
     ros::NodeHandle nodeHandle_for_paramaters(nodeHandle, "FlyingAgentClientConfig");
 
+    // Flags for which measurement streams to use
+    yaml_shouldUse_mocapMeasurements = getParameterBool(nodeHandle_for_paramaters,"shouldUse_mocapMeasurements");
+	yaml_shouldUse_onboardEstimate   = getParameterBool(nodeHandle_for_paramaters,"shouldUse_onboardEstimate");
+
     // Flag for whether to use angle for switching to the Safe Controller
     yaml_isEnabled_strictSafety = getParameterBool(nodeHandle_for_paramaters,"isEnabled_strictSafety");
     yaml_maxTiltAngle_for_strictSafety_degrees = getParameterFloat(nodeHandle_for_paramaters,"maxTiltAngle_for_strictSafety_degrees");
 
     // Number of consecutive occulsions that will deem the
     // object as "long-term" occuled
-	yaml_consecutive_occulsions_threshold = getParameterInt(nodeHandle_for_paramaters,"consecutive_occulsions_threshold");
+	yaml_consecutive_invalid_threshold = getParameterInt(nodeHandle_for_paramaters,"consecutive_invalid_threshold");
 
 	// Time out duration after which Mocap is considered unavailable
-	yaml_mocap_timeout_duration = getParameterFloat(nodeHandle_for_paramaters,"mocap_timeout_duration");
+	yaml_measurement_timeout_duration = getParameterFloat(nodeHandle_for_paramaters,"measurement_timeout_duration");
 
 	// Flag for whether the take-off should be performed
 	//  with the default controller
@@ -1442,6 +1533,37 @@ void fetchFlyingAgentClientConfigYamlParameters(ros::NodeHandle& nodeHandle)
     // Convert from degrees to radians
     yaml_maxTiltAngle_for_strictSafety_radians = DEG2RAD * yaml_maxTiltAngle_for_strictSafety_degrees;
 
+    // Adjust the measurement subscribers
+	// > Localisation data from motion capture
+	if (yaml_shouldUse_mocapMeasurements)
+	{
+		// > Create a node handle to the root of the D-FaLL system
+		ros::NodeHandle nodeHandle_dfall_root("/dfall");
+		// > keeps 50 messages because otherwise the next message may
+	//   overwrite the data while the current message is been used
+		viconSubscriber = nodeHandle_dfall_root.subscribe("ViconDataPublisher/ViconData", 50, viconCallback);
+	}
+	else
+	{
+		viconSubscriber.shutdown();
+	}
+
+	// > Localisation from onboard the flying vehicle
+	if (yaml_shouldUse_onboardEstimate)
+	{
+		// > Create a node handle for the Crazyradio
+		std::string m_namespace = ros::this_node::getNamespace();
+		std::string namespace_to_crazy_radio = m_namespace + "/CrazyRadio";
+		ros::NodeHandle nodeHandle_to_crazy_radio(namespace_to_crazy_radio);
+		// > keeps 20 messages because otherwise the next message may
+		//   overwrite the data while the current message is been used
+		onboardEstimateSubscriber = nodeHandle_to_crazy_radio.subscribe("CFStateEstimate", 20, onboardEstimateCallback);
+	}
+	else
+	{
+		onboardEstimateSubscriber.shutdown();
+	}
+
     // DEBUGGING: Print out one of the processed values
     ROS_INFO_STREAM("[FLYING AGENT CLIENT CONTROLLER] DEBUGGING: after processing yaml_maxTiltAngle_for_strictSafety_radians = " << yaml_maxTiltAngle_for_strictSafety_radians);
 }
@@ -1577,9 +1699,9 @@ int main(int argc, char* argv[])
 
 	// INITIALISE THE MOTION CAPTURE TIME-OUT TIMER
 	// > And stop it immediately
-	m_isAvailable_mocap_data = false;
-	m_timer_mocap_timeout_check = nodeHandle.createTimer(ros::Duration(yaml_mocap_timeout_duration), timerCallback_mocap_timeout_check, true);
-	m_timer_mocap_timeout_check.stop();
+	m_isAvailable_measurement_data = false;
+	m_timer_measurement_data_timeout_check = nodeHandle.createTimer(ros::Duration(yaml_measurement_timeout_duration), timerCallback_measurement_data_timeout_check, true);
+	m_timer_measurement_data_timeout_check.stop();
 
 
 
@@ -1616,6 +1738,10 @@ int main(int argc, char* argv[])
 	constructNamespaceForCoordinator( m_coordID, namespace_to_coordinator );
 	ros::NodeHandle nodeHandle_to_coordinator(namespace_to_coordinator);
 
+	// CREATE A NODE HANDLE FOR THE CRAZYRADIO
+	std::string namespace_to_crazy_radio = m_namespace + "/CrazyRadio";
+	ros::NodeHandle nodeHandle_to_crazy_radio(namespace_to_crazy_radio);
+
 
 	// LOADING OF THIS AGENT'S CONTEXT
 	// Service cleint for loading the allocated flying
@@ -1634,9 +1760,21 @@ int main(int argc, char* argv[])
 
 
 	// LOCALISATION DATA FROM MOTION CAPTURE SYSTEM
-	//keeps 100 messages because otherwise ViconDataPublisher would override the data immediately
-	ros::Subscriber viconSubscriber = nodeHandle_dfall_root.subscribe("ViconDataPublisher/ViconData", 100, viconCallback);
+	// > keeps 50 messages because otherwise the next message may
+	//   overwrite the data while the current message is been used
+	if (yaml_shouldUse_mocapMeasurements)
+	{
+		viconSubscriber = nodeHandle_dfall_root.subscribe("ViconDataPublisher/ViconData", 50, viconCallback);
+	}
+
 
+	// LOCALISATION DATA FROM ONBOARD THE FLYING VEHICLE
+	// > keeps 20 messages because otherwise the next message may
+	//   overwrite the data while the current message is been used
+	if (yaml_shouldUse_onboardEstimate)
+	{
+		onboardEstimateSubscriber = nodeHandle_to_crazy_radio.subscribe("CFStateEstimate", 20, onboardEstimateCallback);
+	}
 
 
 	// PUBLISHER FOR COMMANDING THE CRAZYFLIE
@@ -1674,9 +1812,7 @@ int main(int argc, char* argv[])
 
 
 	// SUBSCRIBER FOR CRAZY RADIO STATUS CHANGES
-	// crazyradio status. Connected, connecting or disconnected
-	std::string namespace_to_crazy_radio = m_namespace + "/CrazyRadio";
-	ros::NodeHandle nodeHandle_to_crazy_radio(namespace_to_crazy_radio);
+	// Crazyradio status: { connected , connecting , disconnected }
 	ros::Subscriber crazyRadioStatusSubscriber = nodeHandle_to_crazy_radio.subscribe("CrazyRadioStatus", 1, crazyRadioStatusCallback);