奥比中光深度摄像头实现follow

奥比中光深度相机(一):环境配置 深度相机可以获取RGB-D数据,不仅可以提取目标的可将光图像,同时还能获得目标距离相机的深度信息。深度相机在测距、三维重建、动物体尺体况分析等多个方面具有广泛的应用潜力。目前,市面上的深度相机包含多个品牌,包括Kinect系列、Intel RealSense系列以及奥比中光系列等,由于奥比中光相机开源了基于python的控制代码,大多深度学习的项目又都是基于python编写的,所以我们选择了奥比中光深度相机Gemini 2L型号。 阅读详情

Github地址:https://github.com/robotBing/skeleton_follow

演示视频地址:http://blog.jiutucao.com:9000/upload/2018/07/skeleton_follow.mp4

  奥比中光摄像头是有ros驱动的,最开始的点云颜色跟随就是直接调用奥比提供的astra_launch包,但是骨骼跟随自己需要做的工作就多得多了。不得不说过程很艰难,使用一门不是最擅长的语言,没有ide,只能用记事本进行代码编写,调试全靠打印信息。时间又紧,只能做出来一个半成品。

  下面说一下开发时的心路历程,先到astra的官网上下载奥比中光的sdk,这个sdk是可以进行骨骼识别的,但是和ros无关,我要做的就是根据提供demo代码,筛选出我需要的数据,对数据进行处理,映射成为ros需要的速度数据,最后将速度数据发布到cmd_vel话题上。最烦的就是没有ide,调用哪个方法要一点一点的试,全靠手打。

  Sdk提供的骨骼识别有19个关节信息,核心程序的思路就是提取身体最中心的关节坐标,映射为速度信息,提取手臂各个关节的坐标,对人的动作进行判断,让机器人在等待15s,开始跟随,停止跟随几个状态转换。程序有两个可以完善的地方1.程序没有使用多线程,等待15s过程中,整个线程停止,导致整个程序停止.2.动作的判断不够全面,受环境干扰太大。两个问题都是致命的,但是修改起来很简单,我就不做改进了,希望学弟们能把程序完善。

sdk下载地址:https://orbbec3d.com/develop

sdk中的demo编译需要sfml支持,下载sfml:

sudo apt-get install libsfml-dev

 

sfml官网教程地址:https://www.sfml-dev.org/tutorials/2.0/start-linux.php

下载sdk后编译例子步骤:

  1. 进入SDK下的samples目录下,新建一个build目录,在终端中进入到build目录下。

cd SDK路径/samples/

mkdir build

cd build

 

  1. 用cmake编译并转到bin目录下,运行测试程序。

cmake ..

make

编译后的可执行文件在build目录下的bin目录里

  下面是核心代码:

#include <SFML/Graphics.hpp>

#include <astra/astra.hpp>

#include <iostream>

#include <cstring>

#include "ros/ros.h"

#include "std_msgs/String.h"

#include <geometry_msgs/Twist.h>

#include <string>

#include <ctime>

#include <sstream>

class sfLine : public sf::Drawable

{

public:

    sfLine(const sf::Vector2f& point1, const sf::Vector2f& point2, sf::Color color, float thickness)

        : color_(color)

    {

        const sf::Vector2f direction = point2 - point1;

        const sf::Vector2f unitDirection = direction / std::sqrt(direction.x*direction.x + direction.y*direction.y);

        const sf::Vector2f normal(-unitDirection.y, unitDirection.x);

        const sf::Vector2f offset = (thickness / 2.f) * normal;

        vertices_[0].position = point1 + offset;

        vertices_[1].position = point2 + offset;

        vertices_[2].position = point2 - offset;

        vertices_[3].position = point1 - offset;

 

        for (int i = 0; i<4; ++i)

            vertices_[i].color = color;

    }

 

    void draw(sf::RenderTarget &target, sf::RenderStates states) const

    {

        target.draw(vertices_, 4, sf::Quads, states);

    }

private:

    sf::Vertex vertices_[4];

    sf::Color color_;

};

class BodyVisualizer : public astra::FrameListener

{

public:

      float line = 0;

      float angle = 0;

      ros::Publisher pub;

      ros::Publisher pubVoice;

      astra::Vector3f shoulderSpinePosition;

      astra::Vector3f leftHandPosition;

      astra::Vector3f rightHandPosition;

      int state = 0 ;

      int timeState = 1;

      virtual void onInit()

      {

      ros::NodeHandle n ;

      pub = n.advertise<geometry_msgs::Twist>("cmd_vel",1);

      pubVoice = n.advertise<std_msgs::String>("speak_string",1);

      }

    static sf::Color get_body_color(std::uint8_t bodyId)

