<commit_before>/* Copyright 2020 Jeffrey Kelling
 *
 * This file is part of Alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#ifdef ALPAKA_ACC_ANY_BT_OACC_ENABLED

#if _OPENACC < 201306
    #error If ALPAKA_ACC_ANY_BT_OACC_ENABLED is set, the compiler has to support OpenACC xx or higher!
#endif

// Base classes.
#include <alpaka/workdiv/WorkDivMembers.hpp>
#include <alpaka/idx/gb/IdxGbOaccBuiltIn.hpp>
#include <alpaka/block/shared/dyn/BlockSharedMemDynMember.hpp>
#include <alpaka/block/shared/st/BlockSharedMemStMember.hpp>
#include <alpaka/block/sync/BlockSyncBarrierOacc.hpp>

// Specialized traits.
#include <alpaka/idx/Traits.hpp>

#include <limits>
#include <typeinfo>

namespace alpaka
{
    namespace kernel
    {
        template<
            typename TDim,
            typename TIdx,
            typename TKernelFnObj,
            typename... TArgs>
        class TaskKernelOacc;
    }
    namespace ctx
    {
        //#############################################################################
        //! The OpenACC block context.
        template<
            typename TDim,
            typename TIdx>
        class CtxBlockOacc final :
            public workdiv::WorkDivMembers<TDim, TIdx>,
            public idx::gb::IdxGbOaccBuiltIn<TDim, TIdx>::BlockShared,
            public block::shared::dyn::BlockSharedMemDynMember<>,
            public block::shared::st::detail::BlockSharedMemStMemberImpl<4>,
            public block::sync::BlockSyncBarrierOacc::BlockShared,
            public concepts::Implements<block::shared::st::ConceptBlockSharedSt, CtxBlockOacc<TDim, TIdx>>
        {
        public:
            // Partial specialization with the correct TDim and TIdx is not allowed.
            template<
                typename TDim2,
                typename TIdx2,
                typename TKernelFnObj,
                typename... TArgs>
            friend class ::alpaka::kernel::TaskKernelOacc;

        protected:
            //-----------------------------------------------------------------------------
            CtxBlockOacc(
                vec::Vec<TDim, TIdx> const & gridBlockExtent,
                vec::Vec<TDim, TIdx> const & blockThreadExtent,
                vec::Vec<TDim, TIdx> const & threadElemExtent,
                TIdx const & gridBlockIdx,
                std::size_t const & blockSharedMemDynSizeBytes) :
                    workdiv::WorkDivMembers<TDim, TIdx>(gridBlockExtent, blockThreadExtent, threadElemExtent),
                    idx::gb::IdxGbOaccBuiltIn<TDim, TIdx>::BlockShared(gridBlockIdx),
                    block::shared::dyn::BlockSharedMemDynMember<>(blockSharedMemDynSizeBytes),
                    //! \TODO can with some TMP determine the amount of statically alloced smem from the kernelFuncObj?
                    block::shared::st::detail::BlockSharedMemStMemberImpl<4>(staticMemBegin(), staticMemCapacity()),
                    block::sync::BlockSyncBarrierOacc::BlockShared()
            {}

        public:
            //-----------------------------------------------------------------------------
            CtxBlockOacc(CtxBlockOacc const &) = delete;
            //-----------------------------------------------------------------------------
            CtxBlockOacc(CtxBlockOacc &&) = delete;
            //-----------------------------------------------------------------------------
            auto operator=(CtxBlockOacc const &) -> CtxBlockOacc & = delete;
            //-----------------------------------------------------------------------------
            auto operator=(CtxBlockOacc &&) -> CtxBlockOacc & = delete;
            //-----------------------------------------------------------------------------
            /*virtual*/ ~CtxBlockOacc() = default;
        };
    }

    namespace block
    {
        namespace sync
        {
            namespace traits
            {
                //#############################################################################
                template<
                    typename TDim,
                    typename TIdx>
                struct SyncBlockThreads<
                    ctx::CtxBlockOacc<TDim, TIdx>>
                {
                    //-----------------------------------------------------------------------------
                    //! Execute op with single thread (any idx, last thread to
                    //! arrive at barrier executes) syncing before and after
                    template<
                        typename TOp>
                    ALPAKA_FN_HOST static auto masterOpBlockThreads(
                        ctx::CtxBlockOacc<TDim, TIdx> const & acc,
                        TOp &&op)
                    -> void
                    {
                        const auto slot = (acc.m_generation&1)<<1;
                        const int workerNum = static_cast<int>(workdiv::getWorkDiv<Block, Threads>(acc).prod());
                        int sum;
                        #pragma acc atomic capture
                        {
                            ++acc.m_syncCounter[slot];
                            sum = acc.m_syncCounter[slot];
                        }
                        if(sum == workerNum)
                        {
                            ++acc.m_generation;
                            const int nextSlot = (acc.m_generation&1)<<1;
                            acc.m_syncCounter[nextSlot] = 0;
                            acc.m_syncCounter[nextSlot+1] = 0;
                            op();
                        }
                        while(sum < workerNum)
                        {
                            #pragma acc atomic read
                            sum = acc.m_syncCounter[slot];
                        }
                        #pragma acc atomic capture
                        {
                            ++acc.m_syncCounter[slot];
                            sum = acc.m_syncCounter[slot];
                        }
                        while(sum < workerNum)
                        {
                            #pragma acc atomic read
                            sum = acc.m_syncCounter[slot+1];
                        }
                    }

                    //-----------------------------------------------------------------------------
                    ALPAKA_FN_HOST static auto syncBlockThreads(
                        ctx::CtxBlockOacc<TDim, TIdx> const & acc)
                    -> void
                    {
                        masterOpBlockThreads<>(acc, [](){});
                    }
                };

                namespace oacc
                {
                    namespace detail
                    {
                        //#############################################################################
                        template<
                            typename TOp>
                        struct AtomicOp;
                        //#############################################################################
                        template<>
                        struct AtomicOp<
                            block::sync::op::Count>
                        {
                            void operator()(int& result, bool value)
                            {
                                #pragma acc atomic update
                                result += static_cast<int>(value);
                            }
                        };
                        //#############################################################################
                        template<>
                        struct AtomicOp<
                            block::sync::op::LogicalAnd>
                        {
                            void operator()(int& result, bool value)
                            {
                                #pragma acc atomic update
                                result &= static_cast<int>(value);
                            }
                        };
                        //#############################################################################
                        template<>
                        struct AtomicOp<
                            block::sync::op::LogicalOr>
                        {
                            void operator()(int& result, bool value)
                            {
                                #pragma acc atomic update
                                result |= static_cast<int>(value);
                            }
                        };
                    }
                }

                //#############################################################################
                template<
                    typename TOp,
                    typename TDim,
                    typename TIdx>
                struct SyncBlockThreadsPredicate<
                    TOp,
                    ctx::CtxBlockOacc<TDim, TIdx>>
                {
                    //-----------------------------------------------------------------------------
                    ALPAKA_NO_HOST_ACC_WARNING
                    ALPAKA_FN_ACC static auto syncBlockThreadsPredicate(
                        ctx::CtxBlockOacc<TDim, TIdx> const & blockSync,
                        int predicate)
                    -> int
                    {
                        // implicit snyc
                        SyncBlockThreads<ctx::CtxBlockOacc<TDim, TIdx>>::masterOpBlockThreads(
                                blockSync,
                                [&blockSync](){blockSync.m_result = TOp::InitialValue;}
                            );

                        int& result(blockSync.m_result);
                        bool const predicateBool(predicate != 0);

                        oacc::detail::AtomicOp<TOp>()(result, predicateBool);

                        SyncBlockThreads<ctx::CtxBlockOacc<TDim, TIdx>>::syncBlockThreads(blockSync);

                        return blockSync.m_result;
                    }
                };
            }
        }
    }
    namespace dim
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenACC accelerator dimension getter trait specialization.
            template<
                typename TDim,
                typename TIdx>
            struct DimType<
                ctx::CtxBlockOacc<TDim, TIdx>>
            {
                using type = TDim;
            };
        }
    }
    namespace idx
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenACC accelerator idx type trait specialization.
            template<
                typename TDim,
                typename TIdx>
            struct IdxType<
                ctx::CtxBlockOacc<TDim, TIdx>>
            {
                using type = TIdx;
            };
        }
    }
    namespace block
    {
        namespace shared
        {
            namespace st
            {
                namespace traits
                {
                    //#############################################################################
                    template<
                        typename T,
                        typename TDim,
                        typename TIdx,
                        std::size_t TuniqueId>
                    struct AllocVar<
                        T,
                        TuniqueId,
                        ctx::CtxBlockOacc<TDim, TIdx>>
                    {
                        //-----------------------------------------------------------------------------
                        static auto allocVar(
                            ctx::CtxBlockOacc<TDim, TIdx> const &smem)
                        -> T &
                        {
                           block::sync::traits::SyncBlockThreads<ctx::CtxBlockOacc<TDim, TIdx>>::masterOpBlockThreads(
                               smem,
                               [&smem](){
                                   smem.template alloc<T>();
                                   }
                               );
                           return smem.template getLatestVar<T>();
                        }
                    };

                    //#############################################################################
                    template<
                        typename TDim,
                        typename TIdx>
                    struct FreeMem<
                        ctx::CtxBlockOacc<TDim, TIdx>>
                    {
                        //-----------------------------------------------------------------------------
                        static auto freeMem(
                            ctx::CtxBlockOacc<TDim, TIdx> const &)
                        -> void
                        {
                            // Nothing to do. Block shared memory is automatically freed when all threads left the block.
                        }
                    };
                }
            }
        }
    }
}

