<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Justin Madsen, Daniel Melanz
// =============================================================================
//
// Front and Rear HMMWV suspension subsystems (double A-arm).
//
// These concrete suspension subsystems are defined with respect to right-handed
// frames having X pointing towards the rear, Y to the right, and Z up (as
// imposed by the base class ChDoubleWishbone) and origins at the
// midpoint between the lower control arm's connection points to the chassis.
//
// =============================================================================

#include "HMMWV_DoubleWishbone.h"

using namespace chrono;

namespace hmmwv {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------

static const double in2m = 0.0254;

const double     HMMWV_DoubleWishboneFront::m_spindleMass = 1;
const double     HMMWV_DoubleWishboneFront::m_UCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneFront::m_LCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneFront::m_uprightMass = 1;

const double     HMMWV_DoubleWishboneFront::m_spindleRadius = 0.15;
const double     HMMWV_DoubleWishboneFront::m_spindleWidth = 0.06;
const double     HMMWV_DoubleWishboneFront::m_LCARadius = 0.02;
const double     HMMWV_DoubleWishboneFront::m_UCARadius = 0.02;
const double     HMMWV_DoubleWishboneFront::m_uprightRadius = 0.02;

const ChVector<> HMMWV_DoubleWishboneFront::m_spindleInertia(1, 1, 1);
const ChVector<> HMMWV_DoubleWishboneFront::m_UCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneFront::m_LCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneFront::m_uprightInertia(5, 5, 5);

const double     HMMWV_DoubleWishboneFront::m_axleInertia = 0.4;

const double     HMMWV_DoubleWishboneFront::m_springCoefficient  = 167062.0;
const double     HMMWV_DoubleWishboneFront::m_dampingCoefficient = 22459.0;
const double     HMMWV_DoubleWishboneFront::m_springRestLength   = 0.4062;

// -----------------------------------------------------------------------------

const double     HMMWV_DoubleWishboneRear::m_spindleMass = 1;
const double     HMMWV_DoubleWishboneRear::m_UCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneRear::m_LCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneRear::m_uprightMass = 1;

const double     HMMWV_DoubleWishboneRear::m_spindleRadius = 0.15;
const double     HMMWV_DoubleWishboneRear::m_spindleWidth = 0.06;
const double     HMMWV_DoubleWishboneRear::m_LCARadius = 0.02;
const double     HMMWV_DoubleWishboneRear::m_UCARadius = 0.02;
const double     HMMWV_DoubleWishboneRear::m_uprightRadius = 0.02;

const ChVector<> HMMWV_DoubleWishboneRear::m_spindleInertia(1, 1, 1);
const ChVector<> HMMWV_DoubleWishboneRear::m_UCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneRear::m_LCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneRear::m_uprightInertia(5, 5, 5);

const double     HMMWV_DoubleWishboneRear::m_axleInertia = 0.4;

const double     HMMWV_DoubleWishboneRear::m_springCoefficient = 369149.0;
const double     HMMWV_DoubleWishboneRear::m_dampingCoefficient = 35024.0;
const double     HMMWV_DoubleWishboneRear::m_springRestLength = 0.4162;

// -----------------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------------
HMMWV_DoubleWishboneFront::HMMWV_DoubleWishboneFront(const std::string& name,
                                                       ChSuspension::Side side,
                                                       bool               driven)
: ChDoubleWishbone(name, side, driven)
{
}

HMMWV_DoubleWishboneRear::HMMWV_DoubleWishboneRear(const std::string& name,
                                                     ChSuspension::Side side,
                                                     bool               driven)
: ChDoubleWishbone(name, side, driven)
{
}

// -----------------------------------------------------------------------------
// Implementations of the getLocation() virtual methods.
// -----------------------------------------------------------------------------

const ChVector<> HMMWV_DoubleWishboneFront::getLocation(PointId which)
{
  switch (which) {
  case SPINDLE:  return in2m * ChVector<>(1.59, 23.72, -1.0350);
  case UPRIGHT:  return in2m * ChVector<>(1.59, 19.72, -1.0350);
  case UCA_F:    return in2m * ChVector<>(1.89, 5.46, 9.63);
  case UCA_B:    return in2m * ChVector<>(10.56, 5.46, 7.69);
  case UCA_U:    return in2m * ChVector<>(2.09, 16.07, 8.48);
  case UCA_CM:   return in2m * ChVector<>(4.85, 9.00, 8.60); // TODO: This is not the correct value
  case LCA_F:    return in2m * ChVector<>(-8.79, 0, 0);
  case LCA_B:    return in2m * ChVector<>(8.79, 0, 0);
  case LCA_U:    return in2m * ChVector<>(1.40, 18.87, -4.65);
  case LCA_CM:   return in2m * ChVector<>(0.47, 6.29, -1.55); // TODO: This is not the correct value
  case SHOCK_C:  return in2m * ChVector<>(-4.10, 15.77, 12.72);
  case SHOCK_U:  return in2m * ChVector<>(-3.83, 18.87, -1.52);
  case TIEROD_C: return in2m * ChVector<>(13.39, -2.29, -1.0350);
  case TIEROD_U: return in2m * ChVector<>(6.92, 20.22, -1.0350);
  default:       return ChVector<>(0, 0, 0);
  }
}

const ChVector<> HMMWV_DoubleWishboneRear::getLocation(PointId which)
{
  switch (which) {
  case SPINDLE:  return in2m * ChVector<>(-1.40, 23.72, -1.035);
  case UPRIGHT:  return in2m * ChVector<>(-1.40, 19.72, -1.035);
  case UCA_F:    return in2m * ChVector<>(-13.78, 6.10, 8.88);
  case UCA_B:    return in2m * ChVector<>(-3.07, 6.10, 8.88);
  case UCA_U:    return in2m * ChVector<>(-1.40, 16.07, 9.28);
  case UCA_CM:   return in2m * ChVector<>(-6.08, 9.42, 9.01); // TODO: This is not the correct value
  case LCA_F:    return in2m * ChVector<>(-8.79, 0, 0);
  case LCA_B:    return in2m * ChVector<>(8.79, 0, 0);
  case LCA_U:    return in2m * ChVector<>(-1.40, 18.87, -4.65);
  case LCA_CM:   return in2m * ChVector<>(-0.47, 6.29, -1.55); // TODO: This is not the correct value
  case SHOCK_C:  return in2m * ChVector<>(4.09, 16.10, 12.72);
  case SHOCK_U:  return in2m * ChVector<>(4.09, 18.87, -1.51);
  case TIEROD_C: return in2m * ChVector<>(-12.70, 4.28, -0.37);
  case TIEROD_U: return in2m * ChVector<>(-6.70, 20.23, -0.37);
  default:       return ChVector<>(0, 0, 0);
  }
}

} // end namespace hmmwv
<commit_msg>Change locations of the attachment points of the shock to the LCA and chassis. Increase spring free length back to original 0.4562 m.<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Justin Madsen, Daniel Melanz
// =============================================================================
//
// Front and Rear HMMWV suspension subsystems (double A-arm).
//
// These concrete suspension subsystems are defined with respect to right-handed
// frames having X pointing towards the rear, Y to the right, and Z up (as
// imposed by the base class ChDoubleWishbone) and origins at the
// midpoint between the lower control arm's connection points to the chassis.
//
// =============================================================================

#include "HMMWV_DoubleWishbone.h"

using namespace chrono;