    {

        if (bodyId == 0)

        {

            return sf::Color(0x00, 0x00, 0x00, 0x00);

        }

        // Case 0 below could mean bodyId == 25 or

        // above due to the "% 24".

        switch (bodyId % 24) {

        case 0:

            return sf::Color(0x00, 0x88, 0x00, 0xFF);

        case 1:

            return sf::Color(0x00, 0x00, 0xFF, 0xFF);

        case 2:

            return sf::Color(0x88, 0x00, 0x00, 0xFF);

        case 3:

            return sf::Color(0x00, 0xFF, 0x00, 0xFF);

        case 4:

            return sf::Color(0x00, 0x00, 0x88, 0xFF);

        case 5:

            return sf::Color(0xFF, 0x00, 0x00, 0xFF);

 

        case 6:

            return sf::Color(0xFF, 0x88, 0x00, 0xFF);

        case 7:

            return sf::Color(0xFF, 0x00, 0xFF, 0xFF);

        case 8:

            return sf::Color(0x88, 0x00, 0xFF, 0xFF);

        case 9:

            return sf::Color(0x00, 0xFF, 0xFF, 0xFF);

        case 10:

            return sf::Color(0x00, 0xFF, 0x88, 0xFF);

        case 11:

            return sf::Color(0xFF, 0xFF, 0x00, 0xFF);

 

        case 12:

            return sf::Color(0x00, 0x88, 0x88, 0xFF);

        case 13:

            return sf::Color(0x00, 0x88, 0xFF, 0xFF);

        case 14:

            return sf::Color(0x88, 0x88, 0x00, 0xFF);

        case 15:

            return sf::Color(0x88, 0xFF, 0x00, 0xFF);

        case 16:

            return sf::Color(0x88, 0x00, 0x88, 0xFF);

        case 17:

            return sf::Color(0xFF, 0x00, 0x88, 0xFF);

 

        case 18:

            return sf::Color(0xFF, 0x88, 0x88, 0xFF);

        case 19:

            return sf::Color(0xFF, 0x88, 0xFF, 0xFF);

        case 20:

            return sf::Color(0x88, 0x88, 0xFF, 0xFF);

        case 21:

            return sf::Color(0x88, 0xFF, 0xFF, 0xFF);

        case 22:

            return sf::Color(0x88, 0xFF, 0x88, 0xFF);

        case 23:

            return sf::Color(0xFF, 0xFF, 0x88, 0xFF);

        default:

            return sf::Color(0xAA, 0xAA, 0xAA, 0xFF);

        }

    }

    void init_depth_texture(int width, int height)

    {

        if (displayBuffer_ == nullptr || width != depthWidth_ || height != depthHeight_)

        {

            depthWidth_ = width;

            depthHeight_ = height;

            int byteLength = depthWidth_ * depthHeight_ * 4;

            displayBuffer_ = BufferPtr(new uint8_t[byteLength]);

            std::memset(displayBuffer_.get(), 0, byteLength);

            texture_.create(depthWidth_, depthHeight_);

            sprite_.setTexture(texture_, true);

            sprite_.setPosition(0, 0);

        }

    }

    void init_overlay_texture(int width, int height)

    {

        if (overlayBuffer_ == nullptr || width != overlayWidth_ || height != overlayHeight_)

        {

            overlayWidth_ = width;

            overlayHeight_ = height;

            int byteLength = overlayWidth_ * overlayHeight_ * 4;

            overlayBuffer_ = BufferPtr(new uint8_t[byteLength]);

            std::fill(&overlayBuffer_[0], &overlayBuffer_[0] + byteLength, 0);

            overlayTexture_.create(overlayWidth_, overlayHeight_);

            overlaySprite_.setTexture(overlayTexture_, true);

            overlaySprite_.setPosition(0, 0);

        }

    }

    void check_fps()

    {

        double fpsFactor = 0.02;

        std::clock_t newTimepoint= std::clock();

        long double frameDuration = (newTimepoint - lastTimepoint_) / static_cast<long double>(CLOCKS_PER_SEC);

        frameDuration_ = frameDuration * fpsFactor + frameDuration_ * (1 - fpsFactor);

        lastTimepoint_ = newTimepoint;

        double fps = 1.0 / frameDuration_;

 

       // printf("FPS: %3.1f (%3.4Lf ms)\n", fps, frameDuration_ * 1000);

    }

    void processDepth(astra::Frame& frame)

    {

        const astra::DepthFrame depthFrame = frame.get<astra::DepthFrame>();

        if (!depthFrame.is_valid()) { return; }

        int width = depthFrame.width();

        int height = depthFrame.height();

        init_depth_texture(width, height);

        const int16_t* depthPtr = depthFrame.data();

        for(int y = 0; y < height; y++)

        {

            for(int x = 0; x < width; x++)

            {

                int index = (x + y * width);

                int index4 = index * 4;

                int16_t depth = depthPtr[index];

                uint8_t value = depth % 255;

                displayBuffer_[index4] = value;

                displayBuffer_[index4 + 1] = value;

                displayBuffer_[index4 + 2] = value;

                displayBuffer_[index4 + 3] = 255;

            }

        }

        texture_.update(displayBuffer_.get());

    }

    void processBodies(astra::Frame& frame)

