/**
 Helper function: setupQuadMotor
 */
void ConfigMultiRotorWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
{
    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);

    setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_MOTOR);

    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, 127);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2, 0);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL, roll*127);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH, pitch*127);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, yaw*127);
}
void HashMap::merge(TransactionContext& txn) {
	if (hashMapImage_->front_ > INITIAL_HASH_ARRAY_SIZE) {
		if (hashMapImage_->split_ == 0) {
			hashMapImage_->front_ = hashMapImage_->front_ >> 1;
			hashMapImage_->split_ = hashMapImage_->front_;
			hashMapImage_->toMerge_ = false;
		}

		hashMapImage_->split_--;
		hashMapImage_->rear_--;
		uint64_t sourceBucketId = hashMapImage_->rear_;

		Bucket sourceBucket(
			txn, *getObjectManager(), maxArraySize_, maxCollisionArraySize_);
		hashArray_.get(txn, sourceBucketId, sourceBucket);

		Bucket::Cursor cursor(txn, *getObjectManager());
		sourceBucket.set(txn, cursor);

		bool isNext = sourceBucket.next(txn, cursor);
		if (!isNext) {
			return;
		}

		uint32_t addr = hashBucketAddrFromObject<T>(
			txn, sourceBucket.getCurrentOId(cursor));
		cursor.array_.reset();

		Bucket targetBucket(
			txn, *getObjectManager(), maxArraySize_, maxCollisionArraySize_);
		hashArray_.get(txn, addr, targetBucket);

		if (targetBucket.merge(txn, sourceBucket, ThresholdMergeLimit_) == 0) {
			hashMapImage_->toMerge_ = false;
			hashMapImage_->split_++;
			hashMapImage_->rear_++;
			return;
		}
	}
void ConfigAutotuneWidget::refreshWidgetsValues(UAVObject *obj)
{
    ModuleSettings *moduleSettings = ModuleSettings::GetInstance(getObjectManager());
    if(obj==moduleSettings)
    {
        bool dirtyBack=isDirty();
        ModuleSettings::DataFields moduleSettingsData = moduleSettings->getData();
        m_autotune->enableAutoTune->setChecked(
            moduleSettingsData.AdminState[ModuleSettings::ADMINSTATE_AUTOTUNE] == ModuleSettings::ADMINSTATE_ENABLED);
        setDirty(dirtyBack);
    }
    ConfigTaskWidget::refreshWidgetsValues(obj);
}
Exemple #4
0
bool Window::configExitGL()
{
    Renderer* rendererImpl = getRendererImpl();
    rendererImpl->setWindow( this );
    seq::Renderer* const renderer = getRenderer();
    const bool last = !getObjectManager()->isShared();

    bool ret = renderer->exitContext();
    if( last && !renderer->exit( ))
        ret = false;

    rendererImpl->setWindow( 0 );
    return ret;
}
/*!
	@brief Free Objects related to HashMap
*/
int32_t HashMap::finalize(TransactionContext& txn) {
	setDirty();
	if (size() > 0) {
		for (uint64_t i = 0; i < hashMapImage_->rear_; i++) {
			Bucket bucket(txn, *getObjectManager(), maxArraySize_,
				maxCollisionArraySize_);
			hashArray_.get(txn, i, bucket);
			bucket.clear(txn);
		}
	}
	hashArray_.finalize(txn);
	BaseObject::finalize();
	return GS_SUCCESS;
}
/**
   Updates the custom airframe settings based on the current airframe.

   Note: does NOT ask for an object refresh itself!
 */
void ConfigVehicleTypeWidget::updateFeedForwardUI()
{
    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

    Q_ASSERT(mixer);

    QPointer<VehicleConfig> vconfig = new VehicleConfig();

    // Update feed forward settings
    m_aircraft->feedForwardSlider->setValue(vconfig->getMixerValue(mixer, "FeedForward") * 100);
    m_aircraft->accelTime->setValue(vconfig->getMixerValue(mixer, "AccelTime"));
    m_aircraft->decelTime->setValue(vconfig->getMixerValue(mixer, "DecelTime"));
    m_aircraft->maxAccelSlider->setValue(vconfig->getMixerValue(mixer, "MaxAccel"));
}
void ConfigModuleWidget::toggleVibrationTest()
{
    VibrationAnalysisSettings *vibrationAnalysisSettings;
    vibrationAnalysisSettings = VibrationAnalysisSettings::GetInstance(getObjectManager());
    VibrationAnalysisSettings::DataFields vibrationAnalysisSettingsData;
    vibrationAnalysisSettingsData = vibrationAnalysisSettings->getData();

    // Toggle state
    if (vibrationAnalysisSettingsData.TestingStatus == VibrationAnalysisSettings::TESTINGSTATUS_ON)
        vibrationAnalysisSettingsData.TestingStatus = VibrationAnalysisSettings::TESTINGSTATUS_OFF;
    else
        vibrationAnalysisSettingsData.TestingStatus = VibrationAnalysisSettings::TESTINGSTATUS_ON;

    // Send data
    vibrationAnalysisSettings->setData(vibrationAnalysisSettingsData);
    vibrationAnalysisSettings->updated();
}
/**
  Launches the AHRS sensors calibration
  */
void ConfigAHRSWidget::launchAHRSCalibration()
{
    m_ahrs->calibInstructions->setText("Estimating sensor variance...");
    m_ahrs->ahrsCalibStart->setEnabled(false);

    UAVObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("AHRSCalibration")));
    UAVObjectField *field = obj->getField(QString("measure_var"));
    field->setValue("MEASURE");
    obj->updated();

    QTimer::singleShot(calibrationDelay*1000, this, SLOT(calibPhase2()));
    m_ahrs->calibProgress->setRange(0,calibrationDelay);
    phaseCounter = 0;
    progressBarIndex = 0;
    connect(&progressBarTimer, SIGNAL(timeout()), this, SLOT(incrementProgress()));
    progressBarTimer.start(1000);
}
void ConfigStabilizationWidget::updateObjectFromThrottleCurve()
{
    UAVObject *stabBank = getObjectManager()->getObject(QString(m_stabTabBars.at(0)->tabData(m_currentStabSettingsBank).toString()));

    Q_ASSERT(stabBank);

    UAVObjectField *field = stabBank->getField("ThrustPIDScaleCurve");
    Q_ASSERT(field);

    QList<double> curve   = ui->thrustPIDScalingCurve->getCurve();
    for (quint32 i = 0; i < field->getNumElements(); i++) {
        field->setValue(curve.at(i), i);
    }

    field = stabBank->getField("EnableThrustPIDScaling");
    Q_ASSERT(field);
    field->setValue(ui->enableThrustPIDScalingCheckBox->isChecked() ? "TRUE" : "FALSE");
}
/**
 * @brief UAVObjectUtilManager::saveNextObject
 *
 * Processes the save queue.
 */