namespace hmmwv {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------

static const double in2m = 0.0254;

const double     HMMWV_DoubleWishboneFront::m_spindleMass = 1;
const double     HMMWV_DoubleWishboneFront::m_UCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneFront::m_LCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneFront::m_uprightMass = 1;

const double     HMMWV_DoubleWishboneFront::m_spindleRadius = 0.15;
const double     HMMWV_DoubleWishboneFront::m_spindleWidth = 0.06;
const double     HMMWV_DoubleWishboneFront::m_LCARadius = 0.02;
const double     HMMWV_DoubleWishboneFront::m_UCARadius = 0.02;
const double     HMMWV_DoubleWishboneFront::m_uprightRadius = 0.02;

const ChVector<> HMMWV_DoubleWishboneFront::m_spindleInertia(1, 1, 1);
const ChVector<> HMMWV_DoubleWishboneFront::m_UCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneFront::m_LCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneFront::m_uprightInertia(5, 5, 5);

const double     HMMWV_DoubleWishboneFront::m_axleInertia = 0.4;

const double     HMMWV_DoubleWishboneFront::m_springCoefficient  = 167062.0;
const double     HMMWV_DoubleWishboneFront::m_dampingCoefficient = 22459.0;
const double     HMMWV_DoubleWishboneFront::m_springRestLength   = 0.4562;

// -----------------------------------------------------------------------------

const double     HMMWV_DoubleWishboneRear::m_spindleMass = 1;
const double     HMMWV_DoubleWishboneRear::m_UCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneRear::m_LCAMass = 1;  // TODO: This is not the correct value
const double     HMMWV_DoubleWishboneRear::m_uprightMass = 1;

const double     HMMWV_DoubleWishboneRear::m_spindleRadius = 0.15;
const double     HMMWV_DoubleWishboneRear::m_spindleWidth = 0.06;
const double     HMMWV_DoubleWishboneRear::m_LCARadius = 0.02;
const double     HMMWV_DoubleWishboneRear::m_UCARadius = 0.02;
const double     HMMWV_DoubleWishboneRear::m_uprightRadius = 0.02;

const ChVector<> HMMWV_DoubleWishboneRear::m_spindleInertia(1, 1, 1);
const ChVector<> HMMWV_DoubleWishboneRear::m_UCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneRear::m_LCAInertia(1, 1, 1);  // TODO: This is not the correct value
const ChVector<> HMMWV_DoubleWishboneRear::m_uprightInertia(5, 5, 5);

const double     HMMWV_DoubleWishboneRear::m_axleInertia = 0.4;

const double     HMMWV_DoubleWishboneRear::m_springCoefficient = 369149.0;
const double     HMMWV_DoubleWishboneRear::m_dampingCoefficient = 35024.0;
const double     HMMWV_DoubleWishboneRear::m_springRestLength = 0.4562;

// -----------------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------------
HMMWV_DoubleWishboneFront::HMMWV_DoubleWishboneFront(const std::string& name,
                                                       ChSuspension::Side side,
                                                       bool               driven)
: ChDoubleWishbone(name, side, driven)
{
}

HMMWV_DoubleWishboneRear::HMMWV_DoubleWishboneRear(const std::string& name,
                                                     ChSuspension::Side side,
                                                     bool               driven)
: ChDoubleWishbone(name, side, driven)
{
}

// -----------------------------------------------------------------------------
// Implementations of the getLocation() virtual methods.
// -----------------------------------------------------------------------------

const ChVector<> HMMWV_DoubleWishboneFront::getLocation(PointId which)
{
  switch (which) {
  case SPINDLE:  return in2m * ChVector<>(1.59, 23.72, -1.0350);
  case UPRIGHT:  return in2m * ChVector<>(1.59, 19.72, -1.0350);
  case UCA_F:    return in2m * ChVector<>(1.89, 5.46, 9.63);
  case UCA_B:    return in2m * ChVector<>(10.56, 5.46, 7.69);
  case UCA_U:    return in2m * ChVector<>(2.09, 16.07, 8.48);
  case UCA_CM:   return in2m * ChVector<>(4.85, 9.00, 8.60); // TODO: This is not the correct value
  case LCA_F:    return in2m * ChVector<>(-8.79, 0, 0);
  case LCA_B:    return in2m * ChVector<>(8.79, 0, 0);
  case LCA_U:    return in2m * ChVector<>(1.40, 18.87, -4.65);
  case LCA_CM:   return in2m * ChVector<>(0.47, 6.29, -1.55); // TODO: This is not the correct value
  case SHOCK_C:  return in2m * ChVector<>(-4.095, 7.508, 12.722);
  case SHOCK_U:  return in2m * ChVector<>(-3.827, 9.295, -1.835);
  case TIEROD_C: return in2m * ChVector<>(13.39, -2.29, -1.0350);
  case TIEROD_U: return in2m * ChVector<>(6.92, 20.22, -1.0350);
  default:       return ChVector<>(0, 0, 0);
  }
}

const ChVector<> HMMWV_DoubleWishboneRear::getLocation(PointId which)
{
  switch (which) {
  case SPINDLE:  return in2m * ChVector<>(-1.40, 23.72, -1.035);
  case UPRIGHT:  return in2m * ChVector<>(-1.40, 19.72, -1.035);
  case UCA_F:    return in2m * ChVector<>(-13.78, 6.10, 8.88);
  case UCA_B:    return in2m * ChVector<>(-3.07, 6.10, 8.88);
  case UCA_U:    return in2m * ChVector<>(-1.40, 16.07, 9.28);
  case UCA_CM:   return in2m * ChVector<>(-6.08, 9.42, 9.01); // TODO: This is not the correct value
  case LCA_F:    return in2m * ChVector<>(-8.79, 0, 0);
  case LCA_B:    return in2m * ChVector<>(8.79, 0, 0);
  case LCA_U:    return in2m * ChVector<>(-1.40, 18.87, -4.65);
  case LCA_CM:   return in2m * ChVector<>(-0.47, 6.29, -1.55); // TODO: This is not the correct value
  case SHOCK_C:  return in2m * ChVector<>(4.095, 7.508, 12.722);
  case SHOCK_U:  return in2m * ChVector<>(3.827, 9.325, -1.511);
  case TIEROD_C: return in2m * ChVector<>(-12.70, 4.28, -0.37);
  case TIEROD_U: return in2m * ChVector<>(-6.70, 20.23, -0.37);
  default:       return ChVector<>(0, 0, 0);
  }
}

} // end namespace hmmwv
<|endoftext|>


<commit_before>/*
* Copyright (C) 2016 German Aerospace Center (DLR/SC)
*
* Created: 2016-12-23 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "test.h" // Brings in the GTest framework
#include "tigl.h"
#include "CTiglPoint.h"
#include "CTiglPointTranslator.h"

#include <string.h>
#include <ctime>

/******************************************************************************/

class TestPerformance : public ::testing::Test
{
protected:
    static void SetUpTestCase()
    {
        const char* filename = "TestData/CPACS_30_D150.xml";
        ReturnCode tixiRet;
        TiglReturnCode tiglRet;

        tiglHandle = -1;
        tixiHandle = -1;

        tixiRet = tixiOpenDocument(filename, &tixiHandle);
        ASSERT_TRUE (tixiRet == SUCCESS);
        tiglRet = tiglOpenCPACSConfiguration(tixiHandle, "D150_VAMP", &tiglHandle);
        ASSERT_TRUE(tiglRet == TIGL_SUCCESS);
    }

    static void TearDownTestCase()
    {
        ASSERT_TRUE(tiglCloseCPACSConfiguration(tiglHandle) == TIGL_SUCCESS);
        ASSERT_TRUE(tixiCloseDocument(tixiHandle) == SUCCESS);
        tiglHandle = -1;
        tixiHandle = -1;
    }

    void SetUp() override {}
    void TearDown() override {}

    static TixiDocumentHandle           tixiHandle;
    static TiglCPACSConfigurationHandle tiglHandle;
};

TixiDocumentHandle TestPerformance::tixiHandle = 0;
TiglCPACSConfigurationHandle TestPerformance::tiglHandle = 0;

TEST_F(TestPerformance, wingGetPoint)
{
    int nruns = 500;
    double number = 0.;

    clock_t start = clock();

    for (int irun = 0; irun < nruns; ++irun) {
        int segIndex = rand() % 3 + 1;
        double px, py, pz;
        double eta = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);
        double xsi = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);

        ASSERT_EQ(TIGL_SUCCESS, tiglWingGetUpperPoint(tiglHandle, 1, segIndex, eta, xsi, &px, &py, &pz));
        ASSERT_EQ(TIGL_SUCCESS, tiglWingGetLowerPoint(tiglHandle, 1, segIndex, eta, xsi, &px, &py, &pz));

        // prevent compiler optimization
        number += 1.0;
    }

    clock_t stop = clock();
    if (fabs(number - nruns) < 1e-10) {
        double time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(2.*number) * 1000000.;
        std::cout << "Time wingGetPoint [us]: " << time_elapsed << std::endl;
    }
}

TEST_F(TestPerformance, fuselageGetPoint)
{
    int nruns = 100;
    double number = 0.;

    int nsegs = 0;
    ASSERT_EQ(TIGL_SUCCESS, tiglFuselageGetSegmentCount(tiglHandle, 1, &nsegs));

    // we are using a cached version, we must activat the cache
    double px, py, pz;
    ASSERT_EQ(TIGL_SUCCESS, tiglFuselageGetPoint(tiglHandle, 1, 1, 0.2, 0.5, &px, &py, &pz));

    clock_t start = clock();

    for (int irun = 0; irun < nruns; ++irun) {
        int segIndex = 1;
        double eta = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);
        double xsi = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);

        ASSERT_EQ(TIGL_SUCCESS, tiglFuselageGetPoint(tiglHandle, 1, segIndex, eta, xsi, &px, &py, &pz));

        // prevent compiler optimization
        number += 1.0;
    }

    clock_t stop = clock();
    if (fabs(number - nruns) < 1e-10) {
        double time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/number * 1000000.;
        std::cout << "Time fuselageGetPoint [us]: " << time_elapsed << std::endl;
    }
}

TEST_F(TestPerformance, pointTranslator)
{
    int nruns = 10000;
    double abs_error = 1e-6;

    tigl::CTiglPoint x1(0,4,0);
    tigl::CTiglPoint x2(8,4,0);
    tigl::CTiglPoint x3(0,0,0);
    tigl::CTiglPoint x4(4,0,0);

    tigl::CTiglPoint p(3,2,1);

    double eta, xsi;
    double x = 0.;

    tigl::CTiglPointTranslator trans(x1, x2, x3, x4 );

    clock_t start = clock();

    for(int i = 0; i < nruns; ++i){
        trans.translate(p, &eta, &xsi) ;
        //just some dummy to prevent compiler optimization
        x = x + 1.0;
    }

    clock_t stop = clock();

    ASSERT_EQ((double)nruns, x);
    ASSERT_NEAR(0.5, eta, abs_error);
    ASSERT_NEAR(0.5, xsi, abs_error);

    double time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time PointTranslator [us]: " << time_elapsed << std::endl;

    ASSERT_TRUE(true);
}

TEST_F(TestPerformance, tiglCheckPointInside)
{
    // some points that are exclusively in one component
    tigl::CTiglPoint pointInFuselage(5., 0., 0.);
    tigl::CTiglPoint pointInWing(16., 6., -1.);
    tigl::CTiglPoint pointInVTP(34., 0., 4.);
    tigl::CTiglPoint pointInSpace(1000., 1000., 1000.);

    TiglBoolean fusePointInside  = TIGL_FALSE;
    TiglBoolean wingPointInside  = TIGL_FALSE;
    TiglBoolean vtpPointInside   = TIGL_FALSE;
    TiglBoolean spacePointInside = TIGL_FALSE;

    int nruns = 50;
    double n;

    clock_t start, stop;
    double time_elapsed;

    // test the four points against the wing
    n = 0.;
    start = clock();
    for(int i = 0; i < nruns; ++i){
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInFuselage.x, pointInFuselage.y, pointInFuselage.z, "D150_VAMP_W1", &fusePointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInWing.x    , pointInWing.y    , pointInWing.z    , "D150_VAMP_W1", &wingPointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInVTP.x     , pointInVTP.y     , pointInVTP.z     , "D150_VAMP_W1", &vtpPointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInSpace.x   , pointInSpace.y   , pointInSpace.z   , "D150_VAMP_W1", &spacePointInside));
        n += 1.;  //dummy to prevent compiler optimization
    }
    stop = clock();

    ASSERT_FALSE(fusePointInside);
    ASSERT_TRUE(wingPointInside);
    ASSERT_FALSE(vtpPointInside);
    ASSERT_FALSE(spacePointInside);

    time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time tiglCheckPointInside wing [us]: " << time_elapsed << std::endl;

    // test the four points against the vtp
    n = 0.;
    start = clock();
    for(int i = 0; i < nruns; ++i){
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInFuselage.x, pointInFuselage.y, pointInFuselage.z, "D150_VAMP_SL1", &fusePointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInWing.x    , pointInWing.y    , pointInWing.z    , "D150_VAMP_SL1", &wingPointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInVTP.x     , pointInVTP.y     , pointInVTP.z     , "D150_VAMP_SL1", &vtpPointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInSpace.x   , pointInSpace.y   , pointInSpace.z   , "D150_VAMP_SL1", &spacePointInside));
        n += 1.;  //dummy to prevent compiler optimization
    }
    stop = clock();

    ASSERT_FALSE(fusePointInside);
    ASSERT_FALSE(wingPointInside);
    ASSERT_TRUE(vtpPointInside);
    ASSERT_FALSE(spacePointInside);

    time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time tiglCheckPointInside vtp [us]: " << time_elapsed << std::endl;

    // test the four points against the fuselage
    n = 0.;
    start = clock();
    for(int i = 0; i < nruns; ++i){
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInFuselage.x, pointInFuselage.y, pointInFuselage.z, "D150_VAMP_FL1", &fusePointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInWing.x    , pointInWing.y    , pointInWing.z    , "D150_VAMP_FL1", &wingPointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInVTP.x     , pointInVTP.y     , pointInVTP.z     , "D150_VAMP_FL1", &vtpPointInside));
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, pointInSpace.x   , pointInSpace.y   , pointInSpace.z   , "D150_VAMP_FL1", &spacePointInside));
        n += 1.;  //dummy to prevent compiler optimization
    }
    stop = clock();

    ASSERT_TRUE(fusePointInside);
    ASSERT_FALSE(wingPointInside);
    ASSERT_FALSE(vtpPointInside);
    ASSERT_FALSE(spacePointInside);

    time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time tiglCheckPointInside fuselage [us]: " << time_elapsed << std::endl;
}
<commit_msg>add warm start to performance test<commit_after>/*
* Copyright (C) 2016 German Aerospace Center (DLR/SC)
*
* Created: 2016-12-23 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "test.h" // Brings in the GTest framework
#include "tigl.h"
#include "CTiglPoint.h"
#include "CTiglPointTranslator.h"

#include "CNamedShape.h"
#include "CCPACSConfigurationManager.h"

#include <string.h>
#include <ctime>

/******************************************************************************/