#endif
<commit_msg>CtxBlockOacc: SyncBlockThreads: Add workaround for NVHPC issue<commit_after>/* Copyright 2020 Jeffrey Kelling
 *
 * This file is part of Alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#ifdef ALPAKA_ACC_ANY_BT_OACC_ENABLED

#if _OPENACC < 201306
    #error If ALPAKA_ACC_ANY_BT_OACC_ENABLED is set, the compiler has to support OpenACC xx or higher!
#endif

// Base classes.
#include <alpaka/workdiv/WorkDivMembers.hpp>
#include <alpaka/idx/gb/IdxGbOaccBuiltIn.hpp>
#include <alpaka/block/shared/dyn/BlockSharedMemDynMember.hpp>
#include <alpaka/block/shared/st/BlockSharedMemStMember.hpp>
#include <alpaka/block/sync/BlockSyncBarrierOacc.hpp>

// Specialized traits.
#include <alpaka/idx/Traits.hpp>

#include <limits>
#include <typeinfo>

namespace alpaka
{
    namespace kernel
    {
        template<
            typename TDim,
            typename TIdx,
            typename TKernelFnObj,
            typename... TArgs>
        class TaskKernelOacc;
    }
    namespace ctx
    {
        //#############################################################################
        //! The OpenACC block context.
        template<
            typename TDim,
            typename TIdx>
        class CtxBlockOacc final :
            public workdiv::WorkDivMembers<TDim, TIdx>,
            public idx::gb::IdxGbOaccBuiltIn<TDim, TIdx>::BlockShared,
            public block::shared::dyn::BlockSharedMemDynMember<>,
            public block::shared::st::detail::BlockSharedMemStMemberImpl<4>,
            public block::sync::BlockSyncBarrierOacc::BlockShared,
            public concepts::Implements<block::shared::st::ConceptBlockSharedSt, CtxBlockOacc<TDim, TIdx>>
        {
        public:
            // Partial specialization with the correct TDim and TIdx is not allowed.
            template<
                typename TDim2,
                typename TIdx2,
                typename TKernelFnObj,
                typename... TArgs>
            friend class ::alpaka::kernel::TaskKernelOacc;

        protected:
            //-----------------------------------------------------------------------------
            CtxBlockOacc(
                vec::Vec<TDim, TIdx> const & gridBlockExtent,
                vec::Vec<TDim, TIdx> const & blockThreadExtent,
                vec::Vec<TDim, TIdx> const & threadElemExtent,
                TIdx const & gridBlockIdx,
                std::size_t const & blockSharedMemDynSizeBytes) :
                    workdiv::WorkDivMembers<TDim, TIdx>(gridBlockExtent, blockThreadExtent, threadElemExtent),
                    idx::gb::IdxGbOaccBuiltIn<TDim, TIdx>::BlockShared(gridBlockIdx),
                    block::shared::dyn::BlockSharedMemDynMember<>(blockSharedMemDynSizeBytes),
                    //! \TODO can with some TMP determine the amount of statically alloced smem from the kernelFuncObj?
                    block::shared::st::detail::BlockSharedMemStMemberImpl<4>(staticMemBegin(), staticMemCapacity()),
                    block::sync::BlockSyncBarrierOacc::BlockShared()
            {}

        public:
            //-----------------------------------------------------------------------------
            CtxBlockOacc(CtxBlockOacc const &) = delete;
            //-----------------------------------------------------------------------------
            CtxBlockOacc(CtxBlockOacc &&) = delete;
            //-----------------------------------------------------------------------------
            auto operator=(CtxBlockOacc const &) -> CtxBlockOacc & = delete;
            //-----------------------------------------------------------------------------
            auto operator=(CtxBlockOacc &&) -> CtxBlockOacc & = delete;
            //-----------------------------------------------------------------------------
            /*virtual*/ ~CtxBlockOacc() = default;
        };
    }

    namespace block
    {
        namespace sync
        {
            namespace traits
            {
                //#############################################################################
                template<
                    typename TDim,
                    typename TIdx>
                struct SyncBlockThreads<
                    ctx::CtxBlockOacc<TDim, TIdx>>
                {
                    //-----------------------------------------------------------------------------
                    //! Execute op with single thread (any idx, last thread to
                    //! arrive at barrier executes) syncing before and after
                    template<
                        typename TOp>
                    ALPAKA_FN_HOST static auto masterOpBlockThreads(
                        ctx::CtxBlockOacc<TDim, TIdx> const & acc,
                        TOp &&op)
                    -> void
                    {
                        const auto slot = (acc.m_generation&1)<<1;
                        const int workerNum = static_cast<int>(workdiv::getWorkDiv<Block, Threads>(acc).prod());
                        int sum;
// Workaround to use an array in an atomic capture rather than
// using the data member m_syncCounter array directly.
// The change is sematically equivlent.
// However, this should work per the OpenACC standard, but appears to be compiler
// issue causing a runtime error.  The error was seen the 20.7 release
// of the NVIDIA HPC Compiler but may be corrected in future releases.
		        int * m_syncCounter = acc.m_syncCounter;
                        #pragma acc atomic capture
                        {
                            ++m_syncCounter[slot];
                            sum = m_syncCounter[slot];
                        }
                        if(sum == workerNum)
                        {
                            ++acc.m_generation;
                            const int nextSlot = (acc.m_generation&1)<<1;
                            m_syncCounter[nextSlot] = 0;
                            m_syncCounter[nextSlot+1] = 0;
                            op();
                        }
                        while(sum < workerNum)
                        {
                            #pragma acc atomic read
                            sum = m_syncCounter[slot];
                        }
                        #pragma acc atomic capture
                        {
                            ++m_syncCounter[slot];
                            sum = m_syncCounter[slot];
                        }
                        while(sum < workerNum)
                        {
                            #pragma acc atomic read
                            sum = m_syncCounter[slot+1];
	                }
                    }

                    //-----------------------------------------------------------------------------
                    ALPAKA_FN_HOST static auto syncBlockThreads(
                        ctx::CtxBlockOacc<TDim, TIdx> const & acc)
                    -> void
                    {
                        masterOpBlockThreads<>(acc, [](){});
                    }
                };

                namespace oacc
                {
                    namespace detail
                    {
                        //#############################################################################
                        template<
                            typename TOp>
                        struct AtomicOp;
                        //#############################################################################
                        template<>
                        struct AtomicOp<
                            block::sync::op::Count>
                        {
                            void operator()(int& result, bool value)
                            {
                                #pragma acc atomic update
                                result += static_cast<int>(value);
                            }
                        };
                        //#############################################################################
                        template<>
                        struct AtomicOp<
                            block::sync::op::LogicalAnd>
                        {
                            void operator()(int& result, bool value)
                            {
                                #pragma acc atomic update
                                result &= static_cast<int>(value);
                            }
                        };
                        //#############################################################################
                        template<>
                        struct AtomicOp<
                            block::sync::op::LogicalOr>
                        {
                            void operator()(int& result, bool value)
                            {
                                #pragma acc atomic update
                                result |= static_cast<int>(value);
                            }
                        };
                    }
                }

                //#############################################################################
                template<
                    typename TOp,
                    typename TDim,
                    typename TIdx>
                struct SyncBlockThreadsPredicate<
                    TOp,
                    ctx::CtxBlockOacc<TDim, TIdx>>
                {
                    //-----------------------------------------------------------------------------
                    ALPAKA_NO_HOST_ACC_WARNING
                    ALPAKA_FN_ACC static auto syncBlockThreadsPredicate(
                        ctx::CtxBlockOacc<TDim, TIdx> const & blockSync,
                        int predicate)
                    -> int
                    {
                        // implicit snyc
                        SyncBlockThreads<ctx::CtxBlockOacc<TDim, TIdx>>::masterOpBlockThreads(
                                blockSync,
                                [&blockSync](){blockSync.m_result = TOp::InitialValue;}
                            );

                        int& result(blockSync.m_result);
                        bool const predicateBool(predicate != 0);

                        oacc::detail::AtomicOp<TOp>()(result, predicateBool);

                        SyncBlockThreads<ctx::CtxBlockOacc<TDim, TIdx>>::syncBlockThreads(blockSync);

                        return blockSync.m_result;
                    }
                };
            }
        }
    }
    namespace dim
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenACC accelerator dimension getter trait specialization.
            template<
                typename TDim,
                typename TIdx>
            struct DimType<
                ctx::CtxBlockOacc<TDim, TIdx>>
            {
                using type = TDim;
            };
        }
    }
    namespace idx
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenACC accelerator idx type trait specialization.
            template<
                typename TDim,
                typename TIdx>
            struct IdxType<
                ctx::CtxBlockOacc<TDim, TIdx>>
            {
                using type = TIdx;
            };
        }
    }
    namespace block
    {
        namespace shared
        {
            namespace st
            {
                namespace traits
                {
                    //#############################################################################
                    template<
                        typename T,
                        typename TDim,
                        typename TIdx,
                        std::size_t TuniqueId>
                    struct AllocVar<
                        T,
                        TuniqueId,
                        ctx::CtxBlockOacc<TDim, TIdx>>
                    {
                        //-----------------------------------------------------------------------------
                        static auto allocVar(
                            ctx::CtxBlockOacc<TDim, TIdx> const &smem)
                        -> T &
                        {
                           block::sync::traits::SyncBlockThreads<ctx::CtxBlockOacc<TDim, TIdx>>::masterOpBlockThreads(
                               smem,
                               [&smem](){
                                   smem.template alloc<T>();
                                   }
                               );
                           return smem.template getLatestVar<T>();
                        }
                    };

                    //#############################################################################
                    template<
                        typename TDim,
                        typename TIdx>
                    struct FreeMem<
                        ctx::CtxBlockOacc<TDim, TIdx>>
                    {
                        //-----------------------------------------------------------------------------
                        static auto freeMem(
                            ctx::CtxBlockOacc<TDim, TIdx> const &)
                        -> void
                        {
                            // Nothing to do. Block shared memory is automatically freed when all threads left the block.
                        }
                    };
                }
            }
        }
    }
}