void UAVObjectUtilManager::saveNextObject()
{
    if ( queue.isEmpty() ) {
        return;
    }

    Q_ASSERT(saveState == IDLE);

    // Get next object from the queue (don't dequeue yet)
    UAVObject* obj = queue.head();
    Q_ASSERT(obj);
    qDebug() << "Send save object request to board " << obj->getName();

    ObjectPersistence * objectPersistence = ObjectPersistence::GetInstance(getObjectManager());
    Q_ASSERT(objectPersistence);

    // "transactionCompleted" is emitted once the objectPersistence object is sent over the telemetry link.
    // Since its metadata state that it should be ACK'ed on flight telemetry, the transactionCompleted signal
    // will be triggered once the GCS telemetry manager receives an ACK from the flight controller, or times
    // out. the success value will reflect success or failure.
    connect(objectPersistence, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject*,bool)));
    // After we update the objectPersistence UAVO, we need to listen to its "objectUpdated" event, which will occur
    // once the flight controller sends this object back to the GCS, with the "Operation" field set to "Completed"
    // or "Error".
    connect(objectPersistence, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectPersistenceUpdated(UAVObject *)));
    saveState = AWAITING_ACK;
    qDebug() << "[saveObjectToFlash] Moving on to AWAITING_ACK";

    ObjectPersistence::DataFields data;
    data.Operation = ObjectPersistence::OPERATION_SAVE;
    data.Selection = ObjectPersistence::SELECTION_SINGLEOBJECT;
    data.ObjectID = obj->getObjID();
    data.InstanceID = obj->getInstID();
    objectPersistence->setData(data);
    objectPersistence->updated();
    // Now: we are going to get the following:
    // - two "objectUpdated" messages (one coming from GCS, one coming from Flight, which will confirm the object
    //   was properly received by both sides). This is because the metadata of objectPersistence has "FlightUpdateOnChange"
    //   set to true.
    //  - then one "transactionCompleted" indicating that the Flight side did not only receive the object but it did
    //    receive it without error (that message will be triggered by reception of the ACK).
    //  - Last we will get one last "objectUpdated" message coming from flight side, where we'll get the results of
    //    the objectPersistence operation we asked for (saved, other).
}
/**
   Setup steerable ground vehicle.

   Returns False if impossible to create the mixer.
 */
bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
{
    // Check coherence:
    // Show any config errors in GUI
    if (throwConfigError(airframeType)) {
        return false;
    }

    // Now setup the channels:
    GUIConfigDataUnion config = getConfigData();
    resetActuators(&config);

    config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
    config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex();

    setConfigData(config);

    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);
    resetMotorAndServoMixers(mixer);

    int channel = m_aircraft->gvSteering1ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);

    channel = m_aircraft->gvSteering2ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);

    channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);

    channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);

    // Output success message
    m_aircraft->gvStatusLabel->setText("Mixer generated");

    return true;
}
/**
  Sends the channel value to the UAV to move the servo.
  Returns immediately if we are not in testing mode
  */