class TestPerformance : public ::testing::Test
{
protected:
    static void SetUpTestCase()
    {
        const char* filename = "TestData/CPACS_30_D150.xml";
        ReturnCode tixiRet;
        TiglReturnCode tiglRet;

        tiglHandle = -1;
        tixiHandle = -1;

        tixiRet = tixiOpenDocument(filename, &tixiHandle);
        ASSERT_TRUE (tixiRet == SUCCESS);
        tiglRet = tiglOpenCPACSConfiguration(tixiHandle, "D150_VAMP", &tiglHandle);
        ASSERT_TRUE(tiglRet == TIGL_SUCCESS);
    }

    static void TearDownTestCase()
    {
        ASSERT_TRUE(tiglCloseCPACSConfiguration(tiglHandle) == TIGL_SUCCESS);
        ASSERT_TRUE(tixiCloseDocument(tixiHandle) == SUCCESS);
        tiglHandle = -1;
        tixiHandle = -1;
    }

    void SetUp() override {}
    void TearDown() override {}

    static TixiDocumentHandle           tixiHandle;
    static TiglCPACSConfigurationHandle tiglHandle;
};

TixiDocumentHandle TestPerformance::tixiHandle = 0;
TiglCPACSConfigurationHandle TestPerformance::tiglHandle = 0;

TEST_F(TestPerformance, wingGetPoint)
{
    int nruns = 500;
    double number = 0.;

    clock_t start = clock();

    for (int irun = 0; irun < nruns; ++irun) {
        int segIndex = rand() % 3 + 1;
        double px, py, pz;
        double eta = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);
        double xsi = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);

        ASSERT_EQ(TIGL_SUCCESS, tiglWingGetUpperPoint(tiglHandle, 1, segIndex, eta, xsi, &px, &py, &pz));
        ASSERT_EQ(TIGL_SUCCESS, tiglWingGetLowerPoint(tiglHandle, 1, segIndex, eta, xsi, &px, &py, &pz));

        // prevent compiler optimization
        number += 1.0;
    }

    clock_t stop = clock();
    if (fabs(number - nruns) < 1e-10) {
        double time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(2.*number) * 1000000.;
        std::cout << "Time wingGetPoint [us]: " << time_elapsed << std::endl;
    }
}

TEST_F(TestPerformance, fuselageGetPoint)
{
    int nruns = 100;
    double number = 0.;

    int nsegs = 0;
    ASSERT_EQ(TIGL_SUCCESS, tiglFuselageGetSegmentCount(tiglHandle, 1, &nsegs));

    // we are using a cached version, we must activat the cache
    double px, py, pz;
    ASSERT_EQ(TIGL_SUCCESS, tiglFuselageGetPoint(tiglHandle, 1, 1, 0.2, 0.5, &px, &py, &pz));

    clock_t start = clock();

    for (int irun = 0; irun < nruns; ++irun) {
        int segIndex = 1;
        double eta = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);
        double xsi = static_cast <double> (rand()) / static_cast <double> (RAND_MAX);

        ASSERT_EQ(TIGL_SUCCESS, tiglFuselageGetPoint(tiglHandle, 1, segIndex, eta, xsi, &px, &py, &pz));

        // prevent compiler optimization
        number += 1.0;
    }

    clock_t stop = clock();
    if (fabs(number - nruns) < 1e-10) {
        double time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/number * 1000000.;
        std::cout << "Time fuselageGetPoint [us]: " << time_elapsed << std::endl;
    }
}

TEST_F(TestPerformance, pointTranslator)
{
    int nruns = 10000;
    double abs_error = 1e-6;

    tigl::CTiglPoint x1(0,4,0);
    tigl::CTiglPoint x2(8,4,0);
    tigl::CTiglPoint x3(0,0,0);
    tigl::CTiglPoint x4(4,0,0);

    tigl::CTiglPoint p(3,2,1);

    double eta, xsi;
    double x = 0.;

    tigl::CTiglPointTranslator trans(x1, x2, x3, x4 );

    clock_t start = clock();

    for(int i = 0; i < nruns; ++i){
        trans.translate(p, &eta, &xsi) ;
        //just some dummy to prevent compiler optimization
        x = x + 1.0;
    }

    clock_t stop = clock();

    ASSERT_EQ((double)nruns, x);
    ASSERT_NEAR(0.5, eta, abs_error);
    ASSERT_NEAR(0.5, xsi, abs_error);

    double time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time PointTranslator [us]: " << time_elapsed << std::endl;

    ASSERT_TRUE(true);
}

TEST_F(TestPerformance, tiglCheckPointInside_false)
{

    // define some points that are exclusively in one component
    tigl::CTiglPoint point(1000., 1000., 1000.);
    TiglBoolean point_inside = TIGL_FALSE;

    // pre-build some geometries to warm start performance tests
    ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, point.x, point.y, point.z, "D150_VAMP_W1" , &point_inside));
    ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, point.x, point.y, point.z, "D150_VAMP_SL1", &point_inside));
    ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, point.x, point.y, point.z, "D150_VAMP_FL1", &point_inside));

    int nruns = 1000;
    double n;

    clock_t start, stop;
    double time_elapsed;

    // test the four points against the wing
    n = 0.;
    start = clock();
    for(int i = 0; i < nruns; ++i){
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, point.x, point.y, point.z, "D150_VAMP_W1", &point_inside));
        n += 1.;  //dummy to prevent compiler optimization
    }
    stop = clock();
    ASSERT_FALSE(point_inside);

    time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time tiglCheckPointInside wing [us]: " << time_elapsed << std::endl;

    // test the four points against the vtp
    n = 0.;
    start = clock();
    for(int i = 0; i < nruns; ++i){
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, point.x, point.y, point.z, "D150_VAMP_SL1", &point_inside));
        n += 1.;  //dummy to prevent compiler optimization
    }
    stop = clock();
    ASSERT_FALSE(point_inside);

    time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time tiglCheckPointInside vtp [us]: " << time_elapsed << std::endl;

    // test the four points against the fuselage
    n = 0.;
    start = clock();
    for(int i = 0; i < nruns; ++i){
        ASSERT_EQ(TIGL_SUCCESS, tiglCheckPointInside(tiglHandle, point.x, point.y, point.z, "D150_VAMP_FL1", &point_inside));
        n += 1.;  //dummy to prevent compiler optimization
    }
    stop = clock();
    ASSERT_FALSE(point_inside);

    time_elapsed = (double)(stop - start)/(double)CLOCKS_PER_SEC/(double)nruns * 1000000.;
    std::cout << "Time tiglCheckPointInside fuselage [us]: " << time_elapsed << std::endl;
}
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Morwenn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <algorithm>
#include <ctime>
#include <iterator>
#include <numeric>
#include <random>
#include <string>
#include <vector>
#include <catch.hpp>
#include <cpp-sort/sorters/spread_sorter.h>
#include <cpp-sort/sort.h>

////////////////////////////////////////////////////////////
// static_if utility

template<bool Condition>
struct static_if
{
    template<typename Func>
    static void run(Func) {}
};

template<>
struct static_if<true>
{
    template<typename Func>
    static void run(Func func)
    {
        func();
    }
};

////////////////////////////////////////////////////////////
// Actual tests

TEST_CASE( "spread_sorter tests", "[spread_sorter]" )
{
    // Pseudo-random number engine
    std::mt19937_64 engine(std::time(nullptr));

    SECTION( "sort with int iterable" )
    {
        std::vector<int> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with unsigned int iterators" )
    {
        std::vector<unsigned> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0u);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with float iterable" )
    {
        std::vector<float> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0.0f);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with double iterators" )
    {
        std::vector<double> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0.0);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with std::string iterable" )
    {
        std::vector<std::string> vec;
        for (int i = 0 ; i < 100'000 ; ++i)
        {
            vec.push_back(std::to_string(i));
        }
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with std::wstring iterators" )
    {
        static_if<sizeof(wchar_t) == 2>::run([&] {
            std::vector<std::wstring> vec;
            for (int i = 0 ; i < 100'000 ; ++i)
            {
                vec.push_back(std::to_wstring(i));
            }
            std::shuffle(std::begin(vec), std::end(vec), engine);
            cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{});
            CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
        });
    }

    SECTION( "reverse sort with std::string iterable" )
    {
        std::vector<std::string> vec;
        for (int i = 0 ; i < 100'000 ; ++i)
        {
            vec.push_back(std::to_string(i));
        }

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{}, std::greater<>{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<>{}) );

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{}, std::greater<std::string>{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<std::string>{}) );
    }

    SECTION( "reverse sort with std::wstring iterators" )
    {
        static_if<sizeof(wchar_t) == 2>::run([&] {
            std::vector<std::wstring> vec;
            for (int i = 0 ; i < 100'000 ; ++i)
            {
                vec.push_back(std::to_wstring(i));
            }

            std::shuffle(std::begin(vec), std::end(vec), engine);
            cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{}, std::greater<>{});
            CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<>{}) );

            std::shuffle(std::begin(vec), std::end(vec), engine);
            cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{}, std::greater<std::wstring>{});
            CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<std::wstring>{}) );
        });
    }
}
<commit_msg>Remove annoying std::wstring tests failing on Linux.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Morwenn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <algorithm>
#include <ctime>
#include <iterator>
#include <numeric>
#include <random>
#include <string>
#include <vector>
#include <catch.hpp>
#include <cpp-sort/sorters/spread_sorter.h>
#include <cpp-sort/sort.h>