#endif
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : implemets Unit Test Log
// ***************************************************************************

#ifndef BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER

// Boost.Test
#include <boost/test/unit_test_log.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/execution_monitor.hpp>

#include <boost/test/detail/unit_test_parameters.hpp>
#include <boost/test/detail/wrap_io_saver.hpp>

#include <boost/test/utils/basic_cstring/compare.hpp>

#include <boost/test/output/compiler_log_formatter.hpp>
#include <boost/test/output/xml_log_formatter.hpp>

// Boost
#include <boost/scoped_ptr.hpp>

// STL
#include <iostream>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {

namespace unit_test {

// ************************************************************************** //
// **************             entry_value_collector            ************** //
// ************************************************************************** //

namespace ut_detail {

entry_value_collector
entry_value_collector::operator<<( const_string v )
{
    unit_test_log << v;

    m_last = false;

    entry_value_collector res;
    return res;
}

//____________________________________________________________________________//

entry_value_collector::~entry_value_collector()
{
    if( m_last )
        unit_test_log << log::end();
}

//____________________________________________________________________________//

} // namespace ut_detail

// ************************************************************************** //
// **************                 unit_test_log                ************** //
// ************************************************************************** //

namespace {

struct unit_test_log_impl {
    // Constructor
    unit_test_log_impl()
    : m_stream( &std::cout )
    , m_stream_state_saver( new io_saver_type( std::cout ) )
    , m_threshold_level( log_all_errors )
    , m_log_formatter( new output::compiler_log_formatter )
    {
    }

    // log data
    typedef scoped_ptr<unit_test_log_formatter> formatter_ptr;
    typedef scoped_ptr<io_saver_type>           saver_ptr;

    std::ostream*       m_stream;
    saver_ptr           m_stream_state_saver;
    log_level           m_threshold_level;
    formatter_ptr       m_log_formatter;

    // entry data
    bool                m_entry_in_progress;
    bool                m_entry_started;
    log_entry_data      m_entry_data;

    // check point data
    log_checkpoint_data m_checkpoint_data;

    // helper functions
    std::ostream&       stream()            { return *m_stream; }
    void                set_checkpoint( const_string file, std::size_t line_num, const_string msg )
    {
        assign_op( m_checkpoint_data.m_message, msg, 0 );
        m_checkpoint_data.m_file_name    = file;
        m_checkpoint_data.m_line_num    = line_num;
    }
};

unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; }

} // local namespace

//____________________________________________________________________________//

void
unit_test_log_t::test_start( counter_t test_cases_amount )
{
    s_log_impl().m_log_formatter->log_start( s_log_impl().stream(), test_cases_amount );

    if( runtime_config::show_build_info() )
        s_log_impl().m_log_formatter->log_build_info( s_log_impl().stream() );

    s_log_impl().m_entry_in_progress = false;
}

//____________________________________________________________________________//

void
unit_test_log_t::test_finish()
{
    s_log_impl().m_log_formatter->log_finish( s_log_impl().stream() );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_aborted()
{
    BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted";
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_start( test_unit const& tu )
{
    if( s_log_impl().m_threshold_level > log_test_suites )
        return;

    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_log_formatter->test_unit_start( s_log_impl().stream(), tu );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed )
{
    if( s_log_impl().m_threshold_level > log_test_suites )
        return;

    s_log_impl().m_checkpoint_data.clear();

    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_log_formatter->test_unit_finish( s_log_impl().stream(), tu, elapsed );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_skipped( test_unit const& tu )
{
    if( s_log_impl().m_threshold_level > log_test_suites )
        return;

    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_log_formatter->test_unit_skipped( s_log_impl().stream(), tu );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_aborted( test_unit const& )
{
    // do nothing
}

//____________________________________________________________________________//

void
unit_test_log_t::assertion_result( bool )
{
    // do nothing
}

//____________________________________________________________________________//

void
unit_test_log_t::exception_caught( execution_exception const& ex )
{
    log_level l =
        ex.code() <= execution_exception::cpp_exception_error   ? log_cpp_exception_errors :
        (ex.code() <= execution_exception::timeout_error        ? log_system_errors
                                                                : log_fatal_errors );

    if( l >= s_log_impl().m_threshold_level ) {
        if( s_log_impl().m_entry_in_progress )
            *this << log::end();

        s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex.what() );
    }
}

//____________________________________________________________________________//

void
unit_test_log_t::set_checkpoint( const_string file, std::size_t line_num, const_string msg )
{
    s_log_impl().set_checkpoint( file, line_num, msg );
}

//____________________________________________________________________________//

char
set_unix_slash( char in )
{
    return in == '\\' ? '/' : in;
}

unit_test_log_t&
unit_test_log_t::operator<<( log::begin const& b )
{
    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_stream_state_saver->restore();

    s_log_impl().m_entry_data.clear();

    assign_op( s_log_impl().m_entry_data.m_file_name, b.m_file_name, 0 );

    // normalize file name
    std::transform( s_log_impl().m_entry_data.m_file_name.begin(), s_log_impl().m_entry_data.m_file_name.end(),
                    s_log_impl().m_entry_data.m_file_name.begin(),
                    &set_unix_slash );

    s_log_impl().m_entry_data.m_line_num = b.m_line_num;

    return *this;
}

//____________________________________________________________________________//

unit_test_log_t&
unit_test_log_t::operator<<( log::end const& )
{
    if( s_log_impl().m_entry_in_progress )
        s_log_impl().m_log_formatter->log_entry_finish( s_log_impl().stream() );

    s_log_impl().m_entry_in_progress = false;

    return *this;
}

//____________________________________________________________________________//

unit_test_log_t&
unit_test_log_t::operator<<( log_level l )
{
    s_log_impl().m_entry_data.m_level = l;

    return *this;
}

//____________________________________________________________________________//

ut_detail::entry_value_collector
unit_test_log_t::operator()( log_level l )
{
    *this << l;

    ut_detail::entry_value_collector res;
    return res;
}

//____________________________________________________________________________//

unit_test_log_t&
unit_test_log_t::operator<<( const_string value )
{
    if( s_log_impl().m_entry_data.m_level >= s_log_impl().m_threshold_level && !value.empty() ) {
        if( !s_log_impl().m_entry_in_progress ) {
            s_log_impl().m_entry_in_progress = true;

            switch( s_log_impl().m_entry_data.m_level ) {
            case log_successful_tests:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_INFO );
                break;
            case log_messages:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_MESSAGE );
                break;
            case log_warnings:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_WARNING );
                break;
            case log_all_errors:
            case log_cpp_exception_errors:
            case log_system_errors:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_ERROR );
                break;
            case log_fatal_errors:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR );
                break;
            case log_nothing:
            case log_test_suites:
            case invalid_log_level:
                return *this;
            }
        }

        s_log_impl().m_log_formatter->log_entry_value( s_log_impl().stream(), value );
    }

    return *this;
}

//____________________________________________________________________________//

void
unit_test_log_t::set_stream( std::ostream& str )
{
    if( s_log_impl().m_entry_in_progress )
        return;

    s_log_impl().m_stream = &str;
    s_log_impl().m_stream_state_saver.reset( new io_saver_type( str ) );
}

//____________________________________________________________________________//

