如何让Webots支持C#语言开发的控制器
Webots支持C、C++、Java、Python、Matlab这五种语言开发控制器,没有直接支持C#,但有个同事已经用C#写了大量的机器人控制代码,想在不把C#代码改写成C++的情况下,直接用webots仿真,那就得想想办法。(不过,让ChatGPT帮忙把一种语言的代码转成另外一种语言的代码,还是挺方便的,准确率很高。)
在Webots的安装路径下,找到lib\controller文件夹,里面有Controller.dll和Controller.lib文件,对于C#,我们只需要Controller.dll文件(C和C++的开发就需要Controller.lib文件),把这个dll文件复制到C#程序编译输出exe的文件夹里,通常是bin\x64\Debug\net8.0,(注意是跟输出的exe文件放在同一文件夹里,而不是跟C#的源代码放在同一文件夹里。既不需要,也不能在VS解决方案中添加对Controller.dll的引用,尝试添加它会报错。Controller.dll是64位的,所以C#程序也要编译成64位的。)
Controller.dll实现了(或者说导出了)Webots\include\controller\c\webots文件夹中所有的头文件中声明的全部函数(共932个),比如最常用wb_robot_init(), wb_robot_step(),wb_motor_set_position(), wb_motor_set_velocity(), wb_motor_get_target_position(),肯定都有的。而cpp的函数其实都是在调用c的函数,看看\Webots\src\controller\cpp里面的cpp文件就明白了。如果你装了VS 2022,可以打开开始菜单中Visual Studio 2022文件夹里的随便点开一个 xxx Command Prompt for VS 2022, 输入
dumpbin /exports "E:\Program Files\Webots\lib\controller\Controller.dll"
就能看到所有的导出函数了。
为了能使用Controller.dll,在C#的cs文件中,
using System.Runtime.InteropServices;
再去robot.h, motor.h等头文件中找你需要的函数的定义,然后在一个C#的class里面加入大量类似下面的语句
[DllImport("Controller.dll")]
public static extern void wb_robot_init();
看.h文件中的函数定义,一定会遇到WbDeviceTag,可以在Webots\include\controller\c\webots\types.h中找到对WbDeviceTag的定义:
typedef unsigned short WbDeviceTag;
对应到C#中就是ushort类型。遇到const char *,就换成string. 把需要用到的函数都经过上面的声明后,就能和在C语言中一样使用这些函数了。示例C#代码如下:
using System.Runtime.InteropServices;public class Program
{[DllImport("Controller.dll")]public static extern void wb_robot_init();[DllImport("Controller.dll")]public static extern void wb_robot_cleanup();[DllImport("Controller.dll")]public static extern void wb_robot_step(int duration);[DllImport("Controller.dll")]public static extern void wb_motor_set_position(ushort tag, double position);[DllImport("Controller.dll")]public static extern void wb_motor_set_velocity(ushort tag, double velocity);[DllImport("Controller.dll")]public static extern void wb_motor_get_target_position(ushort tag);[DllImport("Controller.dll")]public static extern ushort wb_robot_get_device(string name);public static void GetAllMotor(ref ushort[] motor){ motor[10] = wb_robot_get_device("TA_joint_01");motor[9] = wb_robot_get_device("TA_joint_02");motor[8] = wb_robot_get_device("TA_joint_03");motor[7] = wb_robot_get_device("TA_joint_04");motor[6] = wb_robot_get_device("TA_joint_05");}public static void Main(){ wb_robot_init();ushort[] motor = new ushort[11];GetAllMotor(ref motor);wb_motor_set_position(motor[10], Math.PI/2); wb_motor_set_position(motor[8], 3); // 单位是弧度 wb_robot_step(500);wb_robot_cleanup();Console.ReadKey();}
}
启动C#程序后会看到如下报错,暂未发现有什么不良影响,还是能正常操作webots中的机器人。
Error: 找不到指定的模块。
(dynamic library)
Error: failed to load E:/Program Files/Webots/resources/projects/plugins/robot_windows/generic/generic.dll library.
generic.dll的路径是正确的,然而即使把generic.dll跟Controller.dll放在一起,也无法解决这个报错。
相关文章:
如何让Webots支持C#语言开发的控制器
Webots支持C、C、Java、Python、Matlab这五种语言开发控制器,没有直接支持C#,但有个同事已经用C#写了大量的机器人控制代码,想在不把C#代码改写成C的情况下,直接用webots仿真,那就得想想办法。(不过,让Chat…...
如何将本地仓库放到远程仓库中
在我们仓库创建好之后,我们复制好ssh 接着我们需要使用git remote add<shortname><url>这个命令 shortname就是我们远程仓库的别名 接着使用git remote -v这个命令查看一下目前远程仓库的别名和地址 原本还有一个指令git branch -M main 指定分支的名…...
Jedis-事务
一,Jedis 我们要使用Java来操作Redis Jedis是Redis官方推荐的java连接工具。使用Java操作Redis的中间件。如果你要使用Java操作redis,那么一定要对jedis十分的熟悉 二,idea 连接jedis 1,导入jar包 <dependencies><depen…...
智慧安防监控EasyCVR视频调阅和设备录像回看无法自动播放的原因排查与解决
智慧安防监控EasyCVR视频管理平台能在复杂的网络环境中,将前端设备统一集中接入与汇聚管理。国标GB28181协议视频监控/视频汇聚EasyCVR平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、…...
百元不入耳蓝牙耳机哪个好?必入五款高性价比产品
喜欢听歌的朋友都会遇到一个常见问题,长时间戴耳机容易导致耳朵不适,甚至疼痛难忍。这种情况下,要是不听音乐反而感到不舒服,真是让人苦恼,仿佛音乐与耳机无法和谐共存。但是,难道就没有一款既舒适又让人心…...
android APP monkey 测试
monkey 测试 一、电脑ADB安装及使用详解1、什么是 Monkey 测试2、什么是ADB3、ADB的作用4、安装前提条件5、ADB下载6、ADB安装与配置 二、连接安卓手机检查是否连接上安卓手机windows端安装ADB驱动 三、 monkey测试操作指令演示指令APP包名查看方式测试效果 一、电脑ADB安装及使…...
IMBoy缓存系统深度解析:为何选择depcache而非ETS或Redis
在IMBoy即时通讯平台的开发过程中,我们面临了选择最佳缓存系统的关键技术决策。经过细致的考量,我们选择了depcache作为IMBoy的核心缓存机制。本文将阐述IMBoy缓存系统的选型理由,并对比分析depcache与纯ETS方案及Redis方案的不同优势。 1. …...
Twitter Api查询用户粉丝列表
如果大家为了获取实现方式代码的话可能要让大家失望了,这边文章主要是为了节省大家开发时间,少点坑。https://api.twitter.com/2/users/:id/followers ,这个接口很熟悉吧,他是推特提供的获取用户关注者(粉丝࿰…...
深入理解计算机系统 家庭作业 2.96
题目出的很不好,感觉没有标准. #include <stdio.h>typedef unsigned float_bits;int float_f2i(float_bits f) {unsigned sign f >> (31);unsigned exp (f >> 23) & 0xff;unsigned frac f & 0x7fffff;unsigned add (frac & 0x3) 0x3;unsig…...
主函数if __name__ == ‘__main__‘:
在Python中,主函数通常指的是脚本的入口点,也就是当你直接运行一个Python脚本时,会首先执行的函数。在大多数Python脚本中,主函数并不是通过main()这样的函数名来定义的,而是通过检查脚本是作为模块导入还是被直接运行…...
34.Python从入门到精通—Python3 正则表达式检索和替换
34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例 检索和替换repl 参数是一个函数正则表达式对象正则表达式修饰符 - 可选标志正则表达式模式*正则表达式实例 检索和…...
springboot 反射调用ServiceImpl时报错:java.lang.NullPointerExceptio、,mapper为null【解决方法】
springboot 反射调用ServiceImpl时报错:java.lang.NullPointerException、mapper为null【解决方法】 问题描述问题分析解决方案创建SpringBootBeanUtil编写调用方法 executeMethod调用 总结 问题描述 在使用Spring Boot时,我们希望能够通过反射动态调用…...
内网安全之域内密码喷洒
域内密码喷洒一般和域内用户名枚举一起使用,可以在无域内凭据的情况下,通过枚举出域内存在的用户名,进而对域内存在的用户名进行密码喷洒,以此来获得域内有效凭据。 在Kerberos协议认证的AS-REQ阶段,请求包cname对应的…...
何为HTTP状态码?一文清楚基本概念。
在客户端与服务器之间的信息传输过程中,我们可以将其比喻为客户与快递员之间的包裹传递。那么服务器是如何通知客户端,操作是成功还是失败?或者有其他的一些情况呢?(就像客户可以查询快递的状态) 而这背后…...
SV学习笔记(七)
文章目录 类型转换写在前面动态转换子类句柄赋值于父类句柄父类句柄转换为子类句柄 虚方法写在前面非虚函数的调用虚函数的调用虚方法的建议为什么使用虚方法 对象拷贝写在前面赋值和拷贝总结 回调函数写在前面实例完成回调函数功能需要三步: 参数化类写在前面实现一…...
Windows SDK(五)按钮静态文本与编辑框控件
我们首先应该知道,所谓按钮静态文本等等控件都是窗口,他们都是隶属于父窗口下的子窗口,所 以在创建控件前,我们要首先创建一个父窗口,此处我们直接使用Windows桌面程序创建时,程 序自动为我们创建的一个窗…...
基于SSM框架实现的在线心理评测与咨询系统(技术栈 spring+springmvc+mybatis+jsp+jquery+css)
一、项目简介 本项目是一套基于SSM框架实现的在线心理评测与咨询系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试&am…...
GD32F470_ DS18B20温度传感器模块移植
DS18B20温度传感器 DS18B20数字温度传感器提供9位至12位精度的温度测量,并具有非易失性用户可编程上下触发点报警功能。DS18B20通过单总线通信,根据定义,只需要一条数据线(和地线)即可与单片机通信。此外,DS18B20可以直接从数据线…...
【JAVASE】带你了解instanceof和equals的魅力
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 1.instanceof instanceof 是 Java 的保留关键字。它的作用是测试…...
【Linux】进程控制详解
目录 前言 进程创建 认识fork 写时拷贝 再谈fork 进程终止 进程退出码 用代码来终止进程 常见的进程终止的方式 exit _exit 进程等待 进程等待的必要性 进程等待的方式 wait waitpid 详解status参数 详解option参数 前言 本文适合有一点基础的人看的&#…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