    {

        astra::BodyFrame bodyFrame = frame.get<astra::BodyFrame>();

        jointPositions_.clear();

        circles_.clear();

        circleShadows_.clear();

        boneLines_.clear();

        boneShadows_.clear();

        if (!bodyFrame.is_valid() || bodyFrame.info().width() == 0 || bodyFrame.info().height() == 0)

        {

            clear_overlay();

            return;

        }

        const float jointScale = bodyFrame.info().width() / 120.f;

       const auto& bodies = bodyFrame.bodies();

        for (auto& body : bodies)

        {

             //   bodyFrame.frame_index(), body.id(), unsigned(body.hand_poses().left_hand()));

            for(auto& joint : body.joints())

            {

                 onInit();

 

                 astra::JointType jointType = joint.type();

 

                 if(jointType == astra::JointType::ShoulderSpine)

                 {

                     shoulderSpinePosition = joint.world_position();

                    

 

                 }

                 if(jointType == astra::JointType::LeftHand)

                 {

                     leftHandPosition = joint.world_position();

                    

                 }

                 if(jointType == astra::JointType::RightHand)

                 {

                     rightHandPosition = joint.world_position();

                 }

                

                  //set state

                 if(leftHandPosition.y - shoulderSpinePosition.y > 300)

                  {

                     timeState++;

                     std_msgs::String msg;

 

                     std::string ss;

                     ss = "状态变为一,开始跟随" ;

                     msg.data = ss;                                 

                            pubVoice.publish(msg);

                     

                       state = 1 ;

                  }

                 if(rightHandPosition.y - shoulderSpinePosition.y > 300)

                  {

                     timeState++ ;

                     std_msgs::String msg;

 

                     std::string ss;

                     ss = "状态变为二,等待十五秒" ;

                     msg.data = ss;

                     pubVoice.publish(msg);               

                     state = 2 ;

                  }

                 if(leftHandPosition.y>-100 && leftHandPosition.y<100 && rightHandPosition.y<100 && rightHandPosition.y>-100)

                  {

                     timeState++ ;

                     std_msgs::String msg;

 

                     std::string ss;

                     ss = "状态变为零,停止跟随" ;

                     msg.data = ss;

                    

                    if(timeState % 100 == 0)

                       {

                            pubVoice.publish(msg);

                            state = 0 ;

                       }  

                  }

 

                 if(jointType == astra::JointType::MidSpine)

                 {

                    auto worldPosition = joint.world_position();

                    if(worldPosition.x / 500.f>0.2 || worldPosition.x / 500.f<-0.2)

                   {

                      if(worldPosition.x / 500.f>0.3)

                          {

                            angle = 0.3;

                          }else if(worldPosition.x / 500.f<-0.3)

                          {

                            angle = -0.3;

                          }else

                          {

                            angle = worldPosition.x / 500.f ;

                          }

                     

                   } else

                   {

                       if(worldPosition.x / 1000.f>0.3)

                          {

                            angle = 0.3;

                          }else if(worldPosition.x / 1000.f<-0.3)

                          {

                            angle = -0.3;

                          }else

                          {

                            angle = worldPosition.x / 1000.f ;

                          }

                   }

                  if((worldPosition.z - 1500.f) / 500.f > 0.2 ||  (worldPosition.z - 1500.f) / 500.f<-0.2)

                   {

                       if((worldPosition.z -1500.f) / 500.f>0.3)

                          {

                            line = 0.3;

                          }else if((worldPosition.z -1500.f) / 500.f<-0.3)

                          {

                            line = -0.3;

                          }else

                          {

                            line = (worldPosition.z -1500.f) / 500.f ;

                          }

                   }else

                   {

                       if((worldPosition.z -1500.f) / 1000.f>0.3)

                          {

                            line = 0.3;

                          }else if((worldPosition.z -1500.f) / 1000.f<-0.3)

                          {

                            line = -0.3;

                          }else

                          {

                            line = (worldPosition.z -1500.f) / 1000.f ;

                          }

                   }

 

                    publishCmdVel();

                    printf("z:%d\n",state);

                 }

                jointPositions_.push_back(joint.depth_position());

            }

 

            update_body(body, jointScale);

        }

 

        const auto& floor = bodyFrame.floor_info(); //floor

        if (floor.floor_detected())

        {

            const auto& p = floor.floor_plane();

            std::cout << "Floor plane: ["

                << p.a() << ", " << p.b() << ", " << p.c() << ", " << p.d()

                << "]" << std::endl;

 

        }

 

        const auto& bodyMask = bodyFrame.body_mask();

        const auto& floorMask = floor.floor_mask();

 

        update_overlay(bodyMask, floorMask);

    }

 

    void update_body(astra::Body body,

                     const float jointScale)

