|
|
@ -1,10 +1,10 @@
|
||||||
<launch>
|
<launch>
|
||||||
<!-- Select connecting device and serial port ,选择连接设备及串口-->
|
<!-- Select connecting device and serial port ,选择连接设备及串口-->
|
||||||
<arg name="port" default="/dev/ttyUSB0" />
|
<arg name="port" default="/dev/ttyAMA0" />
|
||||||
<arg name="baud" default="115200" />
|
<arg name="baud" default="115200" />
|
||||||
|
|
||||||
<!-- Open communication service --><!-- 开启通讯服务 -->
|
<!-- Open communication service --><!-- 开启通讯服务 -->
|
||||||
<node name="mycobot_services" pkg="mycobot_communication" type="mycobot_topics_pi.py" output="screen">
|
<node name="mycobot_services" pkg="mycobot_320_communication" type="mycobot_topics_pi.py" output="screen">
|
||||||
<param name="port" type="string" value="$(arg port)" />
|
<param name="port" type="string" value="$(arg port)" />
|
||||||
<param name="baud" type="int" value="$(arg baud)" />
|
<param name="baud" type="int" value="$(arg baud)" />
|
||||||
</node>
|
</node>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import time
|
import time
|
||||||
import rospy
|
import rospy
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
|
|
||||||
0
mycobot_320/mycobot_320_communication/scripts/mycobot_topics_jsnn.py
Normal file → Executable file
84
mycobot_320/mycobot_320_communication/scripts/mycobot_topics_pi.py
Normal file → Executable file
|
|
@ -1,10 +1,11 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import signal
|
import signal
|
||||||
import threading
|
import threading
|
||||||
|
import fcntl
|
||||||
|
|
||||||
import rospy
|
import rospy
|
||||||
|
|
||||||
|
|
@ -19,9 +20,45 @@ from mycobot_communication.msg import (
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from pymycobot import MyCobotSocket
|
from pymycobot import MyCobot
|
||||||
|
|
||||||
|
|
||||||
|
# Avoid serial port conflicts and need to be locked
|
||||||
|
def acquire(lock_file):
|
||||||
|
open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC
|
||||||
|
fd = os.open(lock_file, open_mode)
|
||||||
|
|
||||||
|
pid = os.getpid()
|
||||||
|
lock_file_fd = None
|
||||||
|
|
||||||
|
timeout = 50.0
|
||||||
|
start_time = current_time = time.time()
|
||||||
|
while current_time < start_time + timeout:
|
||||||
|
try:
|
||||||
|
# The LOCK_EX means that only one process can hold the lock
|
||||||
|
# The LOCK_NB means that the fcntl.flock() is not blocking
|
||||||
|
# and we are able to implement termination of while loop,
|
||||||
|
# when timeout is reached.
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
except (IOError, OSError):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
lock_file_fd = fd
|
||||||
|
break
|
||||||
|
print('pid waiting for lock:%d'% pid)
|
||||||
|
time.sleep(1.0)
|
||||||
|
current_time = time.time()
|
||||||
|
if lock_file_fd is None:
|
||||||
|
os.close(fd)
|
||||||
|
return lock_file_fd
|
||||||
|
|
||||||
|
|
||||||
|
def release(lock_file_fd):
|
||||||
|
# Do not remove the lockfile:
|
||||||
|
fcntl.flock(lock_file_fd, fcntl.LOCK_UN)
|
||||||
|
os.close(lock_file_fd)
|
||||||
|
return None
|
||||||
|
|
||||||
class Watcher:
|
class Watcher:
|
||||||
"""this class solves two problems with multithreaded
|
"""this class solves two problems with multithreaded
|
||||||
programs in Python, (1) a signal might be delivered
|
programs in Python, (1) a signal might be delivered
|
||||||
|
|
@ -74,11 +111,10 @@ class MycobotTopics(object):
|
||||||
rospy.init_node("mycobot_topics_pi")
|
rospy.init_node("mycobot_topics_pi")
|
||||||
rospy.loginfo("start ...")
|
rospy.loginfo("start ...")
|
||||||
# problem
|
# problem
|
||||||
port = rospy.get_param("~port", "/dev/ttyUSB0")
|
port = rospy.get_param("~port", "/dev/ttyAMA0")
|
||||||
baud = rospy.get_param("~baud", 115200)
|
baud = rospy.get_param("~baud", 115200)
|
||||||
rospy.loginfo("%s,%s" % (port, baud))
|
rospy.loginfo("%s,%s" % (port, baud))
|
||||||
self.mc = MyCobotSocket(port, baud) # port
|
self.mc = MyCobot(port, baud) # port
|
||||||
self.mc.connect() #pi
|
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
|
@ -115,9 +151,12 @@ class MycobotTopics(object):
|
||||||
pub = rospy.Publisher("mycobot/angles_real", MycobotAngles, queue_size=5)
|
pub = rospy.Publisher("mycobot/angles_real", MycobotAngles, queue_size=5)
|
||||||
ma = MycobotAngles()
|
ma = MycobotAngles()
|
||||||
while not rospy.is_shutdown():
|
while not rospy.is_shutdown():
|
||||||
self.lock.acquire()
|
if self.mc:
|
||||||
angles = self.mc.get_angles()
|
# self.lock.acquire()
|
||||||
self.lock.release()
|
lock = acquire("/tmp/mycobot_lock")
|
||||||
|
angles = self.mc.get_angles()
|
||||||
|
release(lock)
|
||||||
|
# self.lock.release()
|
||||||
if angles:
|
if angles:
|
||||||
ma.joint_1 = angles[0]
|
ma.joint_1 = angles[0]
|
||||||
ma.joint_2 = angles[1]
|
ma.joint_2 = angles[1]
|
||||||
|
|
@ -135,9 +174,12 @@ class MycobotTopics(object):
|
||||||
ma = MycobotCoords()
|
ma = MycobotCoords()
|
||||||
|
|
||||||
while not rospy.is_shutdown():
|
while not rospy.is_shutdown():
|
||||||
self.lock.acquire()
|
# self.lock.acquire()
|
||||||
coords = self.mc.get_coords()
|
if self.mc:
|
||||||
self.lock.release()
|
lock = acquire("/tmp/mycobot_lock")
|
||||||
|
coords = self.mc.get_coords()
|
||||||
|
# self.lock.release()
|
||||||
|
release(lock)
|
||||||
if coords:
|
if coords:
|
||||||
ma.x = coords[0]
|
ma.x = coords[0]
|
||||||
ma.y = coords[1]
|
ma.y = coords[1]
|
||||||
|
|
@ -161,7 +203,10 @@ class MycobotTopics(object):
|
||||||
data.joint_6,
|
data.joint_6,
|
||||||
]
|
]
|
||||||
sp = int(data.speed)
|
sp = int(data.speed)
|
||||||
self.mc.send_angles(angles, sp)
|
if self.mc:
|
||||||
|
lock = acquire("/tmp/mycobot_lock")
|
||||||
|
self.mc.send_angles(angles, sp)
|
||||||
|
release(lock)
|
||||||
|
|
||||||
sub = rospy.Subscriber(
|
sub = rospy.Subscriber(
|
||||||
"mycobot/angles_goal", MycobotSetAngles, callback=callback
|
"mycobot/angles_goal", MycobotSetAngles, callback=callback
|
||||||
|
|
@ -173,7 +218,10 @@ class MycobotTopics(object):
|
||||||
angles = [data.x, data.y, data.z, data.rx, data.ry, data.rz]
|
angles = [data.x, data.y, data.z, data.rx, data.ry, data.rz]
|
||||||
sp = int(data.speed)
|
sp = int(data.speed)
|
||||||
model = int(data.model)
|
model = int(data.model)
|
||||||
self.mc.send_coords(angles, sp, model)
|
if self.mc:
|
||||||
|
lock = acquire("/tmp/mycobot_lock")
|
||||||
|
self.mc.send_coords(angles, sp, model)
|
||||||
|
release(lock)
|
||||||
|
|
||||||
sub = rospy.Subscriber(
|
sub = rospy.Subscriber(
|
||||||
"mycobot/coords_goal", MycobotSetCoords, callback=callback
|
"mycobot/coords_goal", MycobotSetCoords, callback=callback
|
||||||
|
|
@ -185,9 +233,15 @@ class MycobotTopics(object):
|
||||||
"""订阅夹爪状态"""
|
"""订阅夹爪状态"""
|
||||||
def callback(data):
|
def callback(data):
|
||||||
if data.Status:
|
if data.Status:
|
||||||
self.mc.set_gripper_state(0, 80)
|
if self.mc:
|
||||||
|
lock = acquire("/tmp/mycobot_lock")
|
||||||
|
self.mc.set_gripper_state(0, 80)
|
||||||
|
release(lock)
|
||||||
else:
|
else:
|
||||||
self.mc.set_gripper_state(1, 80)
|
if self.mc:
|
||||||
|
lock = acquire("/tmp/mycobot_lock")
|
||||||
|
self.mc.set_gripper_state(1, 80)
|
||||||
|
release(lock)
|
||||||
|
|
||||||
sub = rospy.Subscriber(
|
sub = rospy.Subscriber(
|
||||||
"mycobot/gripper_status", MycobotGripperStatus, callback=callback
|
"mycobot/gripper_status", MycobotGripperStatus, callback=callback
|
||||||
|
|
|
||||||
0
mycobot_320/mycobot_320_communication/scripts/mycobot_topics_seeed.py
Normal file → Executable file
205
mycobot_ai/aikit_320_pi/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0.2)
|
||||||
|
project(aikit_320_pi)
|
||||||
|
|
||||||
|
## 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
|
||||||
|
new_mycobot_320
|
||||||
|
new_mycobot_320_pi
|
||||||
|
)
|
||||||
|
|
||||||
|
## 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 # Or other packages containing 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 mycobot_ai
|
||||||
|
# CATKIN_DEPENDS mycobot_280
|
||||||
|
# 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}/mycobot_ai.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/mycobot_ai_node.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}
|
||||||
|
# )
|
||||||
|
|
||||||
|
#############
|
||||||
|
## 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
|
||||||
|
# catkin_install_python(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_mycobot_ai.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)
|
||||||
226
mycobot_ai/aikit_320_pi/config/ai_mycobot_pi.rviz
Executable file
|
|
@ -0,0 +1,226 @@
|
||||||
|
Panels:
|
||||||
|
- Class: rviz/Displays
|
||||||
|
Help Height: 78
|
||||||
|
Name: Displays
|
||||||
|
Property Tree Widget:
|
||||||
|
Expanded:
|
||||||
|
- /Global Options1
|
||||||
|
- /Status1
|
||||||
|
- /RobotModel1
|
||||||
|
- /TF1
|
||||||
|
- /Marker1
|
||||||
|
Splitter Ratio: 0.5
|
||||||
|
Tree Height: 579
|
||||||
|
- Class: rviz/Selection
|
||||||
|
Name: Selection
|
||||||
|
- Class: rviz/Tool Properties
|
||||||
|
Expanded:
|
||||||
|
- /2D Pose Estimate1
|
||||||
|
- /2D Nav Goal1
|
||||||
|
- /Publish Point1
|
||||||
|
Name: Tool Properties
|
||||||
|
Splitter Ratio: 0.5886790156364441
|
||||||
|
- Class: rviz/Views
|
||||||
|
Expanded:
|
||||||
|
- /Current View1
|
||||||
|
Name: Views
|
||||||
|
Splitter Ratio: 0.5
|
||||||
|
- Class: rviz/Time
|
||||||
|
Name: Time
|
||||||
|
SyncMode: 0
|
||||||
|
SyncSource: ""
|
||||||
|
Preferences:
|
||||||
|
PromptSaveOnExit: true
|
||||||
|
Toolbars:
|
||||||
|
toolButtonStyle: 2
|
||||||
|
Visualization Manager:
|
||||||
|
Class: ""
|
||||||
|
Displays:
|
||||||
|
- Alpha: 0.5
|
||||||
|
Cell Size: 1
|
||||||
|
Class: rviz/Grid
|
||||||
|
Color: 160; 160; 164
|
||||||
|
Enabled: true
|
||||||
|
Line Style:
|
||||||
|
Line Width: 0.029999999329447746
|
||||||
|
Value: Lines
|
||||||
|
Name: Grid
|
||||||
|
Normal Cell Count: 0
|
||||||
|
Offset:
|
||||||
|
X: 0
|
||||||
|
Y: 0
|
||||||
|
Z: 0
|
||||||
|
Plane: XY
|
||||||
|
Plane Cell Count: 10
|
||||||
|
Reference Frame: <Fixed Frame>
|
||||||
|
Value: true
|
||||||
|
- Alpha: 1
|
||||||
|
Class: rviz/RobotModel
|
||||||
|
Collision Enabled: false
|
||||||
|
Enabled: true
|
||||||
|
Links:
|
||||||
|
All Links Enabled: true
|
||||||
|
Expand Joint Details: false
|
||||||
|
Expand Link Details: false
|
||||||
|
Expand Tree: false
|
||||||
|
Link Tree Style: Links in Alphabetic Order
|
||||||
|
env:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint1:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint2:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint3:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint4:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint5:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint6:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
joint6_flange:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
Name: RobotModel
|
||||||
|
Robot Description: robot_description
|
||||||
|
TF Prefix: ""
|
||||||
|
Update Interval: 0
|
||||||
|
Value: true
|
||||||
|
Visual Enabled: true
|
||||||
|
- Class: rviz/TF
|
||||||
|
Enabled: true
|
||||||
|
Frame Timeout: 15
|
||||||
|
Frames:
|
||||||
|
All Enabled: true
|
||||||
|
env:
|
||||||
|
Value: true
|
||||||
|
joint1:
|
||||||
|
Value: true
|
||||||
|
joint2:
|
||||||
|
Value: true
|
||||||
|
joint3:
|
||||||
|
Value: true
|
||||||
|
joint4:
|
||||||
|
Value: true
|
||||||
|
joint5:
|
||||||
|
Value: true
|
||||||
|
joint6:
|
||||||
|
Value: true
|
||||||
|
joint6_flange:
|
||||||
|
Value: true
|
||||||
|
Marker Alpha: 1
|
||||||
|
Marker Scale: 0.30000001192092896
|
||||||
|
Name: TF
|
||||||
|
Show Arrows: true
|
||||||
|
Show Axes: true
|
||||||
|
Show Names: true
|
||||||
|
Tree:
|
||||||
|
joint1:
|
||||||
|
env:
|
||||||
|
{}
|
||||||
|
joint2:
|
||||||
|
joint3:
|
||||||
|
joint4:
|
||||||
|
joint5:
|
||||||
|
joint6:
|
||||||
|
joint6_flange:
|
||||||
|
{}
|
||||||
|
Update Interval: 0
|
||||||
|
Value: true
|
||||||
|
- Class: rviz/Marker
|
||||||
|
Enabled: true
|
||||||
|
Marker Topic: cube
|
||||||
|
Name: Marker
|
||||||
|
Namespaces:
|
||||||
|
{}
|
||||||
|
Queue Size: 100
|
||||||
|
Value: true
|
||||||
|
Enabled: true
|
||||||
|
Global Options:
|
||||||
|
Background Color: 48; 48; 48
|
||||||
|
Default Light: true
|
||||||
|
Fixed Frame: joint1
|
||||||
|
Frame Rate: 30
|
||||||
|
Name: root
|
||||||
|
Tools:
|
||||||
|
- Class: rviz/Interact
|
||||||
|
Hide Inactive Objects: true
|
||||||
|
- Class: rviz/MoveCamera
|
||||||
|
- Class: rviz/Select
|
||||||
|
- Class: rviz/FocusCamera
|
||||||
|
- Class: rviz/Measure
|
||||||
|
- Class: rviz/SetInitialPose
|
||||||
|
Theta std deviation: 0.2617993950843811
|
||||||
|
Topic: /initialpose
|
||||||
|
X std deviation: 0.5
|
||||||
|
Y std deviation: 0.5
|
||||||
|
- Class: rviz/SetGoal
|
||||||
|
Topic: /move_base_simple/goal
|
||||||
|
- Class: rviz/PublishPoint
|
||||||
|
Single click: true
|
||||||
|
Topic: /clicked_point
|
||||||
|
Value: true
|
||||||
|
Views:
|
||||||
|
Current:
|
||||||
|
Class: rviz/Orbit
|
||||||
|
Distance: 1.0433008670806885
|
||||||
|
Enable Stereo Rendering:
|
||||||
|
Stereo Eye Separation: 0.05999999865889549
|
||||||
|
Stereo Focal Distance: 1
|
||||||
|
Swap Stereo Eyes: false
|
||||||
|
Value: false
|
||||||
|
Field of View: 0.7853981852531433
|
||||||
|
Focal Point:
|
||||||
|
X: -0.07064759731292725
|
||||||
|
Y: -0.0814988762140274
|
||||||
|
Z: 0.10758385062217712
|
||||||
|
Focal Shape Fixed Size: true
|
||||||
|
Focal Shape Size: 0.05000000074505806
|
||||||
|
Invert Z Axis: false
|
||||||
|
Name: Current View
|
||||||
|
Near Clip Distance: 0.009999999776482582
|
||||||
|
Pitch: 0.3703983426094055
|
||||||
|
Target Frame: <Fixed Frame>
|
||||||
|
Yaw: 0.555390477180481
|
||||||
|
Saved: ~
|
||||||
|
Window Geometry:
|
||||||
|
Displays:
|
||||||
|
collapsed: false
|
||||||
|
Height: 876
|
||||||
|
Hide Left Dock: false
|
||||||
|
Hide Right Dock: false
|
||||||
|
QMainWindow State: 000000ff00000000fd00000004000000000000016a000002cefc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002ce000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c0000026100000001000001c2000002cefc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002ce000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007380000003efc0100000002fb0000000800540069006d0065010000000000000738000003bc00fffffffb0000000800540069006d0065010000000000000450000000000000000000000400000002ce00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
|
||||||
|
Selection:
|
||||||
|
collapsed: false
|
||||||
|
Time:
|
||||||
|
collapsed: false
|
||||||
|
Tool Properties:
|
||||||
|
collapsed: false
|
||||||
|
Views:
|
||||||
|
collapsed: false
|
||||||
|
Width: 1848
|
||||||
|
X: 72
|
||||||
|
Y: 27
|
||||||
229
mycobot_ai/aikit_320_pi/config/aikit_320_pi.rviz
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
Panels:
|
||||||
|
- Class: rviz/Displays
|
||||||
|
Help Height: 78
|
||||||
|
Name: Displays
|
||||||
|
Property Tree Widget:
|
||||||
|
Expanded:
|
||||||
|
- /Global Options1
|
||||||
|
- /Status1
|
||||||
|
- /RobotModel1
|
||||||
|
- /TF1
|
||||||
|
- /TF1/Tree1
|
||||||
|
- /Marker1
|
||||||
|
Splitter Ratio: 0.5
|
||||||
|
Tree Height: 603
|
||||||
|
- Class: rviz/Selection
|
||||||
|
Name: Selection
|
||||||
|
- Class: rviz/Tool Properties
|
||||||
|
Expanded:
|
||||||
|
- /2D Pose Estimate1
|
||||||
|
- /2D Nav Goal1
|
||||||
|
- /Publish Point1
|
||||||
|
Name: Tool Properties
|
||||||
|
Splitter Ratio: 0.5886790156364441
|
||||||
|
- Class: rviz/Views
|
||||||
|
Expanded:
|
||||||
|
- /Current View1
|
||||||
|
Name: Views
|
||||||
|
Splitter Ratio: 0.5
|
||||||
|
- Class: rviz/Time
|
||||||
|
Name: Time
|
||||||
|
SyncMode: 0
|
||||||
|
SyncSource: ""
|
||||||
|
Preferences:
|
||||||
|
PromptSaveOnExit: true
|
||||||
|
Toolbars:
|
||||||
|
toolButtonStyle: 2
|
||||||
|
Visualization Manager:
|
||||||
|
Class: ""
|
||||||
|
Displays:
|
||||||
|
- Alpha: 0.5
|
||||||
|
Cell Size: 1
|
||||||
|
Class: rviz/Grid
|
||||||
|
Color: 160; 160; 164
|
||||||
|
Enabled: true
|
||||||
|
Line Style:
|
||||||
|
Line Width: 0.029999999329447746
|
||||||
|
Value: Lines
|
||||||
|
Name: Grid
|
||||||
|
Normal Cell Count: 0
|
||||||
|
Offset:
|
||||||
|
X: 0
|
||||||
|
Y: 0
|
||||||
|
Z: 0
|
||||||
|
Plane: XY
|
||||||
|
Plane Cell Count: 10
|
||||||
|
Reference Frame: <Fixed Frame>
|
||||||
|
Value: true
|
||||||
|
- Alpha: 1
|
||||||
|
Class: rviz/RobotModel
|
||||||
|
Collision Enabled: false
|
||||||
|
Enabled: true
|
||||||
|
Links:
|
||||||
|
All Links Enabled: true
|
||||||
|
Expand Joint Details: false
|
||||||
|
Expand Link Details: false
|
||||||
|
Expand Tree: false
|
||||||
|
Link Tree Style: Links in Alphabetic Order
|
||||||
|
base:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
env:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
link1:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
link2:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
link3:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
link4:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
link5:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
link6:
|
||||||
|
Alpha: 1
|
||||||
|
Show Axes: false
|
||||||
|
Show Trail: false
|
||||||
|
Value: true
|
||||||
|
Name: RobotModel
|
||||||
|
Robot Description: robot_description
|
||||||
|
TF Prefix: ""
|
||||||
|
Update Interval: 0
|
||||||
|
Value: true
|
||||||
|
Visual Enabled: true
|
||||||
|
- Class: rviz/TF
|
||||||
|
Enabled: true
|
||||||
|
Filter (blacklist): ""
|
||||||
|
Filter (whitelist): ""
|
||||||
|
Frame Timeout: 15
|
||||||
|
Frames:
|
||||||
|
All Enabled: true
|
||||||
|
base:
|
||||||
|
Value: true
|
||||||
|
env:
|
||||||
|
Value: true
|
||||||
|
link1:
|
||||||
|
Value: true
|
||||||
|
link2:
|
||||||
|
Value: true
|
||||||
|
link3:
|
||||||
|
Value: true
|
||||||
|
link4:
|
||||||
|
Value: true
|
||||||
|
link5:
|
||||||
|
Value: true
|
||||||
|
link6:
|
||||||
|
Value: true
|
||||||
|
Marker Alpha: 1
|
||||||
|
Marker Scale: 0.20000000298023224
|
||||||
|
Name: TF
|
||||||
|
Show Arrows: true
|
||||||
|
Show Axes: true
|
||||||
|
Show Names: true
|
||||||
|
Tree:
|
||||||
|
base:
|
||||||
|
env:
|
||||||
|
{}
|
||||||
|
link1:
|
||||||
|
link2:
|
||||||
|
link3:
|
||||||
|
link4:
|
||||||
|
link5:
|
||||||
|
link6:
|
||||||
|
{}
|
||||||
|
Update Interval: 0
|
||||||
|
Value: true
|
||||||
|
- Class: rviz/Marker
|
||||||
|
Enabled: true
|
||||||
|
Marker Topic: cube
|
||||||
|
Name: Marker
|
||||||
|
Namespaces:
|
||||||
|
{}
|
||||||
|
Queue Size: 100
|
||||||
|
Value: true
|
||||||
|
Enabled: true
|
||||||
|
Global Options:
|
||||||
|
Background Color: 48; 48; 48
|
||||||
|
Default Light: true
|
||||||
|
Fixed Frame: base
|
||||||
|
Frame Rate: 30
|
||||||
|
Name: root
|
||||||
|
Tools:
|
||||||
|
- Class: rviz/Interact
|
||||||
|
Hide Inactive Objects: true
|
||||||
|
- Class: rviz/MoveCamera
|
||||||
|
- Class: rviz/Select
|
||||||
|
- Class: rviz/FocusCamera
|
||||||
|
- Class: rviz/Measure
|
||||||
|
- Class: rviz/SetInitialPose
|
||||||
|
Theta std deviation: 0.2617993950843811
|
||||||
|
Topic: /initialpose
|
||||||
|
X std deviation: 0.5
|
||||||
|
Y std deviation: 0.5
|
||||||
|
- Class: rviz/SetGoal
|
||||||
|
Topic: /move_base_simple/goal
|
||||||
|
- Class: rviz/PublishPoint
|
||||||
|
Single click: true
|
||||||
|
Topic: /clicked_point
|
||||||
|
Value: true
|
||||||
|
Views:
|
||||||
|
Current:
|
||||||
|
Class: rviz/Orbit
|
||||||
|
Distance: 1.4485745429992676
|
||||||
|
Enable Stereo Rendering:
|
||||||
|
Stereo Eye Separation: 0.05999999865889549
|
||||||
|
Stereo Focal Distance: 1
|
||||||
|
Swap Stereo Eyes: false
|
||||||
|
Value: false
|
||||||
|
Field of View: 0.7853981852531433
|
||||||
|
Focal Point:
|
||||||
|
X: 0
|
||||||
|
Y: 0
|
||||||
|
Z: 0
|
||||||
|
Focal Shape Fixed Size: true
|
||||||
|
Focal Shape Size: 0.05000000074505806
|
||||||
|
Invert Z Axis: false
|
||||||
|
Name: Current View
|
||||||
|
Near Clip Distance: 0.009999999776482582
|
||||||
|
Pitch: 0.834796667098999
|
||||||
|
Target Frame: <Fixed Frame>
|
||||||
|
Yaw: 0.6185896992683411
|
||||||
|
Saved: ~
|
||||||
|
Window Geometry:
|
||||||
|
Displays:
|
||||||
|
collapsed: false
|
||||||
|
Height: 900
|
||||||
|
Hide Left Dock: false
|
||||||
|
Hide Right Dock: false
|
||||||
|
QMainWindow State: 000000ff00000000fd00000004000000000000016a000002e6fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002e6000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002e6fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002e6000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007380000003efc0100000002fb0000000800540069006d0065010000000000000738000003bc00fffffffb0000000800540069006d00650100000000000004500000000000000000000004b3000002e600000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
|
||||||
|
Selection:
|
||||||
|
collapsed: false
|
||||||
|
Time:
|
||||||
|
collapsed: false
|
||||||
|
Tool Properties:
|
||||||
|
collapsed: false
|
||||||
|
Views:
|
||||||
|
collapsed: false
|
||||||
|
Width: 1848
|
||||||
|
X: 72
|
||||||
|
Y: 27
|
||||||
16
mycobot_ai/aikit_320_pi/launch/test.launch
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<launch>
|
||||||
|
<arg name="model" default="$(find mycobot_description)/urdf/new_320_pi/new_mycobot_vision_v2.urdf"/>
|
||||||
|
<arg name="rvizconfig" default="$(find aikit_320_pi)/config/aikit_320_pi.rviz" />
|
||||||
|
<arg name="gui" default="true" />
|
||||||
|
|
||||||
|
<param name="robot_description" command="$(find xacro)/xacro --inorder $(arg model)" />
|
||||||
|
|
||||||
|
<!-- Combinejoin values to TF -->
|
||||||
|
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
|
||||||
|
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
|
||||||
|
<param name="use_gui" value="$(arg gui)" />
|
||||||
|
<!-- <rosparam param="source_list" subst_value="true">["joint_states"]</rosparam> -->
|
||||||
|
</node>
|
||||||
|
<!-- Show in Rviz ,显示在Rviz-->
|
||||||
|
<node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" />
|
||||||
|
</launch>
|
||||||
28
mycobot_ai/aikit_320_pi/launch/vision_pi.launch
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<launch>
|
||||||
|
<arg name="port" default="/dev/ttyAMA0" />
|
||||||
|
<arg name="baud" default="115200" />
|
||||||
|
|
||||||
|
<!-- <arg name="model" default="$(find mycobot_description)/urdf/mycobot/mycobot_with_vision.urdf"/> -->
|
||||||
|
<arg name="model" default="$(find mycobot_description)/urdf/new_320_pi/new_mycobot_vision_v2.urdf"/>
|
||||||
|
<arg name="rvizconfig" default="$(find aikit_320_pi)/config/aikit_320_pi.rviz" />
|
||||||
|
<!-- <arg name="gui" default="false" /> -->
|
||||||
|
|
||||||
|
<param name="robot_description" command="$(find xacro)/xacro --inorder $(arg model)" />
|
||||||
|
|
||||||
|
<!-- Combinejoin values to TF -->
|
||||||
|
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" >
|
||||||
|
<rosparam param="source_list" subst_value="true">["joint_states"]</rosparam>
|
||||||
|
</node>
|
||||||
|
|
||||||
|
<!-- mycobot-topics -->
|
||||||
|
<include file="$(find mycobot_320_communication)/launch/communication_topic_pi.launch">
|
||||||
|
<arg name="port" value="$(arg port)" />
|
||||||
|
<arg name="baud" value="$(arg baud)" />
|
||||||
|
</include>
|
||||||
|
|
||||||
|
<!-- listen and pub the real angles -->
|
||||||
|
<node name="real_listener" pkg="new_mycobot_320_pi" type="mycobot_320_listen_real_of_topic.py" />
|
||||||
|
|
||||||
|
<!-- Show in Rviz -->
|
||||||
|
<node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" />
|
||||||
|
</launch>
|
||||||
BIN
mycobot_ai/aikit_320_pi/local_photo/goal5.jpeg
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
mycobot_ai/aikit_320_pi/local_photo/img/goal01.jpeg
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
mycobot_ai/aikit_320_pi/local_photo/img/goal03.jpeg
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
mycobot_ai/aikit_320_pi/local_photo/img/goal2.jpeg
Normal file
|
After Width: | Height: | Size: 5 KiB |
BIN
mycobot_ai/aikit_320_pi/local_photo/takephoto.jpeg
Normal file
|
After Width: | Height: | Size: 50 KiB |
62
mycobot_ai/aikit_320_pi/package.xml
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<package format="2">
|
||||||
|
<name>aikit_320_pi</name>
|
||||||
|
<version>0.0.0</version>
|
||||||
|
<description>The aikit_320_pi package</description>
|
||||||
|
|
||||||
|
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||||
|
<!-- Example: -->
|
||||||
|
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
|
||||||
|
<maintainer email="wang@todo.todo">wang</maintainer>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||||
|
<!-- Commonly used license strings: -->
|
||||||
|
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||||
|
<license>TODO</license>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Url tags are optional, but multiple are allowed, one per tag -->
|
||||||
|
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||||
|
<!-- Example: -->
|
||||||
|
<!-- <url type="website">http://wiki.ros.org/mycobot_ai</url> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Author tags are optional, multiple are allowed, one per tag -->
|
||||||
|
<!-- Authors do not have to be maintainers, but could be -->
|
||||||
|
<!-- Example: -->
|
||||||
|
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- The *depend tags are used to specify dependencies -->
|
||||||
|
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||||
|
<!-- Examples: -->
|
||||||
|
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
|
||||||
|
<!-- <depend>roscpp</depend> -->
|
||||||
|
<!-- Note that this is equivalent to the following: -->
|
||||||
|
<!-- <build_depend>roscpp</build_depend> -->
|
||||||
|
<!-- <exec_depend>roscpp</exec_depend> -->
|
||||||
|
<!-- Use build_depend for packages you need at compile time: -->
|
||||||
|
<!-- <build_depend>message_generation</build_depend> -->
|
||||||
|
<!-- Use build_export_depend for packages you need in order to build against this package: -->
|
||||||
|
<!-- <build_export_depend>message_generation</build_export_depend> -->
|
||||||
|
<!-- Use buildtool_depend for build tool packages: -->
|
||||||
|
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||||
|
<!-- Use exec_depend for packages you need at runtime: -->
|
||||||
|
<!-- <exec_depend>message_runtime</exec_depend> -->
|
||||||
|
<!-- Use test_depend for packages you need only for testing: -->
|
||||||
|
<!-- <test_depend>gtest</test_depend> -->
|
||||||
|
<!-- Use doc_depend for packages you need only for building documentation: -->
|
||||||
|
<!-- <doc_depend>doxygen</doc_depend> -->
|
||||||
|
<buildtool_depend>catkin</buildtool_depend>
|
||||||
|
<build_depend>new_mycobot_320</build_depend>
|
||||||
|
<build_export_depend>new_mycobot_320</build_export_depend>
|
||||||
|
<exec_depend>new_mycobot_320</exec_depend>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- The export tag contains other, unspecified, tags -->
|
||||||
|
<export>
|
||||||
|
<!-- Other tools can request additional information be placed here -->
|
||||||
|
|
||||||
|
</export>
|
||||||
|
</package>
|
||||||
21703
mycobot_ai/aikit_320_pi/prof.calltree
Normal file
BIN
mycobot_ai/aikit_320_pi/prof.out
Normal file
BIN
mycobot_ai/aikit_320_pi/res/A/goal1.jpeg
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
mycobot_ai/aikit_320_pi/res/A/goal2.jpeg
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
mycobot_ai/aikit_320_pi/res/A/goal3.jpeg
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
mycobot_ai/aikit_320_pi/res/A/goal4.jpeg
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
mycobot_ai/aikit_320_pi/res/A/goal5.jpeg
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
mycobot_ai/aikit_320_pi/res/A/goal6.jpeg
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
mycobot_ai/aikit_320_pi/res/A/goal7.jpeg
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
mycobot_ai/aikit_320_pi/res/B/goal13.jpeg
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
mycobot_ai/aikit_320_pi/res/B/goal14.jpeg
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
mycobot_ai/aikit_320_pi/res/B/goal15.jpeg
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
mycobot_ai/aikit_320_pi/res/B/goal4.jpeg
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
mycobot_ai/aikit_320_pi/res/B/goal5.jpeg
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
mycobot_ai/aikit_320_pi/res/B/goal6.jpeg
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal1.jpeg
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal2.jpeg
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal3.jpeg
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal4.jpeg
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal5.jpeg
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal6.jpeg
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
mycobot_ai/aikit_320_pi/res/C/goal7.jpeg
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal1.jpeg
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal2.jpeg
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal3.jpeg
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal4.jpeg
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal5.jpeg
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal6.jpeg
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
mycobot_ai/aikit_320_pi/res/D/goal7.jpeg
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
mycobot_ai/aikit_320_pi/res/takephoto.jpeg
Normal file
|
After Width: | Height: | Size: 52 KiB |
13
mycobot_ai/aikit_320_pi/scripts/OpenVideo.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
|
||||||
|
cap = cv2.VideoCapture(0)
|
||||||
|
cap.set(3,640)
|
||||||
|
cap.set(4,480)
|
||||||
|
|
||||||
|
while cv2.waitKey(1)<0:
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if not ret:
|
||||||
|
break
|
||||||
|
cv2.imshow('', frame)
|
||||||
|
|
||||||
127
mycobot_ai/aikit_320_pi/scripts/add_img.py
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
# coding:utf-8
|
||||||
|
from fileinput import filename
|
||||||
|
import os, cv2, sys
|
||||||
|
|
||||||
|
|
||||||
|
def take_photo():
|
||||||
|
# 提醒用户操作字典
|
||||||
|
print("************************************************")
|
||||||
|
print("* 热键(请在摄像头的窗口使用): *")
|
||||||
|
print("* hotkey(please use it in the camera window): *")
|
||||||
|
print("* z: 拍摄图片(take picture) *")
|
||||||
|
print("* q: 退出(quit) *")
|
||||||
|
print("************************************************")
|
||||||
|
|
||||||
|
# 创建/使用local_photo文件夹
|
||||||
|
class_name = "res"
|
||||||
|
if (os.path.exists("res")):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
os.mkdir(class_name)
|
||||||
|
|
||||||
|
# 设置特定值
|
||||||
|
|
||||||
|
index = 'takephoto'
|
||||||
|
cap = cv2.VideoCapture(0)
|
||||||
|
cap.set(3,640)
|
||||||
|
cap.set(4, 480)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# 读入每一帧
|
||||||
|
ret, frame = cap.read()
|
||||||
|
|
||||||
|
cv2.imshow("capture", frame)
|
||||||
|
|
||||||
|
# 存储
|
||||||
|
input = cv2.waitKey(1) & 0xFF
|
||||||
|
# 拍照
|
||||||
|
if input == ord('z'):
|
||||||
|
cv2.imwrite(
|
||||||
|
"%s/%s.jpeg" % (class_name, index),
|
||||||
|
cv2.resize(frame, (600, 480), interpolation=cv2.INTER_AREA))
|
||||||
|
break
|
||||||
|
|
||||||
|
# 退出
|
||||||
|
if input == ord('q'):
|
||||||
|
|
||||||
|
# 关闭窗口
|
||||||
|
cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
|
def cut_photo():
|
||||||
|
|
||||||
|
path = '/home/er/catkin_ws/src/mycobot_ros/mycobot_ai/aikit_320_pi' # pi
|
||||||
|
|
||||||
|
path_red = path + '/res/A'
|
||||||
|
for i, j, k in os.walk(path_red):
|
||||||
|
file_len_red = len(k)
|
||||||
|
|
||||||
|
path_gray = path + '/res/B'
|
||||||
|
for i, j, k in os.walk(path_gray):
|
||||||
|
file_len_gray = len(k)
|
||||||
|
|
||||||
|
path_green = path + '/res/C'
|
||||||
|
for i, j, k in os.walk(path_green):
|
||||||
|
file_len_green = len(k)
|
||||||
|
|
||||||
|
path_blue = path + '/res/D'
|
||||||
|
for i, j, k in os.walk(path_blue):
|
||||||
|
file_len_blue = len(k)
|
||||||
|
print("请截取要识别的部分")
|
||||||
|
print("Please intercept the part to be identified")
|
||||||
|
|
||||||
|
cut = cv2.imread(r"res/takephoto.jpeg")
|
||||||
|
|
||||||
|
cv2.imshow('original', cut)
|
||||||
|
|
||||||
|
# 选择ROI
|
||||||
|
roi = cv2.selectROI(windowName="original",
|
||||||
|
img=cut,
|
||||||
|
showCrosshair=False,
|
||||||
|
fromCenter=False)
|
||||||
|
x, y, w, h = roi
|
||||||
|
print(roi)
|
||||||
|
|
||||||
|
msg = """\
|
||||||
|
Image save location:
|
||||||
|
1 - 保存至A分拣区文件夹 Save to A folder
|
||||||
|
2 - 保存至B分拣区文件夹 Save to B folder
|
||||||
|
3 - 保存至C分拣区文件夹 Save to C folder
|
||||||
|
4 - 保存至D分拣区文件夹 Save to D folder
|
||||||
|
"""
|
||||||
|
print(msg)
|
||||||
|
kw = int(input("请输入保存图片文件夹数字编号(Please enter the number of the folder to save the picture):"))
|
||||||
|
# print(kw)
|
||||||
|
|
||||||
|
# 显示ROI并保存图片
|
||||||
|
if roi != (0, 0, 0, 0):
|
||||||
|
|
||||||
|
crop = cut[y:y + h, x:x + w]
|
||||||
|
# cv2.imshow('crop', crop)
|
||||||
|
# 选择D区文件夹
|
||||||
|
if kw == 1:
|
||||||
|
cv2.imwrite(path + '/res/A/goal{}.jpeg'.format(str(file_len_red + 1)),crop)
|
||||||
|
print('Saved')
|
||||||
|
# 选择B区文件夹
|
||||||
|
elif kw == 2:
|
||||||
|
cv2.imwrite(path + '/res/B/goal{}.jpeg'.format(str(file_len_gray+1)),crop)
|
||||||
|
print('Saved')
|
||||||
|
# 选择C区文件夹
|
||||||
|
elif kw == 3:
|
||||||
|
cv2.imwrite(path + '/res/C/goal{}.jpeg'.format(str(file_len_green+1)),crop)
|
||||||
|
print('Saved')
|
||||||
|
# 选择A区文件夹
|
||||||
|
elif kw == 4:
|
||||||
|
cv2.imwrite(path + '/res/D/goal{}.jpeg'.format(str(file_len_blue+1)),crop)
|
||||||
|
print('Saved')
|
||||||
|
|
||||||
|
# 退出
|
||||||
|
cv2.waitKey(0)
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
take_photo()
|
||||||
|
cut_photo()
|
||||||
490
mycobot_ai/aikit_320_pi/scripts/aikit_color.py
Normal file
|
|
@ -0,0 +1,490 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
import os,sys
|
||||||
|
import rospy
|
||||||
|
from visualization_msgs.msg import Marker
|
||||||
|
from moving_utils import Movement
|
||||||
|
from pymycobot.mycobot import MyCobot
|
||||||
|
|
||||||
|
|
||||||
|
IS_CV_4 = cv2.__version__[0] == '4'
|
||||||
|
__version__ = "1.0"
|
||||||
|
# Adaptive seeed
|
||||||
|
|
||||||
|
|
||||||
|
class Object_detect(Movement):
|
||||||
|
|
||||||
|
def __init__(self, camera_x = 256, camera_y = 0):
|
||||||
|
# inherit the parent class
|
||||||
|
super(Object_detect, self).__init__()
|
||||||
|
# declare mycobot320
|
||||||
|
self.mc = None
|
||||||
|
|
||||||
|
# 移动角度
|
||||||
|
self.move_angles = [
|
||||||
|
[0.61, 45.87, -92.37, -41.3, 89.56, 9.58], # init the point
|
||||||
|
[18.8, -7.91, -54.49, -23.02, -0.79, -14.76], # point to grab
|
||||||
|
[17.22, -5.27, -52.47, -25.75, 89.73, -0.26],
|
||||||
|
]
|
||||||
|
|
||||||
|
# 移动坐标
|
||||||
|
self.move_coords = [
|
||||||
|
[28.9, -226, 246, -171.13, -3.94, -92.37], # D Sorting area
|
||||||
|
[253.3, -216.1, 257, -163.12, -6.12, -95.27], # C Sorting area
|
||||||
|
[241.8, 219.5, 270.6, -168.47, 10.42, -76.84], # A Sorting area
|
||||||
|
[37.8, 233, 251.4, -170.6, -6.75, 88.53], # B Sorting area
|
||||||
|
]
|
||||||
|
|
||||||
|
# which robot: USB* is m5; ACM* is wio; AMA* is raspi
|
||||||
|
self.robot_m5 = os.popen("ls /dev/ttyUSB*").readline()[:-1]
|
||||||
|
self.robot_wio = os.popen("ls /dev/ttyACM*").readline()[:-1]
|
||||||
|
self.robot_raspi = os.popen("ls /dev/ttyAMA*").readline()[:-1]
|
||||||
|
self.robot_jes = os.popen("ls /dev/ttyTHS1").readline()[:-1]
|
||||||
|
self.raspi = False
|
||||||
|
|
||||||
|
# choose place to set cube 选择放置立方体的地方
|
||||||
|
self.color = 0
|
||||||
|
# parameters to calculate camera clipping parameters 计算相机裁剪参数的参数
|
||||||
|
self.x1 = self.x2 = self.y1 = self.y2 = 0
|
||||||
|
# set cache of real coord 设置真实坐标的缓存
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
# set color HSV
|
||||||
|
self.HSV = {
|
||||||
|
"yellow": [np.array([11, 85, 70]), np.array([59, 255, 245])],
|
||||||
|
# "yellow": [np.array([22, 93, 0]), np.array([45, 255, 245])],
|
||||||
|
"red": [np.array([0, 43, 46]), np.array([8, 255, 255])],
|
||||||
|
"green": [np.array([35, 43, 35]), np.array([90, 255, 255])],
|
||||||
|
"blue": [np.array([78, 43, 46]), np.array([110, 255, 255])],
|
||||||
|
"cyan": [np.array([78, 43, 46]), np.array([99, 255, 255])],
|
||||||
|
}
|
||||||
|
|
||||||
|
# use to calculate coord between cube and mycobot320
|
||||||
|
# 用于计算立方体和 mycobot 之间的坐标
|
||||||
|
self.sum_x1 = self.sum_x2 = self.sum_y2 = self.sum_y1 = 0
|
||||||
|
# The coordinates of the grab center point relative to the mycobot320
|
||||||
|
# 抓取中心点相对于 mycobot 的坐标
|
||||||
|
self.camera_x, self.camera_y = camera_x, camera_y
|
||||||
|
# The coordinates of the cube relative to the mycobot320
|
||||||
|
# 立方体相对于 mycobot 的坐标
|
||||||
|
self.c_x, self.c_y = 0, 0
|
||||||
|
# The ratio of pixels to actual values
|
||||||
|
# 像素与实际值的比值
|
||||||
|
self.ratio = 0
|
||||||
|
|
||||||
|
# Get ArUco marker dict that can be detected.
|
||||||
|
# 获取可以检测到的 ArUco 标记字典。
|
||||||
|
self.aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
|
||||||
|
# Get ArUco marker params. 获取 ArUco 标记参数
|
||||||
|
self.aruco_params = cv2.aruco.DetectorParameters_create()
|
||||||
|
|
||||||
|
# init a node and a publisher
|
||||||
|
rospy.init_node("marker", anonymous=True)
|
||||||
|
self.pub = rospy.Publisher('/cube', Marker, queue_size=1)
|
||||||
|
# init a Marker
|
||||||
|
self.marker = Marker()
|
||||||
|
self.marker.header.frame_id = "base"
|
||||||
|
self.marker.ns = "cube"
|
||||||
|
self.marker.type = self.marker.CUBE
|
||||||
|
self.marker.action = self.marker.ADD
|
||||||
|
self.marker.scale.x = 0.04
|
||||||
|
self.marker.scale.y = 0.04
|
||||||
|
self.marker.scale.z = 0.04
|
||||||
|
self.marker.color.a = 1.0
|
||||||
|
self.marker.color.g = 1.0
|
||||||
|
self.marker.color.r = 1.0
|
||||||
|
|
||||||
|
# marker position initial
|
||||||
|
self.marker.pose.position.x = 0
|
||||||
|
self.marker.pose.position.y = 0
|
||||||
|
self.marker.pose.position.z = 0.03
|
||||||
|
self.marker.pose.orientation.x = 0
|
||||||
|
self.marker.pose.orientation.y = 0
|
||||||
|
self.marker.pose.orientation.z = 0
|
||||||
|
self.marker.pose.orientation.w = 1.0
|
||||||
|
|
||||||
|
# publish marker
|
||||||
|
def pub_marker(self, x, y, z=0.03):
|
||||||
|
self.marker.header.stamp = rospy.Time.now()
|
||||||
|
self.marker.pose.position.x = x
|
||||||
|
self.marker.pose.position.y = y
|
||||||
|
self.marker.pose.position.z = z
|
||||||
|
self.marker.color.g = self.color
|
||||||
|
self.pub.publish(self.marker)
|
||||||
|
|
||||||
|
# pump_control pi
|
||||||
|
def gpio_status(self, flag):
|
||||||
|
if flag:
|
||||||
|
"""start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
else:
|
||||||
|
"""stop suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
# 开启吸泵 m5
|
||||||
|
def pump_on(self):
|
||||||
|
"""Start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
def pump_off(self):
|
||||||
|
"""stop suction pump m5"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
# Grasping motion
|
||||||
|
def move(self, x, y, color):
|
||||||
|
# send Angle to move mycobot320
|
||||||
|
print(color)
|
||||||
|
print('x,y:', round(x, 2), round(y, 2))
|
||||||
|
self.mc.send_angles(self.move_angles[2], 50)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# send coordinates to move mycobot
|
||||||
|
self.mc.send_coords([x, y, 250, -173.84, -0.14, -74.37], 100, 1)
|
||||||
|
time.sleep(2.5)
|
||||||
|
|
||||||
|
self.mc.send_coords([x, y, 150, -173.84, -0.14, -74.37], 100, 1)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# open pump
|
||||||
|
self.pump_on()
|
||||||
|
time.sleep(1.5)
|
||||||
|
|
||||||
|
tmp = []
|
||||||
|
while True:
|
||||||
|
if not tmp:
|
||||||
|
tmp = self.mc.get_angles()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# print(tmp)
|
||||||
|
self.mc.send_angles([tmp[0], -0.71, -54.49, -23.02, 89.56, tmp[5]],25) # [18.8, -7.91, -54.49, -23.02, -0.79, -14.76]
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
self.pub_marker(self.move_coords[2][0]/1000.0, self.move_coords[2][1]/1000.0, self.move_coords[2][2]/1000.0)
|
||||||
|
|
||||||
|
self.mc.send_coords(self.move_coords[color], 100, 1)
|
||||||
|
|
||||||
|
self.pub_marker(self.move_coords[color][0]/1000.0, self.move_coords[color][1]/1000.0, self.move_coords[color][2]/1000.0)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# close pump
|
||||||
|
self.pump_off()
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
if color == 1:
|
||||||
|
self.pub_marker(
|
||||||
|
self.move_coords[color][0]/1000.0+0.03, self.move_coords[color][1]/1000.0-0.02
|
||||||
|
)
|
||||||
|
elif color == 0:
|
||||||
|
self.pub_marker(
|
||||||
|
self.move_coords[color][0]/1000.0+0.03, self.move_coords[color][1]/1000.0
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mc.send_angles(self.move_angles[0], 25)
|
||||||
|
time.sleep(4.5)
|
||||||
|
|
||||||
|
# decide whether grab cube 决定是否抓取立方体
|
||||||
|
def decide_move(self, x, y, color):
|
||||||
|
print(x, y, self.cache_x, self.cache_y)
|
||||||
|
# detect the cube status move or run 检测立方体状态移动或运行
|
||||||
|
if (abs(x - self.cache_x) + abs(y - self.cache_y)) / 2 > 5: # mm
|
||||||
|
self.cache_x, self.cache_y = x, y
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
# 调整吸泵吸取位置,y增大,向左移动;y减小,向右移动;x增大,前方移动;x减小,向后方移动
|
||||||
|
self.move(x, y, color)
|
||||||
|
|
||||||
|
# init mycobot320
|
||||||
|
def run(self):
|
||||||
|
if "dev" in self.robot_raspi:
|
||||||
|
self.mc = MyCobot(self.robot_raspi, 115200)
|
||||||
|
self.pump_off()
|
||||||
|
self.mc.send_angles([0.61, 45.87, -92.37, -41.3, 89.56, 9.58], 20)
|
||||||
|
time.sleep(2.5)
|
||||||
|
|
||||||
|
# draw aruco
|
||||||
|
def draw_marker(self, img, x, y):
|
||||||
|
# draw rectangle on img 在 img 上绘制矩形
|
||||||
|
cv2.rectangle(
|
||||||
|
img,
|
||||||
|
(x - 20, y - 20),
|
||||||
|
(x + 20, y + 20),
|
||||||
|
(0, 255, 0),
|
||||||
|
thickness=2,
|
||||||
|
lineType=cv2.FONT_HERSHEY_COMPLEX,
|
||||||
|
)
|
||||||
|
# add text on rectangle
|
||||||
|
cv2.putText(img, "({},{})".format(x, y), (x, y),
|
||||||
|
cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (243, 0, 0), 2,)
|
||||||
|
|
||||||
|
# get points of two aruco 获得两个 aruco 的点位
|
||||||
|
def get_calculate_params(self, img):
|
||||||
|
# Convert the image to a gray image 将图像转换为灰度图像
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
# Detect ArUco marker.
|
||||||
|
corners, ids, rejectImaPoint = cv2.aruco.detectMarkers(
|
||||||
|
gray, self.aruco_dict, parameters=self.aruco_params
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Two Arucos must be present in the picture and in the same order.
|
||||||
|
There are two Arucos in the Corners, and each aruco contains the pixels of its four corners.
|
||||||
|
Determine the center of the aruco by the four corners of the aruco.
|
||||||
|
"""
|
||||||
|
if len(corners) > 0:
|
||||||
|
if ids is not None:
|
||||||
|
if len(corners) <= 1 or ids[0] == 1:
|
||||||
|
return None
|
||||||
|
x1 = x2 = y1 = y2 = 0
|
||||||
|
point_11, point_21, point_31, point_41 = corners[0][0]
|
||||||
|
x1, y1 = int((point_11[0] + point_21[0] + point_31[0] + point_41[0]) / 4.0), int(
|
||||||
|
(point_11[1] + point_21[1] + point_31[1] + point_41[1]) / 4.0)
|
||||||
|
point_1, point_2, point_3, point_4 = corners[1][0]
|
||||||
|
x2, y2 = int((point_1[0] + point_2[0] + point_3[0] + point_4[0]) / 4.0), int(
|
||||||
|
(point_1[1] + point_2[1] + point_3[1] + point_4[1]) / 4.0)
|
||||||
|
|
||||||
|
return x1, x2, y1, y2
|
||||||
|
return None
|
||||||
|
|
||||||
|
# set camera clipping parameters 设置相机裁剪参数
|
||||||
|
def set_cut_params(self, x1, y1, x2, y2):
|
||||||
|
self.x1 = int(x1)
|
||||||
|
self.y1 = int(y1)
|
||||||
|
self.x2 = int(x2)
|
||||||
|
self.y2 = int(y2)
|
||||||
|
|
||||||
|
# set parameters to calculate the coords between cube and mycobot320
|
||||||
|
# 设置参数以计算立方体和 mycobot 之间的坐标
|
||||||
|
def set_params(self, c_x, c_y, ratio):
|
||||||
|
self.c_x = c_x
|
||||||
|
self.c_y = c_y
|
||||||
|
self.ratio = 220.0/ratio
|
||||||
|
|
||||||
|
# calculate the coords between cube and mycobot320
|
||||||
|
# 计算立方体和 mycobot 之间的坐标
|
||||||
|
def get_position(self, x, y):
|
||||||
|
return ((y - self.c_y)*self.ratio + self.camera_x), ((x - self.c_x)*self.ratio + self.camera_y)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Calibrate the camera according to the calibration parameters.
|
||||||
|
Enlarge the video pixel by 1.5 times, which means enlarge the video size by 1.5 times.
|
||||||
|
If two ARuco values have been calculated, clip the video.
|
||||||
|
"""
|
||||||
|
def transform_frame(self, frame):
|
||||||
|
# enlarge the image by 1.5 times
|
||||||
|
fx = 1.5
|
||||||
|
fy = 1.5
|
||||||
|
frame = cv2.resize(frame, (0, 0), fx=fx, fy=fy,
|
||||||
|
interpolation=cv2.INTER_CUBIC)
|
||||||
|
if self.x1 != self.x2:
|
||||||
|
# the cutting ratio here is adjusted according to the actual situation
|
||||||
|
frame = frame[int(self.y2*0.78):int(self.y1*1.1),
|
||||||
|
int(self.x1*0.86):int(self.x2*1.08)]
|
||||||
|
return frame
|
||||||
|
|
||||||
|
# detect cube color
|
||||||
|
def color_detect(self, img):
|
||||||
|
# set the arrangement of color'HSV
|
||||||
|
x = y = 0
|
||||||
|
for mycolor, item in self.HSV.items():
|
||||||
|
# print("mycolor:",mycolor)
|
||||||
|
redLower = np.array(item[0])
|
||||||
|
redUpper = np.array(item[1])
|
||||||
|
|
||||||
|
# transfrom the img to model of gray 将图像转换为灰度模型
|
||||||
|
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
|
||||||
|
# print("hsv",hsv)
|
||||||
|
|
||||||
|
# wipe off all color expect color in range 擦掉所有颜色期望范围内的颜色
|
||||||
|
mask = cv2.inRange(hsv, item[0], item[1])
|
||||||
|
|
||||||
|
# a etching operation on a picture to remove edge roughness
|
||||||
|
# 对图片进行蚀刻操作以去除边缘粗糙度
|
||||||
|
erosion = cv2.erode(mask, np.ones((1, 1), np.uint8), iterations=2)
|
||||||
|
|
||||||
|
# the image for expansion operation, its role is to deepen the color depth in the picture
|
||||||
|
# 用于扩展操作的图像,其作用是加深图片中的颜色深度
|
||||||
|
dilation = cv2.dilate(erosion, np.ones(
|
||||||
|
(1, 1), np.uint8), iterations=2)
|
||||||
|
|
||||||
|
# adds pixels to the image 向图像添加像素
|
||||||
|
target = cv2.bitwise_and(img, img, mask=dilation)
|
||||||
|
|
||||||
|
# the filtered image is transformed into a binary image and placed in binary
|
||||||
|
# 将过滤后的图像转换为二值图像并放入二值
|
||||||
|
ret, binary = cv2.threshold(dilation, 127, 255, cv2.THRESH_BINARY)
|
||||||
|
|
||||||
|
# get the contour coordinates of the image, where contours is the coordinate value, here only the contour is detected
|
||||||
|
# 获取图像的轮廓坐标,其中contours为坐标值,这里只检测轮廓
|
||||||
|
contours, hierarchy = cv2.findContours(
|
||||||
|
dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
|
||||||
|
if len(contours) > 0:
|
||||||
|
# do something about misidentification
|
||||||
|
boxes = [
|
||||||
|
box
|
||||||
|
for box in [cv2.boundingRect(c) for c in contours]
|
||||||
|
if min(img.shape[0], img.shape[1]) / 10
|
||||||
|
< min(box[2], box[3])
|
||||||
|
< min(img.shape[0], img.shape[1]) / 1
|
||||||
|
]
|
||||||
|
if boxes:
|
||||||
|
for box in boxes:
|
||||||
|
x, y, w, h = box
|
||||||
|
# find the largest object that fits the requirements 找到符合要求的最大对象
|
||||||
|
c = max(contours, key=cv2.contourArea)
|
||||||
|
# get the lower left and upper right points of the positioning object
|
||||||
|
# 获取定位对象的左下和右上点
|
||||||
|
x, y, w, h = cv2.boundingRect(c)
|
||||||
|
# locate the target by drawing rectangle 通过绘制矩形来定位目标
|
||||||
|
cv2.rectangle(img, (x, y), (x+w, y+h), (153, 153, 0), 2)
|
||||||
|
# calculate the rectangle center 计算矩形中心
|
||||||
|
x, y = (x*2+w)/2, (y*2+h)/2
|
||||||
|
# calculate the real coordinates of mycobot320 relative to the target
|
||||||
|
# 计算 mycobot 相对于目标的真实坐标
|
||||||
|
|
||||||
|
if mycolor == "yellow":
|
||||||
|
|
||||||
|
self.color = 3
|
||||||
|
break
|
||||||
|
|
||||||
|
elif mycolor == "red":
|
||||||
|
self.color = 0
|
||||||
|
break
|
||||||
|
|
||||||
|
elif mycolor == "cyan":
|
||||||
|
self.color = 2
|
||||||
|
break
|
||||||
|
|
||||||
|
elif mycolor == "blue":
|
||||||
|
self.color =2
|
||||||
|
break
|
||||||
|
elif mycolor == "green":
|
||||||
|
self.color = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# 判断是否正常识别
|
||||||
|
if abs(x) + abs(y) > 0:
|
||||||
|
return x, y
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# open the camera
|
||||||
|
cap_num = 0
|
||||||
|
cap = cv2.VideoCapture(cap_num, cv2.CAP_V4L)
|
||||||
|
|
||||||
|
if not cap.isOpened():
|
||||||
|
cap.open()
|
||||||
|
# init a class of Object_detect
|
||||||
|
detect = Object_detect()
|
||||||
|
# init mycobot320
|
||||||
|
detect.run()
|
||||||
|
|
||||||
|
_init_ = 20
|
||||||
|
init_num = 0
|
||||||
|
nparams = 0
|
||||||
|
num = 0
|
||||||
|
real_sx = real_sy = 0
|
||||||
|
while cv2.waitKey(1) < 0:
|
||||||
|
# read camera
|
||||||
|
_, frame = cap.read()
|
||||||
|
# deal img
|
||||||
|
frame = detect.transform_frame(frame)
|
||||||
|
if _init_ > 0:
|
||||||
|
_init_ -= 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# calculate the parameters of camera clipping 计算相机裁剪的参数
|
||||||
|
if init_num < 20:
|
||||||
|
if detect.get_calculate_params(frame) is None:
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x1, x2, y1, y2 = detect.get_calculate_params(frame)
|
||||||
|
detect.draw_marker(frame, x1, y1)
|
||||||
|
detect.draw_marker(frame, x2, y2)
|
||||||
|
detect.sum_x1 += x1
|
||||||
|
detect.sum_x2 += x2
|
||||||
|
detect.sum_y1 += y1
|
||||||
|
detect.sum_y2 += y2
|
||||||
|
init_num += 1
|
||||||
|
continue
|
||||||
|
elif init_num == 20:
|
||||||
|
detect.set_cut_params(
|
||||||
|
(detect.sum_x1)/20.0,
|
||||||
|
(detect.sum_y1)/20.0,
|
||||||
|
(detect.sum_x2)/20.0,
|
||||||
|
(detect.sum_y2)/20.0,
|
||||||
|
)
|
||||||
|
detect.sum_x1 = detect.sum_x2 = detect.sum_y1 = detect.sum_y2 = 0
|
||||||
|
init_num += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# calculate params of the coords between cube and mycobot320 计算立方体和 mycobot 之间坐标的参数
|
||||||
|
if nparams < 10:
|
||||||
|
if detect.get_calculate_params(frame) is None:
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x1, x2, y1, y2 = detect.get_calculate_params(frame)
|
||||||
|
detect.draw_marker(frame, x1, y1)
|
||||||
|
detect.draw_marker(frame, x2, y2)
|
||||||
|
detect.sum_x1 += x1
|
||||||
|
detect.sum_x2 += x2
|
||||||
|
detect.sum_y1 += y1
|
||||||
|
detect.sum_y2 += y2
|
||||||
|
nparams += 1
|
||||||
|
continue
|
||||||
|
elif nparams == 10:
|
||||||
|
nparams += 1
|
||||||
|
# calculate and set params of calculating real coord between cube and mycobot320
|
||||||
|
# 计算和设置计算立方体和mycobot之间真实坐标的参数
|
||||||
|
detect.set_params(
|
||||||
|
(detect.sum_x1+detect.sum_x2)/20.0,
|
||||||
|
(detect.sum_y1+detect.sum_y2)/20.0,
|
||||||
|
abs(detect.sum_x1-detect.sum_x2)/10.0 +
|
||||||
|
abs(detect.sum_y1-detect.sum_y2)/10.0
|
||||||
|
)
|
||||||
|
print("ok")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# get detect result 获取检测结果
|
||||||
|
detect_result = detect.color_detect(frame)
|
||||||
|
if detect_result is None:
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x, y = detect_result
|
||||||
|
# calculate real coord between cube and mycobot320 计算立方体和 mycobot 之间的真实坐标
|
||||||
|
real_x, real_y = detect.get_position(x, y)
|
||||||
|
# print('real_x',round(real_x, 3),round(real_y, 3))
|
||||||
|
if num == 20:
|
||||||
|
detect.pub_marker(real_sx/20.0/1000.0, real_sy/20.0/1000.0)
|
||||||
|
detect.decide_move(real_sx/20.0, real_sy/20.0, detect.color)
|
||||||
|
num = real_sx = real_sy = 0
|
||||||
|
|
||||||
|
else:
|
||||||
|
num += 1
|
||||||
|
real_sy += real_y
|
||||||
|
real_sx += real_x
|
||||||
|
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
|
||||||
|
# close the window
|
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||||
|
cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
sys.exit()
|
||||||
243
mycobot_ai/aikit_320_pi/scripts/aikit_encode.py
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
#encoding: UTF-8
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from pymycobot.mycobot import MyCobot
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import rospy
|
||||||
|
from visualization_msgs.msg import Marker
|
||||||
|
from moving_utils import Movement
|
||||||
|
|
||||||
|
# y轴偏移量
|
||||||
|
pump_y = -55
|
||||||
|
# x轴偏移量
|
||||||
|
pump_x = 15
|
||||||
|
|
||||||
|
class Detect_marker(Movement):
|
||||||
|
def __init__(self):
|
||||||
|
# set cache of real coord
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
|
||||||
|
# which robot: USB* is m5; ACM* is wio; AMA* is raspi
|
||||||
|
self.robot_m5 = os.popen("ls /dev/ttyUSB*").readline()[:-1]
|
||||||
|
self.robot_wio = os.popen("ls /dev/ttyACM*").readline()[:-1]
|
||||||
|
self.robot_raspi = os.popen("ls /dev/ttyAMA*").readline()[:-1]
|
||||||
|
self.robot_jes = os.popen("ls /dev/ttyTHS1").readline()[:-1]
|
||||||
|
|
||||||
|
# Creating a Camera Object
|
||||||
|
cap_num = 0
|
||||||
|
self.cap = cv2.VideoCapture(cap_num)
|
||||||
|
self.cap.set(3, 640)
|
||||||
|
self.cap.set(4, 480)
|
||||||
|
|
||||||
|
# Determine the placement point of the QR code
|
||||||
|
self.color = 0
|
||||||
|
|
||||||
|
# Get ArUco marker dict that can be detected.
|
||||||
|
self.aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
|
||||||
|
# Get ArUco marker params.
|
||||||
|
self.aruco_params = cv2.aruco.DetectorParameters_create()
|
||||||
|
# 摄像头的内参矩阵
|
||||||
|
self.camera_matrix = np.array([
|
||||||
|
[781.33379113, 0., 347.53500524],
|
||||||
|
[0., 783.79074192, 246.67627253],
|
||||||
|
[0., 0., 1.]])
|
||||||
|
|
||||||
|
# 摄像头的畸变系数
|
||||||
|
self.dist_coeffs = np.array(([[3.41360787e-01, -2.52114260e+00, -1.28012469e-03, 6.70503562e-03,
|
||||||
|
2.57018000e+00]]))
|
||||||
|
|
||||||
|
# init a node and a publisher
|
||||||
|
rospy.init_node("encode_marker", anonymous=True)
|
||||||
|
self.pub = rospy.Publisher('/cube', Marker, queue_size=1)
|
||||||
|
|
||||||
|
self.marker = Marker()
|
||||||
|
self.marker.header.frame_id = "base"
|
||||||
|
self.marker.ns = "cube"
|
||||||
|
self.marker.type = self.marker.CUBE
|
||||||
|
self.marker.action = self.marker.ADD
|
||||||
|
self.marker.scale.x = 0.04
|
||||||
|
self.marker.scale.y = 0.04
|
||||||
|
self.marker.scale.z = 0.04
|
||||||
|
self.marker.color.a = 1
|
||||||
|
self.marker.color.r = 0.3
|
||||||
|
self.marker.color.g = 0.3
|
||||||
|
self.marker.color.b = 0.3
|
||||||
|
|
||||||
|
# marker position initial
|
||||||
|
self.marker.pose.position.x = 0
|
||||||
|
self.marker.pose.position.y = 0
|
||||||
|
self.marker.pose.position.z = 0.03
|
||||||
|
self.marker.pose.orientation.x = 0
|
||||||
|
self.marker.pose.orientation.y = 0
|
||||||
|
self.marker.pose.orientation.z = 0
|
||||||
|
self.marker.pose.orientation.w = 1.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 控制吸泵
|
||||||
|
def pub_pump(self, flag):
|
||||||
|
if flag:
|
||||||
|
"""start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
else:
|
||||||
|
"""stop suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
# Grasping motion
|
||||||
|
def move(self, x, y, color):
|
||||||
|
|
||||||
|
print(color)
|
||||||
|
|
||||||
|
angles = [
|
||||||
|
[0.61, 45.87, -92.37, -41.3, 89.56, 9.58], # init to point
|
||||||
|
[18.8, -7.91, -54.49, -23.02, 89.56, -14.76],
|
||||||
|
[17.22, -5.27, -52.47, -25.75, 89.73, -0.26],
|
||||||
|
]
|
||||||
|
|
||||||
|
coords = [
|
||||||
|
[145.0, -65.5, 280.1, 178.99, 7.67, -179.9], # 初始化点 init point
|
||||||
|
[253.8, 236.8, 224.6, -170, 6.87, -77.91], # A分拣区 A sorting area
|
||||||
|
[35.9, 235.4, 211.8, -169.33, -9.27, 88.3], # B分拣区 B sorting area
|
||||||
|
[266.5, -219.7, 209.3, -170, -3.64, -94.62], # C分拣区 C sorting area
|
||||||
|
[32, -228.3, 201.6, -168.07, -7.17, -92.56], # D分拣区 D sorting area
|
||||||
|
]
|
||||||
|
print('real_x, real_y:', round(coords[0][0] + x, 2), round(coords[0][1] + y, 2))
|
||||||
|
|
||||||
|
# publish marker
|
||||||
|
self.marker.header.stamp = rospy.Time.now()
|
||||||
|
self.marker.pose.position.x = (coords[0][0]-x)/1000.0
|
||||||
|
self.marker.pose.position.y = (coords[0][1]-y)/1000.0
|
||||||
|
self.pub.publish(self.marker)
|
||||||
|
|
||||||
|
# send coordinates to move mycobot
|
||||||
|
self.mc.send_angles(angles[2], 50)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
self.mc.send_coords([coords[0][0] + x, coords[0][1] + y, 240, 178.99, -3.78, -62.9], 100, 1)
|
||||||
|
time.sleep(2)
|
||||||
|
self.mc.send_coords([coords[0][0] + x, coords[0][1] + y, 100.5, 178.99, -3.78, -62.9], 100, 1)
|
||||||
|
time.sleep(2.5)
|
||||||
|
|
||||||
|
# open pump
|
||||||
|
if "dev" in self.robot_raspi:
|
||||||
|
self.pub_pump(True)
|
||||||
|
time.sleep(1.5)
|
||||||
|
|
||||||
|
tmp = []
|
||||||
|
while True:
|
||||||
|
if not tmp:
|
||||||
|
tmp = self.mc.get_angles()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# print(tmp)
|
||||||
|
self.mc.send_angles([tmp[0], -0.71, -54.49, -23.02, 89.56, tmp[5]],25) # [18.8, -7.91, -54.49, -23.02, -0.79, -14.76]
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
self.mc.send_coords(coords[color], 100, 1) # coords[1] 为A分拣区,coords[2] 为B分拣区, coords[3] 为C分拣区,coords[4] 为D分拣区
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
# close pump
|
||||||
|
if "dev" in self.robot_raspi:
|
||||||
|
self.pub_pump(False)
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
# publish marker
|
||||||
|
time.sleep(1)
|
||||||
|
self.marker.header.stamp = rospy.Time.now()
|
||||||
|
self.marker.pose.position.x = coords[1][0]/1000.0
|
||||||
|
self.marker.pose.position.y = coords[1][1]/1000.0
|
||||||
|
self.pub.publish(self.marker)
|
||||||
|
|
||||||
|
self.mc.send_angles(angles[0], 25)
|
||||||
|
time.sleep(4.5)
|
||||||
|
|
||||||
|
# decide whether grab cube
|
||||||
|
def decide_move(self, x, y, color):
|
||||||
|
|
||||||
|
print(x,y)
|
||||||
|
# detect the cube status move or run
|
||||||
|
if (abs(x - self.cache_x) + abs(y - self.cache_y)) / 2 > 5: # mm
|
||||||
|
self.cache_x, self.cache_y = x, y
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
# 调整吸泵吸取位置,y增大,向左移动;y减小,向右移动;x增大,前方移动;x减小,向后方移动
|
||||||
|
self.move(x + 105, y + 130, color)
|
||||||
|
|
||||||
|
# init mycobot
|
||||||
|
def init_mycobot(self):
|
||||||
|
if "dev" in self.robot_raspi:
|
||||||
|
self.mc = MyCobot(self.robot_raspi, 115200)
|
||||||
|
self.pub_pump(False)
|
||||||
|
self.mc.send_angles([0.61, 45.87, -92.37, -41.3, 89.56, 9.58], 20)
|
||||||
|
time.sleep(2.5)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
global pump_y, pump_x
|
||||||
|
self.init_mycobot()
|
||||||
|
print('ok')
|
||||||
|
num = sum_x = sum_y = 0
|
||||||
|
while cv2.waitKey(1) < 0:
|
||||||
|
success, img = self.cap.read()
|
||||||
|
if not success:
|
||||||
|
print("It seems that the image cannot be acquired correctly.")
|
||||||
|
break
|
||||||
|
|
||||||
|
# transfrom the img to model of gray
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
# Detect ArUco marker.
|
||||||
|
corners, ids, rejectImaPoint = cv2.aruco.detectMarkers(
|
||||||
|
gray, self.aruco_dict, parameters=self.aruco_params
|
||||||
|
)
|
||||||
|
|
||||||
|
# Determine the placement point of the QR code
|
||||||
|
if ids == np.array([[1]]):
|
||||||
|
self.color = 1
|
||||||
|
elif ids == np.array([[2]]):
|
||||||
|
self.color = 2
|
||||||
|
elif ids == np.array([[3]]):
|
||||||
|
self.color = 3
|
||||||
|
elif ids == np.array([[4]]):
|
||||||
|
self.color = 4
|
||||||
|
|
||||||
|
if len(corners) > 0:
|
||||||
|
if ids is not None:
|
||||||
|
# get informations of aruco
|
||||||
|
ret = cv2.aruco.estimatePoseSingleMarkers(
|
||||||
|
corners, 0.03, self.camera_matrix, self.dist_coeffs
|
||||||
|
)
|
||||||
|
# rvec:rotation offset,tvec:translation deviator
|
||||||
|
(rvec, tvec) = (ret[0], ret[1])
|
||||||
|
(rvec - tvec).any()
|
||||||
|
xyz = tvec[0, 0, :]
|
||||||
|
# calculate the coordinates of the aruco relative to the pump
|
||||||
|
xyz = [round(xyz[0]*1000+pump_y, 2), round(xyz[1]*1000+pump_x, 2), round(xyz[2]*1000, 2)]
|
||||||
|
|
||||||
|
# cv2.putText(img, str(xyz[:2]), (0, 64), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
|
||||||
|
for i in range(rvec.shape[0]):
|
||||||
|
# draw the aruco on img
|
||||||
|
cv2.aruco.drawDetectedMarkers(img, corners)
|
||||||
|
|
||||||
|
if num < 40 :
|
||||||
|
sum_x += xyz[1]
|
||||||
|
sum_y += xyz[0]
|
||||||
|
num += 1
|
||||||
|
elif num ==40 :
|
||||||
|
self.decide_move(sum_x/40.0, sum_y/40.0, self.color)
|
||||||
|
num = sum_x = sum_y = 0
|
||||||
|
|
||||||
|
cv2.imshow("encode_image", img)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
detect = Detect_marker()
|
||||||
|
detect.run()
|
||||||
|
|
||||||
601
mycobot_ai/aikit_320_pi/scripts/aikit_img.py
Normal file
|
|
@ -0,0 +1,601 @@
|
||||||
|
from multiprocessing import Process, Pipe
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
import os,sys
|
||||||
|
import rospy
|
||||||
|
from visualization_msgs.msg import Marker
|
||||||
|
from moving_utils import Movement
|
||||||
|
|
||||||
|
from pymycobot.mycobot import MyCobot
|
||||||
|
|
||||||
|
IS_CV_4 = cv2.__version__[0] == '4'
|
||||||
|
__version__ = "1.0" # Adaptive seeed
|
||||||
|
|
||||||
|
|
||||||
|
class Object_detect(Movement):
|
||||||
|
|
||||||
|
def __init__(self, camera_x = 263, camera_y = 0):
|
||||||
|
# inherit the parent class
|
||||||
|
super(Object_detect, self).__init__()
|
||||||
|
|
||||||
|
# declare mycobot 280pi
|
||||||
|
self.mc = None
|
||||||
|
# 移动角度
|
||||||
|
self.move_angles = [
|
||||||
|
[0.61, 45.87, -92.37, -41.3, 89.56, 9.58], # init the point
|
||||||
|
[18.8, -7.91, -54.49, -23.02, 89.56, -14.76], # point to grab
|
||||||
|
[17.22, -5.27, -52.47, -25.75, 89.73, -0.26],
|
||||||
|
]
|
||||||
|
|
||||||
|
# 移动坐标
|
||||||
|
self.move_coords = [
|
||||||
|
[32, -228.3, 201.6, -168.07, -7.17, -92.56], # D Sorting area
|
||||||
|
[266.5, -219.7, 209.3, -170, -3.64, -94.62], # C Sorting area
|
||||||
|
[253.8, 236.8, 224.6, -170, 6.87, -77.91], # A Sorting area
|
||||||
|
[35.9, 235.4, 211.8, -169.33, -9.27, 88.3], # B Sorting area
|
||||||
|
]
|
||||||
|
|
||||||
|
# which robot: USB* is m5; ACM* is wio; AMA* is raspi
|
||||||
|
self.robot_m5 = os.popen("ls /dev/ttyUSB*").readline()[:-1]
|
||||||
|
self.robot_wio = os.popen("ls /dev/ttyACM*").readline()[:-1]
|
||||||
|
self.robot_raspi = os.popen("ls /dev/ttyAMA*").readline()[:-1]
|
||||||
|
self.robot_jes = os.popen("ls /dev/ttyTHS1").readline()[:-1]
|
||||||
|
|
||||||
|
# choose place to set cube
|
||||||
|
self.color = 0
|
||||||
|
# parameters to calculate camera clipping parameters
|
||||||
|
self.x1 = self.x2 = self.y1 = self.y2 = 0
|
||||||
|
# set cache of real coord
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
|
||||||
|
# use to calculate coord between cube and mycobot
|
||||||
|
self.sum_x1 = self.sum_x2 = self.sum_y2 = self.sum_y1 = 0
|
||||||
|
# The coordinates of the grab center point relative to the mycobot
|
||||||
|
self.camera_x, self.camera_y = camera_x, camera_y
|
||||||
|
# The coordinates of the cube relative to the mycobot
|
||||||
|
self.c_x, self.c_y = 0, 0
|
||||||
|
# The ratio of pixels to actual values
|
||||||
|
self.ratio = 0
|
||||||
|
# Get ArUco marker dict that can be detected.
|
||||||
|
self.aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
|
||||||
|
# Get ArUco marker params.
|
||||||
|
self.aruco_params = cv2.aruco.DetectorParameters_create()
|
||||||
|
|
||||||
|
# init a Marker
|
||||||
|
rospy.init_node("marker", anonymous=True)
|
||||||
|
self.pub = rospy.Publisher('/cube', Marker, queue_size=1)
|
||||||
|
# init a Marker
|
||||||
|
self.marker = Marker()
|
||||||
|
self.marker.header.frame_id = "base"
|
||||||
|
self.marker.ns = "cube"
|
||||||
|
self.marker.type = self.marker.CUBE
|
||||||
|
self.marker.action = self.marker.ADD
|
||||||
|
self.marker.scale.x = 0.04
|
||||||
|
self.marker.scale.y = 0.04
|
||||||
|
self.marker.scale.z = 0.04
|
||||||
|
self.marker.color.a = 1.0
|
||||||
|
self.marker.color.g = 1.0
|
||||||
|
self.marker.color.r = 1.0
|
||||||
|
|
||||||
|
# marker position initial
|
||||||
|
self.marker.pose.position.x = 0
|
||||||
|
self.marker.pose.position.y = 0
|
||||||
|
self.marker.pose.position.z = 0.03
|
||||||
|
self.marker.pose.orientation.x = 0
|
||||||
|
self.marker.pose.orientation.y = 0
|
||||||
|
self.marker.pose.orientation.z = 0
|
||||||
|
self.marker.pose.orientation.w = 1.0
|
||||||
|
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
|
||||||
|
# publish marker
|
||||||
|
def pub_marker(self, x, y, z=0.03):
|
||||||
|
self.marker.header.stamp = rospy.Time.now()
|
||||||
|
self.marker.pose.position.x = x
|
||||||
|
self.marker.pose.position.y = y
|
||||||
|
self.marker.pose.position.z = z
|
||||||
|
self.marker.color.g = self.color
|
||||||
|
self.pub.publish(self.marker)
|
||||||
|
|
||||||
|
# pump_control pi
|
||||||
|
def gpio_status(self, flag):
|
||||||
|
if flag:
|
||||||
|
"""start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
else:
|
||||||
|
"""stop suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
def pump_on(self):
|
||||||
|
"""Start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
def pump_off(self):
|
||||||
|
"""stop suction pump m5"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
# Grasping motion
|
||||||
|
def move(self, x, y, color):
|
||||||
|
print(color)
|
||||||
|
print('x,y:', round(x, 2), round(y, 2))
|
||||||
|
# send Angle to move mycobot320
|
||||||
|
self.mc.send_angles(self.move_angles[2], 50)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# send coordinates to move mycobot
|
||||||
|
self.mc.send_coords([x, y, 230, -173.84, -0.14, -74.37], 100, 1)
|
||||||
|
time.sleep(2.5)
|
||||||
|
self.mc.send_coords([x, y, 100, -173.84, -0.14, -74.37], 100, 1) #
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# open pump
|
||||||
|
self.gpio_status(True)
|
||||||
|
time.sleep(1.5)
|
||||||
|
|
||||||
|
tmp = []
|
||||||
|
while True:
|
||||||
|
if not tmp:
|
||||||
|
tmp = self.mc.get_angles()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# print(tmp)
|
||||||
|
self.mc.send_angles([tmp[0], -0.71, -54.49, -23.02, 89.56, tmp[5]],25) # [18.8, -7.91, -54.49, -23.02, -0.79, -14.76]
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.mc.send_coords(self.move_coords[color], 100, 1)
|
||||||
|
self.pub_marker(self.move_coords[color][0]/1000.0, self.move_coords[color][1]/1000.0,
|
||||||
|
self.move_coords[color][2]/1000.0)
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
# close pump
|
||||||
|
self.gpio_status(False)
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
self.mc.send_angles(self.move_angles[0], 50)
|
||||||
|
time.sleep(4.5)
|
||||||
|
|
||||||
|
# decide whether grab cube
|
||||||
|
def decide_move(self, x, y, color):
|
||||||
|
print(x, y, self.cache_x, self.cache_y)
|
||||||
|
# detect the cube status move or run
|
||||||
|
if (abs(x - self.cache_x) + abs(y - self.cache_y)) / 2 > 5: # mm
|
||||||
|
self.cache_x, self.cache_y = x, y
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
# 调整吸泵吸取位置,y增大,向左移动;y减小,向右移动;x增大,前方移动;x减小,向后方移动
|
||||||
|
|
||||||
|
self.move(x, y, color)
|
||||||
|
|
||||||
|
|
||||||
|
# init mycobot
|
||||||
|
def run(self):
|
||||||
|
|
||||||
|
if "dev" in self.robot_raspi:
|
||||||
|
self.mc = MyCobot(self.robot_raspi, 115200)
|
||||||
|
self.gpio_status(False)
|
||||||
|
self.mc.send_angles([0.61, 45.87, -92.37, -41.3, 89.56, 9.58], 20)
|
||||||
|
time.sleep(2.5)
|
||||||
|
|
||||||
|
|
||||||
|
# draw aruco
|
||||||
|
def draw_marker(self, img, x, y):
|
||||||
|
# draw rectangle on img
|
||||||
|
cv2.rectangle(
|
||||||
|
img,
|
||||||
|
(x - 20, y - 20),
|
||||||
|
(x + 20, y + 20),
|
||||||
|
(0, 255, 0),
|
||||||
|
thickness=2,
|
||||||
|
lineType=cv2.FONT_HERSHEY_COMPLEX,
|
||||||
|
)
|
||||||
|
# add text on rectangle
|
||||||
|
cv2.putText(
|
||||||
|
img,
|
||||||
|
"({},{})".format(x, y),
|
||||||
|
(x, y),
|
||||||
|
cv2.FONT_HERSHEY_COMPLEX_SMALL,
|
||||||
|
1,
|
||||||
|
(243, 0, 0),
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
|
||||||
|
# get points of two aruco
|
||||||
|
def get_calculate_params(self, img):
|
||||||
|
# Convert the image to a gray image
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
# Detect ArUco marker.
|
||||||
|
corners, ids, rejectImaPoint = cv2.aruco.detectMarkers(
|
||||||
|
gray, self.aruco_dict, parameters=self.aruco_params)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Two Arucos must be present in the picture and in the same order.
|
||||||
|
There are two Arucos in the Corners, and each aruco contains the pixels of its four corners.
|
||||||
|
Determine the center of the aruco by the four corners of the aruco.
|
||||||
|
"""
|
||||||
|
if len(corners) > 0:
|
||||||
|
if ids is not None:
|
||||||
|
if len(corners) <= 1 or ids[0] == 1:
|
||||||
|
return None
|
||||||
|
x1 = x2 = y1 = y2 = 0
|
||||||
|
point_11, point_21, point_31, point_41 = corners[0][0]
|
||||||
|
x1, y1 = int(
|
||||||
|
(point_11[0] + point_21[0] + point_31[0] + point_41[0]) /
|
||||||
|
4.0), int(
|
||||||
|
(point_11[1] + point_21[1] + point_31[1] + point_41[1])
|
||||||
|
/ 4.0)
|
||||||
|
point_1, point_2, point_3, point_4 = corners[1][0]
|
||||||
|
x2, y2 = int(
|
||||||
|
(point_1[0] + point_2[0] + point_3[0] + point_4[0]) /
|
||||||
|
4.0), int(
|
||||||
|
(point_1[1] + point_2[1] + point_3[1] + point_4[1]) /
|
||||||
|
4.0)
|
||||||
|
return x1, x2, y1, y2
|
||||||
|
return None
|
||||||
|
|
||||||
|
# set camera clipping parameters
|
||||||
|
def set_cut_params(self, x1, y1, x2, y2):
|
||||||
|
self.x1 = int(x1)
|
||||||
|
self.y1 = int(y1)
|
||||||
|
self.x2 = int(x2)
|
||||||
|
self.y2 = int(y2)
|
||||||
|
print(self.x1, self.y1, self.x2, self.y2)
|
||||||
|
|
||||||
|
# set parameters to calculate the coords between cube and mycobot
|
||||||
|
def set_params(self, c_x, c_y, ratio):
|
||||||
|
self.c_x = c_x
|
||||||
|
self.c_y = c_y
|
||||||
|
self.ratio = 220.0 / ratio
|
||||||
|
|
||||||
|
# calculate the coords between cube and mycobot
|
||||||
|
def get_position(self, x, y):
|
||||||
|
return ((y - self.c_y) * self.ratio +
|
||||||
|
self.camera_x), ((x - self.c_x) * self.ratio + self.camera_y)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Calibrate the camera according to the calibration parameters.
|
||||||
|
Enlarge the video pixel by 1.5 times, which means enlarge the video size by 1.5 times.
|
||||||
|
If two ARuco values have been calculated, clip the video.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def transform_frame(self, frame):
|
||||||
|
# enlarge the image by 1.5 times
|
||||||
|
fx = 1.5
|
||||||
|
fy = 1.5
|
||||||
|
frame = cv2.resize(frame, (0, 0),
|
||||||
|
fx=fx,
|
||||||
|
fy=fy,
|
||||||
|
interpolation=cv2.INTER_CUBIC)
|
||||||
|
if self.x1 != self.x2:
|
||||||
|
# the cutting ratio here is adjusted according to the actual situation
|
||||||
|
frame = frame[int(self.y2 * 0.2):int(self.y1 * 1.15),
|
||||||
|
int(self.x1 * 0.7):int(self.x2 * 1.15)]
|
||||||
|
return frame
|
||||||
|
|
||||||
|
# according the class_id to get object name
|
||||||
|
def id_class_name(self, class_id):
|
||||||
|
for key, value in self.labels.items():
|
||||||
|
if class_id == int(key):
|
||||||
|
return value
|
||||||
|
|
||||||
|
# detect object
|
||||||
|
def obj_detect(self, img, goal, kp_img, desc_img, kp_list, desc_list, connection):
|
||||||
|
i = 0
|
||||||
|
MIN_MATCH_COUNT = 5
|
||||||
|
# sift = cv2.xfeatures2d.SIFT_create()
|
||||||
|
|
||||||
|
# find the keypoints and descriptors with SIFT
|
||||||
|
# kp = []
|
||||||
|
# des = []
|
||||||
|
kp = kp_list
|
||||||
|
des = desc_list
|
||||||
|
|
||||||
|
kp2, des2 = kp_img, desc_img
|
||||||
|
|
||||||
|
# FLANN parameters
|
||||||
|
FLANN_INDEX_KDTREE = 0
|
||||||
|
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
|
||||||
|
search_params = dict(checks=50) # or pass empty dictionary
|
||||||
|
flann = cv2.FlannBasedMatcher(index_params, search_params)
|
||||||
|
|
||||||
|
x, y = 0, 0
|
||||||
|
try:
|
||||||
|
for i in range(len(des)):
|
||||||
|
matches = flann.knnMatch(des[i], des2, k=2)
|
||||||
|
# store all the good matches as per Lowe's ratio test. 根据Lowe比率测试存储所有良好匹配项。
|
||||||
|
good = []
|
||||||
|
for m, n in matches:
|
||||||
|
if m.distance < 0.7 * n.distance:
|
||||||
|
good.append(m)
|
||||||
|
|
||||||
|
# When there are enough robust matching point pairs 当有足够的健壮匹配点对(至少个MIN_MATCH_COUNT)时
|
||||||
|
if len(good) > MIN_MATCH_COUNT:
|
||||||
|
|
||||||
|
# extract corresponding point pairs from matching 从匹配中提取出对应点对
|
||||||
|
# query index of small objects, training index of scenarios 小对象的查询索引,场景的训练索引
|
||||||
|
src_pts = np.float32([kp[i][m.queryIdx].pt
|
||||||
|
for m in good]).reshape(-1, 1, 2)
|
||||||
|
dst_pts = np.float32([kp2[m.trainIdx].pt
|
||||||
|
for m in good]).reshape(-1, 1, 2)
|
||||||
|
|
||||||
|
# Using matching points to find homography matrix in cv2.ransac 利用匹配点找到CV2.RANSAC中的单应矩阵
|
||||||
|
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,
|
||||||
|
5.0)
|
||||||
|
matchesMask = mask.ravel().tolist()
|
||||||
|
# Calculate the distortion of image, that is the corresponding position in frame 计算图1的畸变,也就是在图2中的对应的位置
|
||||||
|
h, w, d = goal[i].shape
|
||||||
|
pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1],
|
||||||
|
[w - 1, 0]]).reshape(-1, 1, 2)
|
||||||
|
dst = cv2.perspectiveTransform(pts, M)
|
||||||
|
coord = (dst[0][0] + dst[1][0] + dst[2][0] +
|
||||||
|
dst[3][0]) / 4.0
|
||||||
|
connection.send((DRAW_COORDS, coord))
|
||||||
|
# cv2.putText(img, "{}".format(coord), (50, 60),
|
||||||
|
# fontFace=None, fontScale=1,
|
||||||
|
# color=(0, 255, 0), lineType=1)
|
||||||
|
print(format(dst[0][0][0]))
|
||||||
|
x = (dst[0][0][0] + dst[1][0][0] + dst[2][0][0] +
|
||||||
|
dst[3][0][0]) / 4.0
|
||||||
|
y = (dst[0][0][1] + dst[1][0][1] + dst[2][0][1] +
|
||||||
|
dst[3][0][1]) / 4.0
|
||||||
|
|
||||||
|
# bound box 绘制边框
|
||||||
|
# img = cv2.polylines(img, [np.int32(dst)], True, 244, 3, cv2.LINE_AA)
|
||||||
|
connection.send((DRAW_RECT, dst))
|
||||||
|
# cv2.polylines(mixture, [np.int32(dst)], True, (0, 255, 0), 2, cv2.LINE_AA)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if x + y > 0:
|
||||||
|
return x, y
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# The path to save the image folder
|
||||||
|
def parse_folder(folder):
|
||||||
|
restore = []
|
||||||
|
path = '/home/er/catkin_ws/src/mycobot_ros/mycobot_ai/aikit_320_pi/' + folder # pi
|
||||||
|
|
||||||
|
for i, j, k in os.walk(path):
|
||||||
|
for l in k:
|
||||||
|
restore.append(cv2.imread(folder + '/{}'.format(l)))
|
||||||
|
# print(restore)
|
||||||
|
return restore
|
||||||
|
|
||||||
|
def compute_keypoints_and_descriptors(sift, images_lists):
|
||||||
|
kp_list = []
|
||||||
|
desc_list = []
|
||||||
|
for images in images_lists:
|
||||||
|
kp_tmp = []
|
||||||
|
desc_tmp = []
|
||||||
|
for img in images:
|
||||||
|
kp, desc = sift.detectAndCompute(img, None)
|
||||||
|
kp_tmp.append(kp)
|
||||||
|
desc_tmp.append(desc)
|
||||||
|
kp_list.append(kp_tmp)
|
||||||
|
desc_list.append(desc_tmp)
|
||||||
|
|
||||||
|
return kp_list, desc_list
|
||||||
|
|
||||||
|
GET_FRAME = 1
|
||||||
|
STOP_PROCESSING = 2
|
||||||
|
DRAW_COORDS = 3
|
||||||
|
DRAW_RECT = 4
|
||||||
|
CLEAR_DRAW = 5
|
||||||
|
CROP_FRAME = 6
|
||||||
|
|
||||||
|
def get_frame(connection):
|
||||||
|
connection.send(GET_FRAME)
|
||||||
|
frame = connection.recv()
|
||||||
|
return frame
|
||||||
|
|
||||||
|
def process_transform_frame(frame, x1, y1, x2, y2):
|
||||||
|
# enlarge the image by 1.5 times
|
||||||
|
fx = 1.5
|
||||||
|
fy = 1.5
|
||||||
|
frame = cv2.resize(frame, (0, 0),
|
||||||
|
fx=fx,
|
||||||
|
fy=fy,
|
||||||
|
interpolation=cv2.INTER_CUBIC)
|
||||||
|
if x1 != x2:
|
||||||
|
# the cutting ratio here is adjusted according to the actual situation
|
||||||
|
frame = frame[int(y2 * 0.7):int(y1 * 1.15),
|
||||||
|
int(x1 * 0.7):int(x2 * 1.15)]
|
||||||
|
return frame
|
||||||
|
|
||||||
|
def process_display_frame(connection):
|
||||||
|
cap_num = 0
|
||||||
|
coord = None
|
||||||
|
dst = None
|
||||||
|
x1 = 0
|
||||||
|
y1 = 0
|
||||||
|
x2 = 0
|
||||||
|
y2 = 0
|
||||||
|
cap = cv2.VideoCapture(cap_num, cv2.CAP_V4L)
|
||||||
|
# cap = cv2.VideoCapture(cap_num, cv2.CAP_DSHOW)
|
||||||
|
if not cap.isOpened():
|
||||||
|
cap.open()
|
||||||
|
while cv2.waitKey(1) < 0:
|
||||||
|
_, frame = cap.read()
|
||||||
|
frame = process_transform_frame(frame, x1, y1, x2, y2)
|
||||||
|
if connection.poll():
|
||||||
|
request = connection.recv()
|
||||||
|
if request == GET_FRAME:
|
||||||
|
connection.send(frame)
|
||||||
|
elif request == CLEAR_DRAW:
|
||||||
|
coord = None
|
||||||
|
dst = None
|
||||||
|
elif type(request) is tuple:
|
||||||
|
if request[0] == DRAW_COORDS:
|
||||||
|
coord = request[1]
|
||||||
|
elif request[0] == DRAW_RECT:
|
||||||
|
dst = request[1]
|
||||||
|
elif request[0] == CROP_FRAME:
|
||||||
|
x1 = request[1]
|
||||||
|
y1 = request[2]
|
||||||
|
x2 = request[3]
|
||||||
|
y2 = request[4]
|
||||||
|
|
||||||
|
if not coord is None:
|
||||||
|
cv2.putText(frame, "{}".format(coord), (50, 60), fontFace=None,
|
||||||
|
fontScale=1, color=(0, 255, 0), lineType=1)
|
||||||
|
if not dst is None:
|
||||||
|
frame = cv2.polylines(frame, [np.int32(dst)], True, 244, 3, cv2.LINE_AA)
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
time.sleep(0.04)
|
||||||
|
connection.send(STOP_PROCESSING)
|
||||||
|
|
||||||
|
def run():
|
||||||
|
parent_conn, child_conn = Pipe()
|
||||||
|
child = Process(target = process_display_frame, args=(child_conn,))
|
||||||
|
child.start()
|
||||||
|
|
||||||
|
res_queue = [[], [], [], []]
|
||||||
|
res_queue[0] = parse_folder('res/D')
|
||||||
|
res_queue[1] = parse_folder('res/C')
|
||||||
|
res_queue[2] = parse_folder('res/A')
|
||||||
|
res_queue[3] = parse_folder('res/B')
|
||||||
|
|
||||||
|
sift = cv2.xfeatures2d.SIFT_create()
|
||||||
|
# sift = cv2.SIFT_create()
|
||||||
|
kp_list, desc_list = compute_keypoints_and_descriptors(sift, res_queue)
|
||||||
|
|
||||||
|
# init a class of Object_detect
|
||||||
|
detect = Object_detect()
|
||||||
|
|
||||||
|
# init mycobot
|
||||||
|
detect.run()
|
||||||
|
|
||||||
|
# _init_ = 20 #
|
||||||
|
init_num = 0
|
||||||
|
nparams = 0
|
||||||
|
# num = 0
|
||||||
|
# real_sx = real_sy = 0
|
||||||
|
while True:
|
||||||
|
start_time = time.time()
|
||||||
|
if parent_conn.poll():
|
||||||
|
data = parent_conn.recv()
|
||||||
|
if data == STOP_PROCESSING:
|
||||||
|
break
|
||||||
|
# read camera
|
||||||
|
frame = get_frame(parent_conn)
|
||||||
|
# deal img
|
||||||
|
#frame = detect.transform_frame(frame)
|
||||||
|
|
||||||
|
# if _init_ > 0:
|
||||||
|
# _init_ -= 1
|
||||||
|
# continue
|
||||||
|
# calculate the parameters of camera clipping
|
||||||
|
if init_num < 20:
|
||||||
|
if detect.get_calculate_params(frame) is None:
|
||||||
|
# cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x1, x2, y1, y2 = detect.get_calculate_params(frame)
|
||||||
|
detect.draw_marker(frame, x1, y1)
|
||||||
|
detect.draw_marker(frame, x2, y2)
|
||||||
|
detect.sum_x1 += x1
|
||||||
|
detect.sum_x2 += x2
|
||||||
|
detect.sum_y1 += y1
|
||||||
|
detect.sum_y2 += y2
|
||||||
|
init_num += 1
|
||||||
|
continue
|
||||||
|
elif init_num == 20:
|
||||||
|
detect.set_cut_params(
|
||||||
|
(detect.sum_x1) / 20.0,
|
||||||
|
(detect.sum_y1) / 20.0,
|
||||||
|
(detect.sum_x2) / 20.0,
|
||||||
|
(detect.sum_y2) / 20.0,
|
||||||
|
)
|
||||||
|
parent_conn.send((CROP_FRAME,
|
||||||
|
(detect.sum_x1) / 20.0,
|
||||||
|
(detect.sum_y1) / 20.0,
|
||||||
|
(detect.sum_x2) / 20.0,
|
||||||
|
(detect.sum_y2) / 20.0))
|
||||||
|
detect.sum_x1 = detect.sum_x2 = detect.sum_y1 = detect.sum_y2 = 0
|
||||||
|
init_num += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# calculate params of the coords between cube and mycobot
|
||||||
|
if nparams < 10:
|
||||||
|
if detect.get_calculate_params(frame) is None:
|
||||||
|
# cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x1, x2, y1, y2 = detect.get_calculate_params(frame)
|
||||||
|
detect.draw_marker(frame, x1, y1)
|
||||||
|
detect.draw_marker(frame, x2, y2)
|
||||||
|
detect.sum_x1 += x1
|
||||||
|
detect.sum_x2 += x2
|
||||||
|
detect.sum_y1 += y1
|
||||||
|
detect.sum_y2 += y2
|
||||||
|
nparams += 1
|
||||||
|
print ("ok")
|
||||||
|
continue
|
||||||
|
elif nparams == 10:
|
||||||
|
nparams += 1
|
||||||
|
# calculate and set params of calculating real coord between cube and mycobot
|
||||||
|
detect.set_params((detect.sum_x1 + detect.sum_x2) / 20.0,
|
||||||
|
(detect.sum_y1 + detect.sum_y2) / 20.0,
|
||||||
|
abs(detect.sum_x1 - detect.sum_x2) / 10.0 +
|
||||||
|
abs(detect.sum_y1 - detect.sum_y2) / 10.0)
|
||||||
|
print("ok")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# get detect result
|
||||||
|
kp_img, desc_img = sift.detectAndCompute(frame, None)
|
||||||
|
frame = get_frame(parent_conn)
|
||||||
|
for i, v in enumerate(res_queue):
|
||||||
|
# HACK: to update frame every time
|
||||||
|
detect_result = detect.obj_detect(frame, v, kp_img, desc_img, kp_list[i], desc_list[i], parent_conn)
|
||||||
|
if detect_result:
|
||||||
|
x, y = detect_result
|
||||||
|
# calculate real coord between cube and mycobot
|
||||||
|
real_x, real_y = detect.get_position(x, y)
|
||||||
|
detect.color = i
|
||||||
|
detect.pub_marker(real_x / 1000.0, real_y / 1000.0)
|
||||||
|
detect.decide_move(real_x, real_y, detect.color)
|
||||||
|
# if num == 5:
|
||||||
|
# detect.color = i
|
||||||
|
# detect.pub_marker(real_sx / 5.0 / 1000.0,
|
||||||
|
# real_sy / 5.0 / 1000.0)
|
||||||
|
# detect.decide_move(real_sx / 5.0, real_sy / 5.0,
|
||||||
|
# detect.color)
|
||||||
|
# num = real_sx = real_sy = 0
|
||||||
|
# else:
|
||||||
|
# num += 1
|
||||||
|
# real_sy += real_y
|
||||||
|
# real_sx += real_x
|
||||||
|
parent_conn.send(CLEAR_DRAW)
|
||||||
|
|
||||||
|
# cv2.imshow("figure", frame)
|
||||||
|
time.sleep(0.05)
|
||||||
|
end_time = time.time()
|
||||||
|
# print("loop_time = ", end_time - start_time)
|
||||||
|
|
||||||
|
# close the window
|
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||||
|
# cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
child.join()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run()
|
||||||
|
# Object_detect().take_photo()
|
||||||
|
# Object_detect().cut_photo()
|
||||||
482
mycobot_ai/aikit_320_pi/scripts/aikit_shape.py
Normal file
|
|
@ -0,0 +1,482 @@
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
import os,sys
|
||||||
|
import math
|
||||||
|
import rospy
|
||||||
|
from visualization_msgs.msg import Marker
|
||||||
|
from moving_utils import Movement
|
||||||
|
from pymycobot.mycobot import MyCobot
|
||||||
|
|
||||||
|
|
||||||
|
IS_CV_4 = cv2.__version__[0] == '4'
|
||||||
|
__version__ = "1.0"
|
||||||
|
# Adaptive seeed
|
||||||
|
|
||||||
|
|
||||||
|
class Object_detect(Movement):
|
||||||
|
|
||||||
|
def __init__(self, camera_x = 260, camera_y = 0):
|
||||||
|
# inherit the parent class
|
||||||
|
super(Object_detect, self).__init__()
|
||||||
|
# declare mycobot320
|
||||||
|
self.mc = None
|
||||||
|
|
||||||
|
# 移动角度
|
||||||
|
self.move_angles = [
|
||||||
|
[0.61, 45.87, -92.37, -41.3, 89.56, 9.58], # init the point
|
||||||
|
[18.8, -7.91, -54.49, -23.02, 89.56, -14.76], # point to grab
|
||||||
|
[17.22, -5.27, -52.47, -25.75, 89.73, -0.26],
|
||||||
|
]
|
||||||
|
|
||||||
|
# 移动坐标
|
||||||
|
self.move_coords = [
|
||||||
|
[32, -228.3, 201.6, -168.07, -7.17, -92.56], # D Sorting area
|
||||||
|
[266.5, -219.7, 209.3, -170, -3.64, -94.62], # C Sorting area
|
||||||
|
[253.8, 236.8, 224.6, -170, 6.87, -77.91], # A Sorting area
|
||||||
|
[35.9, 235.4, 211.8, -169.33, -9.27, 88.3], # B Sorting area
|
||||||
|
]
|
||||||
|
|
||||||
|
# which robot: USB* is m5; ACM* is wio; AMA* is raspi
|
||||||
|
self.robot_m5 = os.popen("ls /dev/ttyUSB*").readline()[:-1]
|
||||||
|
self.robot_wio = os.popen("ls /dev/ttyACM*").readline()[:-1]
|
||||||
|
self.robot_raspi = os.popen("ls /dev/ttyAMA*").readline()[:-1]
|
||||||
|
self.robot_jes = os.popen("ls /dev/ttyTHS1").readline()[:-1]
|
||||||
|
|
||||||
|
# choose place to set cube
|
||||||
|
self.color = 0
|
||||||
|
# parameters to calculate camera clipping parameters
|
||||||
|
self.x1 = self.x2 = self.y1 = self.y2 = 0
|
||||||
|
# set cache of real coord
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
|
||||||
|
# use to calculate coord between cube and mycobot
|
||||||
|
self.sum_x1 = self.sum_x2 = self.sum_y2 = self.sum_y1 = 0
|
||||||
|
# The coordinates of the grab center point relative to the mycobot
|
||||||
|
self.camera_x, self.camera_y = camera_x, camera_y
|
||||||
|
# The coordinates of the cube relative to the mycobot
|
||||||
|
self.c_x, self.c_y = 0, 0
|
||||||
|
# The ratio of pixels to actual values
|
||||||
|
self.ratio = 0
|
||||||
|
# Get ArUco marker dict that can be detected.
|
||||||
|
self.aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
|
||||||
|
# Get ArUco marker params.
|
||||||
|
self.aruco_params = cv2.aruco.DetectorParameters_create()
|
||||||
|
|
||||||
|
# 初始化背景减法器
|
||||||
|
self.mog =cv2.bgsegm.createBackgroundSubtractorMOG()
|
||||||
|
|
||||||
|
# init a node and a publisher
|
||||||
|
rospy.init_node("marker", anonymous=True)
|
||||||
|
self.pub = rospy.Publisher('/cube', Marker, queue_size=1)
|
||||||
|
# init a Marker
|
||||||
|
self.marker = Marker()
|
||||||
|
self.marker.header.frame_id = "base"
|
||||||
|
self.marker.ns = "cube"
|
||||||
|
self.marker.type = self.marker.CUBE
|
||||||
|
self.marker.action = self.marker.ADD
|
||||||
|
self.marker.scale.x = 0.04
|
||||||
|
self.marker.scale.y = 0.04
|
||||||
|
self.marker.scale.z = 0.04
|
||||||
|
self.marker.color.a = 1.0
|
||||||
|
self.marker.color.g = 1.0
|
||||||
|
self.marker.color.r = 1.0
|
||||||
|
|
||||||
|
# marker position initial
|
||||||
|
self.marker.pose.position.x = 0
|
||||||
|
self.marker.pose.position.y = 0
|
||||||
|
self.marker.pose.position.z = 0.03
|
||||||
|
self.marker.pose.orientation.x = 0
|
||||||
|
self.marker.pose.orientation.y = 0
|
||||||
|
self.marker.pose.orientation.z = 0
|
||||||
|
self.marker.pose.orientation.w = 1.0
|
||||||
|
|
||||||
|
# publish marker
|
||||||
|
def pub_marker(self, x, y, z=0.03):
|
||||||
|
self.marker.header.stamp = rospy.Time.now()
|
||||||
|
self.marker.pose.position.x = x
|
||||||
|
self.marker.pose.position.y = y
|
||||||
|
self.marker.pose.position.z = z
|
||||||
|
self.marker.color.g = self.color
|
||||||
|
self.pub.publish(self.marker)
|
||||||
|
|
||||||
|
# pump_control pi
|
||||||
|
def gpio_status(self, flag):
|
||||||
|
if flag:
|
||||||
|
"""start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
else:
|
||||||
|
"""stop suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
def pump_on(self):
|
||||||
|
"""Start the suction pump"""
|
||||||
|
self.mc.set_basic_output(1, 0)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
def pump_off(self):
|
||||||
|
"""stop suction pump m5"""
|
||||||
|
self.mc.set_basic_output(1, 1)
|
||||||
|
self.mc.set_basic_output(2, 0)
|
||||||
|
time.sleep(1)
|
||||||
|
self.mc.set_basic_output(2, 1)
|
||||||
|
|
||||||
|
# Grasping motion
|
||||||
|
def move(self, x, y, color):
|
||||||
|
# send Angle to move mycobot320
|
||||||
|
print(color)
|
||||||
|
print('x, y:', round(x, 2), round(y, 2))
|
||||||
|
# send Angle to move mycobot320
|
||||||
|
self.mc.send_angles(self.move_angles[2], 50)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# send coordinates to move mycobot
|
||||||
|
self.mc.send_coords([x, y, 230, -173.84, -0.14, -74.37], 100, 1)
|
||||||
|
time.sleep(2.5)
|
||||||
|
self.mc.send_coords([x, y, 100, -173.84, -0.14, -74.37], 100, 1) #
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# open pump
|
||||||
|
self.gpio_status(True)
|
||||||
|
time.sleep(1.5)
|
||||||
|
|
||||||
|
tmp = []
|
||||||
|
while True:
|
||||||
|
if not tmp:
|
||||||
|
tmp = self.mc.get_angles()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# print(tmp)
|
||||||
|
self.mc.send_angles([tmp[0], -0.71, -54.49, -23.02, 89.56, tmp[5]],25) # [18.8, -7.91, -54.49, -23.02, -0.79, -14.76]
|
||||||
|
time.sleep(3)
|
||||||
|
self.pub_marker(self.move_coords[2][0]/1000.0, self.move_coords[2][1]/1000.0, self.move_coords[2][2]/1000.0)
|
||||||
|
|
||||||
|
self.mc.send_coords(self.move_coords[color], 100, 1)
|
||||||
|
|
||||||
|
self.pub_marker(self.move_coords[color][0]/1000.0, self.move_coords[color][1]/1000.0, self.move_coords[color][2]/1000.0)
|
||||||
|
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
# close pump
|
||||||
|
self.gpio_status(False)
|
||||||
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
if color == 1:
|
||||||
|
self.pub_marker(
|
||||||
|
self.move_coords[color][0]/1000.0+0.03, self.move_coords[color][1]/1000.0-0.02
|
||||||
|
)
|
||||||
|
elif color == 0:
|
||||||
|
self.pub_marker(
|
||||||
|
self.move_coords[color][0]/1000.0+0.03, self.move_coords[color][1]/1000.0
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mc.send_angles(self.move_angles[0], 25)
|
||||||
|
time.sleep(4.5)
|
||||||
|
|
||||||
|
# decide whether grab cube
|
||||||
|
def decide_move(self, x, y, color):
|
||||||
|
print(x, y, self.cache_x, self.cache_y)
|
||||||
|
# detect the cube status move or run
|
||||||
|
if (abs(x - self.cache_x) + abs(y - self.cache_y)) / 2 > 5: # mm
|
||||||
|
self.cache_x, self.cache_y = x, y
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.cache_x = self.cache_y = 0
|
||||||
|
# 调整吸泵吸取位置,y增大,向左移动;y减小,向右移动;x增大,前方移动;x减小,向后方移动
|
||||||
|
self.move(x, y, color)
|
||||||
|
|
||||||
|
# init mycobot320
|
||||||
|
def run(self):
|
||||||
|
|
||||||
|
if "dev" in self.robot_raspi:
|
||||||
|
self.mc = MyCobot(self.robot_raspi, 115200)
|
||||||
|
self.gpio_status(False)
|
||||||
|
self.mc.send_angles([0.61, 45.87, -92.37, -41.3, 89.56, 9.58], 20)
|
||||||
|
time.sleep(2.5)
|
||||||
|
|
||||||
|
# draw aruco
|
||||||
|
def draw_marker(self, img, x, y):
|
||||||
|
# draw rectangle on img
|
||||||
|
cv2.rectangle(
|
||||||
|
img,
|
||||||
|
(x - 20, y - 20),
|
||||||
|
(x + 20, y + 20),
|
||||||
|
(0, 255, 0),
|
||||||
|
thickness=2,
|
||||||
|
lineType=cv2.FONT_HERSHEY_COMPLEX,
|
||||||
|
)
|
||||||
|
# add text on rectangle
|
||||||
|
cv2.putText(img, "({},{})".format(x, y), (x, y),
|
||||||
|
cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (243, 0, 0), 2,)
|
||||||
|
|
||||||
|
# get points of two aruco
|
||||||
|
def get_calculate_params(self, img):
|
||||||
|
# Convert the image to a gray image
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
# Detect ArUco marker.
|
||||||
|
corners, ids, rejectImaPoint = cv2.aruco.detectMarkers(
|
||||||
|
gray, self.aruco_dict, parameters=self.aruco_params
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Two Arucos must be present in the picture and in the same order.
|
||||||
|
There are two Arucos in the Corners, and each aruco contains the pixels of its four corners.
|
||||||
|
Determine the center of the aruco by the four corners of the aruco.
|
||||||
|
"""
|
||||||
|
if len(corners) > 0:
|
||||||
|
if ids is not None:
|
||||||
|
if len(corners) <= 1 or ids[0] == 1:
|
||||||
|
return None
|
||||||
|
x1 = x2 = y1 = y2 = 0
|
||||||
|
point_11, point_21, point_31, point_41 = corners[0][0]
|
||||||
|
x1, y1 = int((point_11[0] + point_21[0] + point_31[0] + point_41[0]) / 4.0), int(
|
||||||
|
(point_11[1] + point_21[1] + point_31[1] + point_41[1]) / 4.0)
|
||||||
|
point_1, point_2, point_3, point_4 = corners[1][0]
|
||||||
|
x2, y2 = int((point_1[0] + point_2[0] + point_3[0] + point_4[0]) / 4.0), int(
|
||||||
|
(point_1[1] + point_2[1] + point_3[1] + point_4[1]) / 4.0)
|
||||||
|
return x1, x2, y1, y2
|
||||||
|
return None
|
||||||
|
|
||||||
|
# set camera clipping parameters
|
||||||
|
def set_cut_params(self, x1, y1, x2, y2):
|
||||||
|
self.x1 = int(x1)
|
||||||
|
self.y1 = int(y1)
|
||||||
|
self.x2 = int(x2)
|
||||||
|
self.y2 = int(y2)
|
||||||
|
print(self.x1, self.y1, self.x2, self.y2)
|
||||||
|
|
||||||
|
# set parameters to calculate the coords between cube and mycobot320
|
||||||
|
def set_params(self, c_x, c_y, ratio):
|
||||||
|
self.c_x = c_x
|
||||||
|
self.c_y = c_y
|
||||||
|
self.ratio = 220.0/ratio
|
||||||
|
|
||||||
|
# calculate the coords between cube and mycobot320
|
||||||
|
def get_position(self, x, y):
|
||||||
|
return ((y - self.c_y)*self.ratio + self.camera_x), ((x - self.c_x)*self.ratio + self.camera_y)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Calibrate the camera according to the calibration parameters.
|
||||||
|
Enlarge the video pixel by 1.5 times, which means enlarge the video size by 1.5 times.
|
||||||
|
If two ARuco values have been calculated, clip the video.
|
||||||
|
"""
|
||||||
|
def transform_frame(self, frame):
|
||||||
|
# enlarge the image by 1.5 times
|
||||||
|
fx = 1.5
|
||||||
|
fy = 1.5
|
||||||
|
frame = cv2.resize(frame, (0, 0), fx=fx, fy=fy,
|
||||||
|
interpolation=cv2.INTER_CUBIC)
|
||||||
|
if self.x1 != self.x2:
|
||||||
|
# the cutting ratio here is adjusted according to the actual situation
|
||||||
|
frame = frame[int(self.y2*0.78):int(self.y1*1.1),
|
||||||
|
int(self.x1*0.86):int(self.x2*1.08)]
|
||||||
|
return frame
|
||||||
|
|
||||||
|
# 检测物体的形状
|
||||||
|
def shape_detect(self,img):
|
||||||
|
x = 0
|
||||||
|
y = 0
|
||||||
|
Alpha = 65.6
|
||||||
|
Gamma=-8191.5
|
||||||
|
cal = cv2.addWeighted(img, Alpha,img, 0, Gamma)
|
||||||
|
gray = cv2.cvtColor(cal, cv2.COLOR_BGR2GRAY)
|
||||||
|
|
||||||
|
# 转换为灰度图片
|
||||||
|
#ray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
|
||||||
|
|
||||||
|
# a etching operation on a picture to remove edge roughness
|
||||||
|
erosion = cv2.erode(gray, np.ones((2, 2), np.uint8), iterations=2)
|
||||||
|
|
||||||
|
# the image for expansion operation, its role is to deepen the color depth in the picture
|
||||||
|
dilation = cv2.dilate(erosion, np.ones(
|
||||||
|
(1, 1), np.uint8), iterations=2)
|
||||||
|
|
||||||
|
|
||||||
|
# 设定灰度图的阈值 175, 255
|
||||||
|
_, threshold = cv2.threshold(dilation, 175, 255, cv2.THRESH_BINARY)
|
||||||
|
# 边缘检测
|
||||||
|
edges = cv2.Canny(threshold,50,100)
|
||||||
|
# 检测物体边框
|
||||||
|
contours,_ = cv2.findContours(
|
||||||
|
edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if len(contours)>0:
|
||||||
|
for cnt in contours:
|
||||||
|
# if 6000>cv2.contourArea(cnt) and cv2.contourArea(cnt)>4500:
|
||||||
|
if cv2.contourArea(cnt)>5500:
|
||||||
|
objectType = None
|
||||||
|
peri = cv2.arcLength(cnt,True)
|
||||||
|
approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
|
||||||
|
objCor = len(approx)
|
||||||
|
x, y, w, h = cv2.boundingRect(approx)
|
||||||
|
|
||||||
|
boxes = [
|
||||||
|
box
|
||||||
|
for box in [cv2.boundingRect(c) for c in contours]
|
||||||
|
if min(img.shape[0], img.shape[1]) / 10
|
||||||
|
< min(box[2], box[3])
|
||||||
|
< min(img.shape[0], img.shape[1]) / 1
|
||||||
|
]
|
||||||
|
if boxes:
|
||||||
|
for box in boxes:
|
||||||
|
x, y, w, h = box
|
||||||
|
# find the largest object that fits the requirements
|
||||||
|
c = max(contours, key=cv2.contourArea)
|
||||||
|
rect = cv2.minAreaRect(c)
|
||||||
|
box = cv2.boxPoints(rect)
|
||||||
|
box = np.int0(box)
|
||||||
|
cv2.drawContours(img, [box], 0, (153, 153, 0), 2)
|
||||||
|
x = int(rect[0][0])
|
||||||
|
y = int(rect[0][1])
|
||||||
|
|
||||||
|
if objCor==3:
|
||||||
|
objectType = "Triangle(三角形)"
|
||||||
|
cv2.drawContours(img, [cnt], 0, (0, 0, 255), 3)
|
||||||
|
self.color = 3
|
||||||
|
elif objCor==4:
|
||||||
|
box = cv2.boxPoints(rect)
|
||||||
|
box = np.int0(box)
|
||||||
|
_W = math.sqrt(math.pow((box[0][0] - box[1][0]), 2) + math.pow((box[0][1] - box[1][1]), 2))
|
||||||
|
_H = math.sqrt(math.pow((box[0][0] - box[3][0]), 2) + math.pow((box[0][1] - box[3][1]), 2))
|
||||||
|
aspRatio = _W/float(_H)
|
||||||
|
if 0.98 < aspRatio < 1.03:
|
||||||
|
objectType = "Square(正方形)"
|
||||||
|
cv2.drawContours(img, [cnt], 0, (0, 0, 255), 3)
|
||||||
|
self.color=1
|
||||||
|
else:
|
||||||
|
objectType = "Rectangle(长方形)"
|
||||||
|
cv2.drawContours(img, [cnt], 0, (0, 0, 255), 3)
|
||||||
|
self.color=2
|
||||||
|
elif objCor>=8:
|
||||||
|
objectType = "Circle(圆形)"
|
||||||
|
self.color=0
|
||||||
|
cv2.drawContours(img, [cnt], 0, (0, 0, 255), 3)
|
||||||
|
else:
|
||||||
|
print('not recognized!')
|
||||||
|
print(objectType)
|
||||||
|
|
||||||
|
if abs(x) + abs(y) > 0:
|
||||||
|
return x, y
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# open the camera
|
||||||
|
cap_num = 0
|
||||||
|
cap = cv2.VideoCapture(cap_num, cv2.CAP_V4L)
|
||||||
|
# cap = cv2.VideoCapture(cap_num)
|
||||||
|
cap.set(3, 640)
|
||||||
|
cap.set(4, 480)
|
||||||
|
if not cap.isOpened():
|
||||||
|
cap.open()
|
||||||
|
# init a class of Object_detect
|
||||||
|
detect = Object_detect()
|
||||||
|
# init mycobot320
|
||||||
|
detect.run()
|
||||||
|
|
||||||
|
_init_ = 20
|
||||||
|
init_num = 0
|
||||||
|
nparams = 0
|
||||||
|
num = 0
|
||||||
|
real_sx = real_sy = 0
|
||||||
|
while cv2.waitKey(1) < 0:
|
||||||
|
# read camera
|
||||||
|
_, frame = cap.read()
|
||||||
|
# deal img
|
||||||
|
frame = detect.transform_frame(frame)
|
||||||
|
if _init_ > 0:
|
||||||
|
_init_ -= 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# calculate the parameters of camera clipping
|
||||||
|
if init_num < 20:
|
||||||
|
if detect.get_calculate_params(frame) is None:
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x1, x2, y1, y2 = detect.get_calculate_params(frame)
|
||||||
|
detect.draw_marker(frame, x1, y1)
|
||||||
|
detect.draw_marker(frame, x2, y2)
|
||||||
|
detect.sum_x1 += x1
|
||||||
|
detect.sum_x2 += x2
|
||||||
|
detect.sum_y1 += y1
|
||||||
|
detect.sum_y2 += y2
|
||||||
|
init_num += 1
|
||||||
|
continue
|
||||||
|
elif init_num == 20:
|
||||||
|
detect.set_cut_params(
|
||||||
|
(detect.sum_x1)/20.0,
|
||||||
|
(detect.sum_y1)/20.0,
|
||||||
|
(detect.sum_x2)/20.0,
|
||||||
|
(detect.sum_y2)/20.0,
|
||||||
|
)
|
||||||
|
detect.sum_x1 = detect.sum_x2 = detect.sum_y1 = detect.sum_y2 = 0
|
||||||
|
init_num += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# calculate params of the coords between cube and mycobot320
|
||||||
|
if nparams < 10:
|
||||||
|
if detect.get_calculate_params(frame) is None:
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x1, x2, y1, y2 = detect.get_calculate_params(frame)
|
||||||
|
detect.draw_marker(frame, x1, y1)
|
||||||
|
detect.draw_marker(frame, x2, y2)
|
||||||
|
detect.sum_x1 += x1
|
||||||
|
detect.sum_x2 += x2
|
||||||
|
detect.sum_y1 += y1
|
||||||
|
detect.sum_y2 += y2
|
||||||
|
nparams += 1
|
||||||
|
continue
|
||||||
|
elif nparams == 10:
|
||||||
|
nparams += 1
|
||||||
|
# calculate and set params of calculating real coord between cube and mycobot320
|
||||||
|
detect.set_params(
|
||||||
|
(detect.sum_x1+detect.sum_x2)/20.0,
|
||||||
|
(detect.sum_y1+detect.sum_y2)/20.0,
|
||||||
|
abs(detect.sum_x1-detect.sum_x2)/10.0 +
|
||||||
|
abs(detect.sum_y1-detect.sum_y2)/10.0
|
||||||
|
)
|
||||||
|
print("ok")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# get detect result
|
||||||
|
# detect_result = detect.color_detect(frame)
|
||||||
|
# print('调用检测')
|
||||||
|
detect_result = detect.shape_detect(frame)
|
||||||
|
# print("完成检测")
|
||||||
|
if detect_result is None:
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
x, y = detect_result
|
||||||
|
# calculate real coord between cube and mycobot320
|
||||||
|
real_x, real_y = detect.get_position(x, y)
|
||||||
|
if num == 20:
|
||||||
|
detect.pub_marker(real_sx/20.0/1000.0, real_sy/20.0/1000.0)
|
||||||
|
detect.decide_move(real_sx/20.0, real_sy/20.0, detect.color)
|
||||||
|
num = real_sx = real_sy = 0
|
||||||
|
|
||||||
|
else:
|
||||||
|
num += 1
|
||||||
|
real_sy += real_y
|
||||||
|
real_sx += real_x
|
||||||
|
|
||||||
|
cv2.imshow("figure", frame)
|
||||||
|
|
||||||
|
# close the window
|
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||||
|
cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
sys.exit()
|
||||||
49
mycobot_ai/aikit_320_pi/scripts/moving_utils.py
Executable file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#encoding: UTF-8
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import rospy
|
||||||
|
import time,os
|
||||||
|
|
||||||
|
from mycobot_communication.msg import MycobotSetAngles, MycobotSetCoords, MycobotPumpStatus
|
||||||
|
|
||||||
|
|
||||||
|
class Movement(object):
|
||||||
|
"""Tools class: Communication with mycobot."""
|
||||||
|
def __init__(self):
|
||||||
|
super(Movement, self).__init__()
|
||||||
|
self.angle_pub = rospy.Publisher("mycobot/angles_goal", MycobotSetAngles, queue_size=5)
|
||||||
|
self.coord_pub = rospy.Publisher("mycobot/coords_goal", MycobotSetCoords, queue_size=5)
|
||||||
|
|
||||||
|
self.pump_pub = rospy.Publisher("mycobot/pump_status", MycobotPumpStatus, queue_size=10)
|
||||||
|
|
||||||
|
self.angles = MycobotSetAngles()
|
||||||
|
self.coords = MycobotSetCoords()
|
||||||
|
self.pump = MycobotPumpStatus()
|
||||||
|
|
||||||
|
def pub_coords(self, item, sp=20, m=1):
|
||||||
|
self.coords.x = item[0]
|
||||||
|
self.coords.y = item[1]
|
||||||
|
self.coords.z = item[2]
|
||||||
|
self.coords.rx = item[3]
|
||||||
|
self.coords.ry = item[4]
|
||||||
|
self.coords.rz = item[5]
|
||||||
|
self.coords.speed = sp
|
||||||
|
self.coords.model = m
|
||||||
|
self.coord_pub.publish(self.coords)
|
||||||
|
|
||||||
|
|
||||||
|
def pub_angles(self, item, sp):
|
||||||
|
self.angles.joint_1 = item[0]
|
||||||
|
self.angles.joint_2 = item[1]
|
||||||
|
self.angles.joint_3 = item[2]
|
||||||
|
self.angles.joint_4 = item[3]
|
||||||
|
self.angles.joint_5 = item[4]
|
||||||
|
self.angles.joint_6 = item[5]
|
||||||
|
self.angles.speed = sp
|
||||||
|
self.angle_pub.publish(self.angles)
|
||||||
|
|
||||||
|
|
||||||
|
def pub_pump(self, flag,Pin):
|
||||||
|
self.pump.Status = flag
|
||||||
|
self.pump.Pin1 = Pin[0]
|
||||||
|
self.pump.Pin2 = Pin[1]
|
||||||
|
self.pump_pub.publish(self.pump)
|
||||||
18
mycobot_ai/aikit_320_pi/scripts/test.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
from pymycobot.mycobot import MyCobot
|
||||||
|
import time
|
||||||
|
from pymycobot import PI_BAUD, PI_PORT
|
||||||
|
|
||||||
|
mc = MyCobot(PI_PORT, PI_BAUD)
|
||||||
|
|
||||||
|
coords = [
|
||||||
|
[135.0, -65.5, 280.1, 178.99, 5.38, -179.9],
|
||||||
|
[136.1, -141.6, 243.9, 178.99, 5.38, -179.9]
|
||||||
|
]
|
||||||
|
|
||||||
|
angles = [0, 0, 0, 0, 0, 0]
|
||||||
|
|
||||||
|
mc.send_coords(coords[0], 20, 1)
|
||||||
|
time.sleep(3)
|
||||||
|
mc.send_coords(coords[1], 20, 1)
|
||||||
|
|
||||||
|
|
||||||
1257
mycobot_description/urdf/new_320_pi/ai_kit320.dae
Normal file
204
mycobot_description/urdf/new_320_pi/new_mycobot_vision_v2.urdf
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="firefighter" >
|
||||||
|
|
||||||
|
<xacro:property name="width" value=".2" />
|
||||||
|
|
||||||
|
|
||||||
|
<link name="env">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 1.5708 3.14159-->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/ai_kit320.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<!-- <origin xyz = "0 0 -0.02 " rpy = "1.5708 0 -1.5708"/> -->
|
||||||
|
<origin xyz = "0 0 0.0 " rpy = "0 0 0"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="base">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 1.5708 3.14159-->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/base.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "0.0 0 0 " rpy = " 0 0 3.1415926"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 1.5708 3.14159-->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/base.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "0.0 0 0 " rpy = " 0 0 3.1415926"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="link1">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link1.dae"/>
|
||||||
|
</geometry>
|
||||||
|
|
||||||
|
<origin xyz = "0.115 -0.172 -0.086 " rpy = " 0 0 3.1415926"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link1.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "0.115 -0.172 -0.09 " rpy = " 0 0 3.1415926"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
<link name="link2">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link2.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.075 -0.115 -0.022 " rpy = " 1.5708 0 1.5708"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link2.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.075 -0.115 -0.022 " rpy = " 1.5708 0 1.5708"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
<link name="link3">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link3.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.22 -0.115 0.142 " rpy = " 1.5708 0 1.5708"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link3.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.22 -0.115 0.142 " rpy = " 1.5708 0 1.5708"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
<link name="link4">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link4.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.115 0.338 -0.1435" rpy = " 1.5708 0 0"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link4.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.115 0.338 -0.1435 " rpy = " 1.5708 0 0"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
<link name="link5">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link5.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.1149 -0.0322 -0.482 " rpy = " 0 0 0"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link5.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.1149 -0.0322 -0.482 " rpy = " 0 0 0"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
<link name="link6">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link6.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.11478 0.433 -0.15 " rpy = " 1.5708 0 0"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<!--- 0.0 0 -0.04 -->
|
||||||
|
<mesh filename="package://mycobot_description/urdf/new_320_pi/link6.dae"/>
|
||||||
|
</geometry>
|
||||||
|
<origin xyz = "-0.11478 0.433 -0.15 " rpy = " 1.5708 0 0"/>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
<joint name="joint2_to_joint1" type="revolute">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<limit effort = "1000.0" lower = "-2.96" upper = "2.96" velocity = "0"/>
|
||||||
|
<parent link="base"/>
|
||||||
|
<child link="link1"/>
|
||||||
|
<origin xyz= "0 0 0.162" rpy = "0 0 0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
|
||||||
|
<joint name="joint3_to_joint2" type="revolute">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<limit effort = "1000.0" lower = "-2.79" upper = "2.79" velocity = "0"/>
|
||||||
|
<parent link="link1"/>
|
||||||
|
<child link="link2"/>
|
||||||
|
<origin xyz= "0 0 0" rpy = "0 -1.5708 1.5708"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
|
||||||
|
<joint name="joint4_to_joint3" type="revolute">
|
||||||
|
<axis xyz=" 0 0 1"/>
|
||||||
|
<limit effort = "1000.0" lower = "-2.79" upper = "2.79" velocity = "0"/>
|
||||||
|
<parent link="link2"/>
|
||||||
|
<child link="link3"/>
|
||||||
|
<origin xyz= "0.13635 0 0 " rpy = "0 0 0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
|
||||||
|
<joint name="joint5_to_joint4" type="revolute">
|
||||||
|
<axis xyz=" 0 0 1"/>
|
||||||
|
<limit effort = "1000.0" lower = "-2.79" upper = "2.79" velocity = "0"/>
|
||||||
|
<parent link="link3"/>
|
||||||
|
<child link="link4"/>
|
||||||
|
<!-- <origin xyz = "0.12 0 0.09 " rpy = " 0 0 1.57080"/> -->
|
||||||
|
<origin xyz = "0.1205 0 0.082 " rpy = " 0 0 1.57080"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
|
||||||
|
<joint name="joint6_to_joint5" type="revolute">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<limit effort = "1000.0" lower = "-2.96" upper = "2.96" velocity = "0"/>
|
||||||
|
<parent link="link4"/>
|
||||||
|
<child link="link5"/>
|
||||||
|
<origin xyz= "0 -0.084 0" rpy = "1.5708 0 0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
|
||||||
|
<joint name="joint6output_to_joint6" type="revolute">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<limit effort = "1000.0" lower = "-3.05" upper = "3.05" velocity = "0"/>
|
||||||
|
<parent link="link5"/>
|
||||||
|
<child link="link6"/>
|
||||||
|
<origin xyz= "0 0.06635 0" rpy = "-1.5708 0 0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<joint name="vision_joint" type="fixed">
|
||||||
|
<axis xyz="0 0 0"/>
|
||||||
|
<limit effort = "1000.0" lower = "-3.14" upper = "3.14159" velocity = "0"/>
|
||||||
|
<parent link="base"/>
|
||||||
|
<child link="env"/>
|
||||||
|
<origin xyz= "0 0 0" rpy = "0 0 0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
|
||||||
|
</robot>
|
||||||