void
unit_test_log_t::set_threshold_level( log_level lev )
{
    if( s_log_impl().m_entry_in_progress || lev == invalid_log_level )
        return;

    s_log_impl().m_threshold_level = lev;
}

//____________________________________________________________________________//

void
unit_test_log_t::set_format( output_format log_format )
{
    if( s_log_impl().m_entry_in_progress )
        return;

    if( log_format == CLF )
        set_formatter( new output::compiler_log_formatter );
    else
        set_formatter( new output::xml_log_formatter );
}

//____________________________________________________________________________//

void
unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter )
{
    s_log_impl().m_log_formatter.reset( the_formatter );
}

//____________________________________________________________________________//

} // namespace unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.11  2005/12/14 05:34:21  rogeeff
//  log API simplified
//
//  Revision 1.10  2005/04/30 16:48:51  rogeeff
//  io saver warkaround for classic io is shared
//
//  Revision 1.9  2005/04/29 06:28:35  rogeeff
//  bug fix for manipulator handling
//
//  Revision 1.8  2005/04/12 06:50:46  rogeeff
//  assign_to -> assign_op
//
//  Revision 1.7  2005/03/22 07:06:58  rogeeff
//  assign_to made free function
//
//  Revision 1.6  2005/02/20 08:27:07  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
// ***************************************************************************

#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
<commit_msg>flush log strema on exit<commit_after>//  (C) Copyright Gennadiy Rozental 2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : implemets Unit Test Log
// ***************************************************************************

#ifndef BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER

// Boost.Test
#include <boost/test/unit_test_log.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/execution_monitor.hpp>

#include <boost/test/detail/unit_test_parameters.hpp>
#include <boost/test/detail/wrap_io_saver.hpp>

#include <boost/test/utils/basic_cstring/compare.hpp>

#include <boost/test/output/compiler_log_formatter.hpp>
#include <boost/test/output/xml_log_formatter.hpp>

// Boost
#include <boost/scoped_ptr.hpp>

// STL
#include <iostream>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {

namespace unit_test {

// ************************************************************************** //
// **************             entry_value_collector            ************** //
// ************************************************************************** //

namespace ut_detail {

entry_value_collector
entry_value_collector::operator<<( const_string v )
{
    unit_test_log << v;

    m_last = false;

    entry_value_collector res;
    return res;
}

//____________________________________________________________________________//

entry_value_collector::~entry_value_collector()
{
    if( m_last )
        unit_test_log << log::end();
}

//____________________________________________________________________________//

} // namespace ut_detail

// ************************************************************************** //
// **************                 unit_test_log                ************** //
// ************************************************************************** //

namespace {

struct unit_test_log_impl {
    // Constructor
    unit_test_log_impl()
    : m_stream( &std::cout )
    , m_stream_state_saver( new io_saver_type( std::cout ) )
    , m_threshold_level( log_all_errors )
    , m_log_formatter( new output::compiler_log_formatter )
    {
    }

    // log data
    typedef scoped_ptr<unit_test_log_formatter> formatter_ptr;
    typedef scoped_ptr<io_saver_type>           saver_ptr;

    std::ostream*       m_stream;
    saver_ptr           m_stream_state_saver;
    log_level           m_threshold_level;
    formatter_ptr       m_log_formatter;

    // entry data
    bool                m_entry_in_progress;
    bool                m_entry_started;
    log_entry_data      m_entry_data;

    // check point data
    log_checkpoint_data m_checkpoint_data;

    // helper functions
    std::ostream&       stream()            { return *m_stream; }
    void                set_checkpoint( const_string file, std::size_t line_num, const_string msg )
    {
        assign_op( m_checkpoint_data.m_message, msg, 0 );
        m_checkpoint_data.m_file_name    = file;
        m_checkpoint_data.m_line_num    = line_num;
    }
};

unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; }

} // local namespace

//____________________________________________________________________________//

void
unit_test_log_t::test_start( counter_t test_cases_amount )
{
    s_log_impl().m_log_formatter->log_start( s_log_impl().stream(), test_cases_amount );

    if( runtime_config::show_build_info() )
        s_log_impl().m_log_formatter->log_build_info( s_log_impl().stream() );

    s_log_impl().m_entry_in_progress = false;
}

//____________________________________________________________________________//

void
unit_test_log_t::test_finish()
{
    s_log_impl().m_log_formatter->log_finish( s_log_impl().stream() );

    s_log_impl().stream().flush();
}

//____________________________________________________________________________//

void
unit_test_log_t::test_aborted()
{
    BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted";
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_start( test_unit const& tu )
{
    if( s_log_impl().m_threshold_level > log_test_suites )
        return;

    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_log_formatter->test_unit_start( s_log_impl().stream(), tu );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed )
{
    if( s_log_impl().m_threshold_level > log_test_suites )
        return;

    s_log_impl().m_checkpoint_data.clear();

    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_log_formatter->test_unit_finish( s_log_impl().stream(), tu, elapsed );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_skipped( test_unit const& tu )
{
    if( s_log_impl().m_threshold_level > log_test_suites )
        return;

    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_log_formatter->test_unit_skipped( s_log_impl().stream(), tu );
}

//____________________________________________________________________________//

void
unit_test_log_t::test_unit_aborted( test_unit const& )
{
    // do nothing
}

//____________________________________________________________________________//

void
unit_test_log_t::assertion_result( bool )
{
    // do nothing
}

//____________________________________________________________________________//

void
unit_test_log_t::exception_caught( execution_exception const& ex )
{
    log_level l =
        ex.code() <= execution_exception::cpp_exception_error   ? log_cpp_exception_errors :
        (ex.code() <= execution_exception::timeout_error        ? log_system_errors
                                                                : log_fatal_errors );

    if( l >= s_log_impl().m_threshold_level ) {
        if( s_log_impl().m_entry_in_progress )
            *this << log::end();

        s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex.what() );
    }
}

//____________________________________________________________________________//

void
unit_test_log_t::set_checkpoint( const_string file, std::size_t line_num, const_string msg )
{
    s_log_impl().set_checkpoint( file, line_num, msg );
}

//____________________________________________________________________________//

char
set_unix_slash( char in )
{
    return in == '\\' ? '/' : in;
}

unit_test_log_t&
unit_test_log_t::operator<<( log::begin const& b )
{
    if( s_log_impl().m_entry_in_progress )
        *this << log::end();

    s_log_impl().m_stream_state_saver->restore();

    s_log_impl().m_entry_data.clear();

    assign_op( s_log_impl().m_entry_data.m_file_name, b.m_file_name, 0 );

    // normalize file name
    std::transform( s_log_impl().m_entry_data.m_file_name.begin(), s_log_impl().m_entry_data.m_file_name.end(),
                    s_log_impl().m_entry_data.m_file_name.begin(),
                    &set_unix_slash );

    s_log_impl().m_entry_data.m_line_num = b.m_line_num;

    return *this;
}

//____________________________________________________________________________//

unit_test_log_t&
unit_test_log_t::operator<<( log::end const& )
{
    if( s_log_impl().m_entry_in_progress )
        s_log_impl().m_log_formatter->log_entry_finish( s_log_impl().stream() );

    s_log_impl().m_entry_in_progress = false;

    return *this;
}

//____________________________________________________________________________//

unit_test_log_t&
unit_test_log_t::operator<<( log_level l )
{
    s_log_impl().m_entry_data.m_level = l;

    return *this;
}

//____________________________________________________________________________//

ut_detail::entry_value_collector
unit_test_log_t::operator()( log_level l )
{
    *this << l;

    ut_detail::entry_value_collector res;
    return res;
}

//____________________________________________________________________________//

unit_test_log_t&
unit_test_log_t::operator<<( const_string value )
{
    if( s_log_impl().m_entry_data.m_level >= s_log_impl().m_threshold_level && !value.empty() ) {
        if( !s_log_impl().m_entry_in_progress ) {
            s_log_impl().m_entry_in_progress = true;

            switch( s_log_impl().m_entry_data.m_level ) {
            case log_successful_tests:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_INFO );
                break;
            case log_messages:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_MESSAGE );
                break;
            case log_warnings:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_WARNING );
                break;
            case log_all_errors:
            case log_cpp_exception_errors:
            case log_system_errors:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_ERROR );
                break;
            case log_fatal_errors:
                s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
                                                               unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR );
                break;
            case log_nothing:
            case log_test_suites:
            case invalid_log_level:
                return *this;
            }
        }

        s_log_impl().m_log_formatter->log_entry_value( s_log_impl().stream(), value );
    }

    return *this;
}

//____________________________________________________________________________//

void
unit_test_log_t::set_stream( std::ostream& str )
{
    if( s_log_impl().m_entry_in_progress )
        return;

    s_log_impl().m_stream = &str;
    s_log_impl().m_stream_state_saver.reset( new io_saver_type( str ) );
}

//____________________________________________________________________________//

void
unit_test_log_t::set_threshold_level( log_level lev )
{
    if( s_log_impl().m_entry_in_progress || lev == invalid_log_level )
        return;

    s_log_impl().m_threshold_level = lev;
}