    {

        const auto& joints = body.joints();

 

        if (joints.empty())

        {

            return;

        }

 

        for (const auto& joint : joints)

        {

            astra::JointType type = joint.type();

            const auto& pos = joint.depth_position();

 

            if (joint.status() == astra::JointStatus::NotTracked)

            {

                continue;

            }

 

            auto radius = jointRadius_ * jointScale; // pixels

            sf::Color circleShadowColor(0, 0, 0, 255);

 

             auto color = sf::Color(0x00, 0xFF, 0x00, 0xFF);

 

            if ((type == astra::JointType::LeftHand && astra::HandPose::Grip==body.hand_poses().left_hand()) ||

                (type == astra::JointType::RightHand &&  astra::HandPose::Grip==body.hand_poses().right_hand()))

            {

                radius *= 1.5f;

                circleShadowColor = sf::Color(255, 255, 255, 255);

                color = sf::Color(0x00, 0xAA, 0xFF, 0xFF);

            }

 

            const auto shadowRadius = radius + shadowRadius_ * jointScale;

            const auto radiusDelta = shadowRadius - radius;

 

            sf::CircleShape circle(radius);

 

            circle.setFillColor(sf::Color(color.r, color.g, color.b, 255));

            circle.setPosition(pos.x - radius, pos.y - radius);

            circles_.push_back(circle);

 

            sf::CircleShape shadow(shadowRadius);

            shadow.setFillColor(circleShadowColor);

            shadow.setPosition(circle.getPosition() - sf::Vector2f(radiusDelta, radiusDelta));

            circleShadows_.push_back(shadow);

        }

 

        update_bone(joints, jointScale, astra::JointType::Head, astra::JointType::ShoulderSpine);

 

        update_bone(joints, jointScale, astra::JointType::ShoulderSpine, astra::JointType::LeftShoulder);

        update_bone(joints, jointScale, astra::JointType::LeftShoulder, astra::JointType::LeftElbow);

        update_bone(joints, jointScale, astra::JointType::LeftElbow, astra::JointType::LeftHand);

 

        update_bone(joints, jointScale, astra::JointType::ShoulderSpine, astra::JointType::RightShoulder);

        update_bone(joints, jointScale, astra::JointType::RightShoulder, astra::JointType::RightElbow);

        update_bone(joints, jointScale, astra::JointType::RightElbow, astra::JointType::RightHand);

 

        update_bone(joints, jointScale, astra::JointType::ShoulderSpine, astra::JointType::MidSpine);

        update_bone(joints, jointScale, astra::JointType::MidSpine, astra::JointType::BaseSpine);

 

        update_bone(joints, jointScale, astra::JointType::BaseSpine, astra::JointType::LeftHip);

        update_bone(joints, jointScale, astra::JointType::LeftHip, astra::JointType::LeftKnee);

        update_bone(joints, jointScale, astra::JointType::LeftKnee, astra::JointType::LeftFoot);

 

        update_bone(joints, jointScale, astra::JointType::BaseSpine, astra::JointType::RightHip);

        update_bone(joints, jointScale, astra::JointType::RightHip, astra::JointType::RightKnee);

        update_bone(joints, jointScale, astra::JointType::RightKnee, astra::JointType::RightFoot);

    }

 

    void update_bone(const astra::JointList& joints,

                     const float jointScale,astra::JointType j1,

                     astra::JointType j2)

    {

        const auto& joint1 = joints[int(j1)];

        const auto& joint2 = joints[int(j2)];

 

        if (joint1.status() == astra::JointStatus::NotTracked ||

            joint2.status() == astra::JointStatus::NotTracked)

        {

            return;

        }

        const auto& jp1 = joint1.depth_position();

        const auto& jp2 = joint2.depth_position();

 

        auto p1 = sf::Vector2f(jp1.x, jp1.y);

        auto p2 = sf::Vector2f(jp2.x, jp2.y);

 

        sf::Color color(255, 255, 255, 255);

        float thickness = lineThickness_ * jointScale;

        if (joint1.status() == astra::JointStatus::LowConfidence ||

            joint2.status() == astra::JointStatus::LowConfidence)

        {

            color = sf::Color(128, 128, 128, 255);

            thickness *= 0.5f;

        }

 

        boneLines_.push_back(sfLine(p1,

            p2,

            color,

            thickness));

        const float shadowLineThickness = thickness + shadowRadius_ * jointScale * 2.f;

        boneShadows_.push_back(sfLine(p1,

            p2,

            sf::Color(0, 0, 0, 255),

            shadowLineThickness));

    }

 

    void update_overlay(const astra::BodyMask& bodyMask,

                        const astra::FloorMask& floorMask)