void ConfigOutputWidget::sendChannelTest(int value)
{
	int in_value = value;

	QSlider *ob = (QSlider *)QObject::sender();
	if (!ob) return;
    int index = outSliders.indexOf(ob);
	if (index < 0) return;

	if (reversals[index]->isChecked())
		value = outMin[index]->value() - value + outMax[index]->value();	// the chsnnel is reversed

	// update the label
	outLabels[index]->setText(QString::number(value));

	if (links[index]->checkState())
	{	// the channel is linked to other channels
		// set the linked channels to the same value
		for (int i = 0; i < outSliders.count(); i++)
		{
			if (i == index) continue;
			if (!links[i]->checkState()) continue;

			int val = in_value;
			if (val < outSliders[i]->minimum()) val = outSliders[i]->minimum();
			if (val > outSliders[i]->maximum()) val = outSliders[i]->maximum();

			if (outSliders[i]->value() == val) continue;

			outSliders[i]->setValue(val);
			outLabels[i]->setText(QString::number(val));
		}
	}

	if (!m_config->channelOutTest->isChecked())
		return;

	UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
	if (!obj) return;
	UAVObjectField *channel = obj->getField("Channel");
	if (!channel) return;
	channel->setValue(value, index);
    obj->updated();
}
/**
 Setup steerable ground vehicle.
 
 Returns False if impossible to create the mixer.
 */
bool ConfigGroundVehicleWidget::setupGroundVehicleCar(SystemSettings::AirframeTypeOptions airframeType)
{
    // Check coherence:
	//Show any config errors in GUI
    if (throwConfigError(airframeType)) {
		return false;
	}

    // Now setup the channels:
    GUIConfigDataUnion config = GetConfigData();
    ResetActuators(&config);
	
    config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
    config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex();

    SetConfigData(config);

    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);
    resetMixers(mixerSettings);

    int channel = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_SERVO);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, 127);

    channel = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_SERVO);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, -127);

    channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_MOTOR);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, 127);

    channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_MOTOR);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2, 127);

	//Output success message
    m_aircraft->gvStatusLabel->setText("Mixer generated");
	
    return true;
}
/**
   Virtual function to refresh the UI widget values
 */
void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
{
    Q_ASSERT(m_aircraft);

    setupUI(frameType);

    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);

    QList<double> curveValues;
    getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);

    // is at least one of the curve values != 0?
    if (isValidThrottleCurve(&curveValues)) {
        // yes, use the curve we just read from mixersettings
        m_aircraft->fixedWingThrottle->initCurve(&curveValues);
    } else {
        // no, init a straight curve
        m_aircraft->fixedWingThrottle->initLinearCurve(curveValues.count(), 1.0);
    }

    GUIConfigDataUnion config    = getConfigData();
    fixedGUISettingsStruct fixed = config.fixedwing;

    // Then retrieve how channels are setup
    setComboCurrentIndex(m_aircraft->fwEngineChannelBox, fixed.FixedWingThrottle);
    setComboCurrentIndex(m_aircraft->fwAileron1ChannelBox, fixed.FixedWingRoll1);
    setComboCurrentIndex(m_aircraft->fwAileron2ChannelBox, fixed.FixedWingRoll2);
    setComboCurrentIndex(m_aircraft->fwElevator1ChannelBox, fixed.FixedWingPitch1);
    setComboCurrentIndex(m_aircraft->fwElevator2ChannelBox, fixed.FixedWingPitch2);
    setComboCurrentIndex(m_aircraft->fwRudder1ChannelBox, fixed.FixedWingYaw1);
    setComboCurrentIndex(m_aircraft->fwRudder2ChannelBox, fixed.FixedWingYaw2);

    // Get mixing values for GUI sliders (values stored onboard)
    m_aircraft->elevonSlider3->setValue(getMixerValue(mixer, "RollDifferential"));
    if (frameType == "FixedWingElevon" || frameType == "Elevon") {
        m_aircraft->elevonSlider1->setValue(getMixerValue(mixer, "MixerValueRoll"));
        m_aircraft->elevonSlider2->setValue(getMixerValue(mixer, "MixerValuePitch"));
    } else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
        m_aircraft->elevonSlider1->setValue(getMixerValue(mixer, "MixerValueYaw"));
        m_aircraft->elevonSlider2->setValue(getMixerValue(mixer, "MixerValuePitch"));
    }
}
Exemple #15
0
bool Window::configInitGL( const uint128_t& initID )
{
    Renderer* rendererImpl = getRendererImpl();
    rendererImpl->setWindow( this );

    co::Object* initData = getConfig()->getInitData();
    seq::Renderer* const renderer = getRenderer();
    const bool first = !getObjectManager()->isShared();

    if( first && !renderer->init( initData ))
    {
        rendererImpl->setWindow( 0 );
        return false;
    }
    const bool ret = renderer->initContext( initData );

    rendererImpl->setWindow( 0 );
    return ret;
}
Exemple #16
0
bool eqHello::Renderer::_loadShaders()
{
    seq::ObjectManager& om = getObjectManager();

    if (_program)
        return true;

    _program = om.newProgram(&_program);
    if (!seq::linkProgram(om.glewGetContext(), _program, vertexShader_glsl,
                          fragmentShader_glsl))
    {
        return false;
    }

    EQ_GL_CALL(glUseProgram(_program));
    _matrixUniform = glGetUniformLocation(_program, "MVP");
    EQ_GL_CALL(glUseProgram(0));
    return true;
}
/**
  Request the current config from the board
  */