TEST_CASE( "spread_sorter tests", "[spread_sorter]" )
{
    // Pseudo-random number engine
    std::mt19937_64 engine(std::time(nullptr));

    SECTION( "sort with int iterable" )
    {
        std::vector<int> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with unsigned int iterators" )
    {
        std::vector<unsigned> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0u);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with float iterable" )
    {
        std::vector<float> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0.0f);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with double iterators" )
    {
        std::vector<double> vec(100'000);
        std::iota(std::begin(vec), std::end(vec), 0.0);
        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "sort with std::string" )
    {
        std::vector<std::string> vec;
        for (int i = 0 ; i < 100'000 ; ++i)
        {
            vec.push_back(std::to_string(i));
        }

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec)) );
    }

    SECTION( "reverse sort with std::string" )
    {
        std::vector<std::string> vec;
        for (int i = 0 ; i < 100'000 ; ++i)
        {
            vec.push_back(std::to_string(i));
        }

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{}, std::greater<>{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<>{}) );

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{}, std::greater<>{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<>{}) );

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(vec, cppsort::spread_sorter{}, std::greater<std::string>{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<std::string>{}) );

        std::shuffle(std::begin(vec), std::end(vec), engine);
        cppsort::sort(std::begin(vec), std::end(vec), cppsort::spread_sorter{}, std::greater<std::string>{});
        CHECK( std::is_sorted(std::begin(vec), std::end(vec), std::greater<std::string>{}) );
    }
}
<|endoftext|>


<commit_before><commit_msg>Connection::create_db() and drop_db() use Query::exec() now, for efficiency, rather than Query::execute().<commit_after><|endoftext|>