    {

        const auto* bodyData = bodyMask.data();

        const auto* floorData = floorMask.data();

        const int width = bodyMask.width();

        const int height = bodyMask.height();

 

        init_overlay_texture(width, height);

 

        const int length = width * height;

 

        for (int i = 0; i < length; i++)

        {

            const auto bodyId = bodyData[i];

            const auto isFloor = floorData[i];

 

            sf::Color color(0x0, 0x0, 0x0, 0x0);

 

            if (bodyId != 0)

            {

                color = get_body_color(bodyId);

            }

            else if (isFloor != 0)

            {

                color = sf::Color(0x0, 0x0, 0xFF, 0x88);

            }

 

            const int rgbaOffset = i * 4;

            overlayBuffer_[rgbaOffset] = color.r;

            overlayBuffer_[rgbaOffset + 1] = color.g;

            overlayBuffer_[rgbaOffset + 2] = color.b;

            overlayBuffer_[rgbaOffset + 3] = color.a;

        }

 

        overlayTexture_.update(overlayBuffer_.get());

    }

 

    void clear_overlay()

    {

        int byteLength = overlayWidth_ * overlayHeight_ * 4;

        std::fill(&overlayBuffer_[0], &overlayBuffer_[0] + byteLength, 0);

 

        overlayTexture_.update(overlayBuffer_.get());

    }

 

    virtual void on_frame_ready(astra::StreamReader& reader,

                                astra::Frame& frame) override

    {

        processDepth(frame);

        processBodies(frame);

 

        check_fps();

    }

 

    void draw_bodies(sf::RenderWindow& window)

    {

        const float scaleX = window.getView().getSize().x / overlayWidth_;

        const float scaleY = window.getView().getSize().y / overlayHeight_;

 

        sf::RenderStates states;

        sf::Transform transform;

        transform.scale(scaleX, scaleY);

        states.transform *= transform;

 

        for (const auto& bone : boneShadows_)

            window.draw(bone, states);

 

        for (const auto& c : circleShadows_)

            window.draw(c, states);

 

        for (const auto& bone : boneLines_)

            window.draw(bone, states);

 

        for (auto& c : circles_)

            window.draw(c, states);

 

    }

 

    void draw_to(sf::RenderWindow& window)

    {

        if (displayBuffer_ != nullptr)

        {

            const float scaleX = window.getView().getSize().x / depthWidth_;

            const float scaleY = window.getView().getSize().y / depthHeight_;

            sprite_.setScale(scaleX, scaleY);

 

            window.draw(sprite_); // depth

        }

 

        if (overlayBuffer_ != nullptr)

        {

            const float scaleX = window.getView().getSize().x / overlayWidth_;

            const float scaleY = window.getView().getSize().y / overlayHeight_;

            overlaySprite_.setScale(scaleX, scaleY);

            window.draw(overlaySprite_); //bodymask and floormask

        }

 

        draw_bodies(window);

    }

    void publishCmdVel()

   {

     geometry_msgs::Twist twist;

     if(state == 1)

     {

     twist.linear.x = line;

 

     twist.angular.z = angle;

     pub.publish(twist);

     } else if(state == 2)

     {

        twist.linear.x = 0;

        twist.angular.z = 0;

        pub.publish(twist);

       clock_t delay;

       delay = 90 * 100000 ;

       clock_t start = clock();

       while(clock()-start < delay){

                state = 1;

              }

                    std_msgs::String msg;

 

                     std::string ss;

                     ss = "状态变为一,开始跟随" ;

                     msg.data = ss;

                   

                     pubVoice.publish(msg);

                   

      

     }else

     {

      twist.linear.x = 0;

     twist.angular.z = 0;

     pub.publish(twist);

     }

 

 

    

   }

 

private:

    long double frameDuration_{ 0 };

    std::clock_t lastTimepoint_ { 0 };

    sf::Texture texture_;

    sf::Sprite sprite_;

    using BufferPtr = std::unique_ptr < uint8_t[] >;

    BufferPtr displayBuffer_{ nullptr };

    std::vector<astra::Vector2f> jointPositions_;

    int depthWidth_{0};

    int depthHeight_{0};

    int overlayWidth_{0};

    int overlayHeight_{0};

    std::vector<sfLine> boneLines_;

    std::vector<sfLine> boneShadows_;

    std::vector<sf::CircleShape> circles_;

    std::vector<sf::CircleShape> circleShadows_;

    float lineThickness_{ 0.5f }; // pixels

    float jointRadius_{ 1.0f };   // pixels

    float shadowRadius_{ 0.5f };  // pixels

    BufferPtr overlayBuffer_{ nullptr };

    sf::Texture overlayTexture_;

    sf::Sprite overlaySprite_;

 

};

 

astra::DepthStream configure_depth(astra::StreamReader& reader)

{

    auto depthStream = reader.stream<astra::DepthStream>();

    astra::ImageStreamMode depthMode;

    depthMode.set_width(640);

    depthMode.set_height(480);

    depthMode.set_pixel_format(astra_pixel_formats::ASTRA_PIXEL_FORMAT_DEPTH_MM);

    depthMode.set_fps(30);

    depthStream.set_mode(depthMode);

    return depthStream;

}

 

int main(int argc, char** argv)