void ConfigInputWidget::refreshValues()
{
    UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlSettings")));
    Q_ASSERT(obj);
    //obj->requestUpdate();
    UAVObjectField *field;

    // Now update all the slider values:

    UAVObjectField *field_max = obj->getField(QString("ChannelMax"));
    UAVObjectField *field_min = obj->getField(QString("ChannelMin"));
    UAVObjectField *field_neu = obj->getField(QString("ChannelNeutral"));
    Q_ASSERT(field_max);
    Q_ASSERT(field_min);
    Q_ASSERT(field_neu);
    for (int i = 0; i < 8; i++) {
        QVariant max = field_max->getValue(i);
        QVariant min = field_min->getValue(i);
        QVariant neutral = field_neu->getValue(i);
        inMaxLabels[i]->setText(max.toString());
        inMinLabels[i]->setText(min.toString());
        if (max.toInt()> min.toInt()) {
            inRevCheckboxes[i]->setChecked(false);
            inSliders[i]->setMaximum(max.toInt());
            inSliders[i]->setMinimum(min.toInt());
        } else {
            inRevCheckboxes[i]->setChecked(true);
            inSliders[i]->setMaximum(min.toInt());
            inSliders[i]->setMinimum(max.toInt());
        }
        inSliders[i]->setValue(neutral.toInt());
    }

    // Update receiver type
    field = obj->getField(QString("InputMode"));
    m_config->receiverType->setText(field->getValue().toString());

    // Reset all channel assignement dropdowns:
    foreach (QComboBox *combo, inChannelAssign) {
        combo->setCurrentIndex(0);
    }
/**
 Virtual function to refresh the UI widget values
 */
void ConfigGroundVehicleWidget::refreshAirframeWidgetsValues(SystemSettings::AirframeTypeOptions frameType)
{
    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);

    GUIConfigDataUnion config = GetConfigData();

	//THIS SECTION STILL NEEDS WORK. FOR THE MOMENT, USE THE FIXED-WING ONBOARD SETTING IN ORDER TO MINIMIZE CHANCES OF BOLLOXING REAL CODE
	// Retrieve channel setup values
    setComboCurrentIndex(m_aircraft->gvMotor1ChannelBox, config.ground.GroundVehicleThrottle1);
    setComboCurrentIndex(m_aircraft->gvMotor2ChannelBox, config.ground.GroundVehicleThrottle2);
    setComboCurrentIndex(m_aircraft->gvSteering1ChannelBox, config.ground.GroundVehicleSteering1);
    setComboCurrentIndex(m_aircraft->gvSteering2ChannelBox, config.ground.GroundVehicleSteering2);

    if (frameType == SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL) {
		//CURRENTLY BROKEN UNTIL WE DECIDE HOW DIFFERENTIAL SHOULD BEHAVE
		// If the vehicle type is "differential", restore the slider setting
		
		// Find the channel number for Motor1 
        int channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
        if (channel > -1) { // If for some reason the actuators were incoherent, we might fail here, hence the check.

            m_aircraft->differentialSteeringSlider1->setValue(getMixerVectorValue(mixerSettings,channel,MixerSettings::MIXER1VECTOR_ROLL)*100);
            m_aircraft->differentialSteeringSlider2->setValue(getMixerVectorValue(mixerSettings,channel,MixerSettings::MIXER1VECTOR_PITCH)*100);
		}
	}
    if (frameType == SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE) {
		//CURRENTLY BROKEN UNTIL WE DECIDE HOW MOTORCYCLE SHOULD BEHAVE
//		obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
//		Q_ASSERT(obj);
//		int chMixerNumber = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
//		if (chMixerNumber >=0) {
//			field = obj->getField(mixerVectors.at(chMixerNumber));
//			int ti = field->getElementNames().indexOf("Yaw");
//			m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
//			
//			ti = field->getElementNames().indexOf("Pitch");
//			m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*100);
//		}
	}
}
/**
  Sends the channel value to the UAV to move the servo.
  Returns immediately if we are not in testing mode
  */
void ConfigServoWidget::sendChannelTest(int value)
{
    // First of all, update the label:
    QSlider *ob = (QSlider*)QObject::sender();
    int index = outSliders.indexOf(ob);
    if (reversals[index]->isChecked())
        value = outMin[index]->value()-value+outMax[index]->value();
    else
        outLabels[index]->setText(QString::number(value));

    outLabels[index]->setText(QString::number(value));
    if (!m_config->channelOutTest->isChecked())
        return;

    UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));

    UAVObjectField * channel = obj->getField("Channel");
    channel->setValue(value,index);
    obj->updated();

}
/**
   Virtual function to update curve values from board
 */