<commit_before>/* scopevar.cpp
 * Copyright (C) 2005 Tommi Maekitalo
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "tnt/ecppc/scopevar.h"
#include <tnt/stringescaper.h>
#include <iterator>
#include <iostream>

namespace tnt
{
  namespace ecppc
  {
    void Scopevar::get(std::ostream& out, bool linenumbersEnabled) const
    {
      std::string tag =
          scope_container == ecpp::application_container ? "application"
        : scope_container == ecpp::thread_container      ? "thread"
        : scope_container == ecpp::session_container     ? "session"
        : scope_container == ecpp::request_container     ? "request"
        :                                                  "param";

      std::string macro;
      if (scope_container == ecpp::param_container)
      {
        macro = "TNT_PARAM";
      }
      else
      {
        std::string container =
            scope_container == ecpp::application_container ? "APPLICATION_"
          : scope_container == ecpp::thread_container      ? "THREAD_"
          : scope_container == ecpp::session_container     ? "SESSION_"
          : scope_container == ecpp::request_container     ? "REQUEST_"
          :                                                  "PARAM_";
        std::string key = scope == ecpp::global_scope ? "GLOBAL_"
                        : scope == ecpp::page_scope   ? "PAGE_"
                        : scope_container != ecpp::param_container ? "COMPONENT_"
                        : std::string();
        macro = "TNT_" + container + key + "VAR";
      }

      if (linenumbersEnabled)
        out << "#line " << (myline + 1) << " \"" << myfile << "\"\n";

      out << "  " << macro << '(' << type << ", " << var
          << ", \"" << var << "\", (" << init << ")); "
             "  // <%" << tag << "> " << type << ' ' << var;

      if (!init.empty())
      {
        out << '(';
        std::transform(
          init.begin(),
          init.end(),
          std::ostream_iterator<const char*>(out),
          stringescaper(false));
        out << ')';
      }

      out << '\n';
    }

  }
}
<commit_msg>add missing include<commit_after>/* scopevar.cpp
 * Copyright (C) 2005 Tommi Maekitalo
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "tnt/ecppc/scopevar.h"
#include <tnt/stringescaper.h>
#include <iterator>
#include <iostream>
#include <algorithm>

namespace tnt
{
  namespace ecppc
  {
    void Scopevar::get(std::ostream& out, bool linenumbersEnabled) const
    {
      std::string tag =
          scope_container == ecpp::application_container ? "application"
        : scope_container == ecpp::thread_container      ? "thread"
        : scope_container == ecpp::session_container     ? "session"
        : scope_container == ecpp::request_container     ? "request"
        :                                                  "param";

      std::string macro;
      if (scope_container == ecpp::param_container)
      {
        macro = "TNT_PARAM";
      }
      else
      {
        std::string container =
            scope_container == ecpp::application_container ? "APPLICATION_"
          : scope_container == ecpp::thread_container      ? "THREAD_"
          : scope_container == ecpp::session_container     ? "SESSION_"
          : scope_container == ecpp::request_container     ? "REQUEST_"
          :                                                  "PARAM_";
        std::string key = scope == ecpp::global_scope ? "GLOBAL_"
                        : scope == ecpp::page_scope   ? "PAGE_"
                        : scope_container != ecpp::param_container ? "COMPONENT_"
                        : std::string();
        macro = "TNT_" + container + key + "VAR";
      }

      if (linenumbersEnabled)
        out << "#line " << (myline + 1) << " \"" << myfile << "\"\n";

      out << "  " << macro << '(' << type << ", " << var
          << ", \"" << var << "\", (" << init << ")); "
             "  // <%" << tag << "> " << type << ' ' << var;

      if (!init.empty())
      {
        out << '(';
        std::transform(
          init.begin(),
          init.end(),
          std::ostream_iterator<const char*>(out),
          stringescaper(false));
        out << ')';
      }

      out << '\n';
    }

  }
}
<|endoftext|>


<commit_before>// $Id: lineBasedFile.C,v 1.10 2000/10/19 11:11:34 amoll Exp $

#include <BALL/FORMAT/lineBasedFile.h>
#include <BALL/COMMON/exception.h>
#include <stdio.h>

using namespace std;

namespace BALL
{

	LineBasedFile::LineBasedFileError::LineBasedFileError
		(const char* file, int line, const LineBasedFile* f, const string& message)
		: Exception::GeneralException(file, line, "LineBasedFileError", "")
	{
		message_ = message;
		if (f != 0)
		{
			message_ += "\n last read line number = ";
			char buf[40];
			sprintf(buf, "%i", (int) f->getLineNumber());
			message_ += buf;
			message_ += "\n contents of line: \n";
			message_ += f->getLine();
		}
		Exception::globalHandler.setMessage(message_);
	}

	LineBasedFile::LineBasedFile()
		throw()
		:	File(),
			line_number_(0)
	{
	}

	LineBasedFile::LineBasedFile(const LineBasedFile& f)
	 throw()
		: File(f),
			line_number_(0)
	{
			skipLines(f.line_number_ - 1);
	}

	LineBasedFile::LineBasedFile(const String& filename, File::OpenMode open_mode)
		throw(Exception::FileNotFound)
		: File(filename, open_mode),
			line_number_(0)
	{
		if (!isAccessible())
		{
			throw Exception::FileNotFound(__FILE__, __LINE__, filename);
		}
	}

	const LineBasedFile& LineBasedFile::operator = (const LineBasedFile& f)
		throw()
	{
		open(f.name_, f.getOpenMode());
		line_number_ = 0;
		skipLines(f.line_number_ - 1);
		return *this;
	}

	bool LineBasedFile::search(const String& text, bool return_to_point)
		throw(LineBasedFileError)
	{
		if (!isOpen() || getOpenMode() != IN)
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend for read access or at all.");
		}

		Position start_point = line_number_;
		while (readLine())
		{
			if (startsWith(text))
			{
				return true;
			}
		}

		if (return_to_point)
		{
			goToLine(start_point);
		}
		return false;
	}

	bool LineBasedFile::search(const String& text, const String& stop, bool return_to_point)
		throw(LineBasedFileError)
	{
		if (!isOpen() || getOpenMode() != IN)
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend for read access or at all.");
		}

		Position start_point = line_number_;

		while (readLine())
		{
			if (startsWith(stop))
			{
				if (return_to_point)
				{
					goToLine(start_point);
				}

				return false;
			}

			if (startsWith(text))
			{
				return true;
			}
		}

		if (return_to_point)
		{
			goToLine(start_point);
		}

		return false;
	}

	bool LineBasedFile::readLine()
		throw(LineBasedFileError)
	{
		if (!isOpen() || getOpenMode() != IN)
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend for read access or at all.");
		}

		if (eof())
		{
			return false;
		}

		char* c = new char[200];
		getline(c, 200);
		line_ = c;
		++line_number_;
		return true;
	}

	bool LineBasedFile::skipLines(Size number)
		throw(LineBasedFileError)
	{
		for (Position i = 0; i < number +1; i++)
		{
			if (!readLine())
			{
				return false;
			}
		}

		return true;
	}

	void LineBasedFile::rewind()
		 throw(LineBasedFileError)
	{
		if (!isOpen())
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend.");
		}
		File::reopen();
		line_number_ = 0;
		line_ = "";
	}

	bool LineBasedFile::goToLine(Position line_number)
		 throw(LineBasedFileError)
	{
		if (!isOpen())
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend.");
		}

		if (line_number == line_number_)
		{
			return true;
		}

		if (line_number < line_number_)
		{
			rewind();
			if (line_number == 0)
			{
				return true;
			}

			return skipLines(line_number - 1);
		}

		return skipLines(line_number - line_number_ - 1);
	}

	void LineBasedFile::clear()
		throw()
	{
		line_ = "";
		line_number_ = 0;
		close();
		name_ = "";
	}

	Position LineBasedFile::getLineNumber()
		const throw()
	{
		return line_number_;
	}

	const String& LineBasedFile::getLine()
		const throw()
	{
		return line_;
	}

	void LineBasedFile::test(const char* file, int line, bool condition, const String& msg)
		const throw(LineBasedFileError)
	{
		if (!condition)
		{
			throw LineBasedFileError(file, line, this, msg);
		}
	}

	String LineBasedFile::getField(Position pos, const String& quotes, const String& delimiters)
		const	throw(Exception::IndexUnderflow)
	{
		if (quotes == "")
		{
			return line_.getField((Index) pos, delimiters.c_str());
		}

		return line_.getFieldQuoted((Index) pos, delimiters.c_str(), quotes.c_str());
	}

	Index LineBasedFile::switchString(const vector<String>& data)
		const throw()
	{
		for (Index i = 0; i < data.size(); i++)
		{
			if (line_ == data[i])
			{
				return i;
			}
		}
		return (-1);
	}

	bool LineBasedFile::startsWith(const String& text)
		const throw()
	{
		return line_.hasPrefix(text);
	}

	bool LineBasedFile::has(const String& text)
		const throw()
	{
		return line_.hasSubstring(text);
	}

} //namespace
<commit_msg>fixed: cpy-constr<commit_after>// $Id: lineBasedFile.C,v 1.11 2000/10/19 20:06:23 amoll Exp $

#include <BALL/FORMAT/lineBasedFile.h>
#include <BALL/COMMON/exception.h>
#include <stdio.h>

using namespace std;

namespace BALL
{

	LineBasedFile::LineBasedFileError::LineBasedFileError
		(const char* file, int line, const LineBasedFile* f, const string& message)
		: Exception::GeneralException(file, line, "LineBasedFileError", "")
	{
		message_ = message;
		if (f != 0)
		{
			message_ += "\n last read line number = ";
			char buf[40];
			sprintf(buf, "%i", (int) f->getLineNumber());
			message_ += buf;
			message_ += "\n contents of line: \n";
			message_ += f->getLine();
		}
		Exception::globalHandler.setMessage(message_);
	}

	LineBasedFile::LineBasedFile()
		throw()
		:	File(),
			line_number_(0)
	{
	}

	LineBasedFile::LineBasedFile(const LineBasedFile& f)
	 throw()
		: File(),
			line_number_(0)
	{
			if (f.getName() != "")
			{
				open(f.getName());
				skipLines(f.line_number_ - 1);
			}
	}

	LineBasedFile::LineBasedFile(const String& filename, File::OpenMode open_mode)
		throw(Exception::FileNotFound)
		: File(filename, open_mode),
			line_number_(0)
	{
		if (!isAccessible())
		{
			throw Exception::FileNotFound(__FILE__, __LINE__, filename);
		}
	}

	const LineBasedFile& LineBasedFile::operator = (const LineBasedFile& f)
		throw()
	{
		open(f.name_, f.getOpenMode());
		line_number_ = 0;
		skipLines(f.line_number_ - 1);
		return *this;
	}

	bool LineBasedFile::search(const String& text, bool return_to_point)
		throw(LineBasedFileError)
	{
		if (!isOpen() || getOpenMode() != IN)
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend for read access or at all.");
		}

		Position start_point = line_number_;
		while (readLine())
		{
			if (startsWith(text))
			{
				return true;
			}
		}

		if (return_to_point)
		{
			goToLine(start_point);
		}
		return false;
	}

	bool LineBasedFile::search(const String& text, const String& stop, bool return_to_point)
		throw(LineBasedFileError)
	{
		if (!isOpen() || getOpenMode() != IN)
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend for read access or at all.");
		}

		Position start_point = line_number_;

		while (readLine())
		{
			if (startsWith(stop))
			{
				if (return_to_point)
				{
					goToLine(start_point);
				}

				return false;
			}

			if (startsWith(text))
			{
				return true;
			}
		}

		if (return_to_point)
		{
			goToLine(start_point);
		}

		return false;
	}

	bool LineBasedFile::readLine()
		throw(LineBasedFileError)
	{
		if (!isOpen() || getOpenMode() != IN)
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend for read access or at all.");
		}

		if (eof())
		{
			return false;
		}

		char* c = new char[200];
		getline(c, 200);
		line_ = c;
		++line_number_;
		return true;
	}

	bool LineBasedFile::skipLines(Size number)
		throw(LineBasedFileError)
	{
		for (Position i = 0; i < number +1; i++)
		{
			if (!readLine())
			{
				return false;
			}
		}

		return true;
	}

	void LineBasedFile::rewind()
		 throw(LineBasedFileError)
	{
		if (!isOpen())
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend.");
		}
		File::reopen();
		line_number_ = 0;
		line_ = "";
	}

	bool LineBasedFile::goToLine(Position line_number)
		 throw(LineBasedFileError)
	{
		if (!isOpen())
		{
			throw LineBasedFileError(__FILE__, __LINE__, this,
							"File " + name_ +" is not opend.");
		}

		if (line_number == line_number_)
		{
			return true;
		}

		if (line_number < line_number_)
		{
			rewind();
			if (line_number == 0)
			{
				return true;
			}

			return skipLines(line_number - 1);
		}

		return skipLines(line_number - line_number_ - 1);
	}

	void LineBasedFile::clear()
		throw()
	{
		line_ = "";
		line_number_ = 0;
		close();
		name_ = "";
	}

	Position LineBasedFile::getLineNumber()
		const throw()
	{
		return line_number_;
	}

	const String& LineBasedFile::getLine()
		const throw()
	{
		return line_;
	}

	void LineBasedFile::test(const char* file, int line, bool condition, const String& msg)
		const throw(LineBasedFileError)
	{
		if (!condition)
		{
			throw LineBasedFileError(file, line, this, msg);
		}
	}

	String LineBasedFile::getField(Position pos, const String& quotes, const String& delimiters)
		const	throw(Exception::IndexUnderflow)
	{
		if (quotes == "")
		{
			return line_.getField((Index) pos, delimiters.c_str());
		}

		return line_.getFieldQuoted((Index) pos, delimiters.c_str(), quotes.c_str());
	}

	Index LineBasedFile::switchString(const vector<String>& data)
		const throw()
	{
		for (Index i = 0; i < (Index) data.size(); i++)
		{
			if (line_ == data[i])
			{
				return i;
			}
		}
		return (-1);
	}

	bool LineBasedFile::startsWith(const String& text)
		const throw()
	{
		return line_.hasPrefix(text);
	}

	bool LineBasedFile::has(const String& text)
		const throw()
	{
		return line_.hasSubstring(text);
	}

} //namespace
<|endoftext|>


<commit_before><commit_msg>Add missing casts<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdint.h>
#include <stdbool.h>

#include "command_manager.h"
#include "estimator.h"
#include "rosflight.h"

#include "controller.h"

namespace rosflight_firmware
{

Controller::Controller(ROSflight& rf) :
  RF_(rf)
{
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_ANGLE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_ANGLE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_ANGLE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_RATE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_RATE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_RATE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_ANGLE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_ANGLE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_ANGLE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_RATE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_RATE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_RATE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_YAW_RATE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_YAW_RATE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_YAW_RATE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_MAX_COMMAND);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_TAU);
}

void Controller::init()
{
  prev_time_us_ = 0;

  float max = RF_.params_.get_param_float(PARAM_MAX_COMMAND);
  float min = -max;
  float tau = RF_.params_.get_param_float(PARAM_PID_TAU);

  roll_.init(RF_.params_.get_param_float(PARAM_PID_ROLL_ANGLE_P),
             RF_.params_.get_param_float(PARAM_PID_ROLL_ANGLE_I),
             RF_.params_.get_param_float(PARAM_PID_ROLL_ANGLE_D),
             max, min, tau);
  roll_rate_.init(RF_.params_.get_param_float(PARAM_PID_ROLL_RATE_P),
                  RF_.params_.get_param_float(PARAM_PID_ROLL_RATE_I),
                  RF_.params_.get_param_float(PARAM_PID_ROLL_RATE_D),
                  max, min, tau);
  pitch_.init(RF_.params_.get_param_float(PARAM_PID_PITCH_ANGLE_P),
              RF_.params_.get_param_float(PARAM_PID_PITCH_ANGLE_I),
              RF_.params_.get_param_float(PARAM_PID_PITCH_ANGLE_D),
              max, min, tau);
  pitch_rate_.init(RF_.params_.get_param_float(PARAM_PID_PITCH_RATE_P),
                   RF_.params_.get_param_float(PARAM_PID_PITCH_RATE_I),
                   RF_.params_.get_param_float(PARAM_PID_PITCH_RATE_D),
                   max, min, tau);
  yaw_rate_.init(RF_.params_.get_param_float(PARAM_PID_YAW_RATE_P),
                 RF_.params_.get_param_float(PARAM_PID_YAW_RATE_I),
                 RF_.params_.get_param_float(PARAM_PID_YAW_RATE_D),
                 max, min, tau);
}

void Controller::run()
{
  // Time calculation
  if (prev_time_us_ == 0)
  {
    prev_time_us_ = RF_.estimator_.state().timestamp_us;
    return;
  }

  int32_t dt_us = (RF_.estimator_.state().timestamp_us - prev_time_us_);
  if ( dt_us < 0 )
  {
    RF_.state_manager_.set_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
    return;
  }
  prev_time_us_ = RF_.estimator_.state().timestamp_us;

  // Check if integrators should be updated
  //! @todo better way to figure out if throttle is high
  bool update_integrators = (RF_.state_manager_.state().armed) && (RF_.command_manager_.combined_control().F.value > 0.1f) && dt_us < 100;

  // Run the PID loops
  turbomath::Vector pid_output = run_pid_loops(dt_us, RF_.estimator_.state(), RF_.command_manager_.combined_control(), update_integrators);

  // Add feedforward torques
  output_.x = pid_output.x + RF_.params_.get_param_float(PARAM_X_EQ_TORQUE);
  output_.y = pid_output.y + RF_.params_.get_param_float(PARAM_Y_EQ_TORQUE);
  output_.z = pid_output.z + RF_.params_.get_param_float(PARAM_Z_EQ_TORQUE);
  output_.F = RF_.command_manager_.combined_control().F.value;
}

void Controller::calculate_equilbrium_torque_from_rc()
{
  // Make sure we are disarmed
  if (!(RF_.state_manager_.state().armed))
  {
    // Tell the user that we are doing a equilibrium torque calibration
    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Capturing equilbrium offsets from RC");

    // Prepare for calibration
    // artificially tell the flight controller it is leveled
    Estimator::State fake_state;
    fake_state.angular_velocity.x = 0.0f;
    fake_state.angular_velocity.y = 0.0f;
    fake_state.angular_velocity.z = 0.0f;

    fake_state.attitude.x = 0.0f;
    fake_state.attitude.y = 0.0f;
    fake_state.attitude.z = 0.0f;
    fake_state.attitude.w = 1.0f;

    fake_state.roll = 0.0f;
    fake_state.pitch = 0.0f;
    fake_state.yaw = 0.0f;

    // pass the rc_control through the controller
    // dt is zero, so what this really does is applies the P gain with the settings
    // your RC transmitter, which if it flies level is a really good guess for
    // the static offset torques
    turbomath::Vector pid_output = run_pid_loops(0, fake_state, RF_.command_manager_.rc_control(), false);

    // the output from the controller is going to be the static offsets
    RF_.params_.set_param_float(PARAM_X_EQ_TORQUE, pid_output.x);
    RF_.params_.set_param_float(PARAM_Y_EQ_TORQUE, pid_output.y);
    RF_.params_.set_param_float(PARAM_Z_EQ_TORQUE, pid_output.z);

    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Equilibrium torques found and applied.");
    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Please zero out trims on your transmitter");
  }
  else
  {
    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Cannot perform equilibrium offset calibration while armed");
  }
}

void Controller::param_change_callback(uint16_t param_id)
{
  (void) param_id; // suppress unused parameter warning
  init();
}

turbomath::Vector Controller::run_pid_loops(uint32_t dt_us, const Estimator::State& state, const control_t& command, bool update_integrators)
{
  // Based on the control types coming from the command manager, run the appropriate PID loops
  turbomath::Vector out;

  float dt = 1e-6*dt_us;

  // ROLL
  if (command.x.type == RATE)
    out.x = roll_rate_.run(dt, state.angular_velocity.x, command.x.value, update_integrators);
  else if (command.x.type == ANGLE)
    out.x = roll_.run(dt, state.roll, command.x.value, update_integrators, state.angular_velocity.x);
  else
    out.x = command.x.value;

  // PITCH
  if (command.y.type == RATE)
    out.y = pitch_rate_.run(dt, state.angular_velocity.y, command.y.value, update_integrators);
  else if (command.y.type == ANGLE)
    out.y = pitch_.run(dt, state.pitch, command.y.value, update_integrators, state.angular_velocity.y);
  else
    out.y = command.y.value;

  // YAW
  if (command.z.type == RATE)
    out.z = yaw_rate_.run(dt, state.angular_velocity.z, command.z.value, update_integrators);
  else
    out.z = command.z.value;

  return out;
}

Controller::PID::PID() :
  kp_(0.0f),
  ki_(0.0f),
  kd_(0.0f),
  max_(1.0f),
  min_(-1.0f),
  integrator_(0.0f),
  differentiator_(0.0f),
  prev_x_(0.0f),
  tau_(0.05)
{}

void Controller::PID::init(float kp, float ki, float kd, float max, float min, float tau)
{
  kp_ = kp;
  ki_ = ki;
  kd_ = kd;
  max_ = max;
  min_ = min;
  tau_ = tau;
}

float Controller::PID::run(float dt, float x, float x_c, bool update_integrator)
{
  float xdot;
  if (dt > 0.0001f)
  {
    // calculate D term (use dirty derivative if we don't have access to a measurement of the derivative)
    // The dirty derivative is a sort of low-pass filtered version of the derivative.
    //// (Include reference to Dr. Beard's notes here)
    differentiator_ = (2.0f * tau_ - dt) / (2.0f * tau_ + dt) * differentiator_
        + 2.0f / (2.0f * tau_ + dt) * (x - prev_x_);
    xdot = differentiator_;
  }
  else
  {
    xdot = 0.0f;
  }
  prev_x_ = x;

  return run(dt, x, x_c, update_integrator, xdot);
}

float Controller::PID::run(float dt, float x, float x_c, bool update_integrator, float xdot)
{
  // Calculate Error
  float error = x_c - x;

  // Initialize Terms
  float p_term = error * kp_;
  float i_term = 0.0f;
  float d_term = 0.0f;

  // If there is a derivative term
  if (kd_ > 0.0f)
  {
    d_term = kd_ * xdot;
  }

  //If there is an integrator term and we are updating integrators
  if ((ki_ > 0.0f) && update_integrator)
  {
    // integrate
    integrator_ += error * dt;
    // calculate I term
    i_term = ki_ * integrator_;
  }

  // sum three terms
  float u = p_term - d_term + i_term;

  // Integrator anti-windup
  //// Include reference to Dr. Beard's notes here
  float u_sat = (u > max_) ? max_ : (u < min_) ? min_ : u;
  if (u != u_sat && fabs(i_term) > fabs(u - p_term + d_term) && ki_ > 0.0f)
    integrator_ = (u_sat - p_term + d_term)/ki_;

  // Set output
  return u_sat;
}

} // namespace rosflight_firmware
<commit_msg>fixed integrator<commit_after>/*
 * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdint.h>
#include <stdbool.h>

#include "command_manager.h"
#include "estimator.h"
#include "rosflight.h"

#include "controller.h"

namespace rosflight_firmware
{

Controller::Controller(ROSflight& rf) :
  RF_(rf)
{
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_ANGLE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_ANGLE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_ANGLE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_RATE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_RATE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_ROLL_RATE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_ANGLE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_ANGLE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_ANGLE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_RATE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_RATE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_PITCH_RATE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_YAW_RATE_P);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_YAW_RATE_I);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_YAW_RATE_D);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_MAX_COMMAND);
  RF_.params_.add_callback(std::bind(&Controller::param_change_callback, this, std::placeholders::_1), PARAM_PID_TAU);
}

void Controller::init()
{
  prev_time_us_ = 0;

  float max = RF_.params_.get_param_float(PARAM_MAX_COMMAND);
  float min = -max;
  float tau = RF_.params_.get_param_float(PARAM_PID_TAU);

  roll_.init(RF_.params_.get_param_float(PARAM_PID_ROLL_ANGLE_P),
             RF_.params_.get_param_float(PARAM_PID_ROLL_ANGLE_I),
             RF_.params_.get_param_float(PARAM_PID_ROLL_ANGLE_D),
             max, min, tau);
  roll_rate_.init(RF_.params_.get_param_float(PARAM_PID_ROLL_RATE_P),
                  RF_.params_.get_param_float(PARAM_PID_ROLL_RATE_I),
                  RF_.params_.get_param_float(PARAM_PID_ROLL_RATE_D),
                  max, min, tau);
  pitch_.init(RF_.params_.get_param_float(PARAM_PID_PITCH_ANGLE_P),
              RF_.params_.get_param_float(PARAM_PID_PITCH_ANGLE_I),
              RF_.params_.get_param_float(PARAM_PID_PITCH_ANGLE_D),
              max, min, tau);
  pitch_rate_.init(RF_.params_.get_param_float(PARAM_PID_PITCH_RATE_P),
                   RF_.params_.get_param_float(PARAM_PID_PITCH_RATE_I),
                   RF_.params_.get_param_float(PARAM_PID_PITCH_RATE_D),
                   max, min, tau);
  yaw_rate_.init(RF_.params_.get_param_float(PARAM_PID_YAW_RATE_P),
                 RF_.params_.get_param_float(PARAM_PID_YAW_RATE_I),
                 RF_.params_.get_param_float(PARAM_PID_YAW_RATE_D),
                 max, min, tau);
}

void Controller::run()
{
  // Time calculation
  if (prev_time_us_ == 0)
  {
    prev_time_us_ = RF_.estimator_.state().timestamp_us;
    return;
  }

  int32_t dt_us = (RF_.estimator_.state().timestamp_us - prev_time_us_);
  if ( dt_us < 0 )
  {
    RF_.state_manager_.set_error(StateManager::ERROR_TIME_GOING_BACKWARDS);
    return;
  }
  prev_time_us_ = RF_.estimator_.state().timestamp_us;

  // Check if integrators should be updated
  //! @todo better way to figure out if throttle is high
  bool update_integrators = (RF_.state_manager_.state().armed) && (RF_.command_manager_.combined_control().F.value > 0.1f) && dt_us < 10000;

  // Run the PID loops
  turbomath::Vector pid_output = run_pid_loops(dt_us, RF_.estimator_.state(), RF_.command_manager_.combined_control(), update_integrators);

  // Add feedforward torques
  output_.x = pid_output.x + RF_.params_.get_param_float(PARAM_X_EQ_TORQUE);
  output_.y = pid_output.y + RF_.params_.get_param_float(PARAM_Y_EQ_TORQUE);
  output_.z = pid_output.z + RF_.params_.get_param_float(PARAM_Z_EQ_TORQUE);
  output_.F = RF_.command_manager_.combined_control().F.value;
}

void Controller::calculate_equilbrium_torque_from_rc()
{
  // Make sure we are disarmed
  if (!(RF_.state_manager_.state().armed))
  {
    // Tell the user that we are doing a equilibrium torque calibration
    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Capturing equilbrium offsets from RC");

    // Prepare for calibration
    // artificially tell the flight controller it is leveled
    Estimator::State fake_state;
    fake_state.angular_velocity.x = 0.0f;
    fake_state.angular_velocity.y = 0.0f;
    fake_state.angular_velocity.z = 0.0f;

    fake_state.attitude.x = 0.0f;
    fake_state.attitude.y = 0.0f;
    fake_state.attitude.z = 0.0f;
    fake_state.attitude.w = 1.0f;

    fake_state.roll = 0.0f;
    fake_state.pitch = 0.0f;
    fake_state.yaw = 0.0f;

    // pass the rc_control through the controller
    // dt is zero, so what this really does is applies the P gain with the settings
    // your RC transmitter, which if it flies level is a really good guess for
    // the static offset torques
    turbomath::Vector pid_output = run_pid_loops(0, fake_state, RF_.command_manager_.rc_control(), false);

    // the output from the controller is going to be the static offsets
    RF_.params_.set_param_float(PARAM_X_EQ_TORQUE, pid_output.x);
    RF_.params_.set_param_float(PARAM_Y_EQ_TORQUE, pid_output.y);
    RF_.params_.set_param_float(PARAM_Z_EQ_TORQUE, pid_output.z);

    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Equilibrium torques found and applied.");
    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Please zero out trims on your transmitter");
  }
  else
  {
    RF_.comm_manager_.log(CommLink::LogSeverity::LOG_WARNING, "Cannot perform equilibrium offset calibration while armed");
  }
}

void Controller::param_change_callback(uint16_t param_id)
{
  (void) param_id; // suppress unused parameter warning
  init();
}

turbomath::Vector Controller::run_pid_loops(uint32_t dt_us, const Estimator::State& state, const control_t& command, bool update_integrators)
{
  // Based on the control types coming from the command manager, run the appropriate PID loops
  turbomath::Vector out;

  float dt = 1e-6*dt_us;

  // ROLL
  if (command.x.type == RATE)
    out.x = roll_rate_.run(dt, state.angular_velocity.x, command.x.value, update_integrators);
  else if (command.x.type == ANGLE)
    out.x = roll_.run(dt, state.roll, command.x.value, update_integrators, state.angular_velocity.x);
  else
    out.x = command.x.value;

  // PITCH
  if (command.y.type == RATE)
    out.y = pitch_rate_.run(dt, state.angular_velocity.y, command.y.value, update_integrators);
  else if (command.y.type == ANGLE)
    out.y = pitch_.run(dt, state.pitch, command.y.value, update_integrators, state.angular_velocity.y);
  else
    out.y = command.y.value;

  // YAW
  if (command.z.type == RATE)
    out.z = yaw_rate_.run(dt, state.angular_velocity.z, command.z.value, update_integrators);
  else
    out.z = command.z.value;

  return out;
}

Controller::PID::PID() :
  kp_(0.0f),
  ki_(0.0f),
  kd_(0.0f),
  max_(1.0f),
  min_(-1.0f),
  integrator_(0.0f),
  differentiator_(0.0f),
  prev_x_(0.0f),
  tau_(0.05)
{}

void Controller::PID::init(float kp, float ki, float kd, float max, float min, float tau)
{
  kp_ = kp;
  ki_ = ki;
  kd_ = kd;
  max_ = max;
  min_ = min;
  tau_ = tau;
}

float Controller::PID::run(float dt, float x, float x_c, bool update_integrator)
{
  float xdot;
  if (dt > 0.0001f)
  {
    // calculate D term (use dirty derivative if we don't have access to a measurement of the derivative)
    // The dirty derivative is a sort of low-pass filtered version of the derivative.
    //// (Include reference to Dr. Beard's notes here)
    differentiator_ = (2.0f * tau_ - dt) / (2.0f * tau_ + dt) * differentiator_
        + 2.0f / (2.0f * tau_ + dt) * (x - prev_x_);
    xdot = differentiator_;
  }
  else
  {
    xdot = 0.0f;
  }
  prev_x_ = x;

  return run(dt, x, x_c, update_integrator, xdot);
}

float Controller::PID::run(float dt, float x, float x_c, bool update_integrator, float xdot)
{
  // Calculate Error
  float error = x_c - x;

  // Initialize Terms
  float p_term = error * kp_;
  float i_term = 0.0f;
  float d_term = 0.0f;

  // If there is a derivative term
  if (kd_ > 0.0f)
  {
    d_term = kd_ * xdot;
  }

  //If there is an integrator term and we are updating integrators
  if ((ki_ > 0.0f) && update_integrator)
  {
    // integrate
    integrator_ += error * dt;
    // calculate I term
    i_term = ki_ * integrator_;
  }

  // sum three terms
  float u = p_term - d_term + i_term;

  // Integrator anti-windup
  //// Include reference to Dr. Beard's notes here
  float u_sat = (u > max_) ? max_ : (u < min_) ? min_ : u;
  if (u != u_sat && fabs(i_term) > fabs(u - p_term + d_term) && ki_ > 0.0f)
    integrator_ = (u_sat - p_term + d_term)/ki_;

  // Set output
  return u_sat;
}

} // namespace rosflight_firmware
<|endoftext|>


<commit_before>#include "ros/ros.h"
#include "geometry_msgs/Pose.h"
#include "geometry_msgs/Twist.h"
#include "geometry_msgs/Wrench.h"
#include "uranus_dp/State.h"
#include <Eigen/Dense>
#include <cmath>

class Controller
{
public:
    Controller()
    {
        outputPub   = n.advertise<geometry_msgs::Wrench>("outputTopic", 1);
        stateSub    = n.subscribe("stateTopic", 1, &Controller::stateCallback, this);
        setpointSub = n.subscribe("setpointTopic", 1, &Controller::setpointCallback, this);

        // Set default frequency
        frequency = 10;

        // Allocate dynamic member variables
        T   = Eigen::MatrixXd(4,3);
        tau = Eigen::VectorXd(6);

        // Initialize controller gains
        K_lin_p = Eigen::Matrix3d::Identity();
        K_lin_d = Eigen::Matrix3d::Identity();
        K_ang_p = Eigen::Matrix3d::Identity();
        K_ang_d = Eigen::Matrix3d::Identity();
    }

    // stateCallback updates the private state variables when a new state message arrives.
    void stateCallback(const uranus_dp::State &state_msg)
    {
        // Copy position values
        p(0) = state_msg.pose.position.x;
        p(1) = state_msg.pose.position.y;
        p(2) = state_msg.pose.position.z;

        // Copy orientation values (quaternion)
        q(0) = state_msg.pose.orientation.x;
        q(1) = state_msg.pose.orientation.y;
        q(2) = state_msg.pose.orientation.z;
        q(3) = state_msg.pose.orientation.w;

        // Copy linear velocity values
        v(0) = state_msg.twist.linear.x;
        v(1) = state_msg.twist.linear.y;
        v(2) = state_msg.twist.linear.z;

        // Copy angular velocity values
        omega(0) = state_msg.twist.angular.x;
        omega(1) = state_msg.twist.angular.y;
        omega(2) = state_msg.twist.angular.z;
    }

    // setpointCallback updates the private setpoint variable when a new setpoint message arrives.
    void setpointCallback(const geometry_msgs::Twist &setpoint_msg)
    {
        // Copy linear velocity setpoint values
        v_sp(0) = setpoint_msg.linear.x;
        v_sp(1) = setpoint_msg.linear.y;
        v_sp(2) = setpoint_msg.linear.z;

        // Copy angular velocity setpoint values
        omega_sp(0) = setpoint_msg.angular.x;
        omega_sp(1) = setpoint_msg.angular.y;
        omega_sp(2) = setpoint_msg.angular.z;
    }

    // compute contains the control algorithm, and computes the control output based on the
    // current state and setpoint.
    void compute(void)
    {
        // Only pose control for now

        // Position and orientation errors
        p_err = p_sp - p;
        q_err = q_sp - q;

        // Control output
        updateTransformationMatrices();
        Eigen::Vector3d tau_lin = K_lin_p * p_err + K_lin_d * v;
        Eigen::Vector3d tau_ang = - K_ang_p * T.transpose() * q_err - K_ang_d * omega;
        tau << tau_lin, tau_ang;

        // Create and send output message
        geometry_msgs::Wrench output;
        output.force.x  = tau(0);
        output.force.y  = tau(1);
        output.force.z  = tau(2);
        output.torque.x = tau(3);
        output.torque.y = tau(4);
        output.torque.z = tau(5);
        outputPub.publish(output);
    }

    // setFrequency tells the controller which frequency in Hz compute() is called with.
    void setFrequency(uint16_t newFrequency)
    {
        frequency = newFrequency;
    }
private:
    ros::NodeHandle n;
    ros::Publisher  outputPub;
    ros::Subscriber stateSub;
    ros::Subscriber setpointSub;

    // Controller frequency
    uint16_t frequency;

    // State
    Eigen::Vector3d p;     // Position
    Eigen::Vector4d q;     // Orientation
    Eigen::Vector3d v;     // Linear velocity
    Eigen::Vector3d omega; // Angular velocity

    // Setpoints
    Eigen::Vector3d p_sp;     // Position
    Eigen::Vector4d q_sp;     // Orientation
    Eigen::Vector3d v_sp;     // Linear velocity
    Eigen::Vector3d omega_sp; // Angular velocity

    // Errors
    Eigen::Vector3d p_err;     // Position
    Eigen::Vector4d q_err;     // Orientation
    Eigen::Vector3d v_err;     // Linear velocity
    Eigen::Vector3d omega_err; // Angular velocity

    // Transformation matrices
    Eigen::Matrix3d R;
    Eigen::MatrixXd T;

    // Control output
    Eigen::VectorXd tau;

    // Controller gains
    Eigen::Matrix3d K_lin_d;
    Eigen::Matrix3d K_lin_p;
    Eigen::Matrix3d K_ang_d;
    Eigen::Matrix3d K_ang_p;

    void updateTransformationMatrices(void)
    {
        // Linear velocity transformation matrix
        R(0,0) = 1 - 2*(pow(q(2),2) + pow(q(3),2));
        R(0,1) = 2*(q(1)*q(2) - q(3)*q(0));
        R(0,2) = 2*(q(1)*q(3) - q(2)*q(0));

        R(1,0) = 2*(q(1)*q(2) + q(3)*q(0));
        R(1,1) = 1 - 2*(pow(q(1),2) + pow(q(0),2));
        R(1,2) = 2*(q(2)*q(3) + q(1)*q(0));

        R(2,0) = 2*(q(1)*q(3) + q(2)*q(0));
        R(2,1) = 2*(q(2)*q(3) + q(1)*q(0));
        R(2,2) = 1 - 2*(pow(q(1),2) + pow(q(2),2));

        // Angular velocity transformation matrix
        T(0,0) = -q(1);
        T(0,1) = -q(2);
        T(0,2) = -q(3);

        T(1,0) =  q(0);
        T(1,1) = -q(3);
        T(1,2) =  q(2);

        T(2,0) =  q(3);
        T(2,1) =  q(3);
        T(2,2) = -q(1);

        T(3,0) = -q(2);
        T(3,1) =  q(1);
        T(3,2) =  q(0);

        T *= 0.5;
    }
}; // End of class Controller

int main(int argc, char **argv)
{
    ros::init(argc, argv, "controller");

    Controller controllerObject;

    uint16_t frequency = 10; // Get from parameter server sometime in the future
    controllerObject.setFrequency(frequency);

    ros::Rate loop_rate(frequency);
    while (ros::ok())
    {
        ros::spinOnce();

        controllerObject.compute();

        loop_rate.sleep();
    }

    return 0;
}
<commit_msg>Remove premature optimization<commit_after>#include "ros/ros.h"
#include "geometry_msgs/Pose.h"
#include "geometry_msgs/Twist.h"
#include "geometry_msgs/Wrench.h"
#include "uranus_dp/State.h"
#include <Eigen/Dense>
#include <cmath>

class Controller
{
public:
    Controller()
    {
        outputPub   = n.advertise<geometry_msgs::Wrench>("outputTopic", 1);
        stateSub    = n.subscribe("stateTopic", 1, &Controller::stateCallback, this);
        setpointSub = n.subscribe("setpointTopic", 1, &Controller::setpointCallback, this);

        // Set default frequency
        frequency = 10;

        // Allocate dynamic member variables
        T   = Eigen::MatrixXd(4,3);
        tau = Eigen::VectorXd(6);

        // Initialize controller gains
        K_lin_p = Eigen::Matrix3d::Identity();
        K_lin_d = Eigen::Matrix3d::Identity();
        K_ang_p = Eigen::Matrix3d::Identity();
        K_ang_d = Eigen::Matrix3d::Identity();
    }

    // stateCallback updates the private state variables when a new state message arrives.
    void stateCallback(const uranus_dp::State &state_msg)
    {
        // Copy position values
        p(0) = state_msg.pose.position.x;
        p(1) = state_msg.pose.position.y;
        p(2) = state_msg.pose.position.z;

        // Copy orientation values (quaternion)
        q(0) = state_msg.pose.orientation.x;
        q(1) = state_msg.pose.orientation.y;
        q(2) = state_msg.pose.orientation.z;
        q(3) = state_msg.pose.orientation.w;

        // Copy linear velocity values
        v(0) = state_msg.twist.linear.x;
        v(1) = state_msg.twist.linear.y;
        v(2) = state_msg.twist.linear.z;

        // Copy angular velocity values
        omega(0) = state_msg.twist.angular.x;
        omega(1) = state_msg.twist.angular.y;
        omega(2) = state_msg.twist.angular.z;
    }

    // setpointCallback updates the private setpoint variable when a new setpoint message arrives.
    void setpointCallback(const geometry_msgs::Twist &setpoint_msg)
    {
        // Copy linear velocity setpoint values
        v_sp(0) = setpoint_msg.linear.x;
        v_sp(1) = setpoint_msg.linear.y;
        v_sp(2) = setpoint_msg.linear.z;

        // Copy angular velocity setpoint values
        omega_sp(0) = setpoint_msg.angular.x;
        omega_sp(1) = setpoint_msg.angular.y;
        omega_sp(2) = setpoint_msg.angular.z;
    }

    // compute contains the control algorithm, and computes the control output based on the
    // current state and setpoint.
    void compute(void)
    {
        // Only pose control for now

        // Position and orientation errors
        p_err = p_sp - p;
        q_err = q_sp - q;

        // Control output
        updateTransformationMatrices();
        Eigen::Vector3d tau_lin = K_lin_p * p_err + K_lin_d * v;
        Eigen::Vector3d tau_ang = - K_ang_p * T.transpose() * q_err - K_ang_d * omega;
        tau << tau_lin, tau_ang;

        // Create and send output message
        geometry_msgs::Wrench output;
        output.force.x  = tau(0);
        output.force.y  = tau(1);
        output.force.z  = tau(2);
        output.torque.x = tau(3);
        output.torque.y = tau(4);
        output.torque.z = tau(5);
        outputPub.publish(output);
    }

    // setFrequency tells the controller which frequency in Hz compute() is called with.
    void setFrequency(unsigned int newFrequency)
    {
        frequency = newFrequency;
    }
private:
    ros::NodeHandle n;
    ros::Publisher  outputPub;
    ros::Subscriber stateSub;
    ros::Subscriber setpointSub;

    // Controller frequency
    unsigned int frequency;

    // State
    Eigen::Vector3d p;     // Position
    Eigen::Vector4d q;     // Orientation
    Eigen::Vector3d v;     // Linear velocity
    Eigen::Vector3d omega; // Angular velocity

    // Setpoints
    Eigen::Vector3d p_sp;     // Position
    Eigen::Vector4d q_sp;     // Orientation
    Eigen::Vector3d v_sp;     // Linear velocity
    Eigen::Vector3d omega_sp; // Angular velocity

    // Errors
    Eigen::Vector3d p_err;     // Position
    Eigen::Vector4d q_err;     // Orientation
    Eigen::Vector3d v_err;     // Linear velocity
    Eigen::Vector3d omega_err; // Angular velocity

    // Transformation matrices
    Eigen::Matrix3d R;
    Eigen::MatrixXd T;

    // Control output
    Eigen::VectorXd tau;

    // Controller gains
    Eigen::Matrix3d K_lin_d;
    Eigen::Matrix3d K_lin_p;
    Eigen::Matrix3d K_ang_d;
    Eigen::Matrix3d K_ang_p;

    void updateTransformationMatrices(void)
    {
        // Linear velocity transformation matrix
        R(0,0) = 1 - 2*(pow(q(2),2) + pow(q(3),2));
        R(0,1) = 2*(q(1)*q(2) - q(3)*q(0));
        R(0,2) = 2*(q(1)*q(3) - q(2)*q(0));

        R(1,0) = 2*(q(1)*q(2) + q(3)*q(0));
        R(1,1) = 1 - 2*(pow(q(1),2) + pow(q(0),2));
        R(1,2) = 2*(q(2)*q(3) + q(1)*q(0));

        R(2,0) = 2*(q(1)*q(3) + q(2)*q(0));
        R(2,1) = 2*(q(2)*q(3) + q(1)*q(0));
        R(2,2) = 1 - 2*(pow(q(1),2) + pow(q(2),2));

        // Angular velocity transformation matrix
        T(0,0) = -q(1);
        T(0,1) = -q(2);
        T(0,2) = -q(3);

        T(1,0) =  q(0);
        T(1,1) = -q(3);
        T(1,2) =  q(2);

        T(2,0) =  q(3);
        T(2,1) =  q(3);
        T(2,2) = -q(1);

        T(3,0) = -q(2);
        T(3,1) =  q(1);
        T(3,2) =  q(0);

        T *= 0.5;
    }
}; // End of class Controller

int main(int argc, char **argv)
{
    ros::init(argc, argv, "controller");

    Controller controllerObject;

    unsigned int frequency = 10; // Get from parameter server sometime in the future
    controllerObject.setFrequency(frequency);

    ros::Rate loop_rate(frequency);
    while (ros::ok())
    {
        ros::spinOnce();

        controllerObject.compute();

        loop_rate.sleep();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * FileWriterTest.cpp
 *
 */