{

     ros::init(argc , argv ,"skeleton_follow");

    astra::initialize();

    const char* licenseString = "<INSERT LICENSE KEY HERE>";

    orbbec_body_tracking_set_license(licenseString);

    sf::RenderWindow window(sf::VideoMode(1280, 960), "Simple Body Viewer");

#ifdef _WIN32

    auto fullscreenStyle = sf::Style::None;

#else

    auto fullscreenStyle = sf::Style::Fullscreen;

#endif

 

    const sf::VideoMode fullScreenMode = sf::VideoMode::getFullscreenModes()[0];

    const sf::VideoMode windowedMode(1280, 960);

    bool isFullScreen = false;

 

    astra::StreamSet sensor;

    astra::StreamReader reader = sensor.create_reader();

    BodyVisualizer listener;

    auto depthStream = configure_depth(reader);

    depthStream.start();

    reader.stream<astra::BodyStream>().start();

    reader.add_listener(listener);

    BodyVisualizer bv ;

 

    while (window.isOpen())

    {

        astra_update();

 

        sf::Event event;

 

        while (window.pollEvent(event))

        {

            switch (event.type)

            {

            case sf::Event::Closed:

                window.close();

                break;

            case sf::Event::KeyPressed:

            {

                if (event.key.code == sf::Keyboard::C && event.key.control)

                {

                    window.close();

                }

                switch (event.key.code)

                {

                case sf::Keyboard::Escape:

                    window.close();

                    break;

                case sf::Keyboard::F:

                    if (isFullScreen)

                    {

                        window.create(windowedMode, "Simple Body Viewer", sf::Style::Default);

                    }

                    else

                    {

                        window.create(fullScreenMode, "Simple Body Viewer", fullscreenStyle);

                    }

                    isFullScreen = !isFullScreen;

                    break;

                case sf::Keyboard::R:

                    depthStream.enable_registration(!depthStream.registration_enabled());

                    break;

                case sf::Keyboard::M:

                    depthStream.enable_mirroring(!depthStream.mirroring_enabled());

                    break;

                default:

                    break;

                }

                break;

            }

            default:

                break;

            }

        }

        // clear the window with black color

        window.clear(sf::Color::Black);

        listener.draw_to(window);

        window.display();

    }

    astra::terminate();

    return 0;

}

OpenNI2 SDK for ROS2奥比中光深度摄像头驱动安装配置 进入到下载好的SDK for ROS2 SDK目录中(需要根据自己情况修改,我的路径是:~/Downloads/OpenNI_SDK_ROS2_v1.0.2_linux)。以下主要针对Astra S系列的驱动安装,用于使用ROS2的开发,供大家参考,提供了驱动的下载地址。sudo ldconfig # 刷新链接库。sudo ldconfig # 刷新链接库。sudo ldconfig # 刷新链接库。之后输入 以下指令即可测试摄像头了。安装libusb rules。安装magic_enum。 阅读详情

相关推荐

奥比中光Orbbec Astra-Mini RGB-D 3D体感摄像头在ROS(indigo)中的深度图像处理与彩色数据融合实践

本文详细介绍了奥比中光Orbbec Astra-Mini RGB-D 3D体感摄像头在ROS(indigo)环境中的深度图像处理与彩色数据融合实践。通过驱动适配、数据同步配置、性能优化和典型应用场景实现,帮助开发者高效利用这款国产3D视觉传感器,提升在机器人视觉、手势识别等领域的应用效果。

weixin_26846533的博客 239

在Ubuntu 中 编译Orbbec Astra(奥比中光)RGBD sdk中samples的采坑手记

最近入手了一个乐视三合体体感摄像头,内核是Orbbec Astra,用来玩玩SLAM。 到货了以后,马上就到Orbbec官网找SDK,上面有各个平台的SDK。 win64下的安装很容易,Samples中有自带的二进制文件,自己使用cmake编译起来也很容易,可能是因为win64的驱动比较全。 Ubuntu下的Samples编译就提示需要SFML库,百度了一下SFML,也没有现成的,需要自己编译。按...

yzlh2009的博客 3594

奥比中光深度相机(二):PyQt5实现打开深度摄像头功能

深度相机的打开方法和可见光相机的打开方法略有不同,可见光相机可以利用OpenCV来直接调用,奥比中光深度相机主要是利用官方给出的SDK源码来调用。本文中,我们借鉴官方源码,将调用深度相机的主要代码提取出来,并和我们自己写的代码结合,实现在PyQt5界面中通过点击按钮打开深度相机。注意我们调用了ui界面设计生成的.py文件,命名为depth_camera.py,并放置到ui_code文件夹中,所以我们这里的调用代码为。我们主要是想将调用奥比中光深度相机的关键部分提取出来,并应用在我们自己的代码中。

WYKB_Mr_Q的博客 4101

Windows11下奥比中光Python版本的SDK的安装和使用

奥比中光的PythonSDK,为什么要建两次PyCharm工程,因为第一次建的时候,不知道哪个版本Python是最适合的。第一次新建PyCharm工程的时候,主要的用途就是下载安装了pybind11,这样后续才能进行pyobbecsdk的编译生成pyd,生成了pyd后发现必须使用Python3.12才行。考虑到生成的这个文件采用了python3.12版本,那么我们对应建立的PyCharm工程,也必须是Python3.12的。