//____________________________________________________________________________//

void
unit_test_log_t::set_format( output_format log_format )
{
    if( s_log_impl().m_entry_in_progress )
        return;

    if( log_format == CLF )
        set_formatter( new output::compiler_log_formatter );
    else
        set_formatter( new output::xml_log_formatter );
}

//____________________________________________________________________________//

void
unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter )
{
    s_log_impl().m_log_formatter.reset( the_formatter );
}

//____________________________________________________________________________//

} // namespace unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.12  2006/07/28 15:03:13  rogeeff
//  flush log strema on exit
//
//  Revision 1.11  2005/12/14 05:34:21  rogeeff
//  log API simplified
//
//  Revision 1.10  2005/04/30 16:48:51  rogeeff
//  io saver warkaround for classic io is shared
//
//  Revision 1.9  2005/04/29 06:28:35  rogeeff
//  bug fix for manipulator handling
//
//  Revision 1.8  2005/04/12 06:50:46  rogeeff
//  assign_to -> assign_op
//
//  Revision 1.7  2005/03/22 07:06:58  rogeeff
//  assign_to made free function
//
//  Revision 1.6  2005/02/20 08:27:07  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
// ***************************************************************************

#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <iostream>
#include <sensor_msgs/PointCloud2.h>
#include <std_msgs/String.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/conversions.h>
#include <pcl_ros/transforms.h>
#include <boost/foreach.hpp>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/pcd_io.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_sphere.h>
#include <pcl/sample_consensus/sac_model_cylinder.h>
#include <pcl/segmentation/sac_segmentation.h>

using std::cout;
using std::endl;

std_msgs::String str;
ros::Publisher pub;
int found;

void callback(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  pcl::PCLPointCloud2 pcl_pc2;
  pcl_conversions::toPCL(*cloud,pcl_pc2);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr temp_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
  pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);

  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  pcl::SACSegmentation<pcl::PointXYZRGB> segmentation;
  segmentation.setInputCloud(temp_cloud);
  segmentation.setModelType(pcl::SACMODEL_SPHERE);
  segmentation.setMethodType(pcl::SAC_RANSAC);
  segmentation.setDistanceThreshold(1000);
  segmentation.setOptimizeCoefficients(true);
  segmentation.setRadiusLimits(0.4, 1);
  segmentation.setMaxIterations(1000);

  pcl::PointIndices inlierIndices;
  segmentation.segment(inlierIndices, *coefficients);

  if (inlierIndices.indices.size() != 0)
  {
    ROS_INFO("RANSAC found shape with [%d] points", (int)inlierIndices.indices.size());
    cout << "SPHERE!" << endl;
    str.data = "found";
    if((int)temp_cloud->points[inlierIndices.indices[size/2]].r>(int)temp_cloud->points[inlierIndices.indices[size/2]].g && (int)temp_cloud->points[inlierIndices.indices[size/2]].r>(int)temp_cloud->points[inlierIndices.indices[size/2]].g)
    {
      cout << "RED SPHERE!" << endl;
      str.data = "found red";
      found = 1;
      }
    }

    std_msgs::String nstr;
    nstr.data = str.data;
    pub.publish(nstr);
}

void callback2(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  pcl::PCLPointCloud2 pcl_pc2;
  pcl_conversions::toPCL(*cloud,pcl_pc2);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr temp_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
  pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);

  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  pcl::SACSegmentation<pcl::PointXYZRGB> segmentation;
  segmentation.setOptimizeCoefficients(true);
  segmentation.setModelType(pcl::SACMODEL_PLANE);
  segmentation.setMethodType(pcl::SAC_RANSAC);
  segmentation.setDistanceThreshold(0.01);
  segmentation.setMaxIterations(200);
  segmentation.setInputCloud(temp_cloud);
  segmentation.setEpsAngle (0.1);

  pcl::PointIndices inlierIndices;
  segmentation.segment(inlierIndices, *coefficients);

  if (inlierIndices.indices.size() != 0)
  {
    int size = (int)inlierIndices.indices.size();
    ROS_INFO("RANSAC found shape with [%d] points", size);
    float y1 = temp_cloud->points[inlierIndices.indices[0]].y;
    float z1 = temp_cloud->points[inlierIndices.indices[0]].z;
    float y2 =temp_cloud->points[inlierIndices.indices[size/2]].y;
    float z2 =temp_cloud->points[inlierIndices.indices[size/2]].z;
    float transformedy1 = y1*cos(-1)-z1*sin(-1);
    float transformedy2 = y2*cos(-1)-z2*sin(-1);

    cout << temp_cloud->points[inlierIndices.indices[0]].x << "  " << y1 << "  " << temp_cloud->points[inlierIndices.indices[0]].z << endl;
    cout << temp_cloud->points[inlierIndices.indices[size/2]].x << "  " << y2 << "  " << temp_cloud->points[inlierIndices.indices[size/2]].z << endl;
    cout << transformedy1 << endl;
    cout << transformedy2 << endl;
    cout << (int)temp_cloud->points[inlierIndices.indices[size/2]].r << endl;
    cout << (int)temp_cloud->points[inlierIndices.indices[size/2]].g << endl;
    cout << (int)temp_cloud->points[inlierIndices.indices[size/2]].b << endl;

    if(fabs(transformedy2- transformedy1) < 0.1 && transformedy1 < 1.3)
    {
      cout << "CUBE!" << endl;
      str.data = "found cube";
      cout << "blabla" << endl;
      if((int)temp_cloud->points[inlierIndices.indices[size/2]].g>(int)temp_cloud->points[inlierIndices.indices[size/2]].b && (int)temp_cloud->points[inlierIndices.indices[size/2]].g>(int)temp_cloud->points[inlierIndices.indices[size/2]].r)
      {
        cout << "GREEN CUBE!" << endl;
        str.data = "found green";
      }
    }
  }
}

void callback0(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  callback(cloud);
  callback2(cloud);
  std_msgs::String nstr;
  nstr.data = str.data;
  pub.publish(nstr);
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "subscribed");
  ros::NodeHandle nh("/");
  ros::Subscriber sub;
  str.data = "nothing";
  found = 0;

  sub =nh.subscribe<sensor_msgs::PointCloud2>("/camera/depth/points", 1, callback0);

  ros::init(argc, argv, "publish");
  pub = nh.advertise<std_msgs::String>("detectionresult", 1000);

  ros::Rate spin_rate(1);
  while(ros::ok())
    ros::spin();

  return 0;
}
<commit_msg>Update pointcloud_subs.cpp<commit_after>#include <ros/ros.h>
#include <iostream>
#include <sensor_msgs/PointCloud2.h>
#include <std_msgs/String.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/conversions.h>
#include <pcl_ros/transforms.h>
#include <boost/foreach.hpp>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/pcd_io.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_sphere.h>
#include <pcl/sample_consensus/sac_model_cylinder.h>
#include <pcl/segmentation/sac_segmentation.h>

using std::cout;
using std::endl;

std_msgs::String str;
ros::Publisher pub;
int found;

void callback(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  ///Detection part was inspired from here -> http://answers.ros.org/question/229784/detecting-spheres-using-ransac-in-pcl/
  pcl::PCLPointCloud2 pcl_pc2;
  pcl_conversions::toPCL(*cloud,pcl_pc2);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr temp_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
  pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);

  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  pcl::SACSegmentation<pcl::PointXYZRGB> segmentation;
  segmentation.setInputCloud(temp_cloud);
  ///Shapes that are available for RANSAC -> http://docs.pointclouds.org/1.7.0/group__sample__consensus.html
  segmentation.setModelType(pcl::SACMODEL_SPHERE);
  segmentation.setMethodType(pcl::SAC_RANSAC);
  segmentation.setDistanceThreshold(1000);
  segmentation.setOptimizeCoefficients(true);
  segmentation.setRadiusLimits(0.4, 1);
  segmentation.setMaxIterations(1000);

  pcl::PointIndices inlierIndices;
  segmentation.segment(inlierIndices, *coefficients);

  if (inlierIndices.indices.size() != 0)
  {
    ROS_INFO("RANSAC found shape with [%d] points", (int)inlierIndices.indices.size());
    cout << "SPHERE!" << endl;
    str.data = "found";
    if((int)temp_cloud->points[inlierIndices.indices[size/2]].r>(int)temp_cloud->points[inlierIndices.indices[size/2]].g && (int)temp_cloud->points[inlierIndices.indices[size/2]].r>(int)temp_cloud->points[inlierIndices.indices[size/2]].g)
    {
      cout << "RED SPHERE!" << endl;
      str.data = "found red";
      found = 1;
      }
    }

    std_msgs::String nstr;
    nstr.data = str.data;
    pub.publish(nstr);
}