#define BOOST_TEST_MODULE "FileWriterUnitTests"
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

#include <iostream>

#include <log4cxx/logger.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/simplelayout.h>

#include "FileWriter.h"
#include "framenotifier_data.h"

class FileWriterTestFixture
{
public:
    FileWriterTestFixture() :
        logger(log4cxx::Logger::getLogger("FileWriterUnitTest"))
    {

    }
    log4cxx::LoggerPtr logger;
};
BOOST_FIXTURE_TEST_SUITE(FileWriterUnitTest, FileWriterTestFixture);

BOOST_AUTO_TEST_CASE( FileWriterTest )
{
    FileWriter fw;
    BOOST_CHECK_NO_THROW(fw.createFile("/tmp/blah.h5"));
}

BOOST_AUTO_TEST_SUITE_END(); //FileWriterUnitTest

BOOST_AUTO_TEST_SUITE(FrameUnitTest);

BOOST_AUTO_TEST_CASE( FrameTest )
{
    unsigned short img[12] =  { 1, 2, 3, 4,
                                5, 6, 7, 8,
                                9,10,11,12 };
    dimensions_t img_dims(2); img_dims[0] = 3; img_dims[1] = 4;
    FrameHeader img_header;
    img_header.frame_number = 7;

    Frame frame(100, img_dims);
    BOOST_REQUIRE_EQUAL(frame.get_data_size(), 24);
    BOOST_CHECK_NO_THROW(frame.copy_header(&img_header));
    BOOST_CHECK_NO_THROW(frame.copy_data(static_cast<void*>(img), 24));
}