void ConfigGroundVehicleWidget::initMixerCurves(QString frameType)
{
    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

    Q_ASSERT(mixer);

    QList<double> curveValues;
    getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);

    // is at least one of the curve values != 0?
    if (isValidThrottleCurve(&curveValues)) {
        // yes, use the curve we just read from mixersettings
        m_aircraft->groundVehicleThrottle1->initCurve(&curveValues);
    } else {
        // no, init a straight curve
        if (frameType == "GroundVehicleDifferential") {
            m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 0.8, 0.0);
        } else if (frameType == "GroundVehicleCar") {
            m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 1.0, 0.0);
        } else {
            m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 1.0, 0.0);
        }
    }

    // Setup all Throttle2 curves for all types of airframes
    getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);

    if (isValidThrottleCurve(&curveValues)) {
        m_aircraft->groundVehicleThrottle2->initCurve(&curveValues);
    } else {
        // no, init a straight curve
        if (frameType == "GroundVehicleDifferential") {
            m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 0.8, 0.0);
        } else if (frameType == "GroundVehicleCar") {
            m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0, 0.0);
        } else {
            m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0, 0.0);
        }
    }
}
ConfigCustomWidget::ConfigCustomWidget(QWidget *parent) :
    VehicleConfig(parent), m_aircraft(new Ui_CustomConfigWidget())
{
    m_aircraft->setupUi(this);

    // Put combo boxes in line one of the custom mixer table:
    UAVDataObject *mixer  = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);

    UAVObjectField *field = mixer->getField(QString("Mixer1Type"));
    QStringList list = field->getOptions();
    for (int i = 0; i < (int)VehicleConfig::CHANNEL_NUMELEM; i++) {
        QComboBox *qb = new QComboBox(m_aircraft->customMixerTable);
        qb->addItems(list);
        m_aircraft->customMixerTable->setCellWidget(0, i, qb);
    }

    SpinBoxDelegate *sbd = new SpinBoxDelegate();
    for (int i = 1; i < (int)VehicleConfig::CHANNEL_NUMELEM; i++) {
        m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
    }
}
Exemple #22
0
bool Window::configInitGL( const eq::uint128_t& initID )
{
    if( !eq::Window::configInitGL( initID ))
        return false;

    glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, 1 );
    glEnable( GL_CULL_FACE ); // OPT - produces sparser images in DB mode
    glCullFace( GL_BACK );

    LBASSERT( !_state );
    _state = new VertexBufferState( getObjectManager( ));

    const Config*   config   = static_cast< const Config* >( getConfig( ));
    const InitData& initData = config->getInitData();

    if( initData.showLogo( ))
        _loadLogo();

    if( initData.useGLSL() )
        _loadShaders();

    return true;
}
int32_t HashMap::insertObject(
	TransactionContext& txn, const T key, uint32_t size, OId oId) {
	if (hashMapImage_->toSplit_) {
		split<T>(txn);
	}

	{
		uint32_t addr = hashBucketAddr<T>(key, size);
		Bucket bucket(
			txn, *getObjectManager(), maxArraySize_, maxCollisionArraySize_);
		hashArray_.get(txn, addr, bucket);
		size_t arraySize = bucket.append(txn, oId);
		hashMapImage_->size_++;  

		if (arraySize > hashMapImage_->thresholdSplit_ &&
			hashMapImage_->toMerge_ == false) {
			hashMapImage_->toSplit_ = true;
		}
	}


	return GS_SUCCESS;
}
/**
   Refreshes the current value of the SystemSettings which holds the aircraft type
   Note: The default behavior of ConfigTaskWidget is bypassed.
   Therefore no automatic synchronization of UAV Objects to UI is done.
 */
void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject *o)
{
    Q_UNUSED(o);

    if (!allObjectsUpdated()) {
        return;
    }

    bool dirty = isDirty();

    // Get the Airframe type from the system settings:
    UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));
    Q_ASSERT(system);

    UAVObjectField *field = system->getField(QString("AirframeType"));
    Q_ASSERT(field);

    // At this stage, we will need to have some hardcoded settings in this code, this
    // is not ideal, but there you go.
    QString frameType = field->getValue().toString();
    qDebug() << "ConfigVehicleTypeWidget::refreshWidgetsValues - frame type:" << frameType;

    QString category  = frameCategory(frameType);
    setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText(category));

    VehicleConfig *vehicleConfig = getVehicleConfigWidget(category);
    if (vehicleConfig) {
        vehicleConfig->refreshWidgetsValues(frameType);
    }

    updateFeedForwardUI();

    setDirty(dirty);

    qDebug() << "ConfigVehicleTypeWidget::refreshWidgetsValues - end";
}
Exemple #25
0
void ConfigPlugin::eraseDone(UAVObject * obj)
{
    QMessageBox msgBox;
    ObjectPersistence* objper = ObjectPersistence::GetInstance(getObjectManager());
    ObjectPersistence::DataFields data = objper->getData();
    Q_ASSERT(obj->getInstID() == objper->getInstID());

    if(data.Operation != ObjectPersistence::OPERATION_COMPLETED) {
        return;
    }

    disconnect(objper, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(eraseDone(UAVObject *)));
    if (data.Operation == ObjectPersistence::OPERATION_COMPLETED) {
        settingsErased = true;
        msgBox.setText(tr("Settings are now erased."));
        msgBox.setInformativeText(tr("Please wait for the status LED to begin flashing regularly (up to a minute) then power-cycle your board to complete reset."));
    } else {
        msgBox.setText(tr("Error trying to erase settings."));
        msgBox.setInformativeText(tr("Power-cycle your board after removing all blades. Settings might be inconsistent."));
    }
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    msgBox.exec();
}
/**
  * Apply the stabilization settings computed
  */