8760

Ubuntu18.04+奥比中光摄像头+ORB_SLAM2配置过程记录

前言:ORB_SLAM2+深度相机实现室内稠密点云建图是我的毕业设计,这篇文章主要是记录自己环境的配置过程,相关文章在csdn上也是很多的,这里只是做了一些汇总和过程的总结,假如你遇到我没有碰到的问题,不要着急先在网上搜搜有没有相关的,比如ros wiki上和github上有没有相关issue,还有csdn。二、第二步:修驱动自带的bug不显示rgb图像。三、获取orb_slam2的源码并编译。一、第一步:奥比中光深度相机驱动安装。建入到ORB_SLAM2的目录下执行。1.下载pangolin0.5。

weixin_53206200的博客 1515

ROS下调用奥比中光dabai相机

其实这篇教程本可以不写的,但是介于手上这台相机的特殊性,还是写一下。教程本身就是官方git说明的前一部分,几乎没什么改动,安装起来比realsense还方便些。这款相机是从松灵limo上拆下来的,但是在松灵的宣传册中只看到了d435,很显然这个不是rs中的任何一款。机身本体没有任何文字表明这个是什么相机,在ubuntu中调用lsusb才知道是奥比中光。但是翻遍奥比中光官网的产品列表没有发现这款,购物软件识图也没用,全网都没有外形是梯形的深度相机。

weixin_45702459的博客 1924

奥比中光SDK

2.Python版本Wrapper。1.C++/库版 SDK。

weixin_43580131的博客 140

ubutun20.04安装奥比中光Astra过程中遇到的问题及解决方案。以及安装步骤

ROS\UBUTUN\奥比中光astra 相机驱动安装详细步骤

2301_80467135的博客 4138

在ROS2中使用奥比中光(ORBBEC)的AstraPro深度相机

拷贝到你的ubuntu的一个文件夹中,并解压得到 ros2_astra_camera 文件夹然后新建一个ros2_ws文件夹,再在ros2_ws文件夹中新建src文件夹,然后复制 ros2_astra_camera文件夹里面的astra_camera、astra_camera_msg两个文件夹到src里面。

joyopirate的博客 1万+

CREO5.0二次开发+VS2019配置详解

CREO5.0+VS2019配置更新 一、CREO5.0 配置 二、Visual Studio 2019配置 新建MFC DLL项目 文件>新建>项目,选择MFC DLL,如下图所示 项目名称CREO1 2、配置设置 打开项目属性: 配置资源管理器设置: 设置包含目录、库目录(根据自己CREO的安装位置来设置): 包含目录: 库目录: 预处理器设置: 把下面文字复...

liuyi2517的博客 1万+

避坑指南:用逐飞开源库驱动MT9V03X摄像头时容易忽略的3个细节(附TFT显示优化技巧)

本文详细解析了在智能汽车竞赛中使用MT9V03X摄像头(总钻风)时常见的硬件连接、图像采集和TFT显示优化问题。重点介绍了逐飞开源库中容易被忽略的三个关键细节,包括电源管理、看门狗设置和中断优先级配置,并提供了针对IPS200和TFT180显示屏的优化技巧,帮助参赛队伍提升图像处理效率和显示质量。

study的专栏 744

奥比中光深度摄像头实现骨架识别 并进行ros follow

项目地址:https://github.com/robotBing/skeleton_follow

RobotBing的博客 5217

Bentley ORD(openroads designer) 二次开发(BIM)第七节 在ORD SDK中调用MicroStation SDK

从课程刚开始的时候我们就通过学习,了解了ORD的开发是基于MicroStation的,ORD SDK的接口发布的时候也对MicroStation SDK也做了一次发布。这一章将以我们对ORD SDK知识的了解为基础,使用ORD SDK的接口读取道路几何信息、计算桩号,然后再使用MicroStation SDK 读取地形数据和计算投影点的位置,并创建一组方柱形状的Soild。计算方柱底部坐标要经过两大步骤,通过路线的桩号及偏移距离去定位方柱的平面位置,通过方柱的平面位置计算数字地面模型上的投影点的坐标。

chen286990651的博客 880

中国厂商主导人形机器人市场的技术逻辑与开源实践

机器人操作系统(ROS)作为机器人开发的核心软件框架,通过提供节点通信、硬件抽象和丰富的工具包,构建了机器人感知、决策与控制的基础。其模块化设计原理使得开发者能够高效集成传感器、执行器和算法,极大地加速了机器人原型的开发与迭代。这一技术价值在于降低了机器人研发的门槛,促进了全球开发者社区的协作与创新。在应用场景上,ROS广泛应用于教育科研、服务机器人、自动驾驶等领域,尤其在中国活跃的AI与硬件生态中,结合成熟的电子供应链,催生了大量聚焦场景落地的集成创新。本文以人形机器人为例,探讨如何利用ROS生态与国产硬

