Python(ROSPIO)到C++(ROSCPP)结构.unp

2024-09-30 04:27:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在将一个rospy的IMU驱动程序翻译成roscpp,很难弄清楚这段代码的作用以及如何翻译。在

def ReqConfiguration(self):
    """Ask for the current configuration of the MT device.
    Assume the device is in Config state."""
    try:
        masterID, period, skipfactor, _, _, _, date, time, num, deviceID,\
                length, mode, settings =\
                struct.unpack('!IHHHHI8s8s32x32xHIHHI8x', config)
    except struct.error:
        raise MTException("could not parse configuration.")
    conf = {'output-mode': mode,
            'output-settings': settings,
            'length': length,
            'period': period,
            'skipfactor': skipfactor,
            'Master device ID': masterID,
            'date': date,
            'time': time,
            'number of devices': num,
            'device ID': deviceID}
    return conf

我不得不承认,我以前从未与ros和python一起工作过。 这不是源代码中的1:1代码,我删除了我认为我知道它们做什么的行,但尤其是try块是我不理解的。我真的很感谢你的帮助,因为我对时间很有把握。在

如果有人好奇(上下文原因):我要翻译的文件是mtdevice.py, mtnode.py以及MTPY定义在google上可以找到文件名+关键字ROS IMU Driver

事先非常感谢。在


Tags: ofthe代码datesettingstimemodedevice
2条回答

这段代码将C结构中的字段解包,即masterID、period、skipfactor、、u、date、time、num、deviceID、length、mode、settings,将这些字段存储在Python字典中,并将该字典作为调用结果返回。下划线是结构中未使用部分的占位符。在

另请参见:https://docs.python.org/2/library/struct.html,例如,有关格式字符串('!IHHHI8S8S32X32XHI8X'),它告诉解压函数结构的外观。在

语法a,b,c,d=f()意味着函数返回一个在Python中称为元组的东西。通过将一个元组分配给多个变量,它被拆分成它的字段。在

示例:

 t = (1, 2, 3, 4)

 a, b, c, d = t

 # At this point a == 1, b == 2, c == 3, d == 4
<> P>用C++取代这段代码不应该太难,因为C++的结构与C.很相似,所以最简单的C++配置实现是要返回那个结构。如果您想更靠近Python功能,您的函数可以将Stutt的字段放入C++ STL映射中并返回。格式字符串+链接指向的文档将告诉您结构中的数据类型以及位置。在

注意,unpack的第二个参数保存数据,第一个参数只包含第二个参数的布局(格式)信息,如链接中所述。第二个参数在Python看来似乎是一个字符串,但实际上它是一个C结构。第一个参数告诉Python在该结构中的何处查找内容。在

因此,如果您阅读格式字符串的文档,您可以找到第二个参数(C struct)的布局。但也许你不需要。这取决于函数的调用者。它可能只需要简单的C结构。在

从您添加的注释中我了解到,您的函数中的代码比您显示的要多。结构的字段被分配给类的属性。在

如果你知道C结构(CONFIG)的字段名,那么你可以直接把它们分配给C++类的属性。在

^{pr2}$

我假设config结构的字段名确实是mode、settings、length等,但您必须验证这一点。这个结构的布局可能是在某些C头文件(或文档)中声明的。在

用C++做同样的事情,你会用不同的参数声明^ {< CD1>}:

struct DeviceRecord {
    uint32_t masterId;
    uint16_t period, skipfactor, _a, _b;
    uint32_t _c;
    char date[8];
    char time[8];
    char padding[64];
    uint16_t num;
    uint32_t deviceID;
    uint16_t length, mode;
    uint32_t settings;
    char padding[8];
};

(这个结构可能已经在某个地方声明了;它也可能使用“unsigned int”代替“uint32”和“unsigned short”来代替“uint16”,而“u a”、“u b”和“u c”可能有实名。)

一旦有了结构,问题是如何获取数据。这取决于数据在哪里。如果它在一个文件中,你应该这样做:

^{pr2}$

另一方面,如果它在内存中的某个地方(例如,你有一个char*或void*),那么你只需要将它转换为:

void* data_source = get_data(...); // You'd get this from somewhere
DeviceRecord* rec_ptr = reinterpret_cast<DeviceRecord*>(stat_source);
// Now you can access rec_ptr->masterID etc

如果您有一个std::vector,您可以很容易地得到这样一个指针:

std::vector<uint8_t> data_source = get_data(...); // As above
DeviceRecord* rec_ptr = reinterpret_cast<DeviceRecord*>(data_source.data());
// Now you can access rec_ptr->masterID etc, provided data_source remains in scope. You should probably also avoid modifying data_source.

这里还有一个问题。你收到的数据是用big-endian格式的,但是除非你有一个PowerPC或其他不寻常的处理器,否则你可能在一个小endian机器上。所以在访问数据之前,您需要进行一些字节交换。您可以使用以下函数来执行此操作。在

template<typename Int>
Int swap_int(Int n) {
    if(sizeof(Int) == 2) {
        union {char c[2]; Int i;} swapper;
        swapper.i = n;
        std::swap(swapper.c[0], swapper.c[1]);
        n = swapper.i;
    } else if(sizeof(Int) == 4) {
        union {char c[4]; Int i;} swapper;
        swapper.i = n;
        std::swap(swapper.c[0], swapper.c[3]);
        std::swap(swapper.c[1], swapper.c[2]);
        n = swapper.i;
    }
    return n;
}

它们返回交换的值,而不是就地更改它,所以现在您可以使用swap_int(rec->num)之类的东西访问数据。注意:上面的字节交换代码未经测试;稍后我将尝试编译它,如果需要的话进行修复。在

如果没有更多的信息,我不能给你一个明确的方法来做这件事,但也许这将足以帮助你自己解决它。在

相关问题 更多 >

    热门问题