void ConfigAutotuneWidget::saveStabilization()
{
    StabilizationSettings *stabilizationSettings = StabilizationSettings::GetInstance(getObjectManager());
    Q_ASSERT(stabilizationSettings);
    if(!stabilizationSettings)
        return;

    // Check the settings are reasonable, or if not have the
    // user confirm they want to continue.
    SystemIdent *systemIdent = SystemIdent::GetInstance(getObjectManager());
    Q_ASSERT(systemIdent);
    if(!systemIdent)
        return;
    if (approveSettings(systemIdent->getData()) == false)
        return;

    // Make sure to recompute in case the other stab settings changed since
    // the last time
    recomputeStabilization();

    // Apply this data to the board
    stabilizationSettings->setData(stabSettings);
    stabilizationSettings->updated();
}
/**
   Helper function to
 */
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
{
    UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));

    Q_ASSERT(system);

    QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));

    // Do not allow changes until AirframeType == Custom
    // If user want to save custom mixer : first set AirframeType to 'Custom' without changes and next modify.
    if (field->getValue().toString() == "Custom") {
        UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

        Q_ASSERT(mixer);

        setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
        setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());

        GUIConfigDataUnion configData = getConfigData();
        resetActuators(&configData);

        // Update the table:
        for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
            QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
            if (q->currentText() == "Disabled") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
            } else if (q->currentText() == "Motor") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
                if (configData.custom.Motor1 == 0) {
                    configData.custom.Motor1 = channel + 1;
                } else if (configData.custom.Motor2 == 0) {
                    configData.custom.Motor2 = channel + 1;
                } else if (configData.custom.Motor3 == 0) {
                    configData.custom.Motor3 = channel + 1;
                } else if (configData.custom.Motor4 == 0) {
                    configData.custom.Motor4 = channel + 1;
                } else if (configData.custom.Motor5 == 0) {
                    configData.custom.Motor5 = channel + 1;
                } else if (configData.custom.Motor6 == 0) {
                    configData.custom.Motor6 = channel + 1;
                } else if (configData.custom.Motor7 == 0) {
                    configData.custom.Motor7 = channel + 1;
                } else if (configData.custom.Motor8 == 0) {
                    configData.custom.Motor8 = channel + 1;
                }
            } else if (q->currentText() == "ReversableMotor") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
                if (configData.custom.RevMotor1 == 0) {
                    configData.custom.RevMotor1 = channel + 1;
                } else if (configData.custom.RevMotor2 == 0) {
                    configData.custom.RevMotor2 = channel + 1;
                } else if (configData.custom.RevMotor3 == 0) {
                    configData.custom.RevMotor3 = channel + 1;
                } else if (configData.custom.RevMotor4 == 0) {
                    configData.custom.RevMotor4 = channel + 1;
                } else if (configData.custom.RevMotor5 == 0) {
                    configData.custom.RevMotor5 = channel + 1;
                } else if (configData.custom.RevMotor6 == 0) {
                    configData.custom.RevMotor6 = channel;
                } else if (configData.custom.RevMotor7 == 0) {
                    configData.custom.RevMotor7 = channel;
                } else if (configData.custom.RevMotor8 == 0) {
                    configData.custom.RevMotor8 = channel;
                }
            } else if (q->currentText() == "Servo") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
                if (configData.custom.Servo1 == 0) {
                    configData.custom.Servo1 = channel + 1;
                } else if (configData.custom.Servo2 == 0) {
                    configData.custom.Servo2 = channel + 1;
                } else if (configData.custom.Servo3 == 0) {
                    configData.custom.Servo3 = channel + 1;
                } else if (configData.custom.Servo4 == 0) {
                    configData.custom.Servo4 = channel + 1;
                } else if (configData.custom.Servo5 == 0) {
                    configData.custom.Servo5 = channel + 1;
                } else if (configData.custom.Servo6 == 0) {
                    configData.custom.Servo6 = channel + 1;
                } else if (configData.custom.Servo7 == 0) {
                    configData.custom.Servo7 = channel + 1;
                } else if (configData.custom.Servo8 == 0) {
                    configData.custom.Servo8 = channel + 1;
                }
            } else if (q->currentText() == "CameraRoll") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
            } else if (q->currentText() == "CameraPitch") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
            } else if (q->currentText() == "CameraYaw") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
            } else if (q->currentText() == "Accessory0") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
            } else if (q->currentText() == "Accessory1") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
            } else if (q->currentText() == "Accessory2") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
            } else if (q->currentText() == "Accessory3") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
            } else if (q->currentText() == "Accessory4") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
            } else if (q->currentText() == "Accessory5") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
            }
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
                                m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
                                m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
                                m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
                                m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
                                m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
        }
        setConfigData(configData);
    }
    return "Custom";
}
/**
   Helper function to refresh the UI widget values
 */