weixin_33841722的博客 345

【Zephyr存储专题】09_LittleFs文件系统操作

本文档旨在为开发者介绍Zephyr下Littlef's文件系统相关配置使用指南

zero的博客 3246

Apollo Control——超详细入门教程(六):MPC二次规划问题转化

专栏文章列表 Apollo Control——超详细入门教程(一):基于道路误差的车辆动力学模型 Apollo Control——超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导 Apollo Control——超详细入门教程(三):基于Frenet坐标系及XY坐标系的多项式轨迹生成 Apollo Control——超详细入门教程(四):控制模块轨迹误差计算 Apollo Control——超详细入门教程(五):油门刹车标定表之双线性插值算法 ...

凉了鸭的博客 2233

[ROS2系列] ORBBEC(奥比中光)AstraPro相机在ROS2进行rtabmap 3D建图

ORBBEC(奥比中光)AstraPro相机在ROS2进行rtabmap 3D建图 1、设备:pc;jeston agx orin 2、环境:Ubuntu20.04;ROS2(Foxy)

weixin_45007300的博客 5679

34 python 时间和日期

介绍python里时间和日期的常用方法,以及案例,还有注意事项。

水滴爬呀爬 347

奥比中光深度摄像头_奥比中光astra摄像头总结

1. 奥比中光摄像头(astra pro)在kinetic和melodic下同时显示深度图像和彩色图像(rgb)的方法前言:乐视摄像头采用的是奥比中光astra pro,套了个外壳就原价899,但出事儿后这款摄像头卖不出去了。。。。现在咸鱼上卖100来块,搞视觉的可以整一个玩玩,效果还行。作者主要是在ROS下使用,安装这款摄像头的ROS驱动(astra_camera和astra_launch)后打...

weixin_31235395的博客 6161

QT开发串口程序与单片机通讯

如果有对象对这个信号感兴趣,想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。的内容,虽然实现的功能很简单,但是QT上位机开发的步骤基本就是这些步骤,通过这个基础实例把这些套路摸透我们就可以接着进行后续更多QT程序地开发学习了。QWidget类:所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。我们上面运行的上位机都是在Qt Creator中编译运行的,如果我们需要把编写好的可执行文件发送给别人使用的话还需要进行打包。

谢谢大家的关注和点赞!这里只有纯纯的知识干货,没有一句废话。希望能实实在在帮到大家~要是觉得有用,别忘了给我点支持哟,你 946

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

奥比中光Orbbec Astra Pro RGBD 3D视觉传感器在ROS(indigo和kinetic)使用说明 rgb depth同时显示

Orbbec Astra Pro传感器在ROS(indigo和kinetic)使用说明 rgb depth同时显示 这款摄像头使用uvc输入彩色信息,需要libuvc和libuvc_ros这样才能在ROS正常使用彩色功能。 请在下面网址,分别下载对应包: 1 https://github.com/ktossell 2 https://orbbec3d.com/develop

suijideren的博客 5228

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

ros与深度相机入门教程-在ROS使用奥比中光Orbbec Astra Pro

ros与深度相机入门教程-在ROS使用奥比中光Orbbec Astra Pro ros与深度相机入门教程-在ROS使用奥比中光Orbbec Astra Pro 说明: 介绍如何在ros安装和使用奥比中光Orbbec Astra Pro OrbbecAstra介绍 astra_camera包介绍 astra_launch包介绍 驱动安装 安装依赖:

dxmcu的专栏 6874

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

几种奥比中光SDK的功能说明以及使用方法

本文为大家介绍了多种奥比中光SDK的功能说明及其使用方法,干货满满!快来看一看~

limingmin2020的博客 7400

奥比中光orbbec astra摄像头驱动下载:轻松驱动,开启智能摄像头新体验

奥比中光orbbec astra摄像头驱动下载:轻松驱动,开启智能摄像头新体验 【下载地址】奥比中光orbbecastra摄像头驱动下载 本项目提供了奥比中光Orbbec Astra摄像头在Windows系统下的完整驱动解决方案,包含最新版本的驱动程序、详细安装手册以及符合Windows硬件质量实验室标准的WHQL认证驱...

gitblog_06775的博客 850

奥比中光深度摄像头_奥比中光astra 摄像头采集深度图和RGB图像(小白版)

首先,可以直接使用niviewer这个exe来实现可视化:(在使用之前必须要去官网下载你这个摄像头的驱动并安装:下载地址:https://orbbec3d.com/develop/)我下载的时候需要1个积分。。。然后解压:然后点击NiViewer(应用程序即可)点击之后效果图为:(马赛克是我自己加的)这里说一下你可以右键:点图示的按钮:出现的命令,大家可以自行体验一下,然后注意的是你按c的时候他就...

weixin_39816448的博客 1632
上一篇: rbx1中的follow
下一篇: rosjava入门
RobotBing
博客等级 码龄10年 33粉丝 37原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值