void callback2(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  pcl::PCLPointCloud2 pcl_pc2;
  pcl_conversions::toPCL(*cloud,pcl_pc2);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr temp_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
  pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);

  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  pcl::SACSegmentation<pcl::PointXYZRGB> segmentation;
  segmentation.setOptimizeCoefficients(true);
  segmentation.setModelType(pcl::SACMODEL_PLANE);
  segmentation.setMethodType(pcl::SAC_RANSAC);
  segmentation.setDistanceThreshold(0.01);
  segmentation.setMaxIterations(200);
  segmentation.setInputCloud(temp_cloud);
  segmentation.setEpsAngle (0.1);

  pcl::PointIndices inlierIndices;
  segmentation.segment(inlierIndices, *coefficients);

  if (inlierIndices.indices.size() != 0)
  {
    int size = (int)inlierIndices.indices.size();
    ROS_INFO("RANSAC found shape with [%d] points", size);
    float y1 = temp_cloud->points[inlierIndices.indices[0]].y;
    float z1 = temp_cloud->points[inlierIndices.indices[0]].z;
    float y2 =temp_cloud->points[inlierIndices.indices[size/2]].y;
    float z2 =temp_cloud->points[inlierIndices.indices[size/2]].z;
    float transformedy1 = y1*cos(-1)-z1*sin(-1);
    float transformedy2 = y2*cos(-1)-z2*sin(-1);

    cout << temp_cloud->points[inlierIndices.indices[0]].x << "  " << y1 << "  " << temp_cloud->points[inlierIndices.indices[0]].z << endl;
    cout << temp_cloud->points[inlierIndices.indices[size/2]].x << "  " << y2 << "  " << temp_cloud->points[inlierIndices.indices[size/2]].z << endl;
    cout << transformedy1 << endl;
    cout << transformedy2 << endl;
    cout << (int)temp_cloud->points[inlierIndices.indices[size/2]].r << endl;
    cout << (int)temp_cloud->points[inlierIndices.indices[size/2]].g << endl;
    cout << (int)temp_cloud->points[inlierIndices.indices[size/2]].b << endl;

    if(fabs(transformedy2- transformedy1) < 0.1 && transformedy1 < 1.3)
    {
      cout << "CUBE!" << endl;
      str.data = "found cube";
      cout << "blabla" << endl;
      if((int)temp_cloud->points[inlierIndices.indices[size/2]].g>(int)temp_cloud->points[inlierIndices.indices[size/2]].b && (int)temp_cloud->points[inlierIndices.indices[size/2]].g>(int)temp_cloud->points[inlierIndices.indices[size/2]].r)
      {
        cout << "GREEN CUBE!" << endl;
        str.data = "found green";
      }
    }
  }
}

void callback0(const sensor_msgs::PointCloud2ConstPtr& cloud)
{
  callback(cloud);
  callback2(cloud);
  std_msgs::String nstr;
  nstr.data = str.data;
  pub.publish(nstr);
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "subscribed");
  ros::NodeHandle nh("/");
  ros::Subscriber sub;
  str.data = "nothing";
  found = 0;

  sub =nh.subscribe<sensor_msgs::PointCloud2>("/camera/depth/points", 1, callback0);

  ros::init(argc, argv, "publish");
  pub = nh.advertise<std_msgs::String>("detectionresult", 1000);

  ros::Rate spin_rate(1);
  while(ros::ok())
    ros::spin();

  return 0;
}
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2005-2012.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : facilities for named function parameters support
// ***************************************************************************

#ifndef BOOST_TEST_NAMED_PARAM_022505GER
#define BOOST_TEST_NAMED_PARAM_022505GER

// Boost
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>

// Boost.Test
#include <boost/test/utils/rtti.hpp>
#include <boost/test/utils/assign_op.hpp>

#include <boost/type_traits/remove_reference.hpp>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace nfp { // named function parameters

// ************************************************************************** //
// **************             forward declarations             ************** //
// ************************************************************************** //

template<typename T, typename unique_id,typename RefType>   struct named_parameter;
template<typename unique_id,bool required>                  struct keyword;

namespace nfp_detail {

template<typename NP1,typename NP2>        struct named_parameter_combine;

// ************************************************************************** //
// **************          access_to_invalid_parameter         ************** //
// ************************************************************************** //

struct access_to_invalid_parameter {};

//____________________________________________________________________________//

inline void
report_access_to_invalid_parameter()
{
    throw access_to_invalid_parameter();
}

//____________________________________________________________________________//

// ************************************************************************** //
// **************                      nil                     ************** //
// ************************************************************************** //

struct nil {
    template<typename T>
#if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC)
    operator T() const
#else
    operator T const&() const
#endif
    { report_access_to_invalid_parameter(); static T* v = 0; return *v; }

    template<typename T>
    T any_cast() const
    { report_access_to_invalid_parameter(); static typename remove_reference<T>::type* v = 0; return *v; }

    template<typename Arg1>
    nil operator()( Arg1 const& )
    { report_access_to_invalid_parameter(); return nil(); }

    template<typename Arg1,typename Arg2>
    nil operator()( Arg1 const&, Arg2 const& )
    { report_access_to_invalid_parameter(); return nil(); }

    template<typename Arg1,typename Arg2,typename Arg3>
    nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
    { report_access_to_invalid_parameter(); return nil(); }

    // Visitation support
    template<typename Visitor>
    void            apply_to( Visitor& V ) const {}

    static nil&     inst() { static nil s_inst; return s_inst; }
private:
    nil() {}
};

// ************************************************************************** //
// **************             named_parameter_base             ************** //
// ************************************************************************** //

template<typename Derived>
struct named_parameter_base {
    template<typename NP>
    named_parameter_combine<NP,Derived>
    operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************            named_parameter_combine           ************** //
// ************************************************************************** //

template<typename NP, typename Rest = nil>
struct named_parameter_combine
: Rest
, named_parameter_base<named_parameter_combine<NP,Rest> > {
    typedef typename NP::ref_type  res_type;
    typedef named_parameter_combine<NP,Rest> self_type;

    // Constructor
    named_parameter_combine( NP const& np, Rest const& r )
    : Rest( r )
    , m_param( np )
    {}

    // Access methods
    res_type    operator[]( keyword<typename NP::id,true> kw ) const    { return m_param[kw]; }
    res_type    operator[]( keyword<typename NP::id,false> kw ) const   { return m_param[kw]; }
    using       Rest::operator[];

    bool        has( keyword<typename NP::id,false> kw ) const          { return m_param.has( kw ); }
    using       Rest::has;

    void        erase( keyword<typename NP::id,false> kw ) const        { m_param.erase( kw ); }
    using       Rest::erase;

#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \
    BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0610))
    template<typename NP>
    named_parameter_combine<NP,self_type> operator,( NP const& np ) const
    { return named_parameter_combine<NP,self_type>( np, *this ); }
#else
    using       named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
#endif

    // Visitation support
    template<typename Visitor>
    void            apply_to( Visitor& V ) const
    {
        m_param.apply_to( V );

        Rest::apply_to( V );
    }
private:
    // Data members
    NP          m_param;
};

} // namespace nfp_detail

// ************************************************************************** //
// **************                named_parameter               ************** //
// ************************************************************************** //

template<typename T, typename unique_id, typename ReferenceType=T&>
struct named_parameter
: nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> >
{
    typedef nfp_detail::nil nil_t;
    typedef T               data_type;
    typedef ReferenceType   ref_type;
    typedef unique_id       id;

    // Constructor
    explicit        named_parameter( ref_type v )
    : m_value( v )
    , m_erased( false )
    {}
    named_parameter( named_parameter const& np )
    : m_value( np.m_value )
    , m_erased( np.m_erased )
    {}

    // Access methods
    ref_type        operator[]( keyword<unique_id,true> ) const     { return m_erased ? nil_t::inst().template any_cast<ref_type>() :  m_value; }
    ref_type        operator[]( keyword<unique_id,false> ) const    { return m_erased ? nil_t::inst().template any_cast<ref_type>() :  m_value; }
    template<typename UnknownId>
    nil_t           operator[]( keyword<UnknownId,false> ) const    { return nil_t::inst(); }

    bool            has( keyword<unique_id,false> ) const           { return !m_erased; }
    template<typename UnknownId>
    bool            has( keyword<UnknownId,false> ) const           { return false; }

    void            erase( keyword<unique_id,false> ) const         { m_erased = true; }
    template<typename UnknownId>
    void            erase( keyword<UnknownId,false> ) const         {}

    // Visitation support
    template<typename Visitor>
    void            apply_to( Visitor& V ) const
    {
        V.set_parameter( rtti::type_id<unique_id>(), m_value );
    }

private:
    // Data members
    ref_type        m_value;
    mutable bool    m_erased;
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************                   no_params                  ************** //
// ************************************************************************** //

namespace nfp_detail {
typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
} // namespace nfp_detail

namespace {
nfp_detail::no_params_type no_params( '\0' );
} // local namespace

//____________________________________________________________________________//

// ************************************************************************** //
// **************                    keyword                   ************** //
// ************************************************************************** //

template<typename unique_id, bool required = false>
struct keyword {
    typedef unique_id id;

    template<typename T>
    named_parameter<T const,unique_id>
    operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }

    template<typename T>
    named_parameter<T,unique_id>
    operator=( T& t ) const   { return named_parameter<T,unique_id>( t ); }

    named_parameter<char const*,unique_id,char const*>
    operator=( char const* t ) const   { return named_parameter<char const*,unique_id,char const*>( t ); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************                 typed_keyword                ************** //
// ************************************************************************** //

template<typename T, typename unique_id, bool required = false>
struct typed_keyword : keyword<unique_id,required> {
    named_parameter<T const,unique_id>
    operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }

    named_parameter<T,unique_id>
    operator=( T& t ) const             { return named_parameter<T,unique_id>( t ); }
};

//____________________________________________________________________________//

template<typename unique_id>
struct typed_keyword<bool,unique_id,false>
: keyword<unique_id,false>
, named_parameter<bool,unique_id,bool> {
    typedef unique_id id;

    typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}

    named_parameter<bool,unique_id,bool>
    operator!() const           { return named_parameter<bool,unique_id,bool>( false ); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************               optionally_assign              ************** //
// ************************************************************************** //

template<typename T>
inline void
optionally_assign( T&, nfp_detail::nil )
{
    nfp_detail::report_access_to_invalid_parameter();
}

//____________________________________________________________________________//

template<typename T, typename Source>
inline void
#if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \
    || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) )
