ROS python 代码转换到 C++

10 篇文章 0 订阅

背景:

ROS python 代码转换到 用C++实现,我的关于ar_marker追踪的时候发现点云跳动比较明显。找到了yoc他们的,测试了一下,发现效果还可以,无奈了他们前面的几个代码都是C++的,最后测试demo用Python写的,因此有了这个。其实早在以前学习ROS by Example这本书的时候,尝试用C++写过一部分,这次算是个学习笔记吧。

yujin_ocs/yocs_ar_marker_tracking/scripts/testies.py

代码地址:https://github.com/yujinrobot/yujin_ocs/blob/devel/yocs_ar_marker_tracking/scripts/testies.py

#!/usr/bin/env python

##############################################################################
# Imports
##############################################################################

import math
import rospy
import rocon_utilities.console as console
import visualization_msgs.msg as visualization_msgs
from std_msgs.msg import Float32

# Can't turn it much - different error params?
# Sometimes jumps x-values near the edges -> due to bad z calculations on the fringe (out by 50cm!)
  # should be able to easily filter these out
# a and b disappear near the edges, but I still get readings

##############################################################################
# Functions
##############################################################################

class Marker:
    def __init__(self, id, x, y, z):
        self.id = id
        self.update(x, y, z)
    
    def update(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
        self.distance = math.sqrt(x*x + z*z)

class Jagi(object):
    def __init__(self):
        self.baseline = 0.26
        self.left_marker = Marker(id=0, x=0, y=0, z=0)
        self.right_marker = Marker(id=1, x=0, y=0, z=0)
        self.left_last_timestamp = rospy.get_rostime()
        self.right_last_timestamp = rospy.get_rostime()
        self.x_publisher = rospy.Publisher('x', Float32)
        self.z_publisher = rospy.Publisher('z', Float32)
        self.heading_publisher = rospy.Publisher('heading', Float32)
        self.subscriber = rospy.Subscriber('/visualization_marker', visualization_msgs.Marker, self.callback)


    def print_pythags_results(self):
        b = self.baseline/2 + (self.left_marker.distance*self.left_marker.distance - self.right_marker.distance*self.right_marker.distance)/(2*self.baseline)
        try:
            a = math.sqrt(self.left_marker.distance*self.left_marker.distance - b*b)
        except ValueError:
            print("Value error: measured_distance=%s, b=%s" % (self.left_marker.distance, b))
            return False # self.left_marker not initialised fully yet, so negative sqrt
        print(console.cyan + "           a" + console.reset + " : " + console.yellow + "%s" % a + console.reset)
        print(console.cyan + "           b" + console.reset + " : " + console.yellow + "%s" % b + console.reset)
        return True

    def print_pose_results(self):
        # angle between the robot and the first marker
        alpha = math.atan2(self.left_marker.x, self.left_marker.z)
        alpha_degrees = alpha*180.0/math.pi
        # alpha + beta is angle between the robot and the second marker 
        beta = math.atan2(self.right_marker.x, self.right_marker.z)
        beta_degrees = beta*180.0/math.pi
        # theta is the angle between the wall and the perpendicular in front of the robot
        theta = math.atan2((self.left_marker.z - self.right_marker.z), (self.right_marker.x - self.left_marker.x))
        theta_degrees = theta*180.0/math.pi
    
        print(console.cyan + "       alpha" + console.reset + " : " + console.yellow + "%s" % alpha_degrees + " degrees" + console.reset)
        print(console.cyan + "        beta" + console.reset + " : " + console.yellow + "%s" % beta_degrees + " degrees" + console.reset)
        print(console.cyan + "       theta" + console.reset + " : " + console.yellow + "%s" % theta_degrees + " degrees" + console.reset)
        
        # M1 = (self.left_marker.x, self.left_marker.z)
        # M2 = (self.right_marker.x, self.right_marker.z)
        # M3 = M1 + (M2 - M1)/2   # midpoint of M1, M2
        # Target stop position relative to marker mid point (40cm perpendicularly out)
        # M4 = (-0.4*sin(theta), -0.4*cos(theta))
        # Target stop position
        # M5 = M3 + M4
        target_x = self.left_marker.x + (self.right_marker.x - self.left_marker.x)/2 - 0.4*math.sin(theta)
        target_z = self.left_marker.z + (self.right_marker.z - self.left_marker.z)/2 - 0.4*math.cos(theta)
        target_heading = math.atan2(target_x, target_z)
        target_heading_degrees = target_heading*180.0/math.pi
        
        print(console.cyan + "      target" + console.reset + " : " + console.yellow + "(x=%s, z=%s, heading=%s)" % (target_x, target_z, target_heading_degrees) + console.reset)
        self.x_publisher.publish(Float32(target_x))
        self.z_publisher.publish(Float32(target_z))
        self.heading_publisher.publish(Float32(target_heading_degrees))
    
    def callback(self, data):
        if data.id == 0:
            self.right_marker.update(data.pose.position.x, data.pose.position.y, data.pose.position.z)
            self.right_last_timestamp = data.header.stamp
            print(console.cyan + "r: [x, y, z]" + console.reset + " : " + console.yellow + "[%s, %s, %s]" % (self.right_marker.x, self.right_marker.y, self.right_marker.z) + console.reset)
            print(console.cyan + "r: d" + console.reset + "         : " + console.yellow + "%s" % self.right_marker.distance + console.reset)
        else:
            self.left_last_timestamp = data.header.stamp
            self.left_marker.update(data.pose.position.x, data.pose.position.y, data.pose.position.z)
            print(console.cyan + "l: [x, y, z]" + console.reset + " : " + console.yellow + "[%s, %s, %s]" % (self.left_marker.x, self.left_marker.y, self.left_marker.z) + console.reset)
            print(console.cyan + "l: d" + console.reset + "         : " + console.yellow + "%s" % self.left_marker.distance + console.reset)
        #if math.fabs(self.left_last_timestamp - self.right_last_timestamp) < 0.1:
        if self.left_last_timestamp == self.right_last_timestamp:
            if self.print_pythags_results():
                self.print_pose_results()

##############################################################################
# Main
##############################################################################

if __name__ == '__main__':
    #visualization_msgs/Marker
    rospy.init_node('roles_and_apps')
    jagi = Jagi()
    rospy.spin()

C++ 的改写如下

#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <std_msgs/Float64.h>
#include <math.h>

class Marker
{

public:
    int id;
    float x;
    float y;
    float z;
    float distance;

public:
    Marker()
    {

    }

    Marker(int id, double x, double y, double z)
    {
        this->id = id;
        this->update(x, y, z);
    }

    void update( double x, double y, double z)
    {
        this->x = x;
        this->y = y;
        this->z = z;
       this->distance = sqrt(x*x + z*z);
    }
};

class Jagi : public Marker
{
private:
    double baseline;
    Marker left_marker;
    Marker right_marker;
//    Marker left_marker(0,0.0,0.0,0.0);
//    Marker right_marker(0, 0.0, 0.0, 0.0);
    ros::Time left_last_timestamp, right_last_timestamp;
    ros::Publisher x_publisher, z_publisher, heading_publisher;
    ros::Subscriber subscriber;

    ros::NodeHandle n_;

public:
    Jagi(const ros::NodeHandle& node_handle) : n_(node_handle)
    {
        this->baseline = 0.26; // Kinect baseline?
        this->left_marker = Marker(0, 0.0, 0.0, 0.0) ;// id
        this->right_marker = Marker(1, 0.0, 0.0, 0.0);
        this->left_last_timestamp = ros::Time::now();
        this->right_last_timestamp = ros::Time::now();

        this->x_publisher = n_.advertise<std_msgs::Float64>("x", 10);
        this->z_publisher = n_.advertise<std_msgs::Float64>("z", 10);
        this->heading_publisher = n_.advertise<std_msgs::Float64>("heading", 10);

        this->subscriber = n_.subscribe("/visualization_marker", 20, &Jagi::callback, this);
    }

    void callback( const visualization_msgs::Marker& data)
    {

        if(data.id == 0)
        {
            this->right_marker.update(data.pose.position.x, data.pose.position.y, data.pose.position.z);
            this->right_last_timestamp = data.header.stamp;
            std::cout<< "r: [x, y, z] : " <<this->right_marker.x<<" "<< this->right_marker.y<<" "<< this->right_marker.z <<std::endl;
            std::cout<<"r: d: "<<this->right_marker.distance<<std::endl;

        }else
        {
            this->left_last_timestamp = data.header.stamp;
            this->left_marker.update(data.pose.position.x, data.pose.position.y, data.pose.position.z);
            std::cout<< "l: [x, y, z] : " << this->left_marker.x<<" "<< this->left_marker.y<<" "<< this->left_marker.z <<std::endl;
            std::cout<<"l: d: "<< this->left_marker.distance<<std::endl;
        }

        if (this->left_last_timestamp == this->right_last_timestamp)
        {
            if (this->print_pythags_results())
            {
                this->print_pose_results();
            }
        }

    }

    bool print_pythags_results()
    {
        double a;
        double b = this->baseline/2 + (this->left_marker.distance*this->left_marker.distance - this->right_marker.distance*this->right_marker.distance)/(2*this->baseline);
        try {
             a =  sqrt(this->left_marker.distance*this->left_marker.distance - b*b);
        } catch (std::exception &e)
        {
            printf("Value error: measured_distance=%lf, b=%lf\n" ,this->left_marker.distance, b);
            return false;// this->left_marker not initialised fully yet, so negative sqrt
        }
        printf(" a : %lf\n" , a);
        printf(" b : %lf\n" , b);
        return true;
    }

    void print_pose_results()
    {
        std_msgs::Float64 send_data;
        // angle between the robot and the first marker
        double alpha = atan2(this->left_marker.x, this->left_marker.z);
        double alpha_degrees = alpha*180.0/M_PI;
        // alpha + beta is angle between the robot and the second marker
        double beta = atan2(this->right_marker.x, this->right_marker.z);
        double beta_degrees = beta*180.0/M_PI;
        // theta is the angle between the wall and the perpendicular in front of the robot
        double theta = atan2((this->left_marker.z - this->right_marker.z), (this->right_marker.x - this->left_marker.x));
        double theta_degrees = theta*180.0/M_PI;

        printf( " alpha : %lf degrees" , alpha_degrees);
        printf( " beta : %lf degrees" , beta_degrees );
        printf( " theta : %lf degrees" , theta_degrees);

        // M1 = (this->left_marker.x, this->left_marker.z)
        // M2 = (this->right_marker.x, this->right_marker.z)
        // M3 = M1 + (M2 - M1)/2   // midpoint of M1, M2
        // Target stop position relative to marker mid point (40cm perpendicularly out)
        // M4 = (-0.4*sin(theta), -0.4*cos(theta))
        // Target stop position
        // M5 = M3 + M4

       double target_x = this->left_marker.x + (this->right_marker.x - this->left_marker.x)/2 - 0.4* sin(theta);
       double target_z = this->left_marker.z + (this->right_marker.z - this->left_marker.z)/2 - 0.4* cos(theta);
       double target_heading = atan2(target_x, target_z);
       double target_heading_degrees = target_heading*180.0/M_PI;

        printf( " target : (x=%lf, z=%lf, heading=%lf)" , target_x, target_z, target_heading_degrees);

        send_data.data = target_x;
        this->x_publisher.publish(send_data);

        send_data.data = target_z;
        this->z_publisher.publish(send_data);

        send_data.data = target_heading_degrees;
        this->heading_publisher.publish(send_data);
    }





};

int main(int argc, char **argv)
{
    ros::init(argc, argv, "ar_auto_docking");
    ros::NodeHandle n("~");

    Jagi Jagi(n);

    ros::spin();

    return 0;
}

其中,主要是有一个类的继承和pub发布时候的强制转化,那里花费了较多时间debug。


$ roslaunch yocs_ar_marker_tracking testies-3dsensor.launch

$ roslaunch yocs_ar_marker_tracking tracking.launch

$ rosrun yocs_ar_marker_tracking test_node

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yaked19

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值