From 8052007699577bbf59ea7830ca2d3fbeae5c7974 Mon Sep 17 00:00:00 2001 From: "M. Stokroos" Date: Wed, 14 Sep 2022 10:58:29 +0200 Subject: [PATCH] First commit --- CMakeLists.txt | 216 ++++++++++++++++++++++++++++++++ README.md | 38 ++++++ launch/rofish_teleop_joy.launch | 38 ++++++ package.xml | 65 ++++++++++ rosgraph.png | Bin 0 -> 68221 bytes src/red_rofish_telemetry.cpp | 186 +++++++++++++++++++++++++++ src/rofish_teleop_joy.cpp | 45 +++++++ src/yellow_rofish_telemetry.cpp | 186 +++++++++++++++++++++++++++ 8 files changed, 774 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 launch/rofish_teleop_joy.launch create mode 100644 package.xml create mode 100644 rosgraph.png create mode 100644 src/red_rofish_telemetry.cpp create mode 100644 src/rofish_teleop_joy.cpp create mode 100644 src/yellow_rofish_telemetry.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e595ad2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,216 @@ +cmake_minimum_required(VERSION 2.8.3) +project(rofish) + +## Compile as C++11, supported in ROS Kinetic and newer +# add_compile_options(-std=c++11) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + roscpp + std_msgs + joy +) + +## System dependencies are found with CMake's conventions +# find_package(Boost REQUIRED COMPONENTS system) + + +## Uncomment this if the package has a setup.py. This macro ensures +## modules and global scripts declared therein get installed +## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html +# catkin_python_setup() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +## To declare and build messages, services or actions from within this +## package, follow these steps: +## * Let MSG_DEP_SET be the set of packages whose message types you use in +## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). +## * In the file package.xml: +## * add a build_depend tag for "message_generation" +## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET +## * If MSG_DEP_SET isn't empty the following dependency has been pulled in +## but can be declared for certainty nonetheless: +## * add a exec_depend tag for "message_runtime" +## * In this file (CMakeLists.txt): +## * add "message_generation" and every package in MSG_DEP_SET to +## find_package(catkin REQUIRED COMPONENTS ...) +## * add "message_runtime" and every package in MSG_DEP_SET to +## catkin_package(CATKIN_DEPENDS ...) +## * uncomment the add_*_files sections below as needed +## and list every .msg/.srv/.action file to be processed +## * uncomment the generate_messages entry below +## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) + +## Generate messages in the 'msg' folder +# add_message_files( +# FILES +# Message1.msg +# Message2.msg +# ) + +## Generate services in the 'srv' folder +# add_service_files( +# FILES +# Service1.srv +# Service2.srv +# ) + +## Generate actions in the 'action' folder +# add_action_files( +# FILES +# Action1.action +# Action2.action +# ) + +## Generate added messages and services with any dependencies listed here +# generate_messages( +# DEPENDENCIES +# std_msgs +# ) + +################################################ +## Declare ROS dynamic reconfigure parameters ## +################################################ + +## To declare and build dynamic reconfigure parameters within this +## package, follow these steps: +## * In the file package.xml: +## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" +## * In this file (CMakeLists.txt): +## * add "dynamic_reconfigure" to +## find_package(catkin REQUIRED COMPONENTS ...) +## * uncomment the "generate_dynamic_reconfigure_options" section below +## and list every .cfg file to be processed + +## Generate dynamic reconfigure parameters in the 'cfg' folder +# generate_dynamic_reconfigure_options( +# cfg/DynReconf1.cfg +# cfg/DynReconf2.cfg +# ) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if your package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES rofish +# CATKIN_DEPENDS roscpp std_msgs +# DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +include_directories( +# include + ${catkin_INCLUDE_DIRS} +) + +## Declare a C++ library +# add_library(${PROJECT_NAME} +# src/${PROJECT_NAME}/rofish.cpp +# ) + +## Add cmake target dependencies of the library +## as an example, code may need to be generated before libraries +## either from message generation or dynamic reconfigure +# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Declare a C++ executable +## With catkin_make all packages are built within a single CMake context +## The recommended prefix ensures that target names across packages don't collide +# add_executable(${PROJECT_NAME}_node src/rofish_node.cpp) +add_executable(rofish_teleop_joy src/rofish_teleop_joy.cpp) +add_executable(red_rofish_telemetry src/red_rofish_telemetry.cpp) +add_executable(yellow_rofish_telemetry src/yellow_rofish_telemetry.cpp) + +## Rename C++ executable without prefix +## The above recommended prefix causes long target names, the following renames the +## target back to the shorter version for ease of user use +## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" +# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") + +## Add cmake target dependencies of the executable +## same as for the library above +# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Specify libraries to link a library or executable target against +# target_link_libraries(${PROJECT_NAME}_node +# ${catkin_LIBRARIES} +# ) + target_link_libraries(rofish_teleop_joy + ${catkin_LIBRARIES} ) + target_link_libraries(red_rofish_telemetry + ${catkin_LIBRARIES} ) + target_link_libraries(yellow_rofish_telemetry + ${catkin_LIBRARIES} ) + + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables for installation +## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html +# install(TARGETS ${PROJECT_NAME}_node +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark libraries for installation +## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html +# install(TARGETS ${PROJECT_NAME} +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_rofish.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/README.md b/README.md new file mode 100644 index 0000000..0ac29fc --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# ROFISH - ROS PACKAGE FOR ROBOTIC FISH +This ROS package controls two robotic fish (red and yellow) from two Logitech wireless Gamepad F710 controllers. The robotic fish are the Bionic Koi types from the Design Lab of the Peking University: [https://en.ibdl.pku.edu.cn/news/highlights/895537.htm](https://en.ibdl.pku.edu.cn/news/highlights/895537.htm) +The right joy-handle controls the speed of the fish by pushing the handle forward. The right joy-handle also steers the fish by pushing the handle to the left or right. + +## Preparations +- The project assumes a correct working ROS Noetic setup and workspace environment +- Connect the two radios for the telemetry to the USB port +- Connect the two dongles of the Gamepad controllers to the USB port +- Turn on the red and the yellow robotic fish + +## Launch the package +- start the roscore by typing 'roscore' in the terminal window. +- Open a new terminal and launch the ROS package by typing: `roslaunch rofish rofish_teleop_joy.launch` + + +## Diagnostics +Start the diagnostics in another terminal: + +``` +$ rostopic list +/diagnostics +/red/cmd_vel +/red/joy +/red/joy/set_feedback +/rosout +/rosout_agg +/yellow/cmd_vel +/yellow/joy +/yellow/joy/set_feedback + +$ rosrun rqt_graph rqt_graph + +``` + +Output from rqtgraph: +![rosgraph](rosgraph.png "rosgraph") + + diff --git a/launch/rofish_teleop_joy.launch b/launch/rofish_teleop_joy.launch new file mode 100644 index 0000000..afdc783 --- /dev/null +++ b/launch/rofish_teleop_joy.launch @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.xml b/package.xml new file mode 100644 index 0000000..c8ca55c --- /dev/null +++ b/package.xml @@ -0,0 +1,65 @@ + + + rofish + 0.0.0 + The rofish package + + + + + p229763 + + + + + + TODO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + catkin + roscpp + std_msgs + roscpp + std_msgs + roscpp + std_msgs + + + + + + + + diff --git a/rosgraph.png b/rosgraph.png new file mode 100644 index 0000000000000000000000000000000000000000..d88b6423072132e69e36ac958eb3d0739881fb1a GIT binary patch literal 68221 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�q#TG|0n$b;^H>X*xX6tkJdrprT# zH-fLdogYHB}K2Y>i=d zcZ9o`zc^aFy%Z2Im0G1Rxi>f=M=`@|qU7bvS9LWav#%6qYdgdUDKjy#`=-a~)320c z2P!?|QNMp1d|YGMw19JL;gj)8rm;WmsIQHe23!~23)GO$VriMe({_aK8u{C*f7TkL zo7`^2`PtK7hs(Xv)n0uIhU!i}E!ZwwEBbB-| z`ua{9w2eGxAIG^`^L~GyJnn(16=<_-5jGcW>yq;Y#&Uc_)hLvoxfre zlIFT<@qw`c^Yp6L?<-CntH2`p1FtB$3T5aV%Vh|=QxXHpB}3}1zkhEB zi29Teff!obYt9Z&0*=B|M%5+`LX1!sV`0mZzYjSrU->A!)%UOX7F_U|h>`BE^yr9P zEIb^Bm{nGXgf%ueG73kmi>HU{`oOq40H=-;Kfj%AwR6xEj?c=B*%)h)9z1bLSVV+% zYi8Y-VF_hr>#5MQo}OLRKY(96+<4Y7?YW)!>aDNqs5$N30d#r1UqLt3-4FK$$%cz4 zH_TzR8Qee6sQhxYU9z2U#6EtP&x!gRa4$#JtcXB?Z%a|S-; zV&24H>Q+RM!RfMx54*XT9HL5z#mtxAN=uWHD{@FGib~vc1@g3vVL7%d7iD*YC?6TR zQjs+uB9<%1Bghhd6N`AD*4Hcga%;iro%dAg_DOJQ_-ws0o3UzK?cezKMqy!LuQ%i& z$8+lR_^wTLb ztL797vxL6|N_yXWpx{}fbfTLJJiJf_^HqoJnTb2mSOQ_)9k0MUAF zuU-{R|EaQxgatIodkAI!riGkDH)!rw8 zF?_k3G5F|`{?c=BUktse2mX<%p9HHE?1-x@VD#j|ZqKS)-rxI8?72~saoS_p=lnh0 zOO;=zPM)Gt4OMHv{bii<{j8(rS0Nt38*Sz3|CrrcQNG&9vH675n{zKs(gJzxqtKa~ zmTV|`se5!9qf&KN{g6#oy({0sPxHyPml)8vfio%E+WNQ3MTmQrm!Y+A`|wfRH2pjJ`@4U*;KIXoIcO`I z6#owZH)dw>H0C#NxTc-`rz5*x2dISW`}5EWEqH?l-f5m|Aov#Jl~U>FjXxEDv*Ym)8{4e#aeFd#|!Q%b$!82r9`Qdq#KymIuOB*Abn1?_!lP$&{V{4wHgHQTP*9HLdkUsfsXWx%&eq zf~>(mUm(fewfj|=Ae7e~HWFfDHb5iqC4M(jiHq}uvm+yA_V;f`On5t?$SbeDlw;KT zb1f!hq+|Hp7=b6e{OQ*I^5xA#y9>|#g<*HY$})hC#G(x74wLRT>!U%k#V6e25JL1^ z_)<6AKSQ^Fa<{T1AECWfF|M(T^F&gQ`NB@fNWn@gP$mr=&+y34V0^>!-Ra}sx^fr*cG6}pzcMViz}l6K z=Iqfwb9)14Z(d0v6#K{im#^r0*n90y5^h$kS z-6-Q1qD&s!6Q@BM@4Nd^%})H3D#vvO&9ly_G$h(h4peSJ*kLeAsojTeW=`+zC|I{? zdlU-qHG;(gi5VH2?CtIEe-l6^CwBGK@bDlUZ^(^|2FlR$?t@lUy*KC^n1)1ydbPnE zlKzh$xrqx9iHgB)L@-hJ*Y^Q4`{SBwLb}@8f$;qA|Ip?32CHHke+2&oofq`eS_}2> z&^*+cM!{(xihrTw*4_c`Ha3BfQ3^f&2@sKFMgptC@RS-k6{-u%HFw9`f((GP{|Xcg zm}i1-t#x5B6$O7RxL*=|;&Y%$uC*Vq4sXeO(__Rc3;+@+{MXnFl`AI>VDcM?8%%xI z;UbL%76a7Fc#(w163bC617HEqpoN#}T}_qq+HI}SifP$R+ZCU{T_zkqpCob8($g1A ze{jDX91K>7jxsLI)sd!fw<5-BZ!;umVW{k$y?)KK^I(jhz32#0d!O0zl>Aj}b!k^O zb07D~iF41>fGi8<7?kyh^2(l8O!>3yGZ3OWi5p(Hp^q z5l28|ZH}NY_wKselLMKoJ@7)xi*M6lZ1TE(-w-|4)OYxtmzO%KdCX}H&dW{|18O$8c=!ERBSBWO$}szuSzNpc!%ETKzqlh&dc$UbmKa>X$Qtq~$exE> zk41@NEOaNF2>Gtj0-<+)le@uspjb(~iA2_;7|_l!0(wnihmGLu$$S3#44IyyLOqE*iZo!%3iEzW6b;`K`jRvE0a}nQMBzwZ+&mUA7FK* ziX=(#VCKriNeyA!tJLJ?*UD_pbVqVlpDPlKn26X%s zT^Ef7uS)yR+Jmk`kWbD3ypoY&edq0_xCzbQF+@L8`1{cF#Y{_&bKoqv`jQoWC6L}| z(k6eb*5~Yj$_iURM-vaa+S}Vx$Ln;Y)eVmR863dla>u3Sjt)Jz@He2?g3j}}lRIG6 z*)6d?rJrpXG$=z%q3hDC)&yQ{?Y}~M_I$h|%EiH9?DE!5{kA--ne@>^u;HqC3tk2J zW6!9UPWDunhe&CF^LEE%kUP|{!HivaGE(72{JJ^UaoHp*Pmt-ATm{`e|1h4D=*G?A zG(H9R%g@Ow;Zs53ibtN4OeoLni{dr4LL^P(D#!iOPQ*ljBmPmNi(Gm5I9K{ zG7w4>6BBzvnpg-^K37}x%%I9b(PgG62gQT7j!ynrc60lj`#)Xx3OUijx7+!++3tAc zqwj#q{&{ZmIZigD7Q#I1H1Dx74 zJeEc={_(o6uen2c^`7Wx>1ixdi18+V8VRyTmOBkfvlp1vP>G>s{DW%oxNM;+dP`&O zrFwJ%TppEn=K~QhX(_tvwgR!JcJMfyB9(99G!)k~jx#w}_%fOXe3FyZr%mtYo3DbW z@}I<{N%d*=PTro>iwH5!>GGETAYCROpDQ2UV>10J08-iV^aFQ=S6Alh7c3*}N^f35 z%9D4mhY_AjwHMmvy7RVJ9`CTgq#VCV$**0<$TXQj4g`p7&V3L`>pU-6Caa&l5*iXh zyFxrj*x$d&62IOy?v5Sdcj_~g?GG^F`y$=w0%!0o0A;^^4(&i`O+$g*f#Ca0CPFaubjEsyV`&|TnU#4HrkvtSBDOL*ca^dDq zvytcAfS=C8@uA@NEdY1JATYhV`HYfLgTU45DfSbNymHIRvO0WC26SbJwxwp=uwfdy zKKstwnjZ48bVaj)JSSoKLGlMV>|eim^9%?|DNN2dxVU=1d}C4j+KU;Q7;G?zVK-Bt zc0FkI_+q)?y1#TfumV8UFpuo;Z{O_Uw};wzbK)+Z_FlY8(2&;SzoFsdIzGL;$O5lw z^v*klgy>a#a!}S>!M|tvdyV~H8fq#YSlkk-81)@hLSMqt zuQx}g0shOhaVdpJIpK)9iH;?}#K78m2mVMi=3}x3!kCR1Q2JcP#PC$mX+YXh+leFD zq_dQF04?u^W-O1=b6% z4W)G$AQHR*V*gGqhevQ>d(1z{q{g)gp@ewCnONb7V5AKg1%fgMPiJ~?(M9KPAAjsb zTVN!VNUT{2eAhDWNeK)Or`vrbJqkxk-(p%1Ew42G>~_K;`oJ1ixdSIMTJ2y|@Eeb5 zX@7t_ix}kSQCP?R>1a_g1{F;@x5v-+@n$bn!IcT$BNWU;CX%yNe3Pa@Rh0l^O-t;~ zWK>n-+KW0Ar1vQN>qaHR@jk^Ny@%)BHq0o?pXTM&Fhg-is9;o`vC3PffBkw6#$Mc| zD?6oIp?HY*SxSq8#LF~=El@EC?BHOHY$TBYGN<2P#X9_&eLRGTWXWIwH$c}A@$@MY z*TKt^A2`3b__f44q?Y3}tbK-wYk`RaH<{bG1N>9yv=1=NY#F(#s$~OCxaQx~*Wtd|MUa zHH2lyklSYZ(BKRY2M21Xbp4>s$NA%_4=p9{1`W6*lc7|!gT(tdc=RNMMK5p3Z3c6L zR;6m=v3yQID=xQ?=S~=t$@f*8@ySO&4ZM3t48%~Dlk>uHBTE-8c~Q8-iH{fwO+i^p zS#4un!EiT0qpPT#Z|JR z#3fn|SYb0e$c1b0fj+QBV}}o3w(*#@_9(fNpv{>ae9R3JKG@&n$dOHecbidf5$}?M zcs=c%o*ud_aBDaoDI-uH|@io2A$lDmX2iH`q!bsA%<2Y z#SzkC!v3FotE;B%NV45vvQ3(!Eqkq0bad$IU&1W~jleTFBn*H4Y~H8u@|H@~gybhc zB7FuE0Cg&o6b=p!Vje@xwaH84JQPyf0F;j`cvwdb<5UZFL~Val+Krtcbk#a*c%^yb zTcpuZEa`0(=sVA2kZ3%ysn+x*`lzkPkL>YEJlPvzAomfcKa9#60Q8(ekJ!+t ziQr1|6v;)0W2X}`@#E6v(=^m3tqv0ILv`E0@G9WGqRvmkZMPf8-l23wxG=xWy>ilL~TBw+_+Njan{6C@XkY!y&_4ULVO>+kbtpT`3t zp%Exk8?hJRFTcCx7R`&xqo~cE5giW9pSUcKXs^vO7CQUAUmE53dR(!Mcu+lSLhwFO z6`;Kegs~1_pes0cU-w*6D*%neKz<|U= z0s$nhW_}#}Uo#s+q_zS-0AA9B8-oN&B9uw(%u#t0^3dU@Pkhwmye6a~uXExHhfv04 ze~gu_$D*Bvy;-?8{{4kv8$dVE%=hv9Oh2rByzS-7=cHa`XKz|h!G^wHk&ZGG)$C=s zVvrRA*r89=t?>Srb=1N*k)NU5VMaNN&rpzaX3aQ_IYLE0j*o{D6&no=(wMH4iCuj~ zM3$hRiEION(SaDVjuwywKZ4=ODO}Nn_yiKrHJ22(8_~Zk!w825P|M_VNo22)a#p$G|T%Kh-KAh5KLHo zz_|9&SHxM~xOwv`jtmkGhmKAKhPF*FO*5Cr!rD%!iQBLHpmHV7Nh9BQ1icdxYmy`v z;9rPlb^YGFi-ivO0b(l2++|k4>I#R9JIC=a0vpnC(&96o#d%C(2O!YX#_~ocW$(`# zW1&#guQ0wK4g?<`&kefeJv;Yx8!l^JlLiiT6et-R*x1>_rl!tBkF)>!{rlsWFZt|( z=a6@%&EKW^jV}L|T9%5RU#;cvJ`9Q9ci%+e;O3rH|5`=KL>kr61%KJ0KpRZ}X1MX5 z;FRXN>c*l?ER(@(yf~Xo90I3(5*2j)IqM-jssx9bBadUK|CCNh%ivnO%#I zzjM}{$6))i7fix{4Ul{!Xa-2oLHaR$S{HcuzaZh8{zEMA03~P4#oYzjMtg{%0el%q zC?X6E&`J>ZIZMz+vG)bqIk)_(!F&{wJejdVaLbRN`W6%t>bmGB#2#tu;zEakZFtmi zB5#76rX*>5VVl%;vTbVbcXb)ThHkcD^WHf4jTN801P#SQSgvFs1!KM$+CcqXH`TZV z0ncD%Bk+q4NF0QK%cFP((ap{1QP9I5WjGB*ru2B~4+E7F2}JM$o+6G%Ok7+MK#noK zWjSgf8k3d93rsB(Fw+x6nW34`!sY%E4nh{8?b;_!Y)A44`5P!jNdE}L9|v;ruYmUF z&kxar!xwLTonLn_#R2PG3LsN?XAzBv-3bT2>5dhNUm1ChwpBOj8xcz#J zI3hcgM3ca=Q4OxRWbPG5j8TAA0c_~k<05(lJsnW+t5}HqyLa1Par%9+wqQjiJKpz$NAut$y@0a8N)`+^{>(F1i1Mn`FAXkejA8f@Y@ zNb>6BR*;DSpl*rH7YM8_$c8_%t# zeHn4C#MAOUIt;jR_HUb27bzgAr;{)%tVwa8ANLUlRZlw5x1-#S;WAFar z*#YiEL^5NCasdm5)#~g0Ik~xfST6Xb$NO{*zM%iogS&(M@w`HllPwO^7HY+=3I45$ z#R`-HTk0vc2044MZg~zI*ai_}k9-45xCZVSEW994JvggcGn~%~97AJHzCB!tG42VI z7R%L#T;^HUmS5Uy4*@n$MH9f5g)FbbRJLTVZ^ckmo9APLo2_|RkH<47dP$e?FnFf=#63Sx|P%NF(B z@zVoi+ixT#)%DPAAm!haCxOaUF7RbV(T3Y#4X!!*d1kd1Zfsv(420l>CGxoiB~bvA zc;qCI`oBPNH@{_G_DGsbTl-|s{$=j_gg4)SQwtH>ViFP~OY%KR9nYUrBW?TCNJZm; zqWSn#G+ICzhi;tx8}GW>q|X*`qtyXFZ+PiIQT=Exa97oOGb5v?b6Ew&CZ?wAa*QlS zJ4jQFrywRH6NV!g)^tH+6TN!15vzp6kE6+S@$uQIhNesVsDY*Bi<8$~+NAzT|os+g!&O(6_h(HXFU;Ph)3I4$T#jtB;Z zh0QcSvNPp2hid@f9bKDX^(UNsG{rb*)?p88q9IIm6E{?&?M%iiA$PjGJQuuM zQ~-jII{;=Xv@vW@3s8xD9V!U>wzld?j;nIZhVhEBvS3_VLt84``Zl68Nbr3}ZKx8* z)b-w(D|eBIS6<5KC!hA{#zNPUlf!Wll6w~S z)4pG6SSetISy@?~+m(hTwmgbb*!wMTsqRdyNxgF7r5lfqy)0bmmO3jSR=~N#D(qmR zyB2PA1ZZUemGE;d#X*A0Nzg5bNiC%W--hhf|KgKj`+5))WtL&b8}H3Tyz{nFzH1=Z zy(q0;?^R&5!+hX~emo906mSmPO<#WgRJOJ1$#&VZ&+@-x5h7$B&x`&mGZiVRwR_I0 z+nZbteLt;n_H5~JX>R_A=c#voCap80uVM@1kGF^dM+-irc{)1;|1SxUP30;(qOZFd zk=@Q4!h}_E5NiYfnMa$e*Norz_jmDsq;`^P@PB`u&6x$D;{Sf#j+%h(|9~eR^0#mD13ir@?rn?*IiM-cK-KAhr~IBpm6!WU;qF7Pt(n*@Uwg=+xGwY7ve7R y{OG)MrD#Cqzt5C!kCq76cBi)_`He2h@{TJps~i3t3Us32e{?htYZR&31phzEj>yaa literal 0 HcmV?d00001 diff --git a/src/red_rofish_telemetry.cpp b/src/red_rofish_telemetry.cpp new file mode 100644 index 0000000..85aed11 --- /dev/null +++ b/src/red_rofish_telemetry.cpp @@ -0,0 +1,186 @@ +#include "ros/ros.h" +#include "geometry_msgs/Twist.h" +#include +#include + +#define LOOP_RATE 20 //Hz +#define QUEUE_SIZE 64 //subscriber buffer size + + +// -------------- Serial Port ----------------- +int fd; +bool isConnected = false; +const char *port0 = "/dev/ttyACM0"; //red +//const char *port1 = "/dev/ttyACM1"; //yellow + +int connectit(const char *dev, int baud); +static void initTermios(int fd, uint32_t baud); +struct termios sTermios; +int writecommand(char speed, char dir, bool mode); + + +// --------------- Fish ID -------------------- +const unsigned char prefix[3] = { 0x21, 0x43, 0x00}; +const unsigned char fish_ID[9] = { 0x52, 0x71, 0xa7, 0x29, 0xbc, 0xd6, 0xd9, 0x00, 0xe5}; //red +//const unsigned char fish_ID[9] = { 0x52, 0x71, 0x63, 0x4c, 0xb9, 0xd6, 0xda, 0x00, 0xe5}; //yellow + + +// global vars +float lin_vel = 0; +float ang_vel = 0; + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Twist message Callback +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +void velCallback (const geometry_msgs::Twist::ConstPtr& vel_msg) { + + lin_vel = vel_msg->linear.x; //Get linear velocity from Twist message. + ang_vel = vel_msg->angular.z; //Get the direction from the Twist message. This is not a speed in reality, but steering action. +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* initTermios. Serial I/O +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +static void initTermios(int fd, uint32_t baud) +{ + tcgetattr(fd, &sTermios); /*Get the attributes set by default*/ + + /* ---------- Serial Port Config ------- */ + sTermios.c_cflag |=(CLOCAL|CREAD); + sTermios.c_cflag &= ~(CSTOPB|CSIZE); + sTermios.c_cflag &= ~(PARENB); + sTermios.c_cflag |= CS8; + sTermios.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG); + sTermios.c_cc[VMIN] = 0; + sTermios.c_cc[VTIME] = (unsigned int)(100); + sTermios.c_cc[VSTART] = 0x13; + sTermios.c_cc[VSTOP] = 0x19; + + sTermios.c_iflag &= ~(IXON|IXOFF|IXANY|ICRNL|INLCR); + sTermios.c_oflag &= ~OPOST; + cfsetispeed(&sTermios, baud); + cfsetospeed(&sTermios, baud); + /* -------- Serial Port Config END---- */ + + tcsetattr(fd, TCSANOW, &sTermios); +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* connectit. Open serial port +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int connectit(const char *dev, int baud) { + int fd; + fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fd == -1) { perror("serconnect "); return fd; } + initTermios(fd, baud); + return fd; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* writecommand +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int writecommand(char speed, char dir, bool mode) { + + char msg[15]; + if(!isConnected) return -1; + + if(dir > 8) dir = 8; + if(dir < -7) dir = -7; + + if(speed > 15) speed = 15; + if(speed < 0) speed = 0; + + char direction = dir + 7; + char modeH = mode ? 0x10 : 0x00; + char dirMode = direction + modeH; + char checksum = 0xff - speed - direction - modeH; + for(int i=0;i<3;i++){ + msg[i] = prefix[i]; + } + msg[3] = speed; + msg[4] = dirMode; + msg[5] = checksum; + for(int i=0;i<9;i++){ + msg[6+i] = fish_ID[i]; + } + return write(fd, msg, 15); + //return 0; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Main +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int main(int argc, char **argv) +{ + bool mode=false; //purpose? + float x_move=0; + float y_move=2; + int direction=0; + int speed=0; + int prevDirection=0; + int prevSpeed=0; + + fd = connectit(port0,115200); + if (fd != -1) { + isConnected = true; + ROS_INFO("Serial port ttyACM0 connected..."); + sleep(1); + tcflush(fd,TCIOFLUSH); + } + else { + ROS_ERROR("Error!: Serial port ttyACM0 not found!"); + } + + ros::init(argc, argv, "red_rofish_telemetry"); + ros::NodeHandle nh; + ros::Subscriber sub = nh.subscribe("red/cmd_vel", QUEUE_SIZE, velCallback); + ros::Rate loop_rate(LOOP_RATE); + + while(ros::ok()) { + ros::spinOnce(); + + //do processing here + if (ang_vel >= 0) { + direction = (char) 8*ang_vel; + } + if (ang_vel < 0) { + direction = (char) 7*ang_vel; + } + if (lin_vel >= 0){ + speed = (char) 15*lin_vel; + } + + writecommand(speed, direction, mode); + + if( (direction!=prevDirection) || (speed!=prevSpeed) ){ + ROS_INFO("direction=%d, speed=%d\n", direction, speed); + } + prevDirection = direction; + prevSpeed = speed; + + loop_rate.sleep(); + } +return 0; //never reaches here +} diff --git a/src/rofish_teleop_joy.cpp b/src/rofish_teleop_joy.cpp new file mode 100644 index 0000000..4b537f5 --- /dev/null +++ b/src/rofish_teleop_joy.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#define QUEUE_SIZE 64 //subscriber buffer size + +using namespace std; +float max_linear_vel = 1.0; +float max_angular_vel = 1.0; + +class TeleopJoy{ +public: + TeleopJoy(); +private: + void callBack(const sensor_msgs::Joy::ConstPtr& joy); + ros::NodeHandle n; + ros::Publisher pub; + ros::Subscriber sub; + int i_velLinear , i_velAngular; +}; + +TeleopJoy::TeleopJoy() +{ i_velLinear = 1; + i_velAngular = 0; + n.param("axis_linear", i_velLinear, i_velLinear); + n.param("axis_angular", i_velAngular, i_velAngular); + pub = n.advertise("cmd_vel", 1); + sub = n.subscribe("joy", QUEUE_SIZE, &TeleopJoy::callBack, this); +} + +void TeleopJoy::callBack(const sensor_msgs::Joy::ConstPtr& joy) +{ + geometry_msgs::Twist vel; + vel.angular.z = -max_angular_vel*joy->axes[2]; // right handle left-to-right + vel.linear.x = max_linear_vel*joy->axes[3]; // right handle up + pub.publish(vel); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "rofish_teleop_joy"); + TeleopJoy teleop_robot; + ros::spin(); +} diff --git a/src/yellow_rofish_telemetry.cpp b/src/yellow_rofish_telemetry.cpp new file mode 100644 index 0000000..4fedbf1 --- /dev/null +++ b/src/yellow_rofish_telemetry.cpp @@ -0,0 +1,186 @@ +#include "ros/ros.h" +#include "geometry_msgs/Twist.h" +#include +#include + +#define LOOP_RATE 20 //Hz +#define QUEUE_SIZE 64 //subscriber buffer size + + +// -------------- Serial Port ----------------- +int fd; +bool isConnected = false; +//const char *port0 = "/dev/ttyACM0"; //red +const char *port1 = "/dev/ttyACM1"; //yellow + +int connectit(const char *dev, int baud); +static void initTermios(int fd, uint32_t baud); +struct termios sTermios; +int writecommand(char speed, char dir, bool mode); + + +// --------------- Fish ID -------------------- +const unsigned char prefix[3] = { 0x21, 0x43, 0x00}; +//const unsigned char fish_ID[9] = { 0x52, 0x71, 0xa7, 0x29, 0xbc, 0xd6, 0xd9, 0x00, 0xe5}; //red +const unsigned char fish_ID[9] = { 0x52, 0x71, 0x63, 0x4c, 0xb9, 0xd6, 0xda, 0x00, 0xe5}; //yellow + + +// global vars +float lin_vel = 0; +float ang_vel = 0; + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Twist message Callback +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +void velCallback (const geometry_msgs::Twist::ConstPtr& vel_msg) { + + lin_vel = vel_msg->linear.x; //Get linear velocity from Twist message. + ang_vel = vel_msg->angular.z; //Get the direction from the Twist message. This is not a speed in reality, but steering action. +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* initTermios. Serial I/O +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +static void initTermios(int fd, uint32_t baud) +{ + tcgetattr(fd, &sTermios); /*Get the attributes set by default*/ + + /* ---------- Serial Port Config ------- */ + sTermios.c_cflag |=(CLOCAL|CREAD); + sTermios.c_cflag &= ~(CSTOPB|CSIZE); + sTermios.c_cflag &= ~(PARENB); + sTermios.c_cflag |= CS8; + sTermios.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG); + sTermios.c_cc[VMIN] = 0; + sTermios.c_cc[VTIME] = (unsigned int)(100); + sTermios.c_cc[VSTART] = 0x13; + sTermios.c_cc[VSTOP] = 0x19; + + sTermios.c_iflag &= ~(IXON|IXOFF|IXANY|ICRNL|INLCR); + sTermios.c_oflag &= ~OPOST; + cfsetispeed(&sTermios, baud); + cfsetospeed(&sTermios, baud); + /* -------- Serial Port Config END---- */ + + tcsetattr(fd, TCSANOW, &sTermios); +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* connectit. Open serial port +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int connectit(const char *dev, int baud) { + int fd; + fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fd == -1) { perror("serconnect "); return fd; } + initTermios(fd, baud); + return fd; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* writecommand +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int writecommand(char speed, char dir, bool mode) { + + char msg[15]; + if(!isConnected) return -1; + + if(dir > 8) dir = 8; + if(dir < -7) dir = -7; + + if(speed > 15) speed = 15; + if(speed < 0) speed = 0; + + char direction = dir + 7; + char modeH = mode ? 0x10 : 0x00; + char dirMode = direction + modeH; + char checksum = 0xff - speed - direction - modeH; + for(int i=0;i<3;i++){ + msg[i] = prefix[i]; + } + msg[3] = speed; + msg[4] = dirMode; + msg[5] = checksum; + for(int i=0;i<9;i++){ + msg[6+i] = fish_ID[i]; + } + return write(fd, msg, 15); + //return 0; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Main +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int main(int argc, char **argv) +{ + bool mode=false; //purpose? + float x_move=0; + float y_move=2; + int direction=0; + int speed=0; + int prevDirection=0; + int prevSpeed=0; + + fd = connectit(port1,115200); + if (fd != -1) { + isConnected = true; + ROS_INFO("Serial port ttyACM1 connected..."); + sleep(1); + tcflush(fd,TCIOFLUSH); + } + else { + ROS_ERROR("Error!: Serial port ttyACM1 not found!"); + } + + ros::init(argc, argv, "yellow_rofish_telemetry"); + ros::NodeHandle nh; + ros::Subscriber sub = nh.subscribe("yellow/cmd_vel", QUEUE_SIZE, velCallback); + ros::Rate loop_rate(LOOP_RATE); + + while(ros::ok()) { + ros::spinOnce(); + + //do processing here + if (ang_vel >= 0) { + direction = (char) 8*ang_vel; + } + if (ang_vel < 0) { + direction = (char) 7*ang_vel; + } + if (lin_vel >= 0){ + speed = (char) 15*lin_vel; + } + + writecommand(speed, direction, mode); + + if( (direction!=prevDirection) || (speed!=prevSpeed) ){ + ROS_INFO("direction=%d, speed=%d\n", direction, speed); + } + prevDirection = direction; + prevSpeed = speed; + + loop_rate.sleep(); + } +return 0; //never reaches here +}