optionally_assign( T& target, Source src )
#else
optionally_assign( T& target, Source const& src )
#endif
{
    using namespace unit_test;

    assign_op( target, src, static_cast<int>(0) );
}

//____________________________________________________________________________//

template<typename T, typename Params, typename Keyword>
inline void
optionally_assign( T& target, Params const& p, Keyword k )
{
    if( p.has(k) )
        optionally_assign( target, p[k] );
}

//____________________________________________________________________________//

// ************************************************************************** //
// **************                is_named_params               ************** //
// ************************************************************************** //

template<typename T>
struct is_named_params : public mpl::false_ {};

template<typename T, typename unique_id, typename ReferenceType>
struct is_named_params<named_parameter<T,unique_id,ReferenceType> > : public mpl::true_ {};

template<typename NP, typename Rest>
struct is_named_params<nfp_detail::named_parameter_combine<NP,Rest> > : public mpl::true_ {};

// ************************************************************************** //
// **************                  param_type                  ************** //
// ************************************************************************** //

template<typename Params,typename KeywordType,typename DefaultType=void>
struct param_type {
    typedef DefaultType type;
};

template<typename NP,typename Rest,typename Keyword,typename DefaultType>
struct param_type<nfp_detail::named_parameter_combine<NP,Rest>,Keyword,DefaultType> : param_type<Rest,Keyword,DefaultType> {
};

template<typename T, typename unique_id, typename ReferenceType,bool required,typename DefaultType>
struct param_type<named_parameter<T,unique_id,ReferenceType>,keyword<unique_id,required>,DefaultType> {
    typedef typename std::remove_cv<T>::type type;
};

template<typename T, typename unique_id, typename ReferenceType,typename Rest,bool required,typename DefaultType>
struct param_type<nfp_detail::named_parameter_combine<named_parameter<T,unique_id,ReferenceType>,Rest>,
                  keyword<unique_id,required>,
                  DefaultType> {
    typedef typename std::remove_cv<T>::type type;
};

} // namespace nfp
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_NAMED_PARAM_022505GER

<commit_msg>Fix: guard usage of c++11 <type_traits><commit_after>//  (C) Copyright Gennadiy Rozental 2005-2012.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : facilities for named function parameters support
// ***************************************************************************

#ifndef BOOST_TEST_NAMED_PARAM_022505GER
#define BOOST_TEST_NAMED_PARAM_022505GER

// Boost
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>

// Boost.Test
#include <boost/test/utils/rtti.hpp>
#include <boost/test/utils/assign_op.hpp>

#include <boost/type_traits/remove_reference.hpp>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace nfp { // named function parameters

// ************************************************************************** //
// **************             forward declarations             ************** //
// ************************************************************************** //

template<typename T, typename unique_id,typename RefType>   struct named_parameter;
template<typename unique_id,bool required>                  struct keyword;

namespace nfp_detail {

template<typename NP1,typename NP2>        struct named_parameter_combine;

// ************************************************************************** //
// **************          access_to_invalid_parameter         ************** //
// ************************************************************************** //

struct access_to_invalid_parameter {};

//____________________________________________________________________________//

inline void
report_access_to_invalid_parameter()
{
    throw access_to_invalid_parameter();
}

//____________________________________________________________________________//

// ************************************************************************** //
// **************                      nil                     ************** //
// ************************************************************************** //

struct nil {
    template<typename T>
#if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC)
    operator T() const
#else
    operator T const&() const
#endif
    { report_access_to_invalid_parameter(); static T* v = 0; return *v; }

    template<typename T>
    T any_cast() const
    { report_access_to_invalid_parameter(); static typename remove_reference<T>::type* v = 0; return *v; }

    template<typename Arg1>
    nil operator()( Arg1 const& )
    { report_access_to_invalid_parameter(); return nil(); }

    template<typename Arg1,typename Arg2>
    nil operator()( Arg1 const&, Arg2 const& )
    { report_access_to_invalid_parameter(); return nil(); }

    template<typename Arg1,typename Arg2,typename Arg3>
    nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
    { report_access_to_invalid_parameter(); return nil(); }

    // Visitation support
    template<typename Visitor>
    void            apply_to( Visitor& V ) const {}

    static nil&     inst() { static nil s_inst; return s_inst; }
private:
    nil() {}
};

// ************************************************************************** //
// **************             named_parameter_base             ************** //
// ************************************************************************** //

template<typename Derived>
struct named_parameter_base {
    template<typename NP>
    named_parameter_combine<NP,Derived>
    operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************            named_parameter_combine           ************** //
// ************************************************************************** //

template<typename NP, typename Rest = nil>
struct named_parameter_combine
: Rest
, named_parameter_base<named_parameter_combine<NP,Rest> > {
    typedef typename NP::ref_type  res_type;
    typedef named_parameter_combine<NP,Rest> self_type;

    // Constructor
    named_parameter_combine( NP const& np, Rest const& r )
    : Rest( r )
    , m_param( np )
    {}

    // Access methods
    res_type    operator[]( keyword<typename NP::id,true> kw ) const    { return m_param[kw]; }
    res_type    operator[]( keyword<typename NP::id,false> kw ) const   { return m_param[kw]; }
    using       Rest::operator[];

    bool        has( keyword<typename NP::id,false> kw ) const          { return m_param.has( kw ); }
    using       Rest::has;

    void        erase( keyword<typename NP::id,false> kw ) const        { m_param.erase( kw ); }
    using       Rest::erase;

#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \
    BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0610))
    template<typename NP>
    named_parameter_combine<NP,self_type> operator,( NP const& np ) const
    { return named_parameter_combine<NP,self_type>( np, *this ); }
#else
    using       named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
#endif

    // Visitation support
    template<typename Visitor>
    void            apply_to( Visitor& V ) const
    {
        m_param.apply_to( V );

        Rest::apply_to( V );
    }
private:
    // Data members
    NP          m_param;
};

} // namespace nfp_detail

// ************************************************************************** //
// **************                named_parameter               ************** //
// ************************************************************************** //

