From 85b50aebf20685abb34036bcf68c71c367ccd099 Mon Sep 17 00:00:00 2001 From: marko <marko.guberina@control.lth.se> Date: Sat, 7 Dec 2024 20:04:19 +0000 Subject: [PATCH] pretty close to porting to heron w/ ros2. unfortunatelly there's no time to finish. but the last todo would be to use robot_localization on top of the existing ros2 nav2 stack to get sensors fusion AND the gps-type capability of amcl. other than that ur_rtde can be used simultaneously with the ros2 comm on the mir platform. and, of course, parameters need to be tuned so that they actually correspond to the robot --- python/examples/smc_node.py | 37 +++++++++-- .../__pycache__/managers.cpython-310.pyc | Bin 34124 -> 34343 bytes python/ur_simple_control/managers.py | 35 ++++++++++- .../optimal_control/crocoddyl_mpc.py | 7 ++- .../crocoddyl_optimal_control.py | 6 +- .../__pycache__/get_model.cpython-310.pyc | Bin 5915 -> 6609 bytes python/ur_simple_control/util/get_model.py | 58 ++++++++++++++++++ 7 files changed, 129 insertions(+), 14 deletions(-) diff --git a/python/examples/smc_node.py b/python/examples/smc_node.py index 7fc29a8..6d55386 100644 --- a/python/examples/smc_node.py +++ b/python/examples/smc_node.py @@ -2,12 +2,15 @@ import rclpy from rclpy.node import Node from geometry_msgs import msg +from nav_msgs.msg import Odometry from rclpy import wait_for_message import pinocchio as pin import argcomplete, argparse from functools import partial from ur_simple_control.managers import getMinimalArgParser, ControlLoopManager, RobotManager from ur_simple_control.clik.clik import getClikArgs, getClikController, controlLoopClik, moveL, compliantMoveL, controlLoopCompliantClik, invKinmQP +from ur_simple_control.optimal_control.get_ocp_args import get_OCP_args +from ur_simple_control.optimal_control.crocoddyl_mpc import CrocoIKMPC import threading @@ -16,14 +19,15 @@ def get_args(): parser.description = 'Run closed loop inverse kinematics \ of various kinds. Make sure you know what the goal is before you run!' parser = getClikArgs(parser) + parser = get_OCP_args(parser) argcomplete.autocomplete(parser) args = parser.parse_args() return args -class ROSCommHandler(Node): +class ROSCommHandlerHeron(Node): def __init__(self, args, robot_manager : RobotManager, loop_manager : ControlLoopManager): - super().__init__('ROSCommHandler') + super().__init__('ROSCommHandlerHeron') self.publisher_vel_base = self.create_publisher(msg.Twist, '/cmd_vel', 5) print("created publisher") @@ -35,20 +39,29 @@ class ROSCommHandler(Node): history = rclpy.qos.HistoryPolicy.KEEP_LAST, depth = 1, ) - self.subscription = self.create_subscription(msg.PoseWithCovarianceStamped, +# MASSIVE TODO: you want to be subsribed to a proper localization thing, +# specifically to output from robot_localization + self.subscription_amcl = self.create_subscription(msg.PoseWithCovarianceStamped, '/amcl_pose', self.pose_callback, qos_prof) + self.subscription_odom = self.create_subscription(Odometry, + '/odom', self.odom_callback, qos_prof) #wait_for_message.wait_for_message(msg.PoseWithCovarianceStamped, self, '/amcl_pose') #print("subscribed to /amcl_pose") - self.subscription # prevent unused variable warning + self.subscription_amcl # prevent unused variable warning + self.subscription_odom # prevent unused variable warning self.robot_manager = robot_manager self.loop_manager = loop_manager self.args = args + # ONE TRILLION PERCENT YOU NEED TO INTEGRATE/USE ODOM IN-BETWEEN THESE def pose_callback(self, mesg): self.robot_manager.q[0] = mesg.pose.pose.position.x self.robot_manager.q[1] = mesg.pose.pose.position.y # TODO: check that z can be used as cos(theta) and w as sin(theta) # (they could be defined some other way or theta could be offset of something) + # ONE TRILLION PERCENT THIS ISN'T CORRECT + # TODO: generate a rotation matrix from this quarternion with pinocchio, + # and give this is the value of the x or the y axis self.robot_manager.q[2] = mesg.pose.pose.orientation.z self.robot_manager.q[3] = mesg.pose.pose.orientation.w @@ -56,6 +69,17 @@ class ROSCommHandler(Node): print("received new amcl") #self.publisher_vel_base.publish(vel_cmd) + # HIGHLY LIKELY THAT THIS IS NOT THE THE VELOCITY OF THE BASE FRAME + def odom_callback(self, mesg : Odometry): + self.robot_manager.v_q[0] = mesg.twist.twist.linear.x + self.robot_manager.v_q[1] = mesg.twist.twist.linear.y + # TODO: check that z can be used as cos(theta) and w as sin(theta) + # (they could be defined some other way or theta could be offset of something) + self.robot_manager.v_q[2] = mesg.twist.twist.angular.z + + #vel_cmd = msg.Twist() + print("received new amcl") + #self.publisher_vel_base.publish(vel_cmd) @@ -65,8 +89,9 @@ if __name__ == '__main__': robot = RobotManager(args) goal = robot.defineGoalPointCLI() #goal = pin.SE3.Identity() - loop_manager = compliantMoveL(args, robot, goal, run=False) - ros_comm_handler = ROSCommHandler(args, robot, loop_manager) + #loop_manager = compliantMoveL(args, robot, goal, run=False) + loop_manager = CrocoIKMPC(args, robot, goal, run=False) + ros_comm_handler = ROSCommHandlerHeron(args, robot, loop_manager) thread = threading.Thread(target=rclpy.spin, args=(ros_comm_handler,), daemon=True) thread.start() diff --git a/python/ur_simple_control/__pycache__/managers.cpython-310.pyc b/python/ur_simple_control/__pycache__/managers.cpython-310.pyc index 9450f01b9ff3639106a03cef0cc1522b1ebe61c2..3b476c272538d9a1f12c522c5ae7d32bfa054cde 100644 GIT binary patch delta 5849 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 LRhNaKUWgX}l)H9) delta 5753 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 T%jA2l;*1iLzqRTz3FQL-bT4DA diff --git a/python/ur_simple_control/managers.py b/python/ur_simple_control/managers.py index df733ac..9a943bc 100644 --- a/python/ur_simple_control/managers.py +++ b/python/ur_simple_control/managers.py @@ -13,7 +13,7 @@ from ur_simple_control.util.grippers.robotiq.robotiq_gripper import RobotiqGripp from ur_simple_control.util.grippers.on_robot.twofg import TWOFG import copy import signal -from ur_simple_control.util.get_model import get_model, heron_approximation, heron_approximationDD, getGripperlessUR5e +from ur_simple_control.util.get_model import get_model, heron_approximation, heron_approximationDD, getGripperlessUR5e, mir_approximation from collections import deque from ur_simple_control.visualize.visualize import plotFromDict, realTimePlotter, manipulatorVisualizer from ur_simple_control.util.logging_utils import LogManager @@ -86,7 +86,7 @@ def getMinimalArgParser(): ################################################# parser.add_argument('--robot', type=str, \ help="which robot you're running or simulating", default="ur5e", \ - choices=['ur5e', 'heron', 'heronros', 'gripperlessur5e']) + choices=['ur5e', 'heron', 'heronros', 'gripperlessur5e', 'mirros']) parser.add_argument('--simulation', action=argparse.BooleanOptionalAction, \ help="whether you are running the UR simulator", default=False) parser.add_argument('--robot-ip', type=str, @@ -424,6 +424,9 @@ class RobotManager: if self.robot_name == "heronros": self.model, self.collision_model, self.visual_model, self.data = \ heron_approximation() + if self.robot_name == "mirros": + self.model, self.collision_model, self.visual_model, self.data = \ + mir_approximation() #self.publisher_vel_base = create_publisher(msg.Twist, '/cmd_vel', 5) #self.publisher_vel_base = publisher_vel_base if self.robot_name == "gripperlessur5e": @@ -494,6 +497,10 @@ class RobotManager: # so it can't be all zeros if self.robot_name == "heron": self.q[2] = 1.0 + if self.robot_name == "heronros": + self.q[2] = 1.0 + if self.robot_name == "mirros": + self.q[2] = 1.0 # v_q is the generalization of qd for every type of joint. # for revolute joints it's qd, but for ex. the planar joint it's the body velocity. self.v_q = np.zeros(self.model.nv) @@ -836,13 +843,35 @@ class RobotManager: self.v_q = qd self.q = pin.integrate(self.model, self.q, qd * self.dt) - # TODO: implement real thing if self.robot_name == "heron": # y-direction is not possible on heron qd[1] = 0 self.q = pin.integrate(self.model, self.q, qd * self.dt) + if self.robot_name == "heronros": # y-direction is not possible on heron + # TODO: REMOVE OBVIOUSLY +#############################################33 +# qd[:] = 0.0 +#############################################33 + + qd[1] = 0 + cmd_msg = msg.Twist() + cmd_msg.linear.x = qd[0] + cmd_msg.angular.z = qd[2] + #print("about to publish", cmd_msg) + self.publisher_vel_base.publish(cmd_msg) + # good to keep because updating is slow otherwise + # it's not correct, but it's more correct than not updating + #self.q = pin.integrate(self.model, self.q, qd * self.dt) + + if self.robot_name == "mirros": + # y-direction is not possible on heron + # TODO: REMOVE OBVIOUSLY +#############################################33 + #qd[:] = 0.0 +#############################################33 + qd[1] = 0 cmd_msg = msg.Twist() cmd_msg.linear.x = qd[0] diff --git a/python/ur_simple_control/optimal_control/crocoddyl_mpc.py b/python/ur_simple_control/optimal_control/crocoddyl_mpc.py index 6446153..9f5debc 100644 --- a/python/ur_simple_control/optimal_control/crocoddyl_mpc.py +++ b/python/ur_simple_control/optimal_control/crocoddyl_mpc.py @@ -60,7 +60,7 @@ def CrocoIKMPCControlLoop(args, robot : RobotManager, solver, i, past_data): return breakFlag, save_past_dict, log_item -def CrocoIKMPC(args, robot, goal): +def CrocoIKMPC(args, robot, goal, run=True): """ IKMPC ----- @@ -92,7 +92,10 @@ def CrocoIKMPC(args, robot, goal): } save_past_dict = {} loop_manager = ControlLoopManager(robot, controlLoop, args, save_past_dict, log_item) - loop_manager.run() + if run: + loop_manager.run() + else: + return loop_manager def CrocoEndEffectorPathFollowingMPCControlLoop(args, robot : RobotManager, solver : crocoddyl.SolverBoxFDDP, path_planner : ProcessManager, i, past_data): """ diff --git a/python/ur_simple_control/optimal_control/crocoddyl_optimal_control.py b/python/ur_simple_control/optimal_control/crocoddyl_optimal_control.py index 09157b3..2da5229 100644 --- a/python/ur_simple_control/optimal_control/crocoddyl_optimal_control.py +++ b/python/ur_simple_control/optimal_control/crocoddyl_optimal_control.py @@ -104,7 +104,7 @@ def createCrocoIKOCP(args, robot : RobotManager, x0, goal : pin.SE3): # and this should be 2 * model.nv the way things are defined here. - if robot.robot_name == "heron": + if robot.robot_name == "heron" or robot.robot_name == "heronros" or robot.robot_name == "mirros": xlb = xlb[1:] xub = xub[1:] @@ -293,7 +293,7 @@ def createCrocoEEPathFollowingOCP(args, robot : RobotManager, x0): # from one to point to the other. # point activation input and the residual need to be of the same length obviously, # and this should be 2 * model.nv the way things are defined here. - if robot.robot_name == "heron": + if robot.robot_name == "heron" or robot.robot_name == "heronros" or robot.robot_name == "mirros": xlb = xlb[1:] xub = xub[1:] @@ -447,7 +447,7 @@ def createBaseAndEEPathFollowingOCP(args, robot : RobotManager, x0): # and this should be 2 * model.nv the way things are defined here. - if robot.robot_name == "heron": + if robot.robot_name == "heron" or robot.robot_name == "heronros" or robot.robot_name == "mirros": xlb = xlb[1:] xub = xub[1:] diff --git a/python/ur_simple_control/util/__pycache__/get_model.cpython-310.pyc b/python/ur_simple_control/util/__pycache__/get_model.cpython-310.pyc index f3163af30f2c40fddc884a5ec95aabd5f6cbf222..7d915c240c73fce908dbaf592187296265279892 100644 GIT binary patch delta 586 zcmbQOchQ(HpO=@5fq{YHSypiRGN*}rGK^&twexuSQutdKq6AZzf*CXgHqKisSkKMC zz`)7Cz~Iclz)-Bh$iPs-uz+zPLoGuJV+}(*QwhTY=7kKkj44dDOexH@%q0w2EDKl{ zGSsrvFf3rJVJ=}<z`l^7hGhZALWUZqg)FtKDJ(S%S)3`%HVi4uU>2(l15}K~h9QNm zh9Qd!F3VM)0+NOZve+<`Fl2Er;7MUm;Yi_3;abR2%T~j%fVYOVh7D%%LS{yW621le zP!-Iz>@b;HjuM6i0x8@ztTpU493TfRWU1vW5nLdY&XB^hh;bof4QIS?4dVil8qS4` zj0`ml3q(s?7#4`7@Yb-VFhl%M!jL7NC9#kdsz7ofLoHVgLk%OyI4H@L#uCh+$>&!T z$iTo*6vV*5Fj-f`n1i(>KR?GnQ)+UVh%#4E0!S_qB)3Z>u)dIifkBhIs2n6%0U|0v zL=}jr1`#zNq83C%fQUK}Q4b>AL4*gK@MK_MxFwjISrngGP*9X#k(rxVl9`|P9u#** z3=9k$%xsJtj4X^Sj9g4S+#HN7|GC(>7`Z0%35l_@a4?B56*X<P7COw#q{lc(ERL-Q g<Se1dDPjd|O&~jZCSMg(W0afxM@*K5!=1+-04<D$CjbBd delta 94 zcmca;JX?=1pO=@5fq{YH?t;K{F^h?OGK_f>wewh+f*CaVHZEH$xcQgJW@e@@43pPO w#IbcTFfeEeP8OCd05gj`CL8h!^K;nb=BJeAq}nkuFfbI$Ox_?V%f#aY0L#M|vH$=8 diff --git a/python/ur_simple_control/util/get_model.py b/python/ur_simple_control/util/get_model.py index 71fcdc3..f687b61 100644 --- a/python/ur_simple_control/util/get_model.py +++ b/python/ur_simple_control/util/get_model.py @@ -235,6 +235,64 @@ def heron_approximation(): return model, visual_model.copy(), visual_model, data + +def mir_approximation(): + # mobile base as planar joint (there's probably a better + # option but whatever right now) + model_mobile_base = pin.Model() + model_mobile_base.name = "mobile_base" + geom_model_mobile_base = pin.GeometryModel() + joint_name = "mobile_base_planar_joint" + parent_id = 0 + # TEST + joint_placement = pin.SE3.Identity() + #joint_placement.rotation = pin.rpy.rpyToMatrix(0, -np.pi/2, 0) + #joint_placement.translation[2] = 0.2 + # TODO TODO TODO TODO TODO TODO TODO TODO + # TODO: heron is actually a differential drive, + # meaning that it is not a planar joint. + # we could put in a prismatic + revolute joint + # as the base (both joints being at same position), + # and that should work for our purposes. + # this makes sense for initial testing + # because mobile yumi's base is a planar joint + MOBILE_BASE_JOINT_ID = model_mobile_base.addJoint(parent_id, pin.JointModelPlanar(), + joint_placement.copy(), joint_name) + # we should immediately set velocity limits. + # there are no position limit by default and that is what we want. + # TODO: put in heron's values + # TODO: make these parameters the same as in mpc_params in the planner + model_mobile_base.velocityLimit[0] = 2 + model_mobile_base.velocityLimit[1] = 0 + model_mobile_base.velocityLimit[2] = 2 + # TODO: i have literally no idea what reasonable numbers are here + model_mobile_base.effortLimit[0] = 200 + model_mobile_base.effortLimit[1] = 0 + model_mobile_base.effortLimit[2] = 200 + #print("OBJECT_JOINT_ID",OBJECT_JOINT_ID) + #body_inertia = pin.Inertia.FromBox(args.box_mass, box_dimensions[0], + # box_dimensions[1], box_dimensions[2]) + + # pretty much random numbers + # TODO: find heron (mir) numbers + body_inertia = pin.Inertia.FromBox(30, 0.5, 0.3, 0.4) + # maybe change placement to sth else depending on where its grasped + model_mobile_base.appendBodyToJoint(MOBILE_BASE_JOINT_ID, body_inertia, pin.SE3.Identity()) + box_shape = fcl.Box(0.5, 0.3, 0.4) + body_placement = pin.SE3.Identity() + geometry_mobile_base = pin.GeometryObject("box_shape", MOBILE_BASE_JOINT_ID, box_shape, body_placement.copy()) + + geometry_mobile_base.meshColor = np.array([1., 0.1, 0.1, 1.]) + geom_model_mobile_base.addGeometryObject(geometry_mobile_base) + + # have to add the frame manually + # it's tool0 because that's used everywhere + model_mobile_base.addFrame(pin.Frame('tool0',MOBILE_BASE_JOINT_ID,0,joint_placement.copy(),pin.FrameType.JOINT) ) + + data = model_mobile_base.createData() + + return model_mobile_base, geom_model_mobile_base.copy(), geom_model_mobile_base.copy(), data + # TODO: # try building the mobile base as a rotational joint, # on top of which is a prismatic joint. -- GitLab