void ConfigCustomWidget::refreshWidgetsValues(QString frameType)
{
    Q_ASSERT(m_aircraft);

    setupUI(frameType);

    UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));
    Q_ASSERT(system);
    QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));

    // Do not allow table edit until AirframeType == Custom
    // First save set AirframeType to 'Custom' and next modify.
    if (field->getValue().toString() != "Custom") {
        m_aircraft->customMixerTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
    } else {
        m_aircraft->customMixerTable->setEditTriggers(QAbstractItemView::AllEditTriggers);
    }

    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);

    getChannelDescriptions();

    QList<double> curveValues;
    getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);

    // is at least one of the curve values != 0?
    if (isValidThrottleCurve(&curveValues)) {
        // yes, use the curve we just read from mixersettings
        m_aircraft->customThrottle1Curve->initCurve(&curveValues);
    } else {
        // no, init a straight curve
        m_aircraft->customThrottle1Curve->initLinearCurve(curveValues.count(), 1.0);
    }

    double Throttle2CurveMin = m_aircraft->customThrottle2Curve->getMin();

    if (MixerSettings * mxr = qobject_cast<MixerSettings *>(mixer)) {
        MixerSettings::DataFields mixerSettingsData = mxr->getData();
        if (mixerSettingsData.Curve2Source == MixerSettings::CURVE2SOURCE_THROTTLE && Throttle2CurveMin >= 0) {
            m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_THROTTLE);
        } else {
            m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_PITCH);
        }
    }

    // Setup all Throttle2 curves for all types of airframes
    getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);

    if (isValidThrottleCurve(&curveValues)) {
        m_aircraft->customThrottle2Curve->initCurve(&curveValues);
    } else {
        m_aircraft->customThrottle2Curve->initLinearCurve(curveValues.count(), 1.0, m_aircraft->customThrottle2Curve->getMin());
    }

    // Update the mixer table:
    for (int channel = 0; channel < m_aircraft->customMixerTable->columnCount(); channel++) {
        UAVObjectField *field = mixer->getField(mixerTypes.at(channel));
        if (field) {
            QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
            if (q) {
                QString s = field->getValue().toString();
                setComboCurrentIndex(q, q->findText(s));
            }

            m_aircraft->customMixerTable->item(1, channel)->setText(
                QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1)));
            m_aircraft->customMixerTable->item(2, channel)->setText(
                QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2)));
            m_aircraft->customMixerTable->item(3, channel)->setText(
                QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL)));
            m_aircraft->customMixerTable->item(4, channel)->setText(
                QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH)));
            m_aircraft->customMixerTable->item(5, channel)->setText(
                QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW)));
        }
    }
}
Exemple #29
0
void Channel::_testDepthAssemble()
{
    //----- setup constant data
    const eq::Images& images = _frame.getImages();
    eq::Image* image  = images[ 0 ];
    LBASSERT( image );

    eq::Config* config = getConfig();
    const eq::PixelViewport& pvp    = getPixelViewport();
    const eq::Vector2i offset( pvp.x, pvp.y );

    ConfigEvent event = _createConfigEvent();
    event.area.x() = pvp.w;

    lunchbox::Clock clock;
    eq::Window::ObjectManager* glObjects = getObjectManager();
    const GLEWContext* glewContext = glewGetContext();

    //----- test depth-based assembly algorithms
    for( unsigned i = 0; i < NUM_IMAGES; ++i )
    {
        image = images[ i ];
        LBASSERT( image );
        image->setPixelViewport( pvp );
    }

    event.area.y() = pvp.h;

    for( unsigned i = 0; i < NUM_IMAGES; ++i )
    {
        _draw( i );

        // fill depth & color image
        image = images[ i ];

        LBCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR, 
                                         EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA, 
                                         glewContext ));

        LBCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH, 
                             EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
                                         glewContext ));

        image->clearPixelData( eq::Frame::BUFFER_COLOR );
        image->clearPixelData( eq::Frame::BUFFER_DEPTH );

        image->startReadback( eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH,
                              pvp, eq::Zoom::NONE, glObjects );
        image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));

        if( i == NUM_IMAGES-1 )
            _saveImage( image,"EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
                              "depthAssemble" );

        // benchmark
        eq::Compositor::ImageOp op;
        op.channel = this;
        op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
        op.offset  = offset;

        // fixed-function
        event.data.type = ConfigEvent::ASSEMBLE;
        snprintf( event.formatType, 32, "depth, GL1.1, %d images", i+1 ); 

        clock.reset();
        for( unsigned j = 0; j <= i; ++j )
            eq::Compositor::assembleImageDB_FF( images[j], op );

        event.msec = clock.getTimef();
        config->sendEvent( event );

        // GLSL
        if( GLEW_VERSION_2_0 )
        {
            snprintf( event.formatType, 32, "depth, GLSL,  %d images", i+1 ); 

            clock.reset();
            for( unsigned j = 0; j <= i; ++j )
                eq::Compositor::assembleImageDB_GLSL( images[j], op );
            event.msec = clock.getTimef();
            config->sendEvent( event );
        }

        // CPU
        snprintf( event.formatType, 32, "depth, CPU,   %d images", i+1 ); 

        std::vector< eq::Frame* > frames;
        frames.push_back( &_frame );

        clock.reset();
        eq::Compositor::assembleFramesCPU( frames, this );
        event.msec = clock.getTimef();
        config->sendEvent( event );
    }
}
Exemple #30
0
void Channel::_testTiledOperations()
{
    //----- setup constant data
    const eq::Images& images = _frame.getImages();
    LBASSERT( images[0] );

    eq::Config* config = getConfig();
    const eq::PixelViewport& pvp    = getPixelViewport();
    const eq::Vector2i     offset( pvp.x, pvp.y );

    ConfigEvent event = _createConfigEvent();
    event.area.x() = pvp.w;

    lunchbox::Clock clock;
    eq::Window::ObjectManager* glObjects = getObjectManager();
    const GLEWContext* glewContext = glewGetContext();

    //----- test tiled assembly algorithms
    eq::PixelViewport subPVP = pvp;
    subPVP.h /= NUM_IMAGES;

    for( unsigned i = 0; i < NUM_IMAGES; ++i )
    {
        LBASSERT( images[ i ] );
        images[ i ]->setPixelViewport( subPVP );
    }

    for( unsigned tiles = 0; tiles < NUM_IMAGES; ++tiles )
    {
        _draw( 0 );

        event.area.y() = subPVP.h * (tiles+1);

        //---- readback of 'tiles' depth images
        event.data.type = ConfigEvent::READBACK;
        snprintf( event.formatType, 32, "%d depth tiles", tiles+1 ); 

        event.msec = 0;
        for( unsigned j = 0; j <= tiles; ++j )
        {
            subPVP.y = pvp.y + j * subPVP.h;
            eq::Image* image = images[ j ];
            LBCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH, 
                             EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
                                             glewContext ));
            image->clearPixelData( eq::Frame::BUFFER_DEPTH );

            clock.reset();
            image->startReadback( eq::Frame::BUFFER_DEPTH, subPVP,
                                  eq::Zoom::NONE, glObjects );
            image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));
            event.msec += clock.getTimef();
            
        }

        config->sendEvent( event );

        if( tiles == NUM_IMAGES-1 )
            for( unsigned j = 0; j <= tiles; ++j )
                _saveImage( images[j],
                            "EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
                            "tiles" );

        //---- readback of 'tiles' color images
        event.data.type = ConfigEvent::READBACK;
        snprintf( event.formatType, 32, "%d color tiles", tiles+1 );

        event.msec = 0;
        for( unsigned j = 0; j <= tiles; ++j )
        {
            subPVP.y = pvp.y + j * subPVP.h;
            eq::Image* image = images[ j ];

            LBCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR, 
                                            EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA,
                                              glewContext ));
            image->clearPixelData( eq::Frame::BUFFER_COLOR );

            clock.reset();
            image->startReadback( eq::Frame::BUFFER_COLOR, subPVP,
                                  eq::Zoom::NONE, glObjects );
            image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));
            event.msec += clock.getTimef();
        }
        config->sendEvent( event );

        if( tiles == NUM_IMAGES-1 )
            for( unsigned j = 0; j <= tiles; ++j )
                _saveImage( images[j],"EQ_COMPRESSOR_DATATYPE_BGRA","tiles" );

        //---- benchmark assembly operations
        subPVP.y = pvp.y + tiles * subPVP.h;

        eq::Compositor::ImageOp op;
        op.channel = this;
        op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
        op.offset  = offset;

        // fixed-function
        event.data.type = ConfigEvent::ASSEMBLE;
        snprintf( event.formatType, 32, "tiles, GL1.1, %d images", tiles+1 ); 

        clock.reset();
        for( unsigned j = 0; j <= tiles; ++j )
            eq::Compositor::assembleImage( images[j], op );

        event.msec = clock.getTimef();
        config->sendEvent( event );

        // CPU
        snprintf( event.formatType, 32, "tiles, CPU,   %d images", tiles+1 ); 

        std::vector< eq::Frame* > frames;
        frames.push_back( &_frame );

        clock.reset();
        eq::Compositor::assembleFramesCPU( frames, this );
        event.msec = clock.getTimef();
        config->sendEvent( event );
    }
}