template<typename T, typename unique_id, typename ReferenceType=T&>
struct named_parameter
: nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> >
{
    typedef nfp_detail::nil nil_t;
    typedef T               data_type;
    typedef ReferenceType   ref_type;
    typedef unique_id       id;

    // Constructor
    explicit        named_parameter( ref_type v )
    : m_value( v )
    , m_erased( false )
    {}
    named_parameter( named_parameter const& np )
    : m_value( np.m_value )
    , m_erased( np.m_erased )
    {}

    // Access methods
    ref_type        operator[]( keyword<unique_id,true> ) const     { return m_erased ? nil_t::inst().template any_cast<ref_type>() :  m_value; }
    ref_type        operator[]( keyword<unique_id,false> ) const    { return m_erased ? nil_t::inst().template any_cast<ref_type>() :  m_value; }
    template<typename UnknownId>
    nil_t           operator[]( keyword<UnknownId,false> ) const    { return nil_t::inst(); }

    bool            has( keyword<unique_id,false> ) const           { return !m_erased; }
    template<typename UnknownId>
    bool            has( keyword<UnknownId,false> ) const           { return false; }

    void            erase( keyword<unique_id,false> ) const         { m_erased = true; }
    template<typename UnknownId>
    void            erase( keyword<UnknownId,false> ) const         {}

    // Visitation support
    template<typename Visitor>
    void            apply_to( Visitor& V ) const
    {
        V.set_parameter( rtti::type_id<unique_id>(), m_value );
    }

private:
    // Data members
    ref_type        m_value;
    mutable bool    m_erased;
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************                   no_params                  ************** //
// ************************************************************************** //

namespace nfp_detail {
typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
} // namespace nfp_detail

namespace {
nfp_detail::no_params_type no_params( '\0' );
} // local namespace

//____________________________________________________________________________//

// ************************************************************************** //
// **************                    keyword                   ************** //
// ************************************************************************** //

template<typename unique_id, bool required = false>
struct keyword {
    typedef unique_id id;

    template<typename T>
    named_parameter<T const,unique_id>
    operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }

    template<typename T>
    named_parameter<T,unique_id>
    operator=( T& t ) const   { return named_parameter<T,unique_id>( t ); }

    named_parameter<char const*,unique_id,char const*>
    operator=( char const* t ) const   { return named_parameter<char const*,unique_id,char const*>( t ); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************                 typed_keyword                ************** //
// ************************************************************************** //

template<typename T, typename unique_id, bool required = false>
struct typed_keyword : keyword<unique_id,required> {
    named_parameter<T const,unique_id>
    operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }

    named_parameter<T,unique_id>
    operator=( T& t ) const             { return named_parameter<T,unique_id>( t ); }
};

//____________________________________________________________________________//

template<typename unique_id>
struct typed_keyword<bool,unique_id,false>
: keyword<unique_id,false>
, named_parameter<bool,unique_id,bool> {
    typedef unique_id id;

    typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}

    named_parameter<bool,unique_id,bool>
    operator!() const           { return named_parameter<bool,unique_id,bool>( false ); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************               optionally_assign              ************** //
// ************************************************************************** //

template<typename T>
inline void
optionally_assign( T&, nfp_detail::nil )
{
    nfp_detail::report_access_to_invalid_parameter();
}

//____________________________________________________________________________//

template<typename T, typename Source>
inline void
#if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \
    || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) )
optionally_assign( T& target, Source src )
#else
optionally_assign( T& target, Source const& src )
#endif
{
    using namespace unit_test;

    assign_op( target, src, static_cast<int>(0) );
}

//____________________________________________________________________________//

template<typename T, typename Params, typename Keyword>
inline void
optionally_assign( T& target, Params const& p, Keyword k )
{
    if( p.has(k) )
        optionally_assign( target, p[k] );
}

//____________________________________________________________________________//

// ************************************************************************** //
// **************                is_named_params               ************** //
// ************************************************************************** //

template<typename T>
struct is_named_params : public mpl::false_ {};

template<typename T, typename unique_id, typename ReferenceType>
struct is_named_params<named_parameter<T,unique_id,ReferenceType> > : public mpl::true_ {};

template<typename NP, typename Rest>
struct is_named_params<nfp_detail::named_parameter_combine<NP,Rest> > : public mpl::true_ {};

// ************************************************************************** //
// **************                  param_type                  ************** //
// ************************************************************************** //

template<typename Params,typename KeywordType,typename DefaultType=void>
struct param_type {
    typedef DefaultType type;
};

template<typename NP,typename Rest,typename Keyword,typename DefaultType>
struct param_type<nfp_detail::named_parameter_combine<NP,Rest>,Keyword,DefaultType> : param_type<Rest,Keyword,DefaultType> {
};

#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)

template<typename T, typename unique_id, typename ReferenceType,bool required,typename DefaultType>
struct param_type<named_parameter<T,unique_id,ReferenceType>,keyword<unique_id,required>,DefaultType> {
    typedef typename std::remove_cv<T>::type type;
};

template<typename T, typename unique_id, typename ReferenceType,typename Rest,bool required,typename DefaultType>
struct param_type<nfp_detail::named_parameter_combine<named_parameter<T,unique_id,ReferenceType>,Rest>,
                  keyword<unique_id,required>,
                  DefaultType> {
    typedef typename std::remove_cv<T>::type type;
};

#endif

} // namespace nfp
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_NAMED_PARAM_022505GER

<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "print_number_process.h"

#include <vistk/pipeline_types/basic_types.h>

#include <vistk/pipeline/datum.h>
#include <vistk/pipeline/process_exception.h>

#include <boost/filesystem/path.hpp>

#include <iostream>
#include <fstream>

namespace vistk
{

class print_number_process::priv
{
  public:
    typedef uint32_t number_t;
    typedef boost::filesystem::path path_t;

    priv(path_t const& output_path);
    ~priv();

    path_t const path;

    std::ofstream fout;

    static config::key_t const config_path;
    static port_t const port_input;
};

config::key_t const print_number_process::priv::config_path = config::key_t("output");
process::port_t const print_number_process::priv::port_input = process::port_t("number");

print_number_process
::print_number_process(config_t const& config)
  : process(config)
{
  priv::path_t path = config->get_value<priv::path_t>(priv::config_path, priv::path_t());

  d = boost::shared_ptr<priv>(new priv(path));

  port_flags_t required;

  required.insert(flag_required);

  declare_input_port(priv::port_input, port_info_t(new port_info(
    basic_types::t_integer,
    required,
    port_description_t("Where numbers are read from."))));

  declare_configuration_key(priv::config_path, conf_info_t(new conf_info(
    config::value_t(),
    config::description_t("The path of the file to output to."))));
}

print_number_process
::~print_number_process()
{
}

void
print_number_process
::_init()
{
  boost::filesystem::path::string_type const path = d->path.native();

  if (path.empty())
  {
    config::value_t const value = config::value_t(path.begin(), path.end());

    throw invalid_configuration_value_exception(name(), priv::config_path, value, "The path given was empty");
  }

  d->fout.open(path.c_str());

  if (!d->fout.good())
  {
    std::string const file_path(path.begin(), path.end());

    throw invalid_configuration_exception(name(), "Failed to open the path: " + file_path);
  }
}

void
print_number_process
::_step()
{
  edge_datum_t const input_dat = grab_from_port(priv::port_input);

  switch (input_dat.get<0>()->type())
  {
    case datum::DATUM_DATA:
    {
      priv::number_t const input = input_dat.get<0>()->get_datum<priv::number_t>();

      d->fout << input << std::endl;
      break;
    }
    case datum::DATUM_EMPTY:
      break;
    case datum::DATUM_COMPLETE:
      mark_as_complete();
      break;
    case datum::DATUM_ERROR:
      break;
    case datum::DATUM_INVALID:
    default:
      break;
  }

  process::_step();
}

print_number_process::priv
::priv(path_t const& output_path)
  : path(output_path)
{
}

print_number_process::priv
::~priv()
{
}

}
<commit_msg>Add const correctness<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "print_number_process.h"

#include <vistk/pipeline_types/basic_types.h>

#include <vistk/pipeline/datum.h>
#include <vistk/pipeline/process_exception.h>

#include <boost/filesystem/path.hpp>

#include <iostream>
#include <fstream>

namespace vistk
{

class print_number_process::priv
{
  public:
    typedef uint32_t number_t;
    typedef boost::filesystem::path path_t;

    priv(path_t const& output_path);
    ~priv();

    path_t const path;

    std::ofstream fout;

    static config::key_t const config_path;
    static port_t const port_input;
};

config::key_t const print_number_process::priv::config_path = config::key_t("output");
process::port_t const print_number_process::priv::port_input = process::port_t("number");

print_number_process
::print_number_process(config_t const& config)
  : process(config)
{
  priv::path_t const path = config->get_value<priv::path_t>(priv::config_path, priv::path_t());

  d = boost::shared_ptr<priv>(new priv(path));

  port_flags_t required;

  required.insert(flag_required);

  declare_input_port(priv::port_input, port_info_t(new port_info(
    basic_types::t_integer,
    required,
    port_description_t("Where numbers are read from."))));

  declare_configuration_key(priv::config_path, conf_info_t(new conf_info(
    config::value_t(),
    config::description_t("The path of the file to output to."))));
}

print_number_process
::~print_number_process()
{
}

void
print_number_process
::_init()
{
  boost::filesystem::path::string_type const path = d->path.native();

  if (path.empty())
  {
    config::value_t const value = config::value_t(path.begin(), path.end());

    throw invalid_configuration_value_exception(name(), priv::config_path, value, "The path given was empty");
  }

  d->fout.open(path.c_str());

  if (!d->fout.good())
  {
    std::string const file_path(path.begin(), path.end());

    throw invalid_configuration_exception(name(), "Failed to open the path: " + file_path);
  }
}

void
print_number_process
::_step()
{
  edge_datum_t const input_dat = grab_from_port(priv::port_input);

  switch (input_dat.get<0>()->type())
  {
    case datum::DATUM_DATA:
    {
      priv::number_t const input = input_dat.get<0>()->get_datum<priv::number_t>();

      d->fout << input << std::endl;
      break;
    }
    case datum::DATUM_EMPTY:
      break;
    case datum::DATUM_COMPLETE:
      mark_as_complete();
      break;
    case datum::DATUM_ERROR:
      break;
    case datum::DATUM_INVALID:
    default:
      break;
  }

  process::_step();
}

print_number_process::priv
::priv(path_t const& output_path)
  : path(output_path)
{
}

print_number_process::priv
::~priv()
{
}

}
<|endoftext|>