BOOST_AUTO_TEST_SUITE_END(); //FrameUnitTest
<commit_msg>filewriter: unittest configured logger<commit_after>/*
 * FileWriterTest.cpp
 *
 */
#define BOOST_TEST_MODULE "FileWriterUnitTests"
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

#include <iostream>

#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/simplelayout.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/basicconfigurator.h>
using namespace log4cxx;
using namespace log4cxx::xml;

#include "FileWriter.h"
#include "framenotifier_data.h"

class GlobalConfig {
public:
    GlobalConfig() {
        //std::cout << "GlobalConfig constructor" << std::endl;
        // Create a default simple console appender for log4cxx.
        consoleAppender = new ConsoleAppender(LayoutPtr(new SimpleLayout()));
        BasicConfigurator::configure(AppenderPtr(consoleAppender));
        Logger::getRootLogger()->setLevel(Level::getWarn());
    }
    ~GlobalConfig(){
        //std::cout << "GlobalConfig constructor" << std::endl;
        //delete consoleAppender;
    };
private:
    ConsoleAppender *consoleAppender;
};
BOOST_GLOBAL_FIXTURE(GlobalConfig);

BOOST_AUTO_TEST_SUITE(FrameUnitTest);

BOOST_AUTO_TEST_CASE( FrameTest )
{
    unsigned short img[12] =  { 1, 2, 3, 4,
                                5, 6, 7, 8,
                                9,10,11,12 };
    dimensions_t img_dims(2); img_dims[0] = 3; img_dims[1] = 4;
    FrameHeader img_header;
    img_header.frame_number = 7;

    Frame frame(2, img_dims);
    BOOST_REQUIRE_EQUAL(frame.get_data_size(), 24);
    BOOST_CHECK_NO_THROW(frame.copy_header(&img_header));
    BOOST_CHECK_NO_THROW(frame.copy_data(static_cast<void*>(img), 24));
    BOOST_CHECK_EQUAL(frame.get_frame_number(), 7);

}

BOOST_AUTO_TEST_SUITE_END(); //FrameUnitTest

class FileWriterTestFixture
{
public:
    FileWriterTestFixture() //: logger(log4cxx::Logger::getLogger("FileWriterUnitTest"))
    {}
    ~FileWriterTestFixture(){}
    log4cxx::LoggerPtr logger;
};
BOOST_FIXTURE_TEST_SUITE(FileWriterUnitTest, FileWriterTestFixture);

BOOST_AUTO_TEST_CASE( FileWriterTest )
{
    FileWriter fw;
    BOOST_CHECK_NO_THROW(fw.createFile("/tmp/blah.h5"));
}

BOOST_AUTO_TEST_SUITE_END(); //FileWriterUnitTest

<|endoftext|>


<commit_before><commit_msg>Hook up alt-d on linux.<commit_after><